@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/cli.js CHANGED
@@ -27426,8 +27426,8 @@ var init_parseUtil = __esm({
27426
27426
  init_errors4();
27427
27427
  init_en();
27428
27428
  makeIssue = (params) => {
27429
- const { data, path: path6, errorMaps, issueData } = params;
27430
- const fullPath = [...path6, ...issueData.path || []];
27429
+ const { data, path: path5, errorMaps, issueData } = params;
27430
+ const fullPath = [...path5, ...issueData.path || []];
27431
27431
  const fullIssue = {
27432
27432
  ...issueData,
27433
27433
  path: fullPath
@@ -27738,11 +27738,11 @@ var init_types = __esm({
27738
27738
  init_parseUtil();
27739
27739
  init_util();
27740
27740
  ParseInputLazyPath = class {
27741
- constructor(parent, value, path6, key2) {
27741
+ constructor(parent, value, path5, key2) {
27742
27742
  this._cachedPath = [];
27743
27743
  this.parent = parent;
27744
27744
  this.data = value;
27745
- this._path = path6;
27745
+ this._path = path5;
27746
27746
  this._key = key2;
27747
27747
  }
27748
27748
  get path() {
@@ -32235,6 +32235,613 @@ var init_max_tokens = __esm({
32235
32235
  }
32236
32236
  });
32237
32237
 
32238
+ // src/fs-read.ts
32239
+ import { open } from "fs/promises";
32240
+ import { openSync, readSync, closeSync, fstatSync } from "fs";
32241
+ async function readTextFile(filePath) {
32242
+ const fh = await open(filePath, "r");
32243
+ try {
32244
+ const size5 = (await fh.stat()).size;
32245
+ const buf = Buffer.alloc(size5);
32246
+ let offset = 0;
32247
+ while (offset < size5) {
32248
+ const { bytesRead } = await fh.read(buf, offset, size5 - offset, offset);
32249
+ if (bytesRead === 0) break;
32250
+ offset += bytesRead;
32251
+ }
32252
+ return buf.subarray(0, offset).toString("utf-8");
32253
+ } finally {
32254
+ await fh.close();
32255
+ }
32256
+ }
32257
+ function readTextFileSync(filePath) {
32258
+ const fd = openSync(filePath, "r");
32259
+ try {
32260
+ const size5 = fstatSync(fd).size;
32261
+ const buf = Buffer.alloc(size5);
32262
+ let offset = 0;
32263
+ while (offset < size5) {
32264
+ const bytesRead = readSync(fd, buf, offset, size5 - offset, offset);
32265
+ if (bytesRead === 0) break;
32266
+ offset += bytesRead;
32267
+ }
32268
+ return buf.subarray(0, offset).toString("utf-8");
32269
+ } finally {
32270
+ closeSync(fd);
32271
+ }
32272
+ }
32273
+ var init_fs_read = __esm({
32274
+ "src/fs-read.ts"() {
32275
+ "use strict";
32276
+ }
32277
+ });
32278
+
32279
+ // src/spend-control.ts
32280
+ import * as fs from "fs";
32281
+ import * as path from "path";
32282
+ import { homedir } from "os";
32283
+ function normalizePayee(value) {
32284
+ return EVM_ADDRESS.test(value) ? value.toLowerCase() : value;
32285
+ }
32286
+ function isAddressList(list) {
32287
+ return ADDRESS_LISTS.includes(list);
32288
+ }
32289
+ function normalizePolicyValues(list, values) {
32290
+ return isAddressList(list) ? values.map(normalizePayee) : [...values];
32291
+ }
32292
+ function isValidPolicyValues(values) {
32293
+ return Array.isArray(values) && values.every((v) => typeof v === "string" && v.length > 0);
32294
+ }
32295
+ function isPolicyList(value) {
32296
+ return POLICY_LISTS.includes(value);
32297
+ }
32298
+ function cloneLimits(limits) {
32299
+ const clone = { ...limits };
32300
+ for (const key2 of POLICY_LISTS) {
32301
+ const val = limits[key2];
32302
+ if (val !== void 0) {
32303
+ clone[key2] = [...val];
32304
+ }
32305
+ }
32306
+ return clone;
32307
+ }
32308
+ function parseQuotedAmountUsd(selected) {
32309
+ const raw = selected.amount ?? selected.maxAmountRequired;
32310
+ if (typeof raw !== "string" || !CANONICAL_AMOUNT.test(raw)) {
32311
+ return void 0;
32312
+ }
32313
+ const micros = Number(raw);
32314
+ if (!Number.isSafeInteger(micros)) {
32315
+ return void 0;
32316
+ }
32317
+ return micros / 1e6;
32318
+ }
32319
+ function assertSpendPolicyAllows(control, selected) {
32320
+ const quoted = parseQuotedAmountUsd(selected);
32321
+ if (quoted === void 0 && control.hasAmountLimits()) {
32322
+ throw new SpendPolicyError(
32323
+ `Payment quote carries no usable amount (${JSON.stringify(
32324
+ selected.amount ?? selected.maxAmountRequired
32325
+ )}); refusing to sign against a configured spend limit`
32326
+ );
32327
+ }
32328
+ const estimatedCost2 = quoted ?? 0;
32329
+ const result = control.check(estimatedCost2, {
32330
+ payTo: selected.payTo,
32331
+ network: selected.network,
32332
+ asset: selected.asset
32333
+ });
32334
+ if (!result.allowed) {
32335
+ throw new SpendPolicyError(result.reason ?? "blocked by spend policy", {
32336
+ blockedBy: result.blockedBy,
32337
+ blockedByPolicy: result.blockedByPolicy
32338
+ });
32339
+ }
32340
+ if (!control.hasAggregateLimits()) {
32341
+ return void 0;
32342
+ }
32343
+ return control.reserve(estimatedCost2);
32344
+ }
32345
+ function registerSpendPolicyHook(x402, control) {
32346
+ const reservations = /* @__PURE__ */ new WeakMap();
32347
+ x402.onBeforePaymentCreation(async (ctx) => {
32348
+ const selected = ctx.selectedRequirements;
32349
+ const reservationId = assertSpendPolicyAllows(control, selected);
32350
+ if (reservationId !== void 0) {
32351
+ reservations.set(ctx.selectedRequirements, reservationId);
32352
+ }
32353
+ });
32354
+ x402.onAfterPaymentCreation(async (ctx) => {
32355
+ const key2 = ctx.selectedRequirements;
32356
+ const id2 = reservations.get(key2);
32357
+ if (id2 !== void 0) {
32358
+ reservations.delete(key2);
32359
+ control.settleReservation(id2, { action: "x402 payment" });
32360
+ }
32361
+ });
32362
+ x402.onPaymentCreationFailure(async (ctx) => {
32363
+ const key2 = ctx.selectedRequirements;
32364
+ const id2 = reservations.get(key2);
32365
+ if (id2 !== void 0) {
32366
+ reservations.delete(key2);
32367
+ control.releaseReservation(id2);
32368
+ }
32369
+ });
32370
+ }
32371
+ function formatDuration(seconds) {
32372
+ if (seconds < 60) {
32373
+ return `${seconds}s`;
32374
+ } else if (seconds < 3600) {
32375
+ const mins = Math.ceil(seconds / 60);
32376
+ return `${mins} min`;
32377
+ } else {
32378
+ const hours = Math.floor(seconds / 3600);
32379
+ const mins = Math.ceil(seconds % 3600 / 60);
32380
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
32381
+ }
32382
+ }
32383
+ 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;
32384
+ var init_spend_control = __esm({
32385
+ "src/spend-control.ts"() {
32386
+ "use strict";
32387
+ init_fs_read();
32388
+ WALLET_DIR = path.join(homedir(), ".openclaw", "blockrun");
32389
+ HOUR_MS = 60 * 60 * 1e3;
32390
+ DAY_MS = 24 * HOUR_MS;
32391
+ CAIP2_BASE = "eip155:8453";
32392
+ CAIP2_SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d";
32393
+ POLICY_LISTS = [
32394
+ "allowedPayees",
32395
+ "blockedPayees",
32396
+ "allowedNetworks",
32397
+ "allowedAssets"
32398
+ ];
32399
+ ADDRESS_LISTS = ["allowedPayees", "blockedPayees", "allowedAssets"];
32400
+ EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
32401
+ MalformedSpendPolicyError = class extends Error {
32402
+ constructor(key2) {
32403
+ super(
32404
+ `[ClawRouter] refusing to load spending.json: ${key2} is malformed; a corrupted policy file must not widen what the agent may pay`
32405
+ );
32406
+ this.name = "MalformedSpendPolicyError";
32407
+ }
32408
+ };
32409
+ FileSpendControlStorage = class {
32410
+ spendingFile;
32411
+ constructor() {
32412
+ this.spendingFile = path.join(WALLET_DIR, "spending.json");
32413
+ }
32414
+ load() {
32415
+ try {
32416
+ if (fs.existsSync(this.spendingFile)) {
32417
+ const data = JSON.parse(readTextFileSync(this.spendingFile));
32418
+ const rawLimits = data.limits ?? {};
32419
+ const rawHistory = data.history ?? [];
32420
+ const limits = {};
32421
+ for (const key2 of ["perRequest", "hourly", "daily", "session"]) {
32422
+ const val = rawLimits[key2];
32423
+ if (typeof val === "number" && val > 0 && Number.isFinite(val)) {
32424
+ limits[key2] = val;
32425
+ }
32426
+ }
32427
+ for (const key2 of POLICY_LISTS) {
32428
+ if (!Object.prototype.hasOwnProperty.call(rawLimits, key2)) continue;
32429
+ const val = rawLimits[key2];
32430
+ if (!isValidPolicyValues(val)) {
32431
+ throw new MalformedSpendPolicyError(key2);
32432
+ }
32433
+ if (val.length === 0) continue;
32434
+ limits[key2] = normalizePolicyValues(key2, val);
32435
+ }
32436
+ const history = [];
32437
+ if (Array.isArray(rawHistory)) {
32438
+ for (const r2 of rawHistory) {
32439
+ if (typeof r2?.timestamp === "number" && typeof r2?.amount === "number" && Number.isFinite(r2.timestamp) && Number.isFinite(r2.amount) && r2.amount >= 0) {
32440
+ history.push({
32441
+ timestamp: r2.timestamp,
32442
+ amount: r2.amount,
32443
+ model: typeof r2.model === "string" ? r2.model : void 0,
32444
+ action: typeof r2.action === "string" ? r2.action : void 0
32445
+ });
32446
+ }
32447
+ }
32448
+ }
32449
+ return { limits, history };
32450
+ }
32451
+ } catch (err) {
32452
+ if (err instanceof MalformedSpendPolicyError) {
32453
+ throw err;
32454
+ }
32455
+ console.error(
32456
+ `[ClawRouter] Failed to load spending data, starting fresh (any configured spend policy is NOT in effect until this file is repaired): ${err}`
32457
+ );
32458
+ }
32459
+ return null;
32460
+ }
32461
+ save(data) {
32462
+ try {
32463
+ if (!fs.existsSync(WALLET_DIR)) {
32464
+ fs.mkdirSync(WALLET_DIR, { recursive: true, mode: 448 });
32465
+ }
32466
+ const tmp = `${this.spendingFile}.${process.pid}.tmp`;
32467
+ fs.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
32468
+ fs.renameSync(tmp, this.spendingFile);
32469
+ } catch (err) {
32470
+ console.error(`[ClawRouter] Failed to save spending data: ${err}`);
32471
+ }
32472
+ }
32473
+ /**
32474
+ * Persist history while leaving the stored limits exactly as they are on
32475
+ * disk. Recording spend must not rewrite policy: the proxy reads limits once
32476
+ * at startup, so writing its in-memory copy back on every payment would
32477
+ * erase an operator's hand-edit to spending.json seconds after they made it.
32478
+ */
32479
+ saveHistory(history) {
32480
+ let storedLimits = {};
32481
+ try {
32482
+ const current = this.load();
32483
+ if (current) storedLimits = current.limits;
32484
+ } catch {
32485
+ return;
32486
+ }
32487
+ this.save({ limits: storedLimits, history });
32488
+ }
32489
+ };
32490
+ InMemorySpendControlStorage = class {
32491
+ data = null;
32492
+ load() {
32493
+ return this.data ? {
32494
+ limits: cloneLimits(this.data.limits),
32495
+ history: this.data.history.map((r2) => ({ ...r2 }))
32496
+ } : null;
32497
+ }
32498
+ save(data) {
32499
+ this.data = {
32500
+ limits: cloneLimits(data.limits),
32501
+ history: data.history.map((r2) => ({ ...r2 }))
32502
+ };
32503
+ }
32504
+ };
32505
+ RESERVATION_TTL_MS = 2 * 60 * 1e3;
32506
+ SpendControl = class {
32507
+ limits = {};
32508
+ history = [];
32509
+ sessionSpent = 0;
32510
+ sessionCalls = 0;
32511
+ pending = /* @__PURE__ */ new Map();
32512
+ reservationSeq = 0;
32513
+ /** Limits we loaded and have not changed; history-only saves must not clobber operator edits. */
32514
+ limitsDirty = false;
32515
+ /** Set when spending.json held an unusable policy list: refuse every payment. */
32516
+ policyFileBroken;
32517
+ storage;
32518
+ now;
32519
+ constructor(options) {
32520
+ this.storage = options?.storage ?? new FileSpendControlStorage();
32521
+ this.now = options?.now ?? (() => Date.now());
32522
+ this.load();
32523
+ }
32524
+ setLimit(window2, amount) {
32525
+ if (!Number.isFinite(amount) || amount <= 0) {
32526
+ throw new Error("Limit must be a finite positive number");
32527
+ }
32528
+ this.limits[window2] = amount;
32529
+ this.limitsDirty = true;
32530
+ this.save();
32531
+ }
32532
+ clearLimit(window2) {
32533
+ delete this.limits[window2];
32534
+ this.limitsDirty = true;
32535
+ this.save();
32536
+ }
32537
+ setPolicy(list, values) {
32538
+ if (!isPolicyList(list)) {
32539
+ throw new Error(`Unknown policy list: ${String(list)}`);
32540
+ }
32541
+ if (!isValidPolicyValues(values) || values.length === 0) {
32542
+ throw new Error("Policy list must be a non-empty array of non-empty strings");
32543
+ }
32544
+ this.limits[list] = normalizePolicyValues(list, values);
32545
+ this.limitsDirty = true;
32546
+ this.save();
32547
+ }
32548
+ clearPolicy(list) {
32549
+ if (!isPolicyList(list)) {
32550
+ throw new Error(`Unknown policy list: ${String(list)}`);
32551
+ }
32552
+ delete this.limits[list];
32553
+ this.limitsDirty = true;
32554
+ this.save();
32555
+ }
32556
+ getLimits() {
32557
+ return cloneLimits(this.limits);
32558
+ }
32559
+ check(estimatedCost2, counterparty) {
32560
+ if (this.policyFileBroken !== void 0) {
32561
+ return {
32562
+ allowed: false,
32563
+ reason: `Spend policy is unreadable, refusing all payments: ${this.policyFileBroken}`
32564
+ };
32565
+ }
32566
+ const payeePolicySet = this.limits.blockedPayees && this.limits.blockedPayees.length > 0 || this.limits.allowedPayees && this.limits.allowedPayees.length > 0;
32567
+ if (payeePolicySet) {
32568
+ if (counterparty?.payTo === void 0) {
32569
+ return {
32570
+ allowed: false,
32571
+ blockedByPolicy: this.limits.blockedPayees?.length ? "blockedPayees" : "allowedPayees",
32572
+ reason: "Payee policy is configured but no payTo was provided to check()"
32573
+ };
32574
+ }
32575
+ const payTo = normalizePayee(counterparty.payTo);
32576
+ if (this.limits.blockedPayees?.includes(payTo)) {
32577
+ return {
32578
+ allowed: false,
32579
+ blockedByPolicy: "blockedPayees",
32580
+ reason: `Payee is blocked by policy: ${counterparty.payTo}`
32581
+ };
32582
+ }
32583
+ if (this.limits.allowedPayees && this.limits.allowedPayees.length > 0 && !this.limits.allowedPayees.includes(payTo)) {
32584
+ return {
32585
+ allowed: false,
32586
+ blockedByPolicy: "allowedPayees",
32587
+ reason: `Payee is not in the configured allowlist: ${counterparty.payTo}`
32588
+ };
32589
+ }
32590
+ }
32591
+ if (this.limits.allowedNetworks && this.limits.allowedNetworks.length > 0) {
32592
+ if (counterparty?.network === void 0) {
32593
+ return {
32594
+ allowed: false,
32595
+ blockedByPolicy: "allowedNetworks",
32596
+ reason: "Network policy is configured but no network was provided to check()"
32597
+ };
32598
+ }
32599
+ if (!this.limits.allowedNetworks.includes(counterparty.network)) {
32600
+ return {
32601
+ allowed: false,
32602
+ blockedByPolicy: "allowedNetworks",
32603
+ reason: `Network is not in the configured allowlist: ${counterparty.network}`
32604
+ };
32605
+ }
32606
+ }
32607
+ if (this.limits.allowedAssets && this.limits.allowedAssets.length > 0) {
32608
+ if (counterparty?.asset === void 0) {
32609
+ return {
32610
+ allowed: false,
32611
+ blockedByPolicy: "allowedAssets",
32612
+ reason: "Asset policy is configured but no asset was provided to check()"
32613
+ };
32614
+ }
32615
+ if (!this.limits.allowedAssets.includes(normalizePayee(counterparty.asset))) {
32616
+ return {
32617
+ allowed: false,
32618
+ blockedByPolicy: "allowedAssets",
32619
+ reason: `Asset is not in the configured allowlist: ${counterparty.asset}`
32620
+ };
32621
+ }
32622
+ }
32623
+ const now2 = this.now();
32624
+ if (this.limits.perRequest !== void 0) {
32625
+ if (estimatedCost2 > this.limits.perRequest) {
32626
+ return {
32627
+ allowed: false,
32628
+ blockedBy: "perRequest",
32629
+ remaining: this.limits.perRequest,
32630
+ reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
32631
+ };
32632
+ }
32633
+ }
32634
+ if (this.limits.hourly !== void 0) {
32635
+ const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
32636
+ const remaining = this.limits.hourly - hourlySpent;
32637
+ if (estimatedCost2 > remaining) {
32638
+ const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
32639
+ const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
32640
+ return {
32641
+ allowed: false,
32642
+ blockedBy: "hourly",
32643
+ remaining,
32644
+ reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
32645
+ resetIn
32646
+ };
32647
+ }
32648
+ }
32649
+ if (this.limits.daily !== void 0) {
32650
+ const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
32651
+ const remaining = this.limits.daily - dailySpent;
32652
+ if (estimatedCost2 > remaining) {
32653
+ const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
32654
+ const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
32655
+ return {
32656
+ allowed: false,
32657
+ blockedBy: "daily",
32658
+ remaining,
32659
+ reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
32660
+ resetIn
32661
+ };
32662
+ }
32663
+ }
32664
+ if (this.limits.session !== void 0) {
32665
+ const sessionSpent = this.sessionSpent + this.pendingTotal();
32666
+ const remaining = this.limits.session - sessionSpent;
32667
+ if (estimatedCost2 > remaining) {
32668
+ return {
32669
+ allowed: false,
32670
+ blockedBy: "session",
32671
+ remaining,
32672
+ reason: `Session limit exceeded: $${(sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
32673
+ };
32674
+ }
32675
+ }
32676
+ return { allowed: true };
32677
+ }
32678
+ record(amount, metadata) {
32679
+ if (!Number.isFinite(amount) || amount < 0) {
32680
+ throw new Error("Record amount must be a non-negative finite number");
32681
+ }
32682
+ const record = {
32683
+ timestamp: this.now(),
32684
+ amount,
32685
+ model: metadata?.model,
32686
+ action: metadata?.action
32687
+ };
32688
+ this.history.push(record);
32689
+ this.sessionSpent += amount;
32690
+ this.sessionCalls += 1;
32691
+ this.cleanup();
32692
+ this.save();
32693
+ }
32694
+ /** True when any window that this module can compare an amount against is set. */
32695
+ hasAmountLimits() {
32696
+ return this.limits.perRequest !== void 0 || this.limits.hourly !== void 0 || this.limits.daily !== void 0 || this.limits.session !== void 0;
32697
+ }
32698
+ /** True when a window spans more than one request, so reservations matter. */
32699
+ hasAggregateLimits() {
32700
+ return this.limits.hourly !== void 0 || this.limits.daily !== void 0 || this.limits.session !== void 0;
32701
+ }
32702
+ /**
32703
+ * Hold `amount` against the aggregate windows before a payment is signed.
32704
+ *
32705
+ * Reservations live in memory only and are never persisted: an unsettled
32706
+ * reservation is not spend, and writing it to disk is what made a failed
32707
+ * signer permanently consume budget. They expire on their own so a caller
32708
+ * that never settles or releases (process killed mid-payment, a transport
32709
+ * that hangs past the payment timeout) cannot wedge the window shut.
32710
+ */
32711
+ reserve(amount) {
32712
+ if (!Number.isFinite(amount) || amount < 0) {
32713
+ throw new Error("Reservation amount must be a non-negative finite number");
32714
+ }
32715
+ const id2 = `${this.now()}-${this.reservationSeq += 1}`;
32716
+ this.pending.set(id2, { amount, expiresAt: this.now() + RESERVATION_TTL_MS });
32717
+ return id2;
32718
+ }
32719
+ /** Convert a reservation into recorded spend (the payment was signed). */
32720
+ settleReservation(id2, metadata) {
32721
+ const held = this.pending.get(id2);
32722
+ if (!held) return;
32723
+ this.pending.delete(id2);
32724
+ this.record(held.amount, metadata);
32725
+ }
32726
+ /** Drop a reservation without recording spend (the payment was never signed). */
32727
+ releaseReservation(id2) {
32728
+ this.pending.delete(id2);
32729
+ }
32730
+ /** Total currently held but not yet settled. */
32731
+ pendingTotal() {
32732
+ this.expireReservations();
32733
+ let total = 0;
32734
+ for (const held of this.pending.values()) {
32735
+ total += held.amount;
32736
+ }
32737
+ return total;
32738
+ }
32739
+ expireReservations() {
32740
+ const now2 = this.now();
32741
+ for (const [id2, held] of this.pending) {
32742
+ if (held.expiresAt <= now2) {
32743
+ this.pending.delete(id2);
32744
+ }
32745
+ }
32746
+ }
32747
+ getSpendingInWindow(from15, to) {
32748
+ const recorded = this.history.filter((r2) => r2.timestamp >= from15 && r2.timestamp <= to).reduce((sum, r2) => sum + r2.amount, 0);
32749
+ return recorded + (to >= this.now() ? this.pendingTotal() : 0);
32750
+ }
32751
+ getSpending(window2) {
32752
+ const now2 = this.now();
32753
+ switch (window2) {
32754
+ case "hourly":
32755
+ return this.getSpendingInWindow(now2 - HOUR_MS, now2);
32756
+ case "daily":
32757
+ return this.getSpendingInWindow(now2 - DAY_MS, now2);
32758
+ case "session":
32759
+ return this.sessionSpent + this.pendingTotal();
32760
+ }
32761
+ }
32762
+ getRemaining(window2) {
32763
+ const limit = this.limits[window2];
32764
+ if (limit === void 0) return null;
32765
+ return Math.max(0, limit - this.getSpending(window2));
32766
+ }
32767
+ getStatus() {
32768
+ const now2 = this.now();
32769
+ const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
32770
+ const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
32771
+ return {
32772
+ limits: cloneLimits(this.limits),
32773
+ spending: {
32774
+ hourly: hourlySpent,
32775
+ daily: dailySpent,
32776
+ session: this.sessionSpent
32777
+ },
32778
+ remaining: {
32779
+ hourly: this.limits.hourly !== void 0 ? this.limits.hourly - hourlySpent : null,
32780
+ daily: this.limits.daily !== void 0 ? this.limits.daily - dailySpent : null,
32781
+ session: this.limits.session !== void 0 ? this.limits.session - (this.sessionSpent + this.pendingTotal()) : null
32782
+ },
32783
+ calls: this.sessionCalls
32784
+ };
32785
+ }
32786
+ getHistory(limit) {
32787
+ const records = [...this.history].reverse();
32788
+ return limit ? records.slice(0, limit) : records;
32789
+ }
32790
+ resetSession() {
32791
+ this.sessionSpent = 0;
32792
+ this.sessionCalls = 0;
32793
+ }
32794
+ cleanup() {
32795
+ const cutoff = this.now() - DAY_MS;
32796
+ this.history = this.history.filter((r2) => r2.timestamp >= cutoff);
32797
+ }
32798
+ save() {
32799
+ if (this.policyFileBroken !== void 0) {
32800
+ return;
32801
+ }
32802
+ if (!this.limitsDirty && this.storage.saveHistory) {
32803
+ this.storage.saveHistory([...this.history]);
32804
+ return;
32805
+ }
32806
+ this.storage.save({
32807
+ limits: cloneLimits(this.limits),
32808
+ history: [...this.history]
32809
+ });
32810
+ }
32811
+ load() {
32812
+ let data;
32813
+ try {
32814
+ data = this.storage.load();
32815
+ } catch (err) {
32816
+ if (!(err instanceof MalformedSpendPolicyError)) throw err;
32817
+ this.policyFileBroken = err.message;
32818
+ console.error(`[ClawRouter] ${err.message}`);
32819
+ console.error(
32820
+ "[ClawRouter] All paid requests will be refused until spending.json is repaired. Free models are unaffected."
32821
+ );
32822
+ return;
32823
+ }
32824
+ if (data) {
32825
+ this.limits = cloneLimits(data.limits);
32826
+ this.history = data.history;
32827
+ this.cleanup();
32828
+ }
32829
+ }
32830
+ };
32831
+ SpendPolicyError = class extends Error {
32832
+ blockedBy;
32833
+ blockedByPolicy;
32834
+ constructor(reason, blocked) {
32835
+ super(`Payment creation aborted: ${reason}`);
32836
+ this.name = "SpendPolicyError";
32837
+ this.blockedBy = blocked?.blockedBy;
32838
+ this.blockedByPolicy = blocked?.blockedByPolicy;
32839
+ }
32840
+ };
32841
+ CANONICAL_AMOUNT = /^\d+$/;
32842
+ }
32843
+ });
32844
+
32238
32845
  // src/payment-preauth.ts
32239
32846
  function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, options) {
32240
32847
  const httpClient = new x402HTTPClient(client);
@@ -32279,8 +32886,11 @@ function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, op
32279
32886
  return response2;
32280
32887
  }
32281
32888
  cache2.delete(cacheKey2);
32282
- } catch {
32889
+ } catch (err) {
32283
32890
  cache2.delete(cacheKey2);
32891
+ if (err instanceof SpendPolicyError) {
32892
+ throw err;
32893
+ }
32284
32894
  }
32285
32895
  }
32286
32896
  const clonedRequest = request2.clone();
@@ -32324,6 +32934,7 @@ var init_payment_preauth = __esm({
32324
32934
  "use strict";
32325
32935
  init_esm4();
32326
32936
  init_max_tokens();
32937
+ init_spend_control();
32327
32938
  DEFAULT_TTL_MS = 36e5;
32328
32939
  }
32329
32940
  });
@@ -38908,8 +39519,8 @@ var init_models = __esm({
38908
39519
 
38909
39520
  // src/logger.ts
38910
39521
  import { appendFile, mkdir } from "fs/promises";
38911
- import { join as join2 } from "path";
38912
- import { homedir } from "os";
39522
+ import { join as join3 } from "path";
39523
+ import { homedir as homedir2 } from "os";
38913
39524
  async function ensureDir() {
38914
39525
  if (dirReady) return;
38915
39526
  await mkdir(LOG_DIR, { recursive: true });
@@ -38919,7 +39530,7 @@ async function logUsage(entry) {
38919
39530
  try {
38920
39531
  await ensureDir();
38921
39532
  const date = entry.timestamp.slice(0, 10);
38922
- const file = join2(LOG_DIR, `usage-${date}.jsonl`);
39533
+ const file = join3(LOG_DIR, `usage-${date}.jsonl`);
38923
39534
  await appendFile(file, JSON.stringify(entry) + "\n");
38924
39535
  } catch {
38925
39536
  }
@@ -38928,56 +39539,15 @@ var LOG_DIR, dirReady;
38928
39539
  var init_logger = __esm({
38929
39540
  "src/logger.ts"() {
38930
39541
  "use strict";
38931
- LOG_DIR = join2(homedir(), ".openclaw", "blockrun", "logs");
39542
+ LOG_DIR = join3(homedir2(), ".openclaw", "blockrun", "logs");
38932
39543
  dirReady = false;
38933
39544
  }
38934
39545
  });
38935
39546
 
38936
- // src/fs-read.ts
38937
- import { open } from "fs/promises";
38938
- import { openSync, readSync, closeSync, fstatSync } from "fs";
38939
- async function readTextFile(filePath) {
38940
- const fh = await open(filePath, "r");
38941
- try {
38942
- const size5 = (await fh.stat()).size;
38943
- const buf = Buffer.alloc(size5);
38944
- let offset = 0;
38945
- while (offset < size5) {
38946
- const { bytesRead } = await fh.read(buf, offset, size5 - offset, offset);
38947
- if (bytesRead === 0) break;
38948
- offset += bytesRead;
38949
- }
38950
- return buf.subarray(0, offset).toString("utf-8");
38951
- } finally {
38952
- await fh.close();
38953
- }
38954
- }
38955
- function readTextFileSync(filePath) {
38956
- const fd = openSync(filePath, "r");
38957
- try {
38958
- const size5 = fstatSync(fd).size;
38959
- const buf = Buffer.alloc(size5);
38960
- let offset = 0;
38961
- while (offset < size5) {
38962
- const bytesRead = readSync(fd, buf, offset, size5 - offset, offset);
38963
- if (bytesRead === 0) break;
38964
- offset += bytesRead;
38965
- }
38966
- return buf.subarray(0, offset).toString("utf-8");
38967
- } finally {
38968
- closeSync(fd);
38969
- }
38970
- }
38971
- var init_fs_read = __esm({
38972
- "src/fs-read.ts"() {
38973
- "use strict";
38974
- }
38975
- });
38976
-
38977
39547
  // src/version.ts
38978
39548
  import { createRequire } from "module";
38979
39549
  import { fileURLToPath } from "url";
38980
- import { dirname, join as join3 } from "path";
39550
+ import { dirname, join as join4 } from "path";
38981
39551
  function clientTag() {
38982
39552
  const raw = (process.env.CLAWROUTER_CLIENT ?? "").trim();
38983
39553
  if (!raw) return "";
@@ -38991,7 +39561,7 @@ var init_version4 = __esm({
38991
39561
  __filename2 = fileURLToPath(import.meta.url);
38992
39562
  __dirname = dirname(__filename2);
38993
39563
  require2 = createRequire(import.meta.url);
38994
- pkg = require2(join3(__dirname, "..", "package.json"));
39564
+ pkg = require2(join4(__dirname, "..", "package.json"));
38995
39565
  VERSION = pkg.version;
38996
39566
  USER_AGENT = `clawrouter/${VERSION}${clientTag()}`;
38997
39567
  }
@@ -38999,8 +39569,8 @@ var init_version4 = __esm({
38999
39569
 
39000
39570
  // src/stats.ts
39001
39571
  import { readdir, unlink } from "fs/promises";
39002
- import { join as join4 } from "path";
39003
- import { homedir as homedir2 } from "os";
39572
+ import { join as join5 } from "path";
39573
+ import { homedir as homedir3 } from "os";
39004
39574
  async function parseLogFile(filePath) {
39005
39575
  try {
39006
39576
  const content = await readTextFile(filePath);
@@ -39072,7 +39642,7 @@ async function getStats(days = 7) {
39072
39642
  let totalLatency = 0;
39073
39643
  for (const file of filesToRead) {
39074
39644
  const date = file.replace("usage-", "").replace(".jsonl", "");
39075
- const filePath = join4(LOG_DIR2, file);
39645
+ const filePath = join5(LOG_DIR2, file);
39076
39646
  const entries = await parseLogFile(filePath);
39077
39647
  if (entries.length === 0) continue;
39078
39648
  const dayStats = aggregateDay(date, entries);
@@ -39191,7 +39761,7 @@ async function formatRecentLogs(days = 1) {
39191
39761
  const filesToRead = logFiles.slice(0, days);
39192
39762
  const allEntries = [];
39193
39763
  for (const file of filesToRead) {
39194
- const entries = await parseLogFile(join4(LOG_DIR2, file));
39764
+ const entries = await parseLogFile(join5(LOG_DIR2, file));
39195
39765
  allEntries.push(...entries);
39196
39766
  }
39197
39767
  allEntries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
@@ -39236,7 +39806,7 @@ async function clearStats() {
39236
39806
  try {
39237
39807
  const files = await readdir(LOG_DIR2);
39238
39808
  const logFiles = files.filter((f) => f.startsWith("usage-") && f.endsWith(".jsonl"));
39239
- await Promise.all(logFiles.map((f) => unlink(join4(LOG_DIR2, f))));
39809
+ await Promise.all(logFiles.map((f) => unlink(join5(LOG_DIR2, f))));
39240
39810
  return { deletedFiles: logFiles.length };
39241
39811
  } catch {
39242
39812
  return { deletedFiles: 0 };
@@ -39248,7 +39818,27 @@ var init_stats = __esm({
39248
39818
  "use strict";
39249
39819
  init_fs_read();
39250
39820
  init_version4();
39251
- LOG_DIR2 = join4(homedir2(), ".openclaw", "blockrun", "logs");
39821
+ LOG_DIR2 = join5(homedir3(), ".openclaw", "blockrun", "logs");
39822
+ }
39823
+ });
39824
+
39825
+ // src/timestamp-strip.ts
39826
+ function stripLeadingTextBlockTimestamp(blocks) {
39827
+ let stripped = false;
39828
+ return blocks.map((block) => {
39829
+ if (!stripped && block !== null && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
39830
+ stripped = true;
39831
+ const b = block;
39832
+ return { ...b, text: b.text.replace(TIMESTAMP_PATTERN, "") };
39833
+ }
39834
+ return block;
39835
+ });
39836
+ }
39837
+ var TIMESTAMP_PATTERN;
39838
+ var init_timestamp_strip = __esm({
39839
+ "src/timestamp-strip.ts"() {
39840
+ "use strict";
39841
+ TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
39252
39842
  }
39253
39843
  });
39254
39844
 
@@ -39278,19 +39868,21 @@ function stripTimestamps(obj) {
39278
39868
  for (const [key2, value] of Object.entries(obj)) {
39279
39869
  if (key2 === "content" && typeof value === "string") {
39280
39870
  result[key2] = value.replace(TIMESTAMP_PATTERN, "");
39871
+ } else if (key2 === "content" && Array.isArray(value)) {
39872
+ result[key2] = stripLeadingTextBlockTimestamp(value.map(stripTimestamps));
39281
39873
  } else {
39282
39874
  result[key2] = stripTimestamps(value);
39283
39875
  }
39284
39876
  }
39285
39877
  return result;
39286
39878
  }
39287
- var DEFAULT_TTL_MS2, MAX_BODY_SIZE, TIMESTAMP_PATTERN, RequestDeduplicator;
39879
+ var DEFAULT_TTL_MS2, MAX_BODY_SIZE, RequestDeduplicator;
39288
39880
  var init_dedup = __esm({
39289
39881
  "src/dedup.ts"() {
39290
39882
  "use strict";
39883
+ init_timestamp_strip();
39291
39884
  DEFAULT_TTL_MS2 = 3e4;
39292
39885
  MAX_BODY_SIZE = 1048576;
39293
- TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
39294
39886
  RequestDeduplicator = class {
39295
39887
  inflight = /* @__PURE__ */ new Map();
39296
39888
  completed = /* @__PURE__ */ new Map();
@@ -39408,7 +40000,10 @@ function normalizeForCache(obj) {
39408
40000
  if (typeof msg === "object" && msg !== null) {
39409
40001
  const m = msg;
39410
40002
  if (typeof m.content === "string") {
39411
- return { ...m, content: m.content.replace(TIMESTAMP_PATTERN2, "") };
40003
+ return { ...m, content: m.content.replace(TIMESTAMP_PATTERN, "") };
40004
+ }
40005
+ if (Array.isArray(m.content)) {
40006
+ return { ...m, content: stripLeadingTextBlockTimestamp(m.content) };
39412
40007
  }
39413
40008
  }
39414
40009
  return msg;
@@ -39419,10 +40014,11 @@ function normalizeForCache(obj) {
39419
40014
  }
39420
40015
  return result;
39421
40016
  }
39422
- var DEFAULT_CONFIG, TIMESTAMP_PATTERN2, ResponseCache;
40017
+ var DEFAULT_CONFIG, ResponseCache;
39423
40018
  var init_response_cache = __esm({
39424
40019
  "src/response-cache.ts"() {
39425
40020
  "use strict";
40021
+ init_timestamp_strip();
39426
40022
  DEFAULT_CONFIG = {
39427
40023
  maxSize: 200,
39428
40024
  defaultTTL: 600,
@@ -39430,7 +40026,6 @@ var init_response_cache = __esm({
39430
40026
  // 1MB
39431
40027
  enabled: true
39432
40028
  };
39433
- TIMESTAMP_PATTERN2 = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
39434
40029
  ResponseCache = class {
39435
40030
  cache = /* @__PURE__ */ new Map();
39436
40031
  expirationHeap = [];
@@ -43042,7 +43637,7 @@ function alphabet2(letters) {
43042
43637
  };
43043
43638
  }
43044
43639
  // @__NO_SIDE_EFFECTS__
43045
- function join5(separator = "") {
43640
+ function join6(separator = "") {
43046
43641
  astr2("join", separator);
43047
43642
  return {
43048
43643
  encode: (from15) => {
@@ -43152,7 +43747,7 @@ var genBase58, base58, createBase58check;
43152
43747
  var init_base3 = __esm({
43153
43748
  "node_modules/@scure/base/index.js"() {
43154
43749
  "use strict";
43155
- genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain2(/* @__PURE__ */ radix3(58), /* @__PURE__ */ alphabet2(abc), /* @__PURE__ */ join5(""));
43750
+ genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain2(/* @__PURE__ */ radix3(58), /* @__PURE__ */ alphabet2(abc), /* @__PURE__ */ join6(""));
43156
43751
  base58 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"));
43157
43752
  createBase58check = (sha25610) => {
43158
43753
  afn2(sha25610);
@@ -43301,14 +43896,14 @@ var init_bip32 = __esm({
43301
43896
  }
43302
43897
  this.pubHash = hash160(this._publicKey);
43303
43898
  }
43304
- derive(path6) {
43305
- if (!/^[mM]'?/.test(path6)) {
43899
+ derive(path5) {
43900
+ if (!/^[mM]'?/.test(path5)) {
43306
43901
  throw new Error('Path must start with "m" or "M"');
43307
43902
  }
43308
- if (/^[mM]'?$/.test(path6)) {
43903
+ if (/^[mM]'?$/.test(path5)) {
43309
43904
  return this;
43310
43905
  }
43311
- const parts = path6.replace(/^[mM]'?\//, "").split("/");
43906
+ const parts = path5.replace(/^[mM]'?\//, "").split("/");
43312
43907
  let child = this;
43313
43908
  for (const c of parts) {
43314
43909
  const m = /^(\d+)('?)$/.exec(c);
@@ -51598,14 +52193,14 @@ function createSolanaJsonRpcIntegerOverflowError(methodName, keyPath, value) {
51598
52193
  } else {
51599
52194
  argumentLabel = `\`${keyPath[0].toString()}\``;
51600
52195
  }
51601
- const path6 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
52196
+ const path5 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
51602
52197
  const error = new SolanaError(SOLANA_ERROR__RPC__INTEGER_OVERFLOW, {
51603
52198
  argumentLabel,
51604
52199
  keyPath,
51605
52200
  methodName,
51606
- optionalPathLabel: path6 ? ` at path \`${path6}\`` : "",
52201
+ optionalPathLabel: path5 ? ` at path \`${path5}\`` : "",
51607
52202
  value,
51608
- ...path6 !== void 0 ? { path: path6 } : void 0
52203
+ ...path5 !== void 0 ? { path: path5 } : void 0
51609
52204
  });
51610
52205
  safeCaptureStackTrace(error, createSolanaJsonRpcIntegerOverflowError);
51611
52206
  return error;
@@ -56269,14 +56864,14 @@ function createSolanaJsonRpcIntegerOverflowError2(methodName, keyPath, value) {
56269
56864
  } else {
56270
56865
  argumentLabel = `\`${keyPath[0].toString()}\``;
56271
56866
  }
56272
- const path6 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
56867
+ const path5 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
56273
56868
  const error = new SolanaError(SOLANA_ERROR__RPC__INTEGER_OVERFLOW, {
56274
56869
  argumentLabel,
56275
56870
  keyPath,
56276
56871
  methodName,
56277
- optionalPathLabel: path6 ? ` at path \`${path6}\`` : "",
56872
+ optionalPathLabel: path5 ? ` at path \`${path5}\`` : "",
56278
56873
  value,
56279
- ...path6 !== void 0 ? { path: path6 } : void 0
56874
+ ...path5 !== void 0 ? { path: path5 } : void 0
56280
56875
  });
56281
56876
  safeCaptureStackTrace(error, createSolanaJsonRpcIntegerOverflowError2);
56282
56877
  return error;
@@ -58356,8 +58951,8 @@ __export(auth_exports, {
58356
58951
  setupSolana: () => setupSolana
58357
58952
  });
58358
58953
  import { writeFile, mkdir as mkdir2 } from "fs/promises";
58359
- import { join as join6 } from "path";
58360
- import { homedir as homedir3 } from "os";
58954
+ import { join as join7 } from "path";
58955
+ import { homedir as homedir4 } from "os";
58361
58956
  async function loadSavedWallet() {
58362
58957
  try {
58363
58958
  const key2 = (await readTextFile(WALLET_FILE)).trim();
@@ -58406,7 +59001,7 @@ async function loadMnemonic() {
58406
59001
  return void 0;
58407
59002
  }
58408
59003
  async function saveMnemonic(mnemonic) {
58409
- await mkdir2(WALLET_DIR, { recursive: true });
59004
+ await mkdir2(WALLET_DIR2, { recursive: true });
58410
59005
  await writeFile(MNEMONIC_FILE, mnemonic + "\n", { mode: 384 });
58411
59006
  }
58412
59007
  async function generateAndSaveWallet() {
@@ -58425,7 +59020,7 @@ Then run: npx @blockrun/clawrouter`
58425
59020
  }
58426
59021
  const mnemonic = generateWalletMnemonic();
58427
59022
  const derived = deriveAllKeys(mnemonic);
58428
- await mkdir2(WALLET_DIR, { recursive: true });
59023
+ await mkdir2(WALLET_DIR2, { recursive: true });
58429
59024
  await writeFile(WALLET_FILE, derived.evmPrivateKey + "\n", { mode: 384 });
58430
59025
  await writeFile(MNEMONIC_FILE, mnemonic + "\n", { mode: 384 });
58431
59026
  try {
@@ -58558,7 +59153,7 @@ async function recoverWalletFromMnemonic() {
58558
59153
  console.log(`[ClawRouter] wallet, recovery is safe to proceed.`);
58559
59154
  console.log(`[ClawRouter] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`);
58560
59155
  console.log(`[ClawRouter]`);
58561
- await mkdir2(WALLET_DIR, { recursive: true });
59156
+ await mkdir2(WALLET_DIR2, { recursive: true });
58562
59157
  await writeFile(WALLET_FILE, derived.evmPrivateKey + "\n", { mode: 384 });
58563
59158
  console.log(`[ClawRouter] \u2713 wallet.key restored at ${WALLET_FILE}`);
58564
59159
  console.log(`[ClawRouter] Run: npx @blockrun/clawrouter`);
@@ -58584,7 +59179,7 @@ async function setupSolana() {
58584
59179
  return { mnemonic, solanaPrivateKeyBytes: solanaKeyBytes };
58585
59180
  }
58586
59181
  async function savePaymentChain(chain3) {
58587
- await mkdir2(WALLET_DIR, { recursive: true });
59182
+ await mkdir2(WALLET_DIR2, { recursive: true });
58588
59183
  await writeFile(CHAIN_FILE, chain3 + "\n", { mode: 384 });
58589
59184
  }
58590
59185
  async function loadPaymentChain() {
@@ -58601,17 +59196,17 @@ async function resolvePaymentChain() {
58601
59196
  if (process["env"].CLAWROUTER_PAYMENT_CHAIN === "base") return "base";
58602
59197
  return loadPaymentChain();
58603
59198
  }
58604
- var WALLET_DIR, WALLET_FILE, MNEMONIC_FILE, CHAIN_FILE;
59199
+ var WALLET_DIR2, WALLET_FILE, MNEMONIC_FILE, CHAIN_FILE;
58605
59200
  var init_auth = __esm({
58606
59201
  "src/auth.ts"() {
58607
59202
  "use strict";
58608
59203
  init_fs_read();
58609
59204
  init_accounts();
58610
59205
  init_wallet2();
58611
- WALLET_DIR = join6(homedir3(), ".openclaw", "blockrun");
58612
- WALLET_FILE = join6(WALLET_DIR, "wallet.key");
58613
- MNEMONIC_FILE = join6(WALLET_DIR, "mnemonic");
58614
- CHAIN_FILE = join6(WALLET_DIR, "payment-chain");
59206
+ WALLET_DIR2 = join7(homedir4(), ".openclaw", "blockrun");
59207
+ WALLET_FILE = join7(WALLET_DIR2, "wallet.key");
59208
+ MNEMONIC_FILE = join7(WALLET_DIR2, "mnemonic");
59209
+ CHAIN_FILE = join7(WALLET_DIR2, "payment-chain");
58615
59210
  }
58616
59211
  });
58617
59212
 
@@ -58770,7 +59365,7 @@ function generateCodebookHeader(usedCodes, pathMap = {}) {
58770
59365
  parts.push(`[Dict: ${codeEntries}]`);
58771
59366
  }
58772
59367
  if (Object.keys(pathMap).length > 0) {
58773
- const pathEntries = Object.entries(pathMap).map(([code, path6]) => `${code}=${path6}`).join(", ");
59368
+ const pathEntries = Object.entries(pathMap).map(([code, path5]) => `${code}=${path5}`).join(", ");
58774
59369
  parts.push(`[Paths: ${pathEntries}]`);
58775
59370
  }
58776
59371
  return parts.join("\n");
@@ -58918,8 +59513,8 @@ function extractPaths(messages) {
58918
59513
  }
58919
59514
  function findFrequentPrefixes(paths) {
58920
59515
  const prefixCounts = /* @__PURE__ */ new Map();
58921
- for (const path6 of paths) {
58922
- const parts = path6.split("/").filter(Boolean);
59516
+ for (const path5 of paths) {
59517
+ const parts = path5.split("/").filter(Boolean);
58923
59518
  for (let i = 2; i < parts.length; i++) {
58924
59519
  const prefix = "/" + parts.slice(0, i).join("/") + "/";
58925
59520
  prefixCounts.set(prefix, (prefixCounts.get(prefix) || 0) + 1);
@@ -59703,9 +60298,9 @@ var init_updater = __esm({
59703
60298
  });
59704
60299
 
59705
60300
  // src/exclude-models.ts
59706
- import { readFileSync, writeFileSync, mkdirSync, statSync } from "fs";
59707
- import { join as join7, dirname as dirname2 } from "path";
59708
- import { homedir as homedir4 } from "os";
60301
+ import { readFileSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, statSync } from "fs";
60302
+ import { join as join8, dirname as dirname2 } from "path";
60303
+ import { homedir as homedir5 } from "os";
59709
60304
  function loadExcludeList(filePath = DEFAULT_FILE_PATH) {
59710
60305
  try {
59711
60306
  const mtimeMs = statSync(filePath).mtimeMs;
@@ -59726,8 +60321,8 @@ function loadExcludeList(filePath = DEFAULT_FILE_PATH) {
59726
60321
  function saveExcludeList(set, filePath) {
59727
60322
  const sorted = [...set].sort();
59728
60323
  const dir = dirname2(filePath);
59729
- mkdirSync(dir, { recursive: true });
59730
- writeFileSync(filePath, JSON.stringify(sorted, null, 2) + "\n", "utf-8");
60324
+ mkdirSync2(dir, { recursive: true });
60325
+ writeFileSync2(filePath, JSON.stringify(sorted, null, 2) + "\n", "utf-8");
59731
60326
  loadCache.delete(filePath);
59732
60327
  }
59733
60328
  function addExclusion(model, filePath = DEFAULT_FILE_PATH) {
@@ -59754,7 +60349,7 @@ var init_exclude_models = __esm({
59754
60349
  "src/exclude-models.ts"() {
59755
60350
  "use strict";
59756
60351
  init_models();
59757
- DEFAULT_FILE_PATH = join7(homedir4(), ".openclaw", "blockrun", "exclude-models.json");
60352
+ DEFAULT_FILE_PATH = join8(homedir5(), ".openclaw", "blockrun", "exclude-models.json");
59758
60353
  loadCache = /* @__PURE__ */ new Map();
59759
60354
  }
59760
60355
  });
@@ -61059,14 +61654,14 @@ var require_util = __commonJS({
61059
61654
  }
61060
61655
  const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
61061
61656
  let origin2 = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
61062
- let path6 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
61657
+ let path5 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
61063
61658
  if (origin2[origin2.length - 1] === "/") {
61064
61659
  origin2 = origin2.slice(0, origin2.length - 1);
61065
61660
  }
61066
- if (path6 && path6[0] !== "/") {
61067
- path6 = `/${path6}`;
61661
+ if (path5 && path5[0] !== "/") {
61662
+ path5 = `/${path5}`;
61068
61663
  }
61069
- return new URL(`${origin2}${path6}`);
61664
+ return new URL(`${origin2}${path5}`);
61070
61665
  }
61071
61666
  if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
61072
61667
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -61937,9 +62532,9 @@ var require_diagnostics = __commonJS({
61937
62532
  "undici:client:sendHeaders",
61938
62533
  (evt) => {
61939
62534
  const {
61940
- request: { method, path: path6, origin: origin2 }
62535
+ request: { method, path: path5, origin: origin2 }
61941
62536
  } = evt;
61942
- debugLog("sending request to %s %s%s", method, origin2, path6);
62537
+ debugLog("sending request to %s %s%s", method, origin2, path5);
61943
62538
  }
61944
62539
  );
61945
62540
  }
@@ -61957,14 +62552,14 @@ var require_diagnostics = __commonJS({
61957
62552
  "undici:request:headers",
61958
62553
  (evt) => {
61959
62554
  const {
61960
- request: { method, path: path6, origin: origin2 },
62555
+ request: { method, path: path5, origin: origin2 },
61961
62556
  response: { statusCode }
61962
62557
  } = evt;
61963
62558
  debugLog(
61964
62559
  "received response to %s %s%s - HTTP %d",
61965
62560
  method,
61966
62561
  origin2,
61967
- path6,
62562
+ path5,
61968
62563
  statusCode
61969
62564
  );
61970
62565
  }
@@ -61973,23 +62568,23 @@ var require_diagnostics = __commonJS({
61973
62568
  "undici:request:trailers",
61974
62569
  (evt) => {
61975
62570
  const {
61976
- request: { method, path: path6, origin: origin2 }
62571
+ request: { method, path: path5, origin: origin2 }
61977
62572
  } = evt;
61978
- debugLog("trailers received from %s %s%s", method, origin2, path6);
62573
+ debugLog("trailers received from %s %s%s", method, origin2, path5);
61979
62574
  }
61980
62575
  );
61981
62576
  diagnosticsChannel.subscribe(
61982
62577
  "undici:request:error",
61983
62578
  (evt) => {
61984
62579
  const {
61985
- request: { method, path: path6, origin: origin2 },
62580
+ request: { method, path: path5, origin: origin2 },
61986
62581
  error
61987
62582
  } = evt;
61988
62583
  debugLog(
61989
62584
  "request to %s %s%s errored - %s",
61990
62585
  method,
61991
62586
  origin2,
61992
- path6,
62587
+ path5,
61993
62588
  error.message
61994
62589
  );
61995
62590
  }
@@ -62144,7 +62739,7 @@ var require_request = __commonJS({
62144
62739
  };
62145
62740
  var Request2 = class {
62146
62741
  constructor(origin2, {
62147
- path: path6,
62742
+ path: path5,
62148
62743
  method,
62149
62744
  body,
62150
62745
  headers,
@@ -62161,11 +62756,11 @@ var require_request = __commonJS({
62161
62756
  maxRedirections,
62162
62757
  typeOfService
62163
62758
  }, handler) {
62164
- if (typeof path6 !== "string") {
62759
+ if (typeof path5 !== "string") {
62165
62760
  throw new InvalidArgumentError("path must be a string");
62166
- } else if (path6[0] !== "/" && !(path6.startsWith("http://") || path6.startsWith("https://")) && method !== "CONNECT") {
62761
+ } else if (path5[0] !== "/" && !(path5.startsWith("http://") || path5.startsWith("https://")) && method !== "CONNECT") {
62167
62762
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
62168
- } else if (invalidPathRegex.test(path6)) {
62763
+ } else if (invalidPathRegex.test(path5)) {
62169
62764
  throw new InvalidArgumentError("invalid request path");
62170
62765
  }
62171
62766
  if (typeof method !== "string") {
@@ -62240,7 +62835,7 @@ var require_request = __commonJS({
62240
62835
  this.completed = false;
62241
62836
  this.aborted = false;
62242
62837
  this.upgrade = upgrade || null;
62243
- this.path = query ? serializePathWithQuery(path6, query) : path6;
62838
+ this.path = query ? serializePathWithQuery(path5, query) : path5;
62244
62839
  this.origin = origin2;
62245
62840
  this.protocol = getProtocolFromUrlString(origin2);
62246
62841
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" || method === "QUERY" : idempotent;
@@ -67326,7 +67921,7 @@ var require_client_h1 = __commonJS({
67326
67921
  }
67327
67922
  }
67328
67923
  function writeH1(client, request2) {
67329
- const { method, path: path6, host, upgrade, blocking, reset } = request2;
67924
+ const { method, path: path5, host, upgrade, blocking, reset } = request2;
67330
67925
  let { body, headers, contentLength } = request2;
67331
67926
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
67332
67927
  if (util5.isFormDataLike(body)) {
@@ -67402,7 +67997,7 @@ var require_client_h1 = __commonJS({
67402
67997
  socket[kBlocking] = true;
67403
67998
  }
67404
67999
  setTypeOfService(socket, request2);
67405
- let header = `${method} ${path6} HTTP/1.1\r
68000
+ let header = `${method} ${path5} HTTP/1.1\r
67406
68001
  `;
67407
68002
  if (typeof host === "string") {
67408
68003
  header += `host: ${host}\r
@@ -68483,7 +69078,7 @@ var require_client_h2 = __commonJS({
68483
69078
  const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
68484
69079
  const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
68485
69080
  const session = client[kHTTP2Session];
68486
- const { method, path: path6, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
69081
+ const { method, path: path5, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
68487
69082
  if (upgrade != null && upgrade !== "websocket") {
68488
69083
  util5.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
68489
69084
  return false;
@@ -68546,7 +69141,7 @@ var require_client_h2 = __commonJS({
68546
69141
  }
68547
69142
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
68548
69143
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
68549
- headers[HTTP2_HEADER_PATH] = path6;
69144
+ headers[HTTP2_HEADER_PATH] = path5;
68550
69145
  if (protocol === "ws:" || protocol === "wss:") {
68551
69146
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
68552
69147
  } else {
@@ -68568,7 +69163,7 @@ var require_client_h2 = __commonJS({
68568
69163
  setupUpgradeStream(stream4, state);
68569
69164
  return true;
68570
69165
  }
68571
- headers[HTTP2_HEADER_PATH] = path6;
69166
+ headers[HTTP2_HEADER_PATH] = path5;
68572
69167
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
68573
69168
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
68574
69169
  let body = state.body;
@@ -71238,10 +71833,10 @@ var require_proxy_agent = __commonJS({
71238
71833
  };
71239
71834
  const {
71240
71835
  origin: origin2,
71241
- path: path6 = "/",
71836
+ path: path5 = "/",
71242
71837
  headers = {}
71243
71838
  } = opts;
71244
- opts.path = origin2 + path6;
71839
+ opts.path = origin2 + path5;
71245
71840
  if (!("host" in headers) && !("Host" in headers)) {
71246
71841
  const { host } = new URL(origin2);
71247
71842
  headers.host = host;
@@ -73506,20 +74101,20 @@ var require_mock_utils = __commonJS({
73506
74101
  }
73507
74102
  return normalizedQp;
73508
74103
  }
73509
- function safeUrl(path6) {
73510
- if (typeof path6 !== "string") {
73511
- return path6;
74104
+ function safeUrl(path5) {
74105
+ if (typeof path5 !== "string") {
74106
+ return path5;
73512
74107
  }
73513
- const pathSegments = path6.split("?", 3);
74108
+ const pathSegments = path5.split("?", 3);
73514
74109
  if (pathSegments.length !== 2) {
73515
- return path6;
74110
+ return path5;
73516
74111
  }
73517
74112
  const qp = new URLSearchParams(pathSegments.pop());
73518
74113
  qp.sort();
73519
74114
  return [...pathSegments, qp.toString()].join("?");
73520
74115
  }
73521
- function matchKey(mockDispatch2, { path: path6, method, body, headers }) {
73522
- const pathMatch = matchValue(mockDispatch2.path, path6);
74116
+ function matchKey(mockDispatch2, { path: path5, method, body, headers }) {
74117
+ const pathMatch = matchValue(mockDispatch2.path, path5);
73523
74118
  const methodMatch = matchValue(mockDispatch2.method, method);
73524
74119
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
73525
74120
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -73546,8 +74141,8 @@ var require_mock_utils = __commonJS({
73546
74141
  const basePath = key2.query ? serializePathWithQuery(key2.path, key2.query) : key2.path;
73547
74142
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
73548
74143
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
73549
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path6, ignoreTrailingSlash }) => {
73550
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path6)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path6), resolvedPath);
74144
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path5, ignoreTrailingSlash }) => {
74145
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path5)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path5), resolvedPath);
73551
74146
  });
73552
74147
  if (matchedMockDispatches.length === 0) {
73553
74148
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -73586,22 +74181,22 @@ var require_mock_utils = __commonJS({
73586
74181
  mockDispatches.splice(index2, 1);
73587
74182
  }
73588
74183
  }
73589
- function removeTrailingSlash(path6) {
73590
- if (typeof path6 !== "string") {
73591
- return path6;
74184
+ function removeTrailingSlash(path5) {
74185
+ if (typeof path5 !== "string") {
74186
+ return path5;
73592
74187
  }
73593
- while (path6.endsWith("/")) {
73594
- path6 = path6.slice(0, -1);
74188
+ while (path5.endsWith("/")) {
74189
+ path5 = path5.slice(0, -1);
73595
74190
  }
73596
- if (path6.length === 0) {
73597
- path6 = "/";
74191
+ if (path5.length === 0) {
74192
+ path5 = "/";
73598
74193
  }
73599
- return path6;
74194
+ return path5;
73600
74195
  }
73601
74196
  function buildKey(opts) {
73602
- const { path: path6, method, body, headers, query } = opts;
74197
+ const { path: path5, method, body, headers, query } = opts;
73603
74198
  return {
73604
- path: path6,
74199
+ path: path5,
73605
74200
  method,
73606
74201
  body,
73607
74202
  headers,
@@ -74472,10 +75067,10 @@ var require_pending_interceptors_formatter = __commonJS({
74472
75067
  }
74473
75068
  format(pendingInterceptors) {
74474
75069
  const withPrettyHeaders = pendingInterceptors.map(
74475
- ({ method, path: path6, data: { statusCode }, persist, times, timesInvoked, origin: origin2 }) => ({
75070
+ ({ method, path: path5, data: { statusCode }, persist, times, timesInvoked, origin: origin2 }) => ({
74476
75071
  Method: method,
74477
75072
  Origin: origin2,
74478
- Path: path6,
75073
+ Path: path5,
74479
75074
  "Status code": statusCode,
74480
75075
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
74481
75076
  Invocations: timesInvoked,
@@ -74557,9 +75152,9 @@ var require_mock_agent = __commonJS({
74557
75152
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
74558
75153
  const dispatchOpts = { ...opts };
74559
75154
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
74560
- const [path6, searchParams] = dispatchOpts.path.split("?");
75155
+ const [path5, searchParams] = dispatchOpts.path.split("?");
74561
75156
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
74562
- dispatchOpts.path = `${path6}?${normalizedSearchParams}`;
75157
+ dispatchOpts.path = `${path5}?${normalizedSearchParams}`;
74563
75158
  }
74564
75159
  return this[kAgent].dispatch(dispatchOpts, handler);
74565
75160
  }
@@ -74975,12 +75570,12 @@ var require_snapshot_recorder = __commonJS({
74975
75570
  * @return {Promise<void>} - Resolves when snapshots are loaded
74976
75571
  */
74977
75572
  async loadSnapshots(filePath) {
74978
- const path6 = filePath || this.#snapshotPath;
74979
- if (!path6) {
75573
+ const path5 = filePath || this.#snapshotPath;
75574
+ if (!path5) {
74980
75575
  throw new InvalidArgumentError("Snapshot path is required");
74981
75576
  }
74982
75577
  try {
74983
- const data = await readFile3(resolve(path6), "utf8");
75578
+ const data = await readFile3(resolve(path5), "utf8");
74984
75579
  const parsed = JSON.parse(data);
74985
75580
  if (Array.isArray(parsed)) {
74986
75581
  this.#snapshots.clear();
@@ -74994,7 +75589,7 @@ var require_snapshot_recorder = __commonJS({
74994
75589
  if (error.code === "ENOENT") {
74995
75590
  this.#snapshots.clear();
74996
75591
  } else {
74997
- throw new UndiciError(`Failed to load snapshots from ${path6}`, { cause: error });
75592
+ throw new UndiciError(`Failed to load snapshots from ${path5}`, { cause: error });
74998
75593
  }
74999
75594
  }
75000
75595
  }
@@ -75005,11 +75600,11 @@ var require_snapshot_recorder = __commonJS({
75005
75600
  * @returns {Promise<void>} - Resolves when snapshots are saved
75006
75601
  */
75007
75602
  async saveSnapshots(filePath) {
75008
- const path6 = filePath || this.#snapshotPath;
75009
- if (!path6) {
75603
+ const path5 = filePath || this.#snapshotPath;
75604
+ if (!path5) {
75010
75605
  throw new InvalidArgumentError("Snapshot path is required");
75011
75606
  }
75012
- const resolvedPath = resolve(path6);
75607
+ const resolvedPath = resolve(path5);
75013
75608
  await mkdir5(dirname5(resolvedPath), { recursive: true });
75014
75609
  const data = Array.from(this.#snapshots.entries()).map(([hash5, snapshot]) => ({
75015
75610
  hash: hash5,
@@ -75646,15 +76241,15 @@ var require_redirect_handler = __commonJS({
75646
76241
  return;
75647
76242
  }
75648
76243
  const { origin: origin2, pathname, search } = util5.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
75649
- const path6 = search ? `${pathname}${search}` : pathname;
75650
- const redirectUrlString = `${origin2}${path6}`;
76244
+ const path5 = search ? `${pathname}${search}` : pathname;
76245
+ const redirectUrlString = `${origin2}${path5}`;
75651
76246
  for (const historyUrl of this.history) {
75652
76247
  if (historyUrl.toString() === redirectUrlString) {
75653
76248
  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.`);
75654
76249
  }
75655
76250
  }
75656
76251
  this.opts.headers = cleanRequestHeaders(this.opts.headers, removeContentHeaders, this.opts.origin !== origin2, this.stripHeadersOnRedirect, this.stripHeadersOnCrossOriginRedirect);
75657
- this.opts.path = path6;
76252
+ this.opts.path = path5;
75658
76253
  this.opts.origin = origin2;
75659
76254
  this.opts.query = null;
75660
76255
  }
@@ -77482,10 +78077,10 @@ var require_cache_handler = __commonJS({
77482
78077
  }
77483
78078
  return locationUrl.pathname + locationUrl.search;
77484
78079
  }
77485
- function deleteCachedUri(store, cacheKey2, path6) {
78080
+ function deleteCachedUri(store, cacheKey2, path5) {
77486
78081
  deleteCachedValue(store, {
77487
78082
  ...cacheKey2,
77488
- path: path6
78083
+ path: path5
77489
78084
  });
77490
78085
  for (let i = 0; i < util5.safeHTTPMethods.length; i++) {
77491
78086
  const method = util5.safeHTTPMethods[i];
@@ -77493,7 +78088,7 @@ var require_cache_handler = __commonJS({
77493
78088
  deleteCachedValue(store, {
77494
78089
  ...cacheKey2,
77495
78090
  method,
77496
- path: path6
78091
+ path: path5
77497
78092
  });
77498
78093
  }
77499
78094
  }
@@ -77504,9 +78099,9 @@ var require_cache_handler = __commonJS({
77504
78099
  }
77505
78100
  const values = Array.isArray(headerValue) ? headerValue : [headerValue];
77506
78101
  for (let i = 0; i < values.length; i++) {
77507
- const path6 = getSameOriginPath(cacheKey2, values[i]);
77508
- if (path6 !== void 0) {
77509
- deleteCachedUri(store, cacheKey2, path6);
78102
+ const path5 = getSameOriginPath(cacheKey2, values[i]);
78103
+ if (path5 !== void 0) {
78104
+ deleteCachedUri(store, cacheKey2, path5);
77510
78105
  }
77511
78106
  }
77512
78107
  }
@@ -82503,13 +83098,13 @@ var require_fetch = __commonJS({
82503
83098
  function dispatch({ body }) {
82504
83099
  const url2 = requestCurrentURL(request2);
82505
83100
  const agent = fetchParams.controller.dispatcher;
82506
- const path6 = url2.pathname + url2.search;
83101
+ const path5 = url2.pathname + url2.search;
82507
83102
  const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
82508
83103
  return dispatchWithProtocolPreference(body);
82509
83104
  function dispatchWithProtocolPreference(body2, allowH2) {
82510
83105
  return new Promise((resolve, reject) => agent.dispatch(
82511
83106
  {
82512
- path: hasTrailingQuestionMark ? `${path6}?` : path6,
83107
+ path: hasTrailingQuestionMark ? `${path5}?` : path5,
82513
83108
  origin: url2.origin,
82514
83109
  method: request2.method,
82515
83110
  body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body2,
@@ -83421,9 +84016,9 @@ var require_util4 = __commonJS({
83421
84016
  }
83422
84017
  }
83423
84018
  }
83424
- function validateCookiePath(path6) {
83425
- for (let i = 0; i < path6.length; ++i) {
83426
- const code = path6.charCodeAt(i);
84019
+ function validateCookiePath(path5) {
84020
+ for (let i = 0; i < path5.length; ++i) {
84021
+ const code = path5.charCodeAt(i);
83427
84022
  if (code < 32 || // exclude CTLs (0-31)
83428
84023
  code > 126 || // exclude non-ascii and DEL
83429
84024
  code === 59) {
@@ -86795,11 +87390,11 @@ var require_undici = __commonJS({
86795
87390
  if (typeof opts.path !== "string") {
86796
87391
  throw new InvalidArgumentError("invalid opts.path");
86797
87392
  }
86798
- let path6 = opts.path;
87393
+ let path5 = opts.path;
86799
87394
  if (!opts.path.startsWith("/")) {
86800
- path6 = `/${path6}`;
87395
+ path5 = `/${path5}`;
86801
87396
  }
86802
- url2 = new URL(util5.parseOrigin(url2).origin + path6);
87397
+ url2 = new URL(util5.parseOrigin(url2).origin + path5);
86803
87398
  } else {
86804
87399
  if (!opts) {
86805
87400
  opts = typeof url2 === "object" ? url2 : {};
@@ -87345,8 +87940,8 @@ var init_textual_tool_calls = __esm({
87345
87940
 
87346
87941
  // src/response-store.ts
87347
87942
  import { appendFile as appendFile2, mkdir as mkdir3, readFile, readdir as readdir2 } from "fs/promises";
87348
- import { homedir as homedir5 } from "os";
87349
- import { join as join8 } from "path";
87943
+ import { homedir as homedir6 } from "os";
87944
+ import { join as join9 } from "path";
87350
87945
  import { randomBytes as randomBytes7 } from "crypto";
87351
87946
  function isEnabled() {
87352
87947
  const v = process.env.BLOCKRUN_RESPONSE_STORE;
@@ -87359,7 +87954,7 @@ async function ensureDir2() {
87359
87954
  }
87360
87955
  function dailyFile(date = /* @__PURE__ */ new Date()) {
87361
87956
  const iso = date.toISOString().slice(0, 10);
87362
- return join8(STORE_DIR, `responses-${iso}.jsonl`);
87957
+ return join9(STORE_DIR, `responses-${iso}.jsonl`);
87363
87958
  }
87364
87959
  function genId() {
87365
87960
  return `resp_${Date.now()}_${randomBytes7(3).toString("hex")}`;
@@ -87409,7 +88004,7 @@ async function listRecent(limit = 20, daysBack = 7) {
87409
88004
  d.setUTCDate(d.getUTCDate() - i);
87410
88005
  const iso = d.toISOString().slice(0, 10);
87411
88006
  const name = `responses-${iso}.jsonl`;
87412
- if (files.includes(name)) candidateFiles.push(join8(STORE_DIR, name));
88007
+ if (files.includes(name)) candidateFiles.push(join9(STORE_DIR, name));
87413
88008
  }
87414
88009
  const all3 = [];
87415
88010
  for (const f of candidateFiles) {
@@ -87438,7 +88033,7 @@ var STORE_DIR, dirReady2;
87438
88033
  var init_response_store = __esm({
87439
88034
  "src/response-store.ts"() {
87440
88035
  "use strict";
87441
- STORE_DIR = join8(homedir5(), ".openclaw", "blockrun", "responses");
88036
+ STORE_DIR = join9(homedir6(), ".openclaw", "blockrun", "responses");
87442
88037
  dirReady2 = false;
87443
88038
  }
87444
88039
  });
@@ -89088,10 +89683,10 @@ var init_client3 = __esm({
89088
89683
  import { AsyncLocalStorage } from "async_hooks";
89089
89684
  import { createServer } from "http";
89090
89685
  import { finished } from "stream";
89091
- import { homedir as homedir6 } from "os";
89092
- import { join as join9 } from "path";
89686
+ import { homedir as homedir7 } from "os";
89687
+ import { join as join10 } from "path";
89093
89688
  import { mkdir as mkdir4, writeFile as writeFile2, readFile as readFile2, stat as fsStat } from "fs/promises";
89094
- import { readFileSync as readFileSync2, existsSync } from "fs";
89689
+ import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
89095
89690
  function pickFreeModel(excludeList) {
89096
89691
  for (const m of FREE_MODELS) {
89097
89692
  if (!excludeList?.has(m)) return m;
@@ -89857,8 +90452,8 @@ async function proxyPaidApiRequest(req, res, apiBase, payFetch, getActualPayment
89857
90452
  });
89858
90453
  }
89859
90454
  function readImageFileAsDataUri(filePath) {
89860
- const resolved = filePath.startsWith("~/") ? join9(homedir6(), filePath.slice(2)) : filePath;
89861
- if (!existsSync(resolved)) {
90455
+ const resolved = filePath.startsWith("~/") ? join10(homedir7(), filePath.slice(2)) : filePath;
90456
+ if (!existsSync2(resolved)) {
89862
90457
  throw new Error(`Image file not found: ${resolved}`);
89863
90458
  }
89864
90459
  const ext = resolved.split(".").pop()?.toLowerCase() ?? "png";
@@ -89972,6 +90567,8 @@ async function startProxy(options) {
89972
90567
  const evmPublicClient = createPublicClient({ chain: base, transport: http() });
89973
90568
  const evmSigner = toClientEvmSigner(account, evmPublicClient);
89974
90569
  const x402 = new x402Client();
90570
+ const spendControl = options.spendControl ?? new SpendControl();
90571
+ registerSpendPolicyHook(x402, spendControl);
89975
90572
  registerExactEvmScheme(x402, { signer: evmSigner });
89976
90573
  let solanaAddress;
89977
90574
  if (solanaPrivateKeyBytes) {
@@ -90140,8 +90737,8 @@ async function startProxy(options) {
90140
90737
  if (req.url?.startsWith("/share") && req.method === "GET") {
90141
90738
  try {
90142
90739
  const url2 = new URL(req.url, "http://localhost");
90143
- const path6 = url2.pathname;
90144
- if (path6 === "/share/list") {
90740
+ const path5 = url2.pathname;
90741
+ if (path5 === "/share/list") {
90145
90742
  const limit = Math.min(parseInt(url2.searchParams.get("limit") || "20", 10), 100);
90146
90743
  const entries = await listRecent(limit);
90147
90744
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -90159,7 +90756,7 @@ async function startProxy(options) {
90159
90756
  );
90160
90757
  return;
90161
90758
  }
90162
- if (path6 === "/share/last") {
90759
+ if (path5 === "/share/last") {
90163
90760
  const sessionId = url2.searchParams.get("sessionId") || void 0;
90164
90761
  const entry = await getLast(sessionId);
90165
90762
  if (!entry) {
@@ -90188,7 +90785,7 @@ async function startProxy(options) {
90188
90785
  res.end(JSON.stringify(entry));
90189
90786
  return;
90190
90787
  }
90191
- const idMatch = path6.match(/^\/share\/(resp_[A-Za-z0-9_]+)(?:\/render)?$/);
90788
+ const idMatch = path5.match(/^\/share\/(resp_[A-Za-z0-9_]+)(?:\/render)?$/);
90192
90789
  if (idMatch) {
90193
90790
  const id2 = idMatch[1];
90194
90791
  const entry = await getById(id2);
@@ -90234,7 +90831,7 @@ async function startProxy(options) {
90234
90831
  res.end("Bad request");
90235
90832
  return;
90236
90833
  }
90237
- const filePath = join9(IMAGE_DIR, filename);
90834
+ const filePath = join10(IMAGE_DIR, filename);
90238
90835
  try {
90239
90836
  const s3 = await fsStat(filePath);
90240
90837
  if (!s3.isFile()) throw new Error("not a file");
@@ -90265,7 +90862,7 @@ async function startProxy(options) {
90265
90862
  res.end("Bad request");
90266
90863
  return;
90267
90864
  }
90268
- const filePath = join9(AUDIO_DIR, filename);
90865
+ const filePath = join10(AUDIO_DIR, filename);
90269
90866
  try {
90270
90867
  const s3 = await fsStat(filePath);
90271
90868
  if (!s3.isFile()) throw new Error("not a file");
@@ -90295,7 +90892,7 @@ async function startProxy(options) {
90295
90892
  res.end("Bad request");
90296
90893
  return;
90297
90894
  }
90298
- const filePath = join9(VIDEO_DIR, filename);
90895
+ const filePath = join10(VIDEO_DIR, filename);
90299
90896
  try {
90300
90897
  const s3 = await fsStat(filePath);
90301
90898
  if (!s3.isFile()) throw new Error("not a file");
@@ -90436,7 +91033,7 @@ async function startProxy(options) {
90436
91033
  const [, mimeType, b64] = dataUriMatch;
90437
91034
  const ext = mimeType === "image/jpeg" ? "jpg" : mimeType.split("/")[1] ?? "png";
90438
91035
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90439
- await writeFile2(join9(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
91036
+ await writeFile2(join10(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
90440
91037
  img.url = `http://localhost:${port2}/images/${filename}`;
90441
91038
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90442
91039
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
@@ -90447,7 +91044,7 @@ async function startProxy(options) {
90447
91044
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
90448
91045
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90449
91046
  const buf = Buffer.from(await imgResp.arrayBuffer());
90450
- await writeFile2(join9(IMAGE_DIR, filename), buf);
91047
+ await writeFile2(join10(IMAGE_DIR, filename), buf);
90451
91048
  img.url = `http://localhost:${port2}/images/${filename}`;
90452
91049
  console.log(`[ClawRouter] Image downloaded & saved \u2192 ${img.url}`);
90453
91050
  }
@@ -90559,7 +91156,7 @@ async function startProxy(options) {
90559
91156
  const [, mimeType, b64] = dataUriMatch;
90560
91157
  const ext = mimeType === "image/jpeg" ? "jpg" : mimeType.split("/")[1] ?? "png";
90561
91158
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90562
- await writeFile2(join9(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
91159
+ await writeFile2(join10(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
90563
91160
  img.url = `http://localhost:${port2}/images/${filename}`;
90564
91161
  console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
90565
91162
  } else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
@@ -90570,7 +91167,7 @@ async function startProxy(options) {
90570
91167
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
90571
91168
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90572
91169
  const buf = Buffer.from(await imgResp.arrayBuffer());
90573
- await writeFile2(join9(IMAGE_DIR, filename), buf);
91170
+ await writeFile2(join10(IMAGE_DIR, filename), buf);
90574
91171
  img.url = `http://localhost:${port2}/images/${filename}`;
90575
91172
  console.log(`[ClawRouter] Image downloaded & saved \u2192 ${img.url}`);
90576
91173
  }
@@ -90656,7 +91253,7 @@ async function startProxy(options) {
90656
91253
  const ext = contentType.includes("wav") ? "wav" : "mp3";
90657
91254
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90658
91255
  const buf = Buffer.from(await audioResp.arrayBuffer());
90659
- await writeFile2(join9(AUDIO_DIR, filename), buf);
91256
+ await writeFile2(join10(AUDIO_DIR, filename), buf);
90660
91257
  track.url = `http://localhost:${port2}/audio/${filename}`;
90661
91258
  console.log(`[ClawRouter] Audio saved \u2192 ${track.url}`);
90662
91259
  }
@@ -90816,7 +91413,7 @@ async function startProxy(options) {
90816
91413
  const ext = contentType.includes("webm") ? "webm" : contentType.includes("quicktime") ? "mov" : "mp4";
90817
91414
  const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
90818
91415
  const buf = Buffer.from(await videoResp.arrayBuffer());
90819
- await writeFile2(join9(VIDEO_DIR, filename), buf);
91416
+ await writeFile2(join10(VIDEO_DIR, filename), buf);
90820
91417
  clip.url = `http://localhost:${port2}/videos/${filename}`;
90821
91418
  console.log(`[ClawRouter] Video saved \u2192 ${clip.url}`);
90822
91419
  }
@@ -91156,6 +91753,17 @@ async function tryModelRequest(upstreamUrl, method, headers, body, modelId, maxT
91156
91753
  return { success: true, response };
91157
91754
  } catch (err) {
91158
91755
  const errorMsg = err instanceof Error ? err.message : String(err);
91756
+ if (err instanceof SpendPolicyError) {
91757
+ return {
91758
+ success: false,
91759
+ errorBody: JSON.stringify({
91760
+ error: { message: errorMsg, type: "spend_policy_denied", status: 403 }
91761
+ }),
91762
+ errorStatus: 403,
91763
+ isProviderError: false,
91764
+ errorCategory: "payment_error"
91765
+ };
91766
+ }
91159
91767
  return {
91160
91768
  success: false,
91161
91769
  errorBody: errorMsg,
@@ -93342,6 +93950,7 @@ var init_proxy = __esm({
93342
93950
  init_response_cache();
93343
93951
  init_balance();
93344
93952
  init_auth();
93953
+ init_spend_control();
93345
93954
  init_compression();
93346
93955
  init_version4();
93347
93956
  init_session();
@@ -93357,9 +93966,9 @@ var init_proxy = __esm({
93357
93966
  paymentStore = new AsyncLocalStorage();
93358
93967
  BLOCKRUN_API = "https://blockrun.ai/api";
93359
93968
  BLOCKRUN_SOLANA_API = "https://sol.blockrun.ai/api";
93360
- IMAGE_DIR = join9(homedir6(), ".openclaw", "blockrun", "images");
93361
- AUDIO_DIR = join9(homedir6(), ".openclaw", "blockrun", "audio");
93362
- VIDEO_DIR = join9(homedir6(), ".openclaw", "blockrun", "videos");
93969
+ IMAGE_DIR = join10(homedir7(), ".openclaw", "blockrun", "images");
93970
+ AUDIO_DIR = join10(homedir7(), ".openclaw", "blockrun", "audio");
93971
+ VIDEO_DIR = join10(homedir7(), ".openclaw", "blockrun", "videos");
93363
93972
  AUTO_MODEL = "blockrun/auto";
93364
93973
  ROUTING_PROFILES = /* @__PURE__ */ new Set([
93365
93974
  "blockrun/eco",
@@ -94424,7 +95033,7 @@ function buildTool(service, proxyBaseUrl) {
94424
95033
  required
94425
95034
  },
94426
95035
  execute: async (_toolCallId, params) => {
94427
- let path6;
95036
+ let path5;
94428
95037
  const leftoverParams = {};
94429
95038
  let dynamicMethod = "GET";
94430
95039
  let dynamicBody = void 0;
@@ -94436,7 +95045,7 @@ function buildTool(service, proxyBaseUrl) {
94436
95045
  `predexon_endpoint_call: invalid path '${rawPath}' \u2014 must begin with '/pm/' and contain no '..'`
94437
95046
  );
94438
95047
  }
94439
- path6 = `/v1${normalized}`;
95048
+ path5 = `/v1${normalized}`;
94440
95049
  if (typeof params.method === "string") {
94441
95050
  const upper = params.method.toUpperCase();
94442
95051
  if (upper !== "GET" && upper !== "POST") {
@@ -94485,19 +95094,19 @@ function buildTool(service, proxyBaseUrl) {
94485
95094
  }
94486
95095
  }
94487
95096
  } else {
94488
- path6 = `/v1${service.proxyPath}`;
95097
+ path5 = `/v1${service.proxyPath}`;
94489
95098
  for (const [key2, value] of Object.entries(params)) {
94490
95099
  if (value === void 0 || value === null) continue;
94491
95100
  const placeholder = `:${key2}`;
94492
- if (path6.includes(placeholder)) {
94493
- path6 = path6.replace(placeholder, encodeURIComponent(String(value)));
95101
+ if (path5.includes(placeholder)) {
95102
+ path5 = path5.replace(placeholder, encodeURIComponent(String(value)));
94494
95103
  } else {
94495
95104
  leftoverParams[key2] = value;
94496
95105
  }
94497
95106
  }
94498
95107
  }
94499
95108
  const effectiveMethod = service.proxyPath === "/pm/__dynamic__" ? dynamicMethod : service.method;
94500
- let url2 = `${proxyBaseUrl}${path6}`;
95109
+ let url2 = `${proxyBaseUrl}${path5}`;
94501
95110
  if (effectiveMethod === "GET" && Object.keys(leftoverParams).length > 0) {
94502
95111
  const qs = new URLSearchParams();
94503
95112
  for (const [key2, value] of Object.entries(leftoverParams)) {
@@ -106176,11 +106785,11 @@ var require_mime_types = __commonJS({
106176
106785
  }
106177
106786
  return exts[0];
106178
106787
  }
106179
- function lookup(path6) {
106180
- if (!path6 || typeof path6 !== "string") {
106788
+ function lookup(path5) {
106789
+ if (!path5 || typeof path5 !== "string") {
106181
106790
  return false;
106182
106791
  }
106183
- var extension3 = extname("x." + path6).toLowerCase().substr(1);
106792
+ var extension3 = extname("x." + path5).toLowerCase().substr(1);
106184
106793
  if (!extension3) {
106185
106794
  return false;
106186
106795
  }
@@ -107295,7 +107904,7 @@ var require_form_data = __commonJS({
107295
107904
  "use strict";
107296
107905
  var CombinedStream = require_combined_stream();
107297
107906
  var util5 = __require("util");
107298
- var path6 = __require("path");
107907
+ var path5 = __require("path");
107299
107908
  var http5 = __require("http");
107300
107909
  var https2 = __require("https");
107301
107910
  var parseUrl3 = __require("url").parse;
@@ -107426,11 +108035,11 @@ var require_form_data = __commonJS({
107426
108035
  FormData3.prototype._getContentDisposition = function(value, options) {
107427
108036
  var filename;
107428
108037
  if (typeof options.filepath === "string") {
107429
- filename = path6.normalize(options.filepath).replace(/\\/g, "/");
108038
+ filename = path5.normalize(options.filepath).replace(/\\/g, "/");
107430
108039
  } else if (options.filename || value && (value.name || value.path)) {
107431
- filename = path6.basename(options.filename || value && (value.name || value.path));
108040
+ filename = path5.basename(options.filename || value && (value.name || value.path));
107432
108041
  } else if (value && value.readable && hasOwn(value, "httpVersion")) {
107433
- filename = path6.basename(value.client._httpMessage.path || "");
108042
+ filename = path5.basename(value.client._httpMessage.path || "");
107434
108043
  }
107435
108044
  if (filename) {
107436
108045
  return 'filename="' + escapeHeaderParam(filename) + '"';
@@ -107644,9 +108253,9 @@ function isVisitable(thing) {
107644
108253
  function removeBrackets(key2) {
107645
108254
  return utils_default.endsWith(key2, "[]") ? key2.slice(0, -2) : key2;
107646
108255
  }
107647
- function renderKey(path6, key2, dots) {
107648
- if (!path6) return key2;
107649
- return path6.concat(key2).map(function each(token, i) {
108256
+ function renderKey(path5, key2, dots) {
108257
+ if (!path5) return key2;
108258
+ return path5.concat(key2).map(function each(token, i) {
107650
108259
  token = removeBrackets(token);
107651
108260
  return !dots && i ? "[" + token + "]" : token;
107652
108261
  }).join(dots ? "." : "");
@@ -107729,13 +108338,13 @@ function toFormData(obj, formData, options) {
107729
108338
  return currentValue;
107730
108339
  });
107731
108340
  }
107732
- function defaultVisitor(value, key2, path6) {
108341
+ function defaultVisitor(value, key2, path5) {
107733
108342
  let arr = value;
107734
108343
  if (utils_default.isReactNative(formData) && utils_default.isReactNativeBlob(value)) {
107735
- formData.append(renderKey(path6, key2, dots), convertValue(value));
108344
+ formData.append(renderKey(path5, key2, dots), convertValue(value));
107736
108345
  return false;
107737
108346
  }
107738
- if (value && !path6 && typeof value === "object") {
108347
+ if (value && !path5 && typeof value === "object") {
107739
108348
  if (utils_default.endsWith(key2, "{}")) {
107740
108349
  key2 = metaTokens ? key2 : key2.slice(0, -2);
107741
108350
  value = stringifyWithDepthLimit(value, 1);
@@ -107754,7 +108363,7 @@ function toFormData(obj, formData, options) {
107754
108363
  if (isVisitable(value)) {
107755
108364
  return true;
107756
108365
  }
107757
- formData.append(renderKey(path6, key2, dots), convertValue(value));
108366
+ formData.append(renderKey(path5, key2, dots), convertValue(value));
107758
108367
  return false;
107759
108368
  }
107760
108369
  const exposedHelpers = Object.assign(predicates, {
@@ -107762,17 +108371,17 @@ function toFormData(obj, formData, options) {
107762
108371
  convertValue,
107763
108372
  isVisitable
107764
108373
  });
107765
- function build(value, path6, depth = 0) {
108374
+ function build(value, path5, depth = 0) {
107766
108375
  if (utils_default.isUndefined(value)) return;
107767
108376
  throwIfMaxDepthExceeded(depth);
107768
108377
  if (stack.indexOf(value) !== -1) {
107769
- throw new Error("Circular reference detected in " + path6.join("."));
108378
+ throw new Error("Circular reference detected in " + path5.join("."));
107770
108379
  }
107771
108380
  stack.push(value);
107772
108381
  utils_default.forEach(value, function each(el, key2) {
107773
- const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key2) ? key2.trim() : key2, path6, exposedHelpers);
108382
+ const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key2) ? key2.trim() : key2, path5, exposedHelpers);
107774
108383
  if (result === true) {
107775
- build(el, path6 ? path6.concat(key2) : [key2], depth + 1);
108384
+ build(el, path5 ? path5.concat(key2) : [key2], depth + 1);
107776
108385
  }
107777
108386
  });
107778
108387
  stack.pop();
@@ -108051,7 +108660,7 @@ var init_platform = __esm({
108051
108660
  // node_modules/axios/lib/helpers/toURLEncodedForm.js
108052
108661
  function toURLEncodedForm(data, options) {
108053
108662
  return toFormData_default(data, new platform_default.classes.URLSearchParams(), {
108054
- visitor: function(value, key2, path6, helpers) {
108663
+ visitor: function(value, key2, path5, helpers) {
108055
108664
  if (platform_default.isNode && utils_default.isBuffer(value)) {
108056
108665
  this.append(key2, value.toString("base64"));
108057
108666
  return false;
@@ -108080,14 +108689,14 @@ function throwIfDepthExceeded(index2) {
108080
108689
  }
108081
108690
  }
108082
108691
  function parsePropPath(name) {
108083
- const path6 = [];
108692
+ const path5 = [];
108084
108693
  const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
108085
108694
  let match;
108086
108695
  while ((match = pattern.exec(name)) !== null) {
108087
- throwIfDepthExceeded(path6.length);
108088
- path6.push(match[0] === "[]" ? "" : match[1] || match[0]);
108696
+ throwIfDepthExceeded(path5.length);
108697
+ path5.push(match[0] === "[]" ? "" : match[1] || match[0]);
108089
108698
  }
108090
- return path6;
108699
+ return path5;
108091
108700
  }
108092
108701
  function arrayToObject(arr) {
108093
108702
  const obj = {};
@@ -108102,12 +108711,12 @@ function arrayToObject(arr) {
108102
108711
  return obj;
108103
108712
  }
108104
108713
  function formDataToJSON(formData) {
108105
- function buildPath(path6, value, target, index2) {
108714
+ function buildPath(path5, value, target, index2) {
108106
108715
  throwIfDepthExceeded(index2);
108107
- let name = path6[index2++];
108716
+ let name = path5[index2++];
108108
108717
  if (name === "__proto__") return true;
108109
108718
  const isNumericKey = Number.isFinite(+name);
108110
- const isLast = index2 >= path6.length;
108719
+ const isLast = index2 >= path5.length;
108111
108720
  name = !name && utils_default.isArray(target) ? target.length : name;
108112
108721
  if (isLast) {
108113
108722
  if (utils_default.hasOwnProp(target, name)) {
@@ -108120,7 +108729,7 @@ function formDataToJSON(formData) {
108120
108729
  if (!utils_default.hasOwnProp(target, name) || !utils_default.isObject(target[name])) {
108121
108730
  target[name] = [];
108122
108731
  }
108123
- const result = buildPath(path6, value, target[name], index2);
108732
+ const result = buildPath(path5, value, target[name], index2);
108124
108733
  if (result && utils_default.isArray(target[name])) {
108125
108734
  target[name] = arrayToObject(target[name]);
108126
108735
  }
@@ -111667,9 +112276,9 @@ var init_http4 = __esm({
111667
112276
  auth = urlUsername + ":" + urlPassword;
111668
112277
  }
111669
112278
  auth && headers.delete("authorization");
111670
- let path6;
112279
+ let path5;
111671
112280
  try {
111672
- path6 = buildURL(
112281
+ path5 = buildURL(
111673
112282
  parsed.pathname + parsed.search,
111674
112283
  own2("params"),
111675
112284
  own2("paramsSerializer")
@@ -111688,7 +112297,7 @@ var init_http4 = __esm({
111688
112297
  false
111689
112298
  );
111690
112299
  const options = Object.assign(/* @__PURE__ */ Object.create(null), {
111691
- path: path6,
112300
+ path: path5,
111692
112301
  method,
111693
112302
  headers: toByteStringHeaderObject(headers),
111694
112303
  agents: { http: httpAgent, https: httpsAgent },
@@ -112105,14 +112714,14 @@ var init_cookies = __esm({
112105
112714
  cookies_default = platform_default.hasStandardBrowserEnv ? (
112106
112715
  // Standard browser envs support document.cookie
112107
112716
  {
112108
- write(name, value, expires, path6, domain, secure, sameSite) {
112717
+ write(name, value, expires, path5, domain, secure, sameSite) {
112109
112718
  if (typeof document === "undefined") return;
112110
112719
  const cookie = [`${name}=${encodeURIComponent(value)}`];
112111
112720
  if (utils_default.isNumber(expires)) {
112112
112721
  cookie.push(`expires=${new Date(expires).toUTCString()}`);
112113
112722
  }
112114
- if (utils_default.isString(path6)) {
112115
- cookie.push(`path=${path6}`);
112723
+ if (utils_default.isString(path5)) {
112724
+ cookie.push(`path=${path5}`);
112116
112725
  }
112117
112726
  if (utils_default.isString(domain)) {
112118
112727
  cookie.push(`domain=${domain}`);
@@ -115541,15 +116150,15 @@ var init_constants3 = __esm({
115541
116150
  });
115542
116151
 
115543
116152
  // src/polymarket/wallet-adapter.ts
115544
- import fs from "fs";
115545
- import { homedir as homedir7 } from "os";
115546
- import { join as join10 } from "path";
116153
+ import fs2 from "fs";
116154
+ import { homedir as homedir8 } from "os";
116155
+ import { join as join11 } from "path";
115547
116156
  function getOrCreateWalletKey() {
115548
116157
  const envKey = process.env.BLOCKRUN_WALLET_KEY?.trim();
115549
116158
  if (envKey && /^0x[0-9a-fA-F]{64}$/.test(envKey)) return envKey;
115550
116159
  let key2;
115551
116160
  try {
115552
- key2 = fs.readFileSync(WALLET_FILE2, "utf-8").trim();
116161
+ key2 = fs2.readFileSync(WALLET_FILE2, "utf-8").trim();
115553
116162
  } catch (err) {
115554
116163
  if (err.code === "ENOENT") {
115555
116164
  throw new Error(
@@ -115591,7 +116200,7 @@ var init_wallet_adapter = __esm({
115591
116200
  init_esm();
115592
116201
  init_chains();
115593
116202
  init_constants3();
115594
- WALLET_FILE2 = join10(homedir7(), ".openclaw", "blockrun", "wallet.key");
116203
+ WALLET_FILE2 = join11(homedir8(), ".openclaw", "blockrun", "wallet.key");
115595
116204
  BASE_RPC_URLS = [
115596
116205
  "https://mainnet.base.org",
115597
116206
  "https://base.llamarpc.com",
@@ -115602,21 +116211,21 @@ var init_wallet_adapter = __esm({
115602
116211
  });
115603
116212
 
115604
116213
  // src/polymarket/creds.ts
115605
- import fs2 from "fs";
115606
- import path from "path";
116214
+ import fs3 from "fs";
116215
+ import path2 from "path";
115607
116216
  import os from "os";
115608
116217
  function readJsonFile(file) {
115609
116218
  try {
115610
- if (!fs2.existsSync(file)) return null;
115611
- const raw = fs2.readFileSync(file, "utf-8").trim();
116219
+ if (!fs3.existsSync(file)) return null;
116220
+ const raw = fs3.readFileSync(file, "utf-8").trim();
115612
116221
  return raw ? JSON.parse(raw) : null;
115613
116222
  } catch {
115614
116223
  return null;
115615
116224
  }
115616
116225
  }
115617
116226
  function writeJsonFile(file, value) {
115618
- fs2.mkdirSync(BLOCKRUN_DIR, { recursive: true });
115619
- fs2.writeFileSync(file, JSON.stringify(value, null, 2), { mode: 384 });
116227
+ fs3.mkdirSync(BLOCKRUN_DIR, { recursive: true });
116228
+ fs3.writeFileSync(file, JSON.stringify(value, null, 2), { mode: 384 });
115620
116229
  }
115621
116230
  function credsKey(address2, sigType) {
115622
116231
  return `${address2.toLowerCase()}:${sigType}`;
@@ -115668,10 +116277,10 @@ var BLOCKRUN_DIR, CREDS_FILE, BUILDER_CREDS_FILE, STATE_FILE;
115668
116277
  var init_creds = __esm({
115669
116278
  "src/polymarket/creds.ts"() {
115670
116279
  "use strict";
115671
- BLOCKRUN_DIR = path.join(os.homedir(), ".openclaw", "blockrun");
115672
- CREDS_FILE = path.join(BLOCKRUN_DIR, ".polymarket-creds");
115673
- BUILDER_CREDS_FILE = path.join(BLOCKRUN_DIR, ".polymarket-builder-creds");
115674
- STATE_FILE = path.join(BLOCKRUN_DIR, ".polymarket.json");
116280
+ BLOCKRUN_DIR = path2.join(os.homedir(), ".openclaw", "blockrun");
116281
+ CREDS_FILE = path2.join(BLOCKRUN_DIR, ".polymarket-creds");
116282
+ BUILDER_CREDS_FILE = path2.join(BLOCKRUN_DIR, ".polymarket-builder-creds");
116283
+ STATE_FILE = path2.join(BLOCKRUN_DIR, ".polymarket.json");
115675
116284
  }
115676
116285
  });
115677
116286
 
@@ -116853,13 +117462,13 @@ function __disposeResources(env) {
116853
117462
  }
116854
117463
  return next();
116855
117464
  }
116856
- function __rewriteRelativeImportExtension(path6, preserveJsx) {
116857
- if (typeof path6 === "string" && /^\.\.?\//.test(path6)) {
116858
- return path6.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
117465
+ function __rewriteRelativeImportExtension(path5, preserveJsx) {
117466
+ if (typeof path5 === "string" && /^\.\.?\//.test(path5)) {
117467
+ return path5.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
116859
117468
  return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
116860
117469
  });
116861
117470
  }
116862
- return path6;
117471
+ return path5;
116863
117472
  }
116864
117473
  var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
116865
117474
  var init_tslib_es6 = __esm({
@@ -149156,9 +149765,9 @@ var require_setupKzg = __commonJS({
149156
149765
  Object.defineProperty(exports, "__esModule", { value: true });
149157
149766
  exports.setupKzg = setupKzg;
149158
149767
  var defineKzg_js_1 = require_defineKzg();
149159
- function setupKzg(parameters, path6) {
149768
+ function setupKzg(parameters, path5) {
149160
149769
  try {
149161
- parameters.loadTrustedSetup(path6);
149770
+ parameters.loadTrustedSetup(path5);
149162
149771
  } catch (e7) {
149163
149772
  const error = e7;
149164
149773
  if (!error.message.includes("trusted setup is already loaded"))
@@ -197243,12 +197852,12 @@ var init_fragments = __esm({
197243
197852
  // node_modules/@ethersproject/abi/lib.esm/coders/abstract-coder.js
197244
197853
  function checkResultErrors(result) {
197245
197854
  const errors = [];
197246
- const checkErrors = function(path6, object) {
197855
+ const checkErrors = function(path5, object) {
197247
197856
  if (!Array.isArray(object)) {
197248
197857
  return;
197249
197858
  }
197250
197859
  for (let key2 in object) {
197251
- const childPath = path6.slice();
197860
+ const childPath = path5.slice();
197252
197861
  childPath.push(key2);
197253
197862
  try {
197254
197863
  checkErrors(childPath, object[key2]);
@@ -203066,8 +203675,8 @@ function createCommonjsModule(fn, basedir, module) {
203066
203675
  return module = {
203067
203676
  path: basedir,
203068
203677
  exports: {},
203069
- require: function(path6, base3) {
203070
- return commonjsRequire(path6, base3 === void 0 || base3 === null ? module.path : base3);
203678
+ require: function(path5, base3) {
203679
+ return commonjsRequire(path5, base3 === void 0 || base3 === null ? module.path : base3);
203071
203680
  }
203072
203681
  }, fn(module, module.exports), module.exports;
203073
203682
  }
@@ -206917,9 +207526,9 @@ var init_lib23 = __esm({
206917
207526
  if (index2 > 4294967295) {
206918
207527
  throw new Error("invalid index - " + String(index2));
206919
207528
  }
206920
- let path6 = this.path;
206921
- if (path6) {
206922
- path6 += "/" + (index2 & ~HardenedBit);
207529
+ let path5 = this.path;
207530
+ if (path5) {
207531
+ path5 += "/" + (index2 & ~HardenedBit);
206923
207532
  }
206924
207533
  const data = new Uint8Array(37);
206925
207534
  if (index2 & HardenedBit) {
@@ -206927,8 +207536,8 @@ var init_lib23 = __esm({
206927
207536
  throw new Error("cannot derive child of neutered node");
206928
207537
  }
206929
207538
  data.set(arrayify(this.privateKey), 1);
206930
- if (path6) {
206931
- path6 += "'";
207539
+ if (path5) {
207540
+ path5 += "'";
206932
207541
  }
206933
207542
  } else {
206934
207543
  data.set(arrayify(this.publicKey));
@@ -206947,21 +207556,21 @@ var init_lib23 = __esm({
206947
207556
  const ek = new SigningKey(hexlify(IL));
206948
207557
  Ki = ek._addPoint(this.publicKey);
206949
207558
  }
206950
- let mnemonicOrPath = path6;
207559
+ let mnemonicOrPath = path5;
206951
207560
  const srcMnemonic = this.mnemonic;
206952
207561
  if (srcMnemonic) {
206953
207562
  mnemonicOrPath = Object.freeze({
206954
207563
  phrase: srcMnemonic.phrase,
206955
- path: path6,
207564
+ path: path5,
206956
207565
  locale: srcMnemonic.locale || "en"
206957
207566
  });
206958
207567
  }
206959
207568
  return new _HDNode(_constructorGuard4, ki, Ki, this.fingerprint, bytes32(IR), index2, this.depth + 1, mnemonicOrPath);
206960
207569
  }
206961
- derivePath(path6) {
206962
- const components = path6.split("/");
207570
+ derivePath(path5) {
207571
+ const components = path5.split("/");
206963
207572
  if (components.length === 0 || components[0] === "m" && this.depth !== 0) {
206964
- throw new Error("invalid path - " + path6);
207573
+ throw new Error("invalid path - " + path5);
206965
207574
  }
206966
207575
  if (components[0] === "m") {
206967
207576
  components.shift();
@@ -207696,9 +208305,9 @@ function getPassword(password) {
207696
208305
  }
207697
208306
  return arrayify(password);
207698
208307
  }
207699
- function searchPath(object, path6) {
208308
+ function searchPath(object, path5) {
207700
208309
  let currentChild = object;
207701
- const comps = path6.toLowerCase().split("/");
208310
+ const comps = path5.toLowerCase().split("/");
207702
208311
  for (let i = 0; i < comps.length; i++) {
207703
208312
  let matchingChild = null;
207704
208313
  for (const key2 in currentChild) {
@@ -208347,12 +208956,12 @@ function _getAccount(data, key2) {
208347
208956
  const mnemonicIv = looseArrayify(searchPath(data, "x-ethers/mnemonicCounter"));
208348
208957
  const mnemonicCounter = new import_aes_js2.default.Counter(mnemonicIv);
208349
208958
  const mnemonicAesCtr = new import_aes_js2.default.ModeOfOperation.ctr(mnemonicKey, mnemonicCounter);
208350
- const path6 = searchPath(data, "x-ethers/path") || defaultPath;
208959
+ const path5 = searchPath(data, "x-ethers/path") || defaultPath;
208351
208960
  const locale = searchPath(data, "x-ethers/locale") || "en";
208352
208961
  const entropy = arrayify(mnemonicAesCtr.decrypt(mnemonicCiphertext));
208353
208962
  try {
208354
208963
  const mnemonic = entropyToMnemonic2(entropy, locale);
208355
- const node = HDNode.fromMnemonic(mnemonic, null, locale).derivePath(path6);
208964
+ const node = HDNode.fromMnemonic(mnemonic, null, locale).derivePath(path5);
208356
208965
  if (node.privateKey != account.privateKey) {
208357
208966
  throw new Error("mnemonic mismatch");
208358
208967
  }
@@ -208452,12 +209061,12 @@ function encrypt(account, password, options, progressCallback) {
208452
209061
  const privateKey = arrayify(account.privateKey);
208453
209062
  const passwordBytes = getPassword(password);
208454
209063
  let entropy = null;
208455
- let path6 = null;
209064
+ let path5 = null;
208456
209065
  let locale = null;
208457
209066
  if (hasMnemonic(account)) {
208458
209067
  const srcMnemonic = account.mnemonic;
208459
209068
  entropy = arrayify(mnemonicToEntropy2(srcMnemonic.phrase, srcMnemonic.locale || "en"));
208460
- path6 = srcMnemonic.path || defaultPath;
209069
+ path5 = srcMnemonic.path || defaultPath;
208461
209070
  locale = srcMnemonic.locale || "en";
208462
209071
  }
208463
209072
  let client = options.client;
@@ -208543,7 +209152,7 @@ function encrypt(account, password, options, progressCallback) {
208543
209152
  gethFilename: "UTC--" + timestamp + "--" + data.address,
208544
209153
  mnemonicCounter: hexlify(mnemonicIv).substring(2),
208545
209154
  mnemonicCiphertext: hexlify(mnemonicCiphertext).substring(2),
208546
- path: path6,
209155
+ path: path5,
208547
209156
  locale,
208548
209157
  version: "0.1"
208549
209158
  };
@@ -208837,11 +209446,11 @@ var init_lib26 = __esm({
208837
209446
  static fromEncryptedJsonSync(json, password) {
208838
209447
  return new _Wallet(decryptJsonWalletSync(json, password));
208839
209448
  }
208840
- static fromMnemonic(mnemonic, path6, wordlist3) {
208841
- if (!path6) {
208842
- path6 = defaultPath;
209449
+ static fromMnemonic(mnemonic, path5, wordlist3) {
209450
+ if (!path5) {
209451
+ path5 = defaultPath;
208843
209452
  }
208844
- return new _Wallet(HDNode.fromMnemonic(mnemonic, null, wordlist3).derivePath(path6));
209453
+ return new _Wallet(HDNode.fromMnemonic(mnemonic, null, wordlist3).derivePath(path5));
208845
209454
  }
208846
209455
  };
208847
209456
  }
@@ -214837,21 +215446,21 @@ var init_web3_provider = __esm({
214837
215446
  if (provider == null) {
214838
215447
  logger43.throwArgumentError("missing provider", "provider", provider);
214839
215448
  }
214840
- let path6 = null;
215449
+ let path5 = null;
214841
215450
  let jsonRpcFetchFunc = null;
214842
215451
  let subprovider = null;
214843
215452
  if (typeof provider === "function") {
214844
- path6 = "unknown:";
215453
+ path5 = "unknown:";
214845
215454
  jsonRpcFetchFunc = provider;
214846
215455
  } else {
214847
- path6 = provider.host || provider.path || "";
214848
- if (!path6 && provider.isMetaMask) {
214849
- path6 = "metamask";
215456
+ path5 = provider.host || provider.path || "";
215457
+ if (!path5 && provider.isMetaMask) {
215458
+ path5 = "metamask";
214850
215459
  }
214851
215460
  subprovider = provider;
214852
215461
  if (provider.request) {
214853
- if (path6 === "") {
214854
- path6 = "eip-1193:";
215462
+ if (path5 === "") {
215463
+ path5 = "eip-1193:";
214855
215464
  }
214856
215465
  jsonRpcFetchFunc = buildEip1193Fetcher(provider);
214857
215466
  } else if (provider.sendAsync) {
@@ -214861,11 +215470,11 @@ var init_web3_provider = __esm({
214861
215470
  } else {
214862
215471
  logger43.throwArgumentError("unsupported provider", "provider", provider);
214863
215472
  }
214864
- if (!path6) {
214865
- path6 = "unknown:";
215473
+ if (!path5) {
215474
+ path5 = "unknown:";
214866
215475
  }
214867
215476
  }
214868
- super(path6, network);
215477
+ super(path5, network);
214869
215478
  defineReadOnly(this, "jsonRpcFetchFunc", jsonRpcFetchFunc);
214870
215479
  defineReadOnly(this, "provider", subprovider);
214871
215480
  }
@@ -215703,7 +216312,7 @@ var require_axios = __commonJS({
215703
216312
  var https2 = __require("https");
215704
216313
  var http23 = __require("http2");
215705
216314
  var util5 = __require("util");
215706
- var path6 = __require("path");
216315
+ var path5 = __require("path");
215707
216316
  var followRedirects2 = require_follow_redirects();
215708
216317
  var zlib2 = __require("zlib");
215709
216318
  var stream4 = __require("stream");
@@ -216771,9 +217380,9 @@ var require_axios = __commonJS({
216771
217380
  function removeBrackets2(key2) {
216772
217381
  return utils$1.endsWith(key2, "[]") ? key2.slice(0, -2) : key2;
216773
217382
  }
216774
- function renderKey2(path7, key2, dots) {
216775
- if (!path7) return key2;
216776
- return path7.concat(key2).map(function each(token, i) {
217383
+ function renderKey2(path6, key2, dots) {
217384
+ if (!path6) return key2;
217385
+ return path6.concat(key2).map(function each(token, i) {
216777
217386
  token = removeBrackets2(token);
216778
217387
  return !dots && i ? "[" + token + "]" : token;
216779
217388
  }).join(dots ? "." : "");
@@ -216851,13 +217460,13 @@ var require_axios = __commonJS({
216851
217460
  return currentValue;
216852
217461
  });
216853
217462
  }
216854
- function defaultVisitor(value, key2, path7) {
217463
+ function defaultVisitor(value, key2, path6) {
216855
217464
  let arr = value;
216856
217465
  if (utils$1.isReactNative(formData) && utils$1.isReactNativeBlob(value)) {
216857
- formData.append(renderKey2(path7, key2, dots), convertValue(value));
217466
+ formData.append(renderKey2(path6, key2, dots), convertValue(value));
216858
217467
  return false;
216859
217468
  }
216860
- if (value && !path7 && typeof value === "object") {
217469
+ if (value && !path6 && typeof value === "object") {
216861
217470
  if (utils$1.endsWith(key2, "{}")) {
216862
217471
  key2 = metaTokens ? key2 : key2.slice(0, -2);
216863
217472
  value = stringifyWithDepthLimit(value, 1);
@@ -216876,7 +217485,7 @@ var require_axios = __commonJS({
216876
217485
  if (isVisitable2(value)) {
216877
217486
  return true;
216878
217487
  }
216879
- formData.append(renderKey2(path7, key2, dots), convertValue(value));
217488
+ formData.append(renderKey2(path6, key2, dots), convertValue(value));
216880
217489
  return false;
216881
217490
  }
216882
217491
  const exposedHelpers = Object.assign(predicates2, {
@@ -216884,17 +217493,17 @@ var require_axios = __commonJS({
216884
217493
  convertValue,
216885
217494
  isVisitable: isVisitable2
216886
217495
  });
216887
- function build(value, path7, depth = 0) {
217496
+ function build(value, path6, depth = 0) {
216888
217497
  if (utils$1.isUndefined(value)) return;
216889
217498
  throwIfMaxDepthExceeded(depth);
216890
217499
  if (stack.indexOf(value) !== -1) {
216891
- throw new Error("Circular reference detected in " + path7.join("."));
217500
+ throw new Error("Circular reference detected in " + path6.join("."));
216892
217501
  }
216893
217502
  stack.push(value);
216894
217503
  utils$1.forEach(value, function each(el, key2) {
216895
- const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key2) ? key2.trim() : key2, path7, exposedHelpers);
217504
+ const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key2) ? key2.trim() : key2, path6, exposedHelpers);
216896
217505
  if (result === true) {
216897
- build(el, path7 ? path7.concat(key2) : [key2], depth + 1);
217506
+ build(el, path6 ? path6.concat(key2) : [key2], depth + 1);
216898
217507
  }
216899
217508
  });
216900
217509
  stack.pop();
@@ -217083,7 +217692,7 @@ var require_axios = __commonJS({
217083
217692
  };
217084
217693
  function toURLEncodedForm2(data, options) {
217085
217694
  return toFormData3(data, new platform2.classes.URLSearchParams(), {
217086
- visitor: function(value, key2, path7, helpers) {
217695
+ visitor: function(value, key2, path6, helpers) {
217087
217696
  if (platform2.isNode && utils$1.isBuffer(value)) {
217088
217697
  this.append(key2, value.toString("base64"));
217089
217698
  return false;
@@ -217100,14 +217709,14 @@ var require_axios = __commonJS({
217100
217709
  }
217101
217710
  }
217102
217711
  function parsePropPath2(name) {
217103
- const path7 = [];
217712
+ const path6 = [];
217104
217713
  const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
217105
217714
  let match;
217106
217715
  while ((match = pattern.exec(name)) !== null) {
217107
- throwIfDepthExceeded2(path7.length);
217108
- path7.push(match[0] === "[]" ? "" : match[1] || match[0]);
217716
+ throwIfDepthExceeded2(path6.length);
217717
+ path6.push(match[0] === "[]" ? "" : match[1] || match[0]);
217109
217718
  }
217110
- return path7;
217719
+ return path6;
217111
217720
  }
217112
217721
  function arrayToObject2(arr) {
217113
217722
  const obj = {};
@@ -217122,12 +217731,12 @@ var require_axios = __commonJS({
217122
217731
  return obj;
217123
217732
  }
217124
217733
  function formDataToJSON2(formData) {
217125
- function buildPath(path7, value, target, index2) {
217734
+ function buildPath(path6, value, target, index2) {
217126
217735
  throwIfDepthExceeded2(index2);
217127
- let name = path7[index2++];
217736
+ let name = path6[index2++];
217128
217737
  if (name === "__proto__") return true;
217129
217738
  const isNumericKey = Number.isFinite(+name);
217130
- const isLast = index2 >= path7.length;
217739
+ const isLast = index2 >= path6.length;
217131
217740
  name = !name && utils$1.isArray(target) ? target.length : name;
217132
217741
  if (isLast) {
217133
217742
  if (utils$1.hasOwnProp(target, name)) {
@@ -217140,7 +217749,7 @@ var require_axios = __commonJS({
217140
217749
  if (!utils$1.hasOwnProp(target, name) || !utils$1.isObject(target[name])) {
217141
217750
  target[name] = [];
217142
217751
  }
217143
- const result = buildPath(path7, value, target[name], index2);
217752
+ const result = buildPath(path6, value, target[name], index2);
217144
217753
  if (result && utils$1.isArray(target[name])) {
217145
217754
  target[name] = arrayToObject2(target[name]);
217146
217755
  }
@@ -218751,8 +219360,8 @@ var require_axios = __commonJS({
218751
219360
  const allowedSocketPaths = own3("allowedSocketPaths");
218752
219361
  if (allowedSocketPaths != null) {
218753
219362
  const allowed = Array.isArray(allowedSocketPaths) ? allowedSocketPaths : [allowedSocketPaths];
218754
- const resolvedSocket = path6.resolve(socketPath);
218755
- const isAllowed = allowed.some((entry) => typeof entry === "string" && path6.resolve(entry) === resolvedSocket);
219363
+ const resolvedSocket = path5.resolve(socketPath);
219364
+ const isAllowed = allowed.some((entry) => typeof entry === "string" && path5.resolve(entry) === resolvedSocket);
218756
219365
  if (!isAllowed) {
218757
219366
  return reject(new AxiosError3(`socketPath "${socketPath}" is not permitted by allowedSocketPaths`, AxiosError3.ERR_BAD_OPTION_VALUE, config));
218758
219367
  }
@@ -219051,14 +219660,14 @@ var require_axios = __commonJS({
219051
219660
  var cookies = platform2.hasStandardBrowserEnv ? (
219052
219661
  // Standard browser envs support document.cookie
219053
219662
  {
219054
- write(name, value, expires, path7, domain, secure, sameSite) {
219663
+ write(name, value, expires, path6, domain, secure, sameSite) {
219055
219664
  if (typeof document === "undefined") return;
219056
219665
  const cookie = [`${name}=${encodeURIComponent(value)}`];
219057
219666
  if (utils$1.isNumber(expires)) {
219058
219667
  cookie.push(`expires=${new Date(expires).toUTCString()}`);
219059
219668
  }
219060
- if (utils$1.isString(path7)) {
219061
- cookie.push(`path=${path7}`);
219669
+ if (utils$1.isString(path6)) {
219670
+ cookie.push(`path=${path6}`);
219062
219671
  }
219063
219672
  if (utils$1.isString(domain)) {
219064
219673
  cookie.push(`domain=${domain}`);
@@ -223547,18 +224156,18 @@ var require_client2 = __commonJS({
223547
224156
  }
223548
224157
  console.log(`Transaction not found or not in given states, timing out!`);
223549
224158
  }
223550
- async sendAuthedRequest(method, path6, body) {
224159
+ async sendAuthedRequest(method, path5, body) {
223551
224160
  if (this.canBuilderAuth()) {
223552
- const builderHeaders = await this._generateBuilderHeaders(method, path6, body);
224161
+ const builderHeaders = await this._generateBuilderHeaders(method, path5, body);
223553
224162
  if (builderHeaders !== void 0) {
223554
- return this.send(path6, method, { headers: builderHeaders, data: body });
224163
+ return this.send(path5, method, { headers: builderHeaders, data: body });
223555
224164
  }
223556
224165
  }
223557
- return this.send(path6, method, { data: body });
224166
+ return this.send(path5, method, { data: body });
223558
224167
  }
223559
- async _generateBuilderHeaders(method, path6, body) {
224168
+ async _generateBuilderHeaders(method, path5, body) {
223560
224169
  if (this.builderConfig !== void 0) {
223561
- const builderHeaders = await this.builderConfig.generateBuilderHeaders(method, path6, body);
224170
+ const builderHeaders = await this.builderConfig.generateBuilderHeaders(method, path5, body);
223562
224171
  if (builderHeaders == void 0) {
223563
224172
  return void 0;
223564
224173
  }
@@ -223649,12 +224258,12 @@ var require_signer = __commonJS({
223649
224258
  constructor(creds) {
223650
224259
  this.creds = creds;
223651
224260
  }
223652
- createBuilderHeaderPayload(method, path6, body, timestamp) {
224261
+ createBuilderHeaderPayload(method, path5, body, timestamp) {
223653
224262
  let ts = Math.floor(Date.now() / 1e3);
223654
224263
  if (timestamp !== void 0) {
223655
224264
  ts = timestamp;
223656
224265
  }
223657
- const builderSig = (0, signing_1.buildHmacSignature)(this.creds.secret, ts, method, path6, body);
224266
+ const builderSig = (0, signing_1.buildHmacSignature)(this.creds.secret, ts, method, path5, body);
223658
224267
  return {
223659
224268
  POLY_BUILDER_API_KEY: this.creds.key,
223660
224269
  POLY_BUILDER_PASSPHRASE: this.creds.passphrase,
@@ -223743,17 +224352,17 @@ var require_config2 = __commonJS({
223743
224352
  * @param path
223744
224353
  * @param body
223745
224354
  */
223746
- async generateBuilderHeaders(method, path6, body, timestamp) {
224355
+ async generateBuilderHeaders(method, path5, body, timestamp) {
223747
224356
  this.ensureValid();
223748
224357
  const builderType = this.getBuilderType();
223749
224358
  if (builderType == types_1.BuilderType.LOCAL) {
223750
- return Promise.resolve(this.signer?.createBuilderHeaderPayload(method, path6, body, timestamp));
224359
+ return Promise.resolve(this.signer?.createBuilderHeaderPayload(method, path5, body, timestamp));
223751
224360
  }
223752
224361
  if (builderType == types_1.BuilderType.REMOTE) {
223753
224362
  const url2 = this.remoteBuilderConfig.url;
223754
224363
  const payload = {
223755
224364
  method,
223756
- path: path6,
224365
+ path: path5,
223757
224366
  body,
223758
224367
  timestamp
223759
224368
  };
@@ -224535,11 +225144,11 @@ var init_withdraw = __esm({
224535
225144
  });
224536
225145
 
224537
225146
  // node_modules/@blockrun/llm/dist/index.js
224538
- import * as path2 from "path";
225147
+ import * as path3 from "path";
224539
225148
  import * as os2 from "os";
224540
225149
  import * as path22 from "path";
224541
225150
  import * as os22 from "os";
224542
- import * as path3 from "path";
225151
+ import * as path32 from "path";
224543
225152
  import * as os3 from "os";
224544
225153
  import * as path4 from "path";
224545
225154
  import * as os4 from "os";
@@ -224713,7 +225322,7 @@ function resolveDefaultTimeout() {
224713
225322
  function sleep2(ms) {
224714
225323
  return new Promise((r2) => setTimeout(r2, ms));
224715
225324
  }
224716
- 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;
225325
+ 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;
224717
225326
  var init_dist7 = __esm({
224718
225327
  "node_modules/@blockrun/llm/dist/index.js"() {
224719
225328
  "use strict";
@@ -224761,8 +225370,8 @@ var init_dist7 = __esm({
224761
225370
  };
224762
225371
  BLOCKRUN_SERVICE_CODE2 = "blockrun";
224763
225372
  LOCALHOST_DOMAINS = ["localhost", "127.0.0.1"];
224764
- BLOCKRUN_DIR2 = path2.join(os2.homedir(), ".blockrun");
224765
- COST_LOG_FILE = path2.join(BLOCKRUN_DIR2, "cost_log.jsonl");
225373
+ BLOCKRUN_DIR2 = path3.join(os2.homedir(), ".blockrun");
225374
+ COST_LOG_FILE = path3.join(BLOCKRUN_DIR2, "cost_log.jsonl");
224766
225375
  SDK_VERSION = "3.10.0";
224767
225376
  USER_AGENT2 = `blockrun-ts/${SDK_VERSION}`;
224768
225377
  DEFAULT_TIMEOUT = resolveDefaultTimeout();
@@ -224807,15 +225416,15 @@ var init_dist7 = __esm({
224807
225416
  * `/api` is tolerated and stripped). Query params are URL-encoded; arrays
224808
225417
  * become repeated keys (`?a=1&a=2`); undefined/null are dropped.
224809
225418
  */
224810
- async get(path52, params) {
224811
- const url2 = this.buildUrl(path52, params);
225419
+ async get(path5, params) {
225420
+ const url2 = this.buildUrl(path5, params);
224812
225421
  return this.requestWithPayment(url2, "GET");
224813
225422
  }
224814
225423
  /**
224815
225424
  * POST a BlockRun endpoint with a JSON body.
224816
225425
  */
224817
- async post(path52, body) {
224818
- const url2 = this.buildUrl(path52);
225426
+ async post(path5, body) {
225427
+ const url2 = this.buildUrl(path5);
224819
225428
  return this.requestWithPayment(url2, "POST", body);
224820
225429
  }
224821
225430
  /**
@@ -224830,8 +225439,8 @@ var init_dist7 = __esm({
224830
225439
  * short-circuits and returns the body. Most long-running endpoints (image,
224831
225440
  * video, music, voice) return 202 with a poll_url.
224832
225441
  */
224833
- async poll(path52, body, options) {
224834
- const submitUrl = this.buildUrl(path52);
225442
+ async poll(path5, body, options) {
225443
+ const submitUrl = this.buildUrl(path5);
224835
225444
  const budgetMs = options?.budgetMs ?? DEFAULT_POLL_BUDGET_MS;
224836
225445
  const intervalMs = options?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
224837
225446
  const resp402 = await this.fetchWithTimeout(submitUrl, {
@@ -224930,8 +225539,8 @@ var init_dist7 = __esm({
224930
225539
  * process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
224931
225540
  * }
224932
225541
  */
224933
- async *stream(path52, body) {
224934
- const url2 = this.buildUrl(path52);
225542
+ async *stream(path5, body) {
225543
+ const url2 = this.buildUrl(path5);
224935
225544
  const requestBody = JSON.stringify(body ?? {});
224936
225545
  const resp402 = await this.fetchWithTimeout(url2, {
224937
225546
  method: "POST",
@@ -224997,8 +225606,8 @@ var init_dist7 = __esm({
224997
225606
  // --------------------------------------------------------------------
224998
225607
  // Internal: shared infrastructure
224999
225608
  // --------------------------------------------------------------------
225000
- buildUrl(path52, params) {
225001
- let normalized = path52.startsWith("/") ? path52 : `/${path52}`;
225609
+ buildUrl(path5, params) {
225610
+ let normalized = path5.startsWith("/") ? path5 : `/${path5}`;
225002
225611
  if (normalized.startsWith("/api/")) {
225003
225612
  normalized = normalized.slice(4);
225004
225613
  }
@@ -225146,10 +225755,10 @@ var init_dist7 = __esm({
225146
225755
  return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
225147
225756
  }
225148
225757
  };
225149
- WALLET_DIR2 = path22.join(os22.homedir(), ".blockrun");
225150
- WALLET_FILE3 = path22.join(WALLET_DIR2, ".session");
225151
- WALLET_DIR22 = path3.join(os3.homedir(), ".blockrun");
225152
- SOLANA_WALLET_FILE = path3.join(WALLET_DIR22, ".solana-session");
225758
+ WALLET_DIR3 = path22.join(os22.homedir(), ".blockrun");
225759
+ WALLET_FILE3 = path22.join(WALLET_DIR3, ".session");
225760
+ WALLET_DIR22 = path32.join(os3.homedir(), ".blockrun");
225761
+ SOLANA_WALLET_FILE = path32.join(WALLET_DIR22, ".solana-session");
225153
225762
  CACHE_DIR = path4.join(os4.homedir(), ".blockrun", "cache");
225154
225763
  DATA_DIR = path4.join(os4.homedir(), ".blockrun", "data");
225155
225764
  COST_LOG_FILE2 = path4.join(os4.homedir(), ".blockrun", "cost_log.jsonl");
@@ -225645,261 +226254,6 @@ var init_mcp_config = __esm({
225645
226254
  }
225646
226255
  });
225647
226256
 
225648
- // src/spend-control.ts
225649
- import * as fs3 from "fs";
225650
- import * as path5 from "path";
225651
- import { homedir as homedir12 } from "os";
225652
- function formatDuration(seconds) {
225653
- if (seconds < 60) {
225654
- return `${seconds}s`;
225655
- } else if (seconds < 3600) {
225656
- const mins = Math.ceil(seconds / 60);
225657
- return `${mins} min`;
225658
- } else {
225659
- const hours = Math.floor(seconds / 3600);
225660
- const mins = Math.ceil(seconds % 3600 / 60);
225661
- return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
225662
- }
225663
- }
225664
- var WALLET_DIR3, HOUR_MS, DAY_MS, FileSpendControlStorage, InMemorySpendControlStorage, SpendControl;
225665
- var init_spend_control = __esm({
225666
- "src/spend-control.ts"() {
225667
- "use strict";
225668
- init_fs_read();
225669
- WALLET_DIR3 = path5.join(homedir12(), ".openclaw", "blockrun");
225670
- HOUR_MS = 60 * 60 * 1e3;
225671
- DAY_MS = 24 * HOUR_MS;
225672
- FileSpendControlStorage = class {
225673
- spendingFile;
225674
- constructor() {
225675
- this.spendingFile = path5.join(WALLET_DIR3, "spending.json");
225676
- }
225677
- load() {
225678
- try {
225679
- if (fs3.existsSync(this.spendingFile)) {
225680
- const data = JSON.parse(readTextFileSync(this.spendingFile));
225681
- const rawLimits = data.limits ?? {};
225682
- const rawHistory = data.history ?? [];
225683
- const limits = {};
225684
- for (const key2 of ["perRequest", "hourly", "daily", "session"]) {
225685
- const val = rawLimits[key2];
225686
- if (typeof val === "number" && val > 0 && Number.isFinite(val)) {
225687
- limits[key2] = val;
225688
- }
225689
- }
225690
- const history = [];
225691
- if (Array.isArray(rawHistory)) {
225692
- for (const r2 of rawHistory) {
225693
- if (typeof r2?.timestamp === "number" && typeof r2?.amount === "number" && Number.isFinite(r2.timestamp) && Number.isFinite(r2.amount) && r2.amount >= 0) {
225694
- history.push({
225695
- timestamp: r2.timestamp,
225696
- amount: r2.amount,
225697
- model: typeof r2.model === "string" ? r2.model : void 0,
225698
- action: typeof r2.action === "string" ? r2.action : void 0
225699
- });
225700
- }
225701
- }
225702
- }
225703
- return { limits, history };
225704
- }
225705
- } catch (err) {
225706
- console.error(`[ClawRouter] Failed to load spending data, starting fresh: ${err}`);
225707
- }
225708
- return null;
225709
- }
225710
- save(data) {
225711
- try {
225712
- if (!fs3.existsSync(WALLET_DIR3)) {
225713
- fs3.mkdirSync(WALLET_DIR3, { recursive: true, mode: 448 });
225714
- }
225715
- fs3.writeFileSync(this.spendingFile, JSON.stringify(data, null, 2), {
225716
- mode: 384
225717
- });
225718
- } catch (err) {
225719
- console.error(`[ClawRouter] Failed to save spending data: ${err}`);
225720
- }
225721
- }
225722
- };
225723
- InMemorySpendControlStorage = class {
225724
- data = null;
225725
- load() {
225726
- return this.data ? {
225727
- limits: { ...this.data.limits },
225728
- history: this.data.history.map((r2) => ({ ...r2 }))
225729
- } : null;
225730
- }
225731
- save(data) {
225732
- this.data = {
225733
- limits: { ...data.limits },
225734
- history: data.history.map((r2) => ({ ...r2 }))
225735
- };
225736
- }
225737
- };
225738
- SpendControl = class {
225739
- limits = {};
225740
- history = [];
225741
- sessionSpent = 0;
225742
- sessionCalls = 0;
225743
- storage;
225744
- now;
225745
- constructor(options) {
225746
- this.storage = options?.storage ?? new FileSpendControlStorage();
225747
- this.now = options?.now ?? (() => Date.now());
225748
- this.load();
225749
- }
225750
- setLimit(window2, amount) {
225751
- if (!Number.isFinite(amount) || amount <= 0) {
225752
- throw new Error("Limit must be a finite positive number");
225753
- }
225754
- this.limits[window2] = amount;
225755
- this.save();
225756
- }
225757
- clearLimit(window2) {
225758
- delete this.limits[window2];
225759
- this.save();
225760
- }
225761
- getLimits() {
225762
- return { ...this.limits };
225763
- }
225764
- check(estimatedCost2) {
225765
- const now2 = this.now();
225766
- if (this.limits.perRequest !== void 0) {
225767
- if (estimatedCost2 > this.limits.perRequest) {
225768
- return {
225769
- allowed: false,
225770
- blockedBy: "perRequest",
225771
- remaining: this.limits.perRequest,
225772
- reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
225773
- };
225774
- }
225775
- }
225776
- if (this.limits.hourly !== void 0) {
225777
- const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
225778
- const remaining = this.limits.hourly - hourlySpent;
225779
- if (estimatedCost2 > remaining) {
225780
- const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
225781
- const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
225782
- return {
225783
- allowed: false,
225784
- blockedBy: "hourly",
225785
- remaining,
225786
- reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
225787
- resetIn
225788
- };
225789
- }
225790
- }
225791
- if (this.limits.daily !== void 0) {
225792
- const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
225793
- const remaining = this.limits.daily - dailySpent;
225794
- if (estimatedCost2 > remaining) {
225795
- const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
225796
- const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
225797
- return {
225798
- allowed: false,
225799
- blockedBy: "daily",
225800
- remaining,
225801
- reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
225802
- resetIn
225803
- };
225804
- }
225805
- }
225806
- if (this.limits.session !== void 0) {
225807
- const remaining = this.limits.session - this.sessionSpent;
225808
- if (estimatedCost2 > remaining) {
225809
- return {
225810
- allowed: false,
225811
- blockedBy: "session",
225812
- remaining,
225813
- reason: `Session limit exceeded: $${(this.sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
225814
- };
225815
- }
225816
- }
225817
- return { allowed: true };
225818
- }
225819
- record(amount, metadata) {
225820
- if (!Number.isFinite(amount) || amount < 0) {
225821
- throw new Error("Record amount must be a non-negative finite number");
225822
- }
225823
- const record = {
225824
- timestamp: this.now(),
225825
- amount,
225826
- model: metadata?.model,
225827
- action: metadata?.action
225828
- };
225829
- this.history.push(record);
225830
- this.sessionSpent += amount;
225831
- this.sessionCalls += 1;
225832
- this.cleanup();
225833
- this.save();
225834
- }
225835
- getSpendingInWindow(from15, to) {
225836
- return this.history.filter((r2) => r2.timestamp >= from15 && r2.timestamp <= to).reduce((sum, r2) => sum + r2.amount, 0);
225837
- }
225838
- getSpending(window2) {
225839
- const now2 = this.now();
225840
- switch (window2) {
225841
- case "hourly":
225842
- return this.getSpendingInWindow(now2 - HOUR_MS, now2);
225843
- case "daily":
225844
- return this.getSpendingInWindow(now2 - DAY_MS, now2);
225845
- case "session":
225846
- return this.sessionSpent;
225847
- }
225848
- }
225849
- getRemaining(window2) {
225850
- const limit = this.limits[window2];
225851
- if (limit === void 0) return null;
225852
- return Math.max(0, limit - this.getSpending(window2));
225853
- }
225854
- getStatus() {
225855
- const now2 = this.now();
225856
- const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
225857
- const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
225858
- return {
225859
- limits: { ...this.limits },
225860
- spending: {
225861
- hourly: hourlySpent,
225862
- daily: dailySpent,
225863
- session: this.sessionSpent
225864
- },
225865
- remaining: {
225866
- hourly: this.limits.hourly !== void 0 ? this.limits.hourly - hourlySpent : null,
225867
- daily: this.limits.daily !== void 0 ? this.limits.daily - dailySpent : null,
225868
- session: this.limits.session !== void 0 ? this.limits.session - this.sessionSpent : null
225869
- },
225870
- calls: this.sessionCalls
225871
- };
225872
- }
225873
- getHistory(limit) {
225874
- const records = [...this.history].reverse();
225875
- return limit ? records.slice(0, limit) : records;
225876
- }
225877
- resetSession() {
225878
- this.sessionSpent = 0;
225879
- this.sessionCalls = 0;
225880
- }
225881
- cleanup() {
225882
- const cutoff = this.now() - DAY_MS;
225883
- this.history = this.history.filter((r2) => r2.timestamp >= cutoff);
225884
- }
225885
- save() {
225886
- this.storage.save({
225887
- limits: { ...this.limits },
225888
- history: [...this.history]
225889
- });
225890
- }
225891
- load() {
225892
- const data = this.storage.load();
225893
- if (data) {
225894
- this.limits = data.limits;
225895
- this.history = data.history;
225896
- this.cleanup();
225897
- }
225898
- }
225899
- };
225900
- }
225901
- });
225902
-
225903
226257
  // src/retry.ts
225904
226258
  function sleep3(ms) {
225905
226259
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -225968,6 +226322,8 @@ __export(index_exports, {
225968
226322
  BALANCE_THRESHOLDS: () => BALANCE_THRESHOLDS,
225969
226323
  BLOCKRUN_MODELS: () => BLOCKRUN_MODELS,
225970
226324
  BalanceMonitor: () => BalanceMonitor,
226325
+ CAIP2_BASE: () => CAIP2_BASE,
226326
+ CAIP2_SOLANA_MAINNET: () => CAIP2_SOLANA_MAINNET,
225971
226327
  DEFAULT_RETRY_CONFIG: () => DEFAULT_RETRY_CONFIG,
225972
226328
  DEFAULT_ROUTING_CONFIG: () => DEFAULT_ROUTING_CONFIG,
225973
226329
  DEFAULT_SESSION_CONFIG: () => DEFAULT_SESSION_CONFIG,
@@ -225976,6 +226332,7 @@ __export(index_exports, {
225976
226332
  InMemorySpendControlStorage: () => InMemorySpendControlStorage,
225977
226333
  InsufficientFundsError: () => InsufficientFundsError2,
225978
226334
  MODEL_ALIASES: () => MODEL_ALIASES,
226335
+ MalformedSpendPolicyError: () => MalformedSpendPolicyError,
225979
226336
  OPENCLAW_MODELS: () => OPENCLAW_MODELS,
225980
226337
  PARTNER_SERVICES: () => PARTNER_SERVICES,
225981
226338
  RequestDeduplicator: () => RequestDeduplicator,
@@ -225984,6 +226341,7 @@ __export(index_exports, {
225984
226341
  SessionStore: () => SessionStore,
225985
226342
  SolanaBalanceMonitor: () => SolanaBalanceMonitor,
225986
226343
  SpendControl: () => SpendControl,
226344
+ SpendPolicyError: () => SpendPolicyError,
225987
226345
  VISIBLE_OPENCLAW_MODELS: () => VISIBLE_OPENCLAW_MODELS,
225988
226346
  blockrunProvider: () => blockrunProvider,
225989
226347
  buildImageGenerationProvider: () => buildImageGenerationProvider,
@@ -226023,6 +226381,7 @@ __export(index_exports, {
226023
226381
  loadPaymentChain: () => loadPaymentChain,
226024
226382
  logUsage: () => logUsage,
226025
226383
  parseCallArgs: () => parseCallArgs,
226384
+ registerSpendPolicyHook: () => registerSpendPolicyHook,
226026
226385
  resolveModelAlias: () => resolveModelAlias,
226027
226386
  resolvePaymentChain: () => resolvePaymentChain,
226028
226387
  route: () => route,
@@ -226037,7 +226396,7 @@ import {
226037
226396
  readdirSync,
226038
226397
  mkdirSync as mkdirSync3,
226039
226398
  copyFileSync,
226040
- renameSync
226399
+ renameSync as renameSync2
226041
226400
  } from "fs";
226042
226401
  import { readFile as readFileAsync } from "fs/promises";
226043
226402
  import { homedir as homedir13 } from "os";
@@ -226315,7 +226674,7 @@ function injectModelsConfig(logger48, options = {}) {
226315
226674
  try {
226316
226675
  const tmpPath = `${configPath}.tmp.${process.pid}`;
226317
226676
  writeFileSync3(tmpPath, JSON.stringify(config, null, 2));
226318
- renameSync(tmpPath, configPath);
226677
+ renameSync2(tmpPath, configPath);
226319
226678
  logger48.info("Smart routing enabled (blockrun/auto)");
226320
226679
  } catch (err) {
226321
226680
  logger48.info(`Failed to write config: ${err instanceof Error ? err.message : String(err)}`);
@@ -226351,7 +226710,7 @@ function syncAgentModelCache(logger48, options = {}) {
226351
226710
  entry.models = VISIBLE_OPENCLAW_MODELS;
226352
226711
  const tmpPath = `${cachePath}.tmp.${process.pid}`;
226353
226712
  writeFileSync3(tmpPath, JSON.stringify(cache2, null, 2));
226354
- renameSync(tmpPath, cachePath);
226713
+ renameSync2(tmpPath, cachePath);
226355
226714
  logger48.info(
226356
226715
  `Repaired ${agent} model cache: ${staleCount} \u2192 ${expectedIds.length} BlockRun models`
226357
226716
  );
@@ -227715,7 +228074,7 @@ ${errText}`
227715
228074
  }
227716
228075
  const tmpPath = `${configPath}.tmp.${process.pid}`;
227717
228076
  writeFileSync3(tmpPath, JSON.stringify(config, null, 2));
227718
- renameSync(tmpPath, configPath);
228077
+ renameSync2(tmpPath, configPath);
227719
228078
  api.logger.info("ClawRouter config cleaned up");
227720
228079
  }
227721
228080
  } catch (err) {
@@ -227810,7 +228169,7 @@ init_stats();
227810
228169
  init_proxy();
227811
228170
  init_version4();
227812
228171
  import { platform, arch, freemem, totalmem } from "os";
227813
- import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
228172
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
227814
228173
  function formatBytes(bytes) {
227815
228174
  const gb = bytes / (1024 * 1024 * 1024);
227816
228175
  return `${gb.toFixed(1)}GB`;
@@ -228099,7 +228458,7 @@ async function analyzeWithAI(diagnostics, userQuestion, model = "sonnet") {
228099
228458
  const paymentChain = diagnostics.wallet.paymentChain;
228100
228459
  if (paymentChain === "solana") {
228101
228460
  try {
228102
- if (!existsSync2(MNEMONIC_FILE)) {
228461
+ if (!existsSync3(MNEMONIC_FILE)) {
228103
228462
  throw new Error(`mnemonic file missing at ${MNEMONIC_FILE}`);
228104
228463
  }
228105
228464
  const mnemonic = readFileSync3(MNEMONIC_FILE, "utf8").trim();
@@ -228262,8 +228621,8 @@ Environment Variables:
228262
228621
  For more info: https://blockrun.ai/clawrouter.md
228263
228622
  `);
228264
228623
  }
228265
- async function queryProxy(path6, port) {
228266
- const res = await fetch(`http://127.0.0.1:${port}${path6}`);
228624
+ async function queryProxy(path5, port) {
228625
+ const res = await fetch(`http://127.0.0.1:${port}${path5}`);
228267
228626
  if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
228268
228627
  return res.json();
228269
228628
  }
@@ -228343,8 +228702,8 @@ Use: clawrouter share <id> --as=<feishu|slack|discord|telegram|whatsapp|plain>
228343
228702
  const { join: pjoin } = await import("path");
228344
228703
  const paths = [];
228345
228704
  for (const p of VALID_PRESETS) {
228346
- const path6 = idOrLast === "last" ? `/share/last?as=${p}` : `/share/${idOrLast}/render?as=${p}`;
228347
- const result = await queryProxy(path6, port);
228705
+ const path5 = idOrLast === "last" ? `/share/last?as=${p}` : `/share/${idOrLast}/render?as=${p}`;
228706
+ const result = await queryProxy(path5, port);
228348
228707
  const file = pjoin(tmpdir(), `claw-share-${result.id}-${p}.txt`);
228349
228708
  await writeFile3(file, result.rendered, "utf8");
228350
228709
  paths.push(file);
@@ -228365,8 +228724,8 @@ Use: clawrouter share <id> --as=<feishu|slack|discord|telegram|whatsapp|plain>
228365
228724
  process.exit(1);
228366
228725
  }
228367
228726
  try {
228368
- const path6 = idOrLast === "last" ? `/share/last?as=${chosenPreset}` : `/share/${idOrLast}/render?as=${chosenPreset}`;
228369
- const result = await queryProxy(path6, port);
228727
+ const path5 = idOrLast === "last" ? `/share/last?as=${chosenPreset}` : `/share/${idOrLast}/render?as=${chosenPreset}`;
228728
+ const result = await queryProxy(path5, port);
228370
228729
  process.stdout.write(result.rendered);
228371
228730
  if (!result.rendered.endsWith("\n")) process.stdout.write("\n");
228372
228731
  const clipErr = await copyToClipboard(result.rendered);
@@ -228486,8 +228845,8 @@ Usage Stats (last ${days} days)
228486
228845
  }
228487
228846
  async function cmdPhone(port, subcommand, numbersAction, arg, areaCode) {
228488
228847
  const base3 = `http://127.0.0.1:${port}`;
228489
- async function postJson(path6, body) {
228490
- const resp = await fetch(`${base3}${path6}`, {
228848
+ async function postJson(path5, body) {
228849
+ const resp = await fetch(`${base3}${path5}`, {
228491
228850
  method: "POST",
228492
228851
  headers: { "content-type": "application/json" },
228493
228852
  body: JSON.stringify(body)
@@ -228589,12 +228948,12 @@ Releasing ${arg}...
228589
228948
  console.error(`\u2717 Usage: clawrouter phone ${subcommand} <+E.164-number>`);
228590
228949
  process.exit(1);
228591
228950
  }
228592
- const path6 = subcommand === "fraud" ? "/v1/phone/lookup/fraud" : "/v1/phone/lookup";
228951
+ const path5 = subcommand === "fraud" ? "/v1/phone/lookup/fraud" : "/v1/phone/lookup";
228593
228952
  const price = subcommand === "fraud" ? "$0.05" : "$0.01";
228594
228953
  console.log(`
228595
228954
  Looking up ${arg}... (${price})
228596
228955
  `);
228597
- const result = await postJson(path6, { phoneNumber: arg });
228956
+ const result = await postJson(path5, { phoneNumber: arg });
228598
228957
  console.log(JSON.stringify(result, null, 2));
228599
228958
  console.log();
228600
228959
  }