@blockrun/clawrouter 0.12.256 → 0.12.258
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -26
- package/dist/cli.js +1321 -741
- package/dist/index.d.ts +235 -113
- package/dist/index.js +1307 -727
- package/dist/router/index.js +43 -30
- package/docs/9-free-ai-models-zero-cost-blockrun.md +73 -86
- package/docs/anthropic-cost-savings.md +4 -4
- package/docs/anthropic-third-party-harness-changes.md +3 -3
- package/docs/clawrouter-cuts-llm-api-costs-500x.md +1 -1
- package/docs/clawrouter-vs-openrouter-llm-routing-comparison.md +3 -3
- package/docs/configuration.md +81 -0
- package/docs/features.md +9 -8
- package/docs/routing-profiles.md +24 -22
- package/docs/subscription-failover.md +1 -1
- package/package.json +3 -3
- package/scripts/benchmark.py +2 -2
- package/scripts/reinstall.sh +7 -5
- package/skills/clawrouter/SKILL.md +4 -4
- package/src/top-models.json +8 -4
package/dist/index.js
CHANGED
|
@@ -81,6 +81,8 @@ var init_top_models = __esm({
|
|
|
81
81
|
"xai/grok-4.5",
|
|
82
82
|
"xai/grok-4.3",
|
|
83
83
|
"xai/grok-build-0.1",
|
|
84
|
+
"zai/glm-5.3",
|
|
85
|
+
"zai/glm-5.3-flash",
|
|
84
86
|
"zai/glm-5.2",
|
|
85
87
|
"zai/glm-5.1",
|
|
86
88
|
"zai/glm-5-turbo",
|
|
@@ -92,11 +94,13 @@ var init_top_models = __esm({
|
|
|
92
94
|
"deepseek/deepseek-v4-pro",
|
|
93
95
|
"deepseek/deepseek-chat",
|
|
94
96
|
"deepseek/deepseek-reasoner",
|
|
97
|
+
"free/nemotron-3.5-lightning",
|
|
98
|
+
"free/nemotron-3-nano-30b",
|
|
99
|
+
"free/laguna-xs-2.1",
|
|
100
|
+
"free/north-mini-code",
|
|
95
101
|
"free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
96
|
-
"free/
|
|
97
|
-
"free/
|
|
98
|
-
"free/nemotron-nano-9b-v2",
|
|
99
|
-
"free/nemotron-nano-12b-v2-vl"
|
|
102
|
+
"free/nemotron-3-ultra-550b",
|
|
103
|
+
"free/llama-3.2-11b-vision"
|
|
100
104
|
];
|
|
101
105
|
}
|
|
102
106
|
});
|
|
@@ -409,14 +413,20 @@ var init_models = __esm({
|
|
|
409
413
|
"xai/grok-3-fast": "xai/grok-4-fast-reasoning",
|
|
410
414
|
// delisted (too expensive)
|
|
411
415
|
// NVIDIA — backward compat aliases (nvidia/xxx → free/xxx)
|
|
412
|
-
// Default free model is
|
|
413
|
-
// opens the eco SIMPLE tier on. It replaced
|
|
414
|
-
//
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
//
|
|
419
|
-
|
|
416
|
+
// Default free model is nemotron-3.5-lightning — the same model
|
|
417
|
+
// @blockrun/router-core opens the eco SIMPLE tier on. It replaced
|
|
418
|
+
// step-3.7-flash on 2026-08-30, when NVIDIA retired FOUR of the five visible
|
|
419
|
+
// free models in a single sweep (blockrun #448): step-3.7-flash,
|
|
420
|
+
// nemotron-nano-9b-v2 and nemotron-nano-12b-v2-vl all published 410 Gone, and
|
|
421
|
+
// mistral-nemotron went the quiet way — still listed, >150s and zero bytes.
|
|
422
|
+
// We follow blockrun's own retarget of step-3.7-flash rather than picking a
|
|
423
|
+
// different survivor, so the proxy and the gateway name the same model.
|
|
424
|
+
//
|
|
425
|
+
// gpt-oss-120b/20b RECOVERED on the same probe run and are reachable again,
|
|
426
|
+
// but they stay withheld from blockrun's public catalog over NVIDIA's
|
|
427
|
+
// prompt-retention terms — so pins that NAME gpt-oss stay routable below and
|
|
428
|
+
// nothing generic may land on it.
|
|
429
|
+
nvidia: "free/nemotron-3.5-lightning",
|
|
420
430
|
"gpt-120b": "free/gpt-oss-120b",
|
|
421
431
|
// names the model itself — gateway redirects
|
|
422
432
|
"gpt-20b": "free/gpt-oss-20b",
|
|
@@ -429,10 +439,10 @@ var init_models = __esm({
|
|
|
429
439
|
// straight to gpt-oss-120b. Ids naming v4-flash itself keep the real id (the
|
|
430
440
|
// gateway redirects them); the v3.2/v4-pro ids follow blockrun's retarget
|
|
431
441
|
// rather than chaining through a second dead model.
|
|
432
|
-
"nvidia/deepseek-v3.2": "free/
|
|
433
|
-
"free/deepseek-v3.2": "free/
|
|
434
|
-
"nvidia/deepseek-v4-pro": "free/
|
|
435
|
-
"free/deepseek-v4-pro": "free/
|
|
442
|
+
"nvidia/deepseek-v3.2": "free/nemotron-3.5-lightning",
|
|
443
|
+
"free/deepseek-v3.2": "free/nemotron-3.5-lightning",
|
|
444
|
+
"nvidia/deepseek-v4-pro": "free/nemotron-3.5-lightning",
|
|
445
|
+
"free/deepseek-v4-pro": "free/nemotron-3.5-lightning",
|
|
436
446
|
"nvidia/deepseek-v4-flash": "free/deepseek-v4-flash",
|
|
437
447
|
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
438
448
|
// qwen3-coder-480b retired (NVIDIA EOL 2026-06-14). Its server-side redirect used
|
|
@@ -459,16 +469,16 @@ var init_models = __esm({
|
|
|
459
469
|
// Retired free IDs → successors (mirror blockrun's 2026-07-17 redirect map:
|
|
460
470
|
// ultra-253b redirects to gpt-oss-120b; the two supers have NO server redirect —
|
|
461
471
|
// they stay hidden-but-routable, so their pins pass through to the real ids).
|
|
462
|
-
"nvidia/nemotron-ultra-253b": "free/
|
|
472
|
+
"nvidia/nemotron-ultra-253b": "free/nemotron-3.5-lightning",
|
|
463
473
|
// mistral-large-3-675b un-retired 2026-06-14, then EOL'd for good 2026-07-28:
|
|
464
474
|
// blockrun's re-probe got HTTP 410 Gone from NVIDIA on both passes (baa967b).
|
|
465
475
|
// Pin stays routable — the gateway redirects it to gpt-oss-120b.
|
|
466
476
|
"nvidia/mistral-large-3-675b": "free/mistral-large-3-675b",
|
|
467
477
|
"nvidia/qwen3.5-122b-a10b": "free/qwen3.5-122b-a10b",
|
|
468
478
|
// devstral-2-123b died upstream; blockrun redirects it to gpt-oss-120b (2026-07-17 map)
|
|
469
|
-
"nvidia/devstral-2-123b": "free/
|
|
470
|
-
"free/nemotron-ultra-253b": "free/
|
|
471
|
-
"free/devstral-2-123b": "free/
|
|
479
|
+
"nvidia/devstral-2-123b": "free/nemotron-3.5-lightning",
|
|
480
|
+
"free/nemotron-ultra-253b": "free/nemotron-3.5-lightning",
|
|
481
|
+
"free/devstral-2-123b": "free/nemotron-3.5-lightning",
|
|
472
482
|
// Explicit-ish pins — dead upstream since 2026-07-28, gateway redirects to gpt-oss-120b
|
|
473
483
|
"mistral-large": "free/mistral-large-3-675b",
|
|
474
484
|
"mistral-large-3-675b": "free/mistral-large-3-675b",
|
|
@@ -479,74 +489,124 @@ var init_models = __esm({
|
|
|
479
489
|
// gateway's retarget (blockrun's /free-deepseek page points at gpt-oss-120b
|
|
480
490
|
// too). Shorthands naming v4-flash itself stay on the real id — the gateway
|
|
481
491
|
// redirects them, same treatment as seed-oss/mistral-large pins.
|
|
482
|
-
"deepseek-free": "free/
|
|
483
|
-
"deepseek-v4-pro": "free/
|
|
492
|
+
"deepseek-free": "free/nemotron-3.5-lightning",
|
|
493
|
+
"deepseek-v4-pro": "free/nemotron-3.5-lightning",
|
|
484
494
|
// free shorthand; pro dead upstream (410)
|
|
485
495
|
"deepseek-v4-flash": "free/deepseek-v4-flash",
|
|
486
|
-
"v4-pro": "free/
|
|
496
|
+
"v4-pro": "free/nemotron-3.5-lightning",
|
|
487
497
|
"v4-flash": "free/deepseek-v4-flash",
|
|
488
|
-
|
|
489
|
-
//
|
|
490
|
-
|
|
498
|
+
// mistral-nemotron died 2026-08-30 and it was the LAST free Mistral anywhere —
|
|
499
|
+
// blockrun's own /free-mistral page now says so plainly instead of naming one.
|
|
500
|
+
// Point the generic shorthand at the free default rather than advertise a
|
|
501
|
+
// Mistral we cannot serve.
|
|
502
|
+
"mistral-free": "free/nemotron-3.5-lightning",
|
|
503
|
+
"glm-free": "free/nemotron-3.5-lightning",
|
|
491
504
|
// seed-oss-36b (the prior target) EOL'd 2026-08-03
|
|
492
|
-
|
|
493
|
-
//
|
|
505
|
+
// A free Llama exists again: nemotron-super-49b (Llama-3.3-based) hit 410 on
|
|
506
|
+
// 2026-08-30, and a 12-model sweep of what NVIDIA still serves found Llama 3.2
|
|
507
|
+
// 11B Vision as the only one that finishes a real completion.
|
|
508
|
+
"llama-free": "free/llama-3.2-11b-vision",
|
|
494
509
|
// qwen3-coder-480b retired 2026-06-14 → seed-oss-36b, which then EOL'd 2026-08-03.
|
|
495
510
|
// Follow the gateway's own retarget rather than chaining to a second dead model.
|
|
496
|
-
"qwen-coder": "free/
|
|
511
|
+
"qwen-coder": "free/nemotron-3.5-lightning",
|
|
497
512
|
// no live free Qwen; follows the free default
|
|
498
|
-
"qwen-coder-free": "free/
|
|
499
|
-
"qwen-thinking": "free/
|
|
513
|
+
"qwen-coder-free": "free/nemotron-3.5-lightning",
|
|
514
|
+
"qwen-thinking": "free/nemotron-3.5-lightning",
|
|
500
515
|
// qwen3-next died 2026-07-17; no live free Qwen left
|
|
501
516
|
"qwen3-next": "free/qwen3-next-80b-a3b-instruct",
|
|
502
517
|
// explicit-ish pin — gateway redirects
|
|
503
518
|
"qwen3-next-80b": "free/qwen3-next-80b-a3b-instruct",
|
|
504
|
-
"mistral-small": "free/
|
|
505
|
-
//
|
|
519
|
+
"mistral-small": "free/nemotron-3.5-lightning",
|
|
520
|
+
// no free Mistral left upstream (2026-08-30)
|
|
506
521
|
// New live free models (2026-06-14 BlockRun free-tier refresh)
|
|
507
522
|
// seed-oss pins name the model itself — kept routable, the gateway redirects them.
|
|
508
523
|
"seed-oss": "free/seed-oss-36b",
|
|
509
524
|
"seed-oss-36b": "free/seed-oss-36b",
|
|
510
|
-
|
|
511
|
-
//
|
|
525
|
+
// A free coder exists again — two of them, both sub-second. north-mini-code is
|
|
526
|
+
// the faster (607ms median) and 256K ctx against laguna's 131K.
|
|
527
|
+
"coder-free": "free/north-mini-code",
|
|
512
528
|
"mistral-nemotron": "free/mistral-nemotron",
|
|
513
529
|
"step-flash": "free/step-3.7-flash",
|
|
514
530
|
"step-3.7-flash": "free/step-3.7-flash",
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
"nano-
|
|
531
|
+
// nemotron-nano-9b-v2 hit 410 on 2026-08-30; the generic shorthands follow
|
|
532
|
+
// blockrun's redirect to its replacement, while the 9b-naming pins above stay
|
|
533
|
+
// on the real id (the gateway resolves them).
|
|
534
|
+
"nemotron-nano-9b": "free/nemotron-3-nano-30b",
|
|
535
|
+
"nemotron-nano": "free/nemotron-3-nano-30b",
|
|
536
|
+
// nemotron-nano-12b-v2-vl hit 410 the same day; vision in, vision out — the
|
|
537
|
+
// target is blockrun's own, and nano-omni is the only vision-capable free
|
|
538
|
+
// model left.
|
|
539
|
+
"nemotron-nano-vl": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
540
|
+
"nano-vl": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
519
541
|
// Vision-capable free models
|
|
520
542
|
"nemotron-omni": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
521
543
|
"nano-omni": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
522
544
|
"vision-free": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
523
545
|
// Retired shorthand aliases redirect to live successors. The catch-all target
|
|
524
546
|
// moved llama-4-maverick → gpt-oss-120b (2026-07-17) → step-3.7-flash
|
|
525
|
-
// (2026-08-29
|
|
526
|
-
nemotron: "free/nemotron-3-
|
|
547
|
+
// (2026-08-29) → nemotron-3.5-lightning (2026-08-30, blockrun #448).
|
|
548
|
+
nemotron: "free/nemotron-3.5-lightning",
|
|
527
549
|
// strongest live Nemotron
|
|
528
|
-
"nemotron-ultra": "free/
|
|
529
|
-
"nemotron-253b": "free/
|
|
530
|
-
"nemotron-super": "free/
|
|
531
|
-
"nemotron-49b": "free/
|
|
532
|
-
"nemotron-120b": "free/
|
|
533
|
-
devstral: "free/
|
|
550
|
+
"nemotron-ultra": "free/nemotron-3.5-lightning",
|
|
551
|
+
"nemotron-253b": "free/nemotron-3.5-lightning",
|
|
552
|
+
"nemotron-super": "free/nemotron-3.5-lightning",
|
|
553
|
+
"nemotron-49b": "free/nemotron-3.5-lightning",
|
|
554
|
+
"nemotron-120b": "free/nemotron-3.5-lightning",
|
|
555
|
+
devstral: "free/nemotron-3.5-lightning",
|
|
534
556
|
// seed-oss-36b EOL'd 2026-08-03
|
|
535
|
-
"devstral-2": "free/
|
|
557
|
+
"devstral-2": "free/nemotron-3.5-lightning",
|
|
536
558
|
maverick: "free/llama-4-maverick",
|
|
537
559
|
// explicit-ish pin — gateway redirects
|
|
560
|
+
// ── The 2026-08-30 free lineup (blockrun #448) ────────────────────────────
|
|
561
|
+
// nvidia/* bridges for the four NVIDIA-hosted additions.
|
|
562
|
+
"nvidia/nemotron-3.5-lightning": "free/nemotron-3.5-lightning",
|
|
563
|
+
"nvidia/nemotron-3-nano-30b": "free/nemotron-3-nano-30b",
|
|
564
|
+
"nvidia/nemotron-3-ultra-550b": "free/nemotron-3-ultra-550b",
|
|
565
|
+
"nvidia/llama-3.2-11b-vision": "free/llama-3.2-11b-vision",
|
|
566
|
+
// The two non-NVIDIA free models keep the `free/` picker convention; their
|
|
567
|
+
// real upstream ids are accepted as pins and rewritten in toUpstreamModelId
|
|
568
|
+
// (see FREE_UPSTREAM_OVERRIDES in proxy.ts).
|
|
569
|
+
"cohere/north-mini-code": "free/north-mini-code",
|
|
570
|
+
"poolside/laguna-xs-2.1": "free/laguna-xs-2.1",
|
|
571
|
+
// Shorthands.
|
|
572
|
+
lightning: "free/nemotron-3.5-lightning",
|
|
573
|
+
"nemotron-lightning": "free/nemotron-3.5-lightning",
|
|
574
|
+
"nemotron-3.5-lightning": "free/nemotron-3.5-lightning",
|
|
575
|
+
"nano-30b": "free/nemotron-3-nano-30b",
|
|
576
|
+
"nemotron-nano-30b": "free/nemotron-3-nano-30b",
|
|
577
|
+
"ultra-550b": "free/nemotron-3-ultra-550b",
|
|
578
|
+
"nemotron-ultra-550b": "free/nemotron-3-ultra-550b",
|
|
579
|
+
"llama-vision": "free/llama-3.2-11b-vision",
|
|
580
|
+
"llama-3.2-vision": "free/llama-3.2-11b-vision",
|
|
581
|
+
"north-mini": "free/north-mini-code",
|
|
582
|
+
"north-mini-code": "free/north-mini-code",
|
|
583
|
+
laguna: "free/laguna-xs-2.1",
|
|
584
|
+
"laguna-xs": "free/laguna-xs-2.1",
|
|
538
585
|
// `free` = the free-tier default. Must equal router-core's ecoTiers.SIMPLE
|
|
539
586
|
// primary and the head of proxy.ts FREE_MODELS so `/model free`, the eco
|
|
540
587
|
// profile and the budget-cap free fallback all agree on one live model.
|
|
541
|
-
free: "free/
|
|
588
|
+
free: "free/nemotron-3.5-lightning",
|
|
542
589
|
// MiniMax (minimax → current flagship: M3)
|
|
543
590
|
minimax: "minimax/minimax-m3",
|
|
544
591
|
"minimax-m3": "minimax/minimax-m3",
|
|
545
592
|
"minimax-m2.7": "minimax/minimax-m2.7",
|
|
546
593
|
"minimax-m2.5": "minimax/minimax-m2.5",
|
|
547
594
|
// Z.AI GLM-5
|
|
548
|
-
glm
|
|
549
|
-
//
|
|
595
|
+
// Bare `glm` PROMOTED 5.2 → 5.3 (2026-08-30). Same rule as `opus` 4.8 → 5: the
|
|
596
|
+
// cost tradeoff is zero — identical $1.40/$4.40 AND an identical 1M ctx /
|
|
597
|
+
// 131072 maxOutput envelope, so nothing can bill or truncate differently for a
|
|
598
|
+
// caller who never typed a version. blockrun's own copy already names glm-5.3
|
|
599
|
+
// the Z.AI flagship, so leaving `glm` on 5.2 would make the proxy disagree
|
|
600
|
+
// with the gateway it fronts. `glm-5.2` and every other version pin still
|
|
601
|
+
// resolve to their own model.
|
|
602
|
+
glm: "zai/glm-5.3",
|
|
603
|
+
"glm-5.3": "zai/glm-5.3",
|
|
604
|
+
"glm-5-3": "zai/glm-5.3",
|
|
605
|
+
// GLM-5.3 Flash — Z.AI's first natively multimodal GLM-5. Also router-core's
|
|
606
|
+
// eco MEDIUM and COMPLEX primary.
|
|
607
|
+
"glm-5.3-flash": "zai/glm-5.3-flash",
|
|
608
|
+
"glm-5-3-flash": "zai/glm-5.3-flash",
|
|
609
|
+
"glm-flash": "zai/glm-5.3-flash",
|
|
550
610
|
"glm-5.2": "zai/glm-5.2",
|
|
551
611
|
"glm-5": "zai/glm-5",
|
|
552
612
|
"glm-5.1": "zai/glm-5.1",
|
|
@@ -608,10 +668,10 @@ var init_models = __esm({
|
|
|
608
668
|
},
|
|
609
669
|
{
|
|
610
670
|
id: "free",
|
|
611
|
-
name: "Free \u2192
|
|
671
|
+
name: "Free \u2192 Nemotron 3.5 Lightning",
|
|
612
672
|
inputPrice: 0,
|
|
613
673
|
outputPrice: 0,
|
|
614
|
-
contextWindow:
|
|
674
|
+
contextWindow: 1e6,
|
|
615
675
|
maxOutput: 16384,
|
|
616
676
|
reasoning: true
|
|
617
677
|
},
|
|
@@ -652,7 +712,7 @@ var init_models = __esm({
|
|
|
652
712
|
inputPrice: 0.25,
|
|
653
713
|
outputPrice: 2,
|
|
654
714
|
contextWindow: 2e5,
|
|
655
|
-
maxOutput:
|
|
715
|
+
maxOutput: 128e3,
|
|
656
716
|
toolCalling: true
|
|
657
717
|
},
|
|
658
718
|
{
|
|
@@ -662,7 +722,7 @@ var init_models = __esm({
|
|
|
662
722
|
inputPrice: 0.05,
|
|
663
723
|
outputPrice: 0.4,
|
|
664
724
|
contextWindow: 128e3,
|
|
665
|
-
maxOutput:
|
|
725
|
+
maxOutput: 128e3,
|
|
666
726
|
toolCalling: true,
|
|
667
727
|
deprecated: true,
|
|
668
728
|
fallbackModel: "openai/gpt-5.4-nano"
|
|
@@ -823,7 +883,7 @@ var init_models = __esm({
|
|
|
823
883
|
version: "5.4",
|
|
824
884
|
inputPrice: 2.5,
|
|
825
885
|
outputPrice: 15,
|
|
826
|
-
contextWindow:
|
|
886
|
+
contextWindow: 105e4,
|
|
827
887
|
maxOutput: 128e3,
|
|
828
888
|
reasoning: true,
|
|
829
889
|
vision: true,
|
|
@@ -848,7 +908,7 @@ var init_models = __esm({
|
|
|
848
908
|
version: "5.4",
|
|
849
909
|
inputPrice: 30,
|
|
850
910
|
outputPrice: 180,
|
|
851
|
-
contextWindow:
|
|
911
|
+
contextWindow: 105e4,
|
|
852
912
|
maxOutput: 128e3,
|
|
853
913
|
reasoning: true,
|
|
854
914
|
vision: true,
|
|
@@ -861,7 +921,7 @@ var init_models = __esm({
|
|
|
861
921
|
inputPrice: 0.2,
|
|
862
922
|
outputPrice: 1.25,
|
|
863
923
|
contextWindow: 105e4,
|
|
864
|
-
maxOutput:
|
|
924
|
+
maxOutput: 128e3,
|
|
865
925
|
toolCalling: true
|
|
866
926
|
},
|
|
867
927
|
// OpenAI GPT-5.3 Family
|
|
@@ -872,7 +932,7 @@ var init_models = __esm({
|
|
|
872
932
|
inputPrice: 1.75,
|
|
873
933
|
outputPrice: 14,
|
|
874
934
|
contextWindow: 128e3,
|
|
875
|
-
maxOutput:
|
|
935
|
+
maxOutput: 128e3,
|
|
876
936
|
reasoning: true,
|
|
877
937
|
vision: true,
|
|
878
938
|
agentic: true,
|
|
@@ -898,7 +958,7 @@ var init_models = __esm({
|
|
|
898
958
|
inputPrice: 2,
|
|
899
959
|
outputPrice: 8,
|
|
900
960
|
contextWindow: 128e3,
|
|
901
|
-
maxOutput:
|
|
961
|
+
maxOutput: 32768,
|
|
902
962
|
vision: true,
|
|
903
963
|
toolCalling: true
|
|
904
964
|
},
|
|
@@ -909,7 +969,7 @@ var init_models = __esm({
|
|
|
909
969
|
inputPrice: 0.4,
|
|
910
970
|
outputPrice: 1.6,
|
|
911
971
|
contextWindow: 128e3,
|
|
912
|
-
maxOutput:
|
|
972
|
+
maxOutput: 32768,
|
|
913
973
|
toolCalling: true
|
|
914
974
|
},
|
|
915
975
|
{
|
|
@@ -919,7 +979,7 @@ var init_models = __esm({
|
|
|
919
979
|
inputPrice: 0.1,
|
|
920
980
|
outputPrice: 0.4,
|
|
921
981
|
contextWindow: 128e3,
|
|
922
|
-
maxOutput:
|
|
982
|
+
maxOutput: 32768,
|
|
923
983
|
toolCalling: true
|
|
924
984
|
},
|
|
925
985
|
{
|
|
@@ -985,7 +1045,7 @@ var init_models = __esm({
|
|
|
985
1045
|
inputPrice: 1.1,
|
|
986
1046
|
outputPrice: 4.4,
|
|
987
1047
|
contextWindow: 128e3,
|
|
988
|
-
maxOutput:
|
|
1048
|
+
maxOutput: 1e5,
|
|
989
1049
|
reasoning: true,
|
|
990
1050
|
toolCalling: true
|
|
991
1051
|
},
|
|
@@ -996,7 +1056,7 @@ var init_models = __esm({
|
|
|
996
1056
|
inputPrice: 1.1,
|
|
997
1057
|
outputPrice: 4.4,
|
|
998
1058
|
contextWindow: 128e3,
|
|
999
|
-
maxOutput:
|
|
1059
|
+
maxOutput: 1e5,
|
|
1000
1060
|
reasoning: true,
|
|
1001
1061
|
toolCalling: true
|
|
1002
1062
|
},
|
|
@@ -1009,7 +1069,7 @@ var init_models = __esm({
|
|
|
1009
1069
|
inputPrice: 1,
|
|
1010
1070
|
outputPrice: 5,
|
|
1011
1071
|
contextWindow: 2e5,
|
|
1012
|
-
maxOutput:
|
|
1072
|
+
maxOutput: 64e3,
|
|
1013
1073
|
vision: true,
|
|
1014
1074
|
agentic: true,
|
|
1015
1075
|
toolCalling: true
|
|
@@ -1033,8 +1093,8 @@ var init_models = __esm({
|
|
|
1033
1093
|
version: "4.6",
|
|
1034
1094
|
inputPrice: 3,
|
|
1035
1095
|
outputPrice: 15,
|
|
1036
|
-
contextWindow:
|
|
1037
|
-
maxOutput:
|
|
1096
|
+
contextWindow: 1e6,
|
|
1097
|
+
maxOutput: 128e3,
|
|
1038
1098
|
reasoning: true,
|
|
1039
1099
|
vision: true,
|
|
1040
1100
|
agentic: true,
|
|
@@ -1064,7 +1124,7 @@ var init_models = __esm({
|
|
|
1064
1124
|
inputPrice: 5,
|
|
1065
1125
|
outputPrice: 25,
|
|
1066
1126
|
contextWindow: 2e5,
|
|
1067
|
-
maxOutput:
|
|
1127
|
+
maxOutput: 64e3,
|
|
1068
1128
|
reasoning: true,
|
|
1069
1129
|
vision: true,
|
|
1070
1130
|
agentic: true,
|
|
@@ -1148,7 +1208,7 @@ var init_models = __esm({
|
|
|
1148
1208
|
version: "3.1",
|
|
1149
1209
|
inputPrice: 2,
|
|
1150
1210
|
outputPrice: 12,
|
|
1151
|
-
contextWindow:
|
|
1211
|
+
contextWindow: 1048576,
|
|
1152
1212
|
maxOutput: 65536,
|
|
1153
1213
|
reasoning: true,
|
|
1154
1214
|
vision: true,
|
|
@@ -1160,7 +1220,7 @@ var init_models = __esm({
|
|
|
1160
1220
|
version: "3.0",
|
|
1161
1221
|
inputPrice: 2,
|
|
1162
1222
|
outputPrice: 12,
|
|
1163
|
-
contextWindow:
|
|
1223
|
+
contextWindow: 1048576,
|
|
1164
1224
|
maxOutput: 65536,
|
|
1165
1225
|
reasoning: true,
|
|
1166
1226
|
vision: true,
|
|
@@ -1212,7 +1272,7 @@ var init_models = __esm({
|
|
|
1212
1272
|
version: "3.0",
|
|
1213
1273
|
inputPrice: 0.5,
|
|
1214
1274
|
outputPrice: 3,
|
|
1215
|
-
contextWindow:
|
|
1275
|
+
contextWindow: 1048576,
|
|
1216
1276
|
maxOutput: 65536,
|
|
1217
1277
|
reasoning: true,
|
|
1218
1278
|
vision: true
|
|
@@ -1223,7 +1283,7 @@ var init_models = __esm({
|
|
|
1223
1283
|
version: "2.5",
|
|
1224
1284
|
inputPrice: 1.25,
|
|
1225
1285
|
outputPrice: 10,
|
|
1226
|
-
contextWindow:
|
|
1286
|
+
contextWindow: 1048576,
|
|
1227
1287
|
maxOutput: 65536,
|
|
1228
1288
|
reasoning: true,
|
|
1229
1289
|
vision: true,
|
|
@@ -1235,7 +1295,7 @@ var init_models = __esm({
|
|
|
1235
1295
|
version: "2.5",
|
|
1236
1296
|
inputPrice: 0.3,
|
|
1237
1297
|
outputPrice: 2.5,
|
|
1238
|
-
contextWindow:
|
|
1298
|
+
contextWindow: 1048576,
|
|
1239
1299
|
maxOutput: 65536,
|
|
1240
1300
|
vision: true,
|
|
1241
1301
|
toolCalling: true
|
|
@@ -1246,7 +1306,7 @@ var init_models = __esm({
|
|
|
1246
1306
|
version: "2.5",
|
|
1247
1307
|
inputPrice: 0.1,
|
|
1248
1308
|
outputPrice: 0.4,
|
|
1249
|
-
contextWindow:
|
|
1309
|
+
contextWindow: 1048576,
|
|
1250
1310
|
maxOutput: 65536,
|
|
1251
1311
|
toolCalling: true
|
|
1252
1312
|
},
|
|
@@ -1256,8 +1316,8 @@ var init_models = __esm({
|
|
|
1256
1316
|
version: "3.1",
|
|
1257
1317
|
inputPrice: 0.25,
|
|
1258
1318
|
outputPrice: 1.5,
|
|
1259
|
-
contextWindow:
|
|
1260
|
-
maxOutput:
|
|
1319
|
+
contextWindow: 1048576,
|
|
1320
|
+
maxOutput: 65536,
|
|
1261
1321
|
toolCalling: true
|
|
1262
1322
|
},
|
|
1263
1323
|
// DeepSeek — V4 family (2026-04-24). The legacy deepseek-chat/reasoner
|
|
@@ -1270,8 +1330,8 @@ var init_models = __esm({
|
|
|
1270
1330
|
version: "4-flash",
|
|
1271
1331
|
inputPrice: 0.14,
|
|
1272
1332
|
outputPrice: 0.28,
|
|
1273
|
-
contextWindow:
|
|
1274
|
-
maxOutput:
|
|
1333
|
+
contextWindow: 1048576,
|
|
1334
|
+
maxOutput: 65536,
|
|
1275
1335
|
toolCalling: true
|
|
1276
1336
|
},
|
|
1277
1337
|
{
|
|
@@ -1280,8 +1340,8 @@ var init_models = __esm({
|
|
|
1280
1340
|
version: "4-flash",
|
|
1281
1341
|
inputPrice: 0.14,
|
|
1282
1342
|
outputPrice: 0.28,
|
|
1283
|
-
contextWindow:
|
|
1284
|
-
maxOutput:
|
|
1343
|
+
contextWindow: 1048576,
|
|
1344
|
+
maxOutput: 65536,
|
|
1285
1345
|
reasoning: true,
|
|
1286
1346
|
toolCalling: true
|
|
1287
1347
|
},
|
|
@@ -1407,7 +1467,7 @@ var init_models = __esm({
|
|
|
1407
1467
|
inputPrice: 0.6,
|
|
1408
1468
|
outputPrice: 3,
|
|
1409
1469
|
contextWindow: 262144,
|
|
1410
|
-
maxOutput:
|
|
1470
|
+
maxOutput: 65536,
|
|
1411
1471
|
reasoning: true,
|
|
1412
1472
|
vision: true,
|
|
1413
1473
|
agentic: true,
|
|
@@ -1420,7 +1480,7 @@ var init_models = __esm({
|
|
|
1420
1480
|
inputPrice: 0.6,
|
|
1421
1481
|
outputPrice: 3,
|
|
1422
1482
|
contextWindow: 262144,
|
|
1423
|
-
maxOutput:
|
|
1483
|
+
maxOutput: 16384,
|
|
1424
1484
|
reasoning: true,
|
|
1425
1485
|
vision: true,
|
|
1426
1486
|
agentic: true,
|
|
@@ -1458,7 +1518,7 @@ var init_models = __esm({
|
|
|
1458
1518
|
version: "4",
|
|
1459
1519
|
inputPrice: 0.2,
|
|
1460
1520
|
outputPrice: 0.5,
|
|
1461
|
-
contextWindow:
|
|
1521
|
+
contextWindow: 2e6,
|
|
1462
1522
|
maxOutput: 16384,
|
|
1463
1523
|
reasoning: true,
|
|
1464
1524
|
toolCalling: true
|
|
@@ -1469,7 +1529,7 @@ var init_models = __esm({
|
|
|
1469
1529
|
version: "4",
|
|
1470
1530
|
inputPrice: 0.2,
|
|
1471
1531
|
outputPrice: 0.5,
|
|
1472
|
-
contextWindow:
|
|
1532
|
+
contextWindow: 2e6,
|
|
1473
1533
|
maxOutput: 16384,
|
|
1474
1534
|
toolCalling: true
|
|
1475
1535
|
},
|
|
@@ -1479,7 +1539,7 @@ var init_models = __esm({
|
|
|
1479
1539
|
version: "4.1",
|
|
1480
1540
|
inputPrice: 0.2,
|
|
1481
1541
|
outputPrice: 0.5,
|
|
1482
|
-
contextWindow:
|
|
1542
|
+
contextWindow: 2e6,
|
|
1483
1543
|
maxOutput: 16384,
|
|
1484
1544
|
reasoning: true,
|
|
1485
1545
|
toolCalling: true
|
|
@@ -1490,7 +1550,7 @@ var init_models = __esm({
|
|
|
1490
1550
|
version: "4.1",
|
|
1491
1551
|
inputPrice: 0.2,
|
|
1492
1552
|
outputPrice: 0.5,
|
|
1493
|
-
contextWindow:
|
|
1553
|
+
contextWindow: 2e6,
|
|
1494
1554
|
maxOutput: 16384,
|
|
1495
1555
|
toolCalling: true
|
|
1496
1556
|
},
|
|
@@ -1502,7 +1562,7 @@ var init_models = __esm({
|
|
|
1502
1562
|
version: "4-0709",
|
|
1503
1563
|
inputPrice: 3,
|
|
1504
1564
|
outputPrice: 15,
|
|
1505
|
-
contextWindow:
|
|
1565
|
+
contextWindow: 256e3,
|
|
1506
1566
|
maxOutput: 16384,
|
|
1507
1567
|
reasoning: true,
|
|
1508
1568
|
toolCalling: true
|
|
@@ -1513,7 +1573,7 @@ var init_models = __esm({
|
|
|
1513
1573
|
version: "2",
|
|
1514
1574
|
inputPrice: 2,
|
|
1515
1575
|
outputPrice: 10,
|
|
1516
|
-
contextWindow:
|
|
1576
|
+
contextWindow: 32768,
|
|
1517
1577
|
maxOutput: 16384,
|
|
1518
1578
|
vision: true,
|
|
1519
1579
|
toolCalling: true
|
|
@@ -1818,7 +1878,13 @@ var init_models = __esm({
|
|
|
1818
1878
|
maxOutput: 16384
|
|
1819
1879
|
},
|
|
1820
1880
|
{
|
|
1821
|
-
// Mistral × NVIDIA hybrid
|
|
1881
|
+
// Mistral × NVIDIA hybrid, 131K context. DEAD 2026-08-30 — the QUIET kind:
|
|
1882
|
+
// NVIDIA still LISTS it but a completion returns zero bytes after >150s on
|
|
1883
|
+
// both of blockrun's probe passes (blockrun #448, the #391 shape). Upstream
|
|
1884
|
+
// hid it and redirects callers to a live workhorse. Entry kept so explicit
|
|
1885
|
+
// pins stay routable; off the picker and the FREE_MODELS cascade.
|
|
1886
|
+
// There is no free Mistral left on NVIDIA — do not point a generic
|
|
1887
|
+
// "a free mistral" shorthand at one.
|
|
1822
1888
|
id: "free/mistral-nemotron",
|
|
1823
1889
|
name: "[Free] Mistral Nemotron",
|
|
1824
1890
|
version: "nemotron",
|
|
@@ -1828,7 +1894,13 @@ var init_models = __esm({
|
|
|
1828
1894
|
maxOutput: 16384
|
|
1829
1895
|
},
|
|
1830
1896
|
{
|
|
1831
|
-
// StepFun Step 3.7 Flash: reasoning-focused, 131K context.
|
|
1897
|
+
// StepFun Step 3.7 Flash: reasoning-focused, 131K context. EOL'd 2026-08-30
|
|
1898
|
+
// — NVIDIA published 410 Gone on both of blockrun's probe passes (#448), in
|
|
1899
|
+
// the same sweep that took nemotron-nano-9b-v2, nemotron-nano-12b-v2-vl and
|
|
1900
|
+
// (hidden) nemotron-super-49b. It had been ClawRouter's free default since
|
|
1901
|
+
// 2026-08-29; the gateway redirects it to nemotron-3.5-lightning, which is
|
|
1902
|
+
// exactly why nothing looked broken. Entry kept so explicit pins stay
|
|
1903
|
+
// routable; off the picker and the FREE_MODELS cascade.
|
|
1832
1904
|
id: "free/step-3.7-flash",
|
|
1833
1905
|
name: "[Free] StepFun Step 3.7 Flash",
|
|
1834
1906
|
version: "3.7-flash",
|
|
@@ -1840,6 +1912,8 @@ var init_models = __esm({
|
|
|
1840
1912
|
},
|
|
1841
1913
|
{
|
|
1842
1914
|
// NVIDIA Nemotron Nano 9B v2: fast lightweight generalist, 131K context.
|
|
1915
|
+
// EOL'd 2026-08-30 (410 Gone, same sweep). Gateway redirects it to
|
|
1916
|
+
// nemotron-3-nano-30b. Entry kept for pins; off the picker and the cascade.
|
|
1843
1917
|
id: "free/nemotron-nano-9b-v2",
|
|
1844
1918
|
name: "[Free] Nemotron Nano 9B v2",
|
|
1845
1919
|
version: "nano-9b-v2",
|
|
@@ -1851,6 +1925,9 @@ var init_models = __esm({
|
|
|
1851
1925
|
},
|
|
1852
1926
|
{
|
|
1853
1927
|
// NVIDIA Nemotron Nano 12B v2 VL: vision-language (text + image), 131K context.
|
|
1928
|
+
// EOL'd 2026-08-30 (410 Gone, same sweep). Gateway redirects it to
|
|
1929
|
+
// nemotron-3-nano-omni, the only vision-capable free model left. Entry kept
|
|
1930
|
+
// for pins; off the picker and the cascade.
|
|
1854
1931
|
id: "free/nemotron-nano-12b-v2-vl",
|
|
1855
1932
|
name: "[Free] Nemotron Nano 12B v2 VL",
|
|
1856
1933
|
version: "nano-12b-v2-vl",
|
|
@@ -1861,9 +1938,155 @@ var init_models = __esm({
|
|
|
1861
1938
|
reasoning: true,
|
|
1862
1939
|
vision: true
|
|
1863
1940
|
},
|
|
1941
|
+
// ── 2026-08-30 free-tier rebuild (blockrun #448) ─────────────────────────
|
|
1942
|
+
// NVIDIA retired FOUR of the five VISIBLE free models in one sweep. blockrun
|
|
1943
|
+
// replaced them and moved two survivors onto OpenRouter's $0 ":free" pool,
|
|
1944
|
+
// taking the visible free set from 5 to 7 and spanning three hosts for the
|
|
1945
|
+
// first time (NVIDIA, OpenRouter, and two non-NVIDIA makers).
|
|
1946
|
+
//
|
|
1947
|
+
// All seven live free models were tool-probed through the gateway on
|
|
1948
|
+
// 2026-08-30 and every one returned a structured `tool_calls` array with
|
|
1949
|
+
// valid JSON args and finish_reason: "tool_calls" (nemotron-3-nano-30b looked
|
|
1950
|
+
// like a textual leak at max_tokens:120 — that was truncation; at 300 it is
|
|
1951
|
+
// structured). The evidence is recorded here on purpose, but `toolCalling` is
|
|
1952
|
+
// deliberately NOT set: no free entry has ever carried it, filterByToolCalling
|
|
1953
|
+
// keeps the free tier out of tool-bearing requests, and the budget pre-check
|
|
1954
|
+
// at proxy.ts:5217 is written on the same assumption. Flipping the tier into
|
|
1955
|
+
// agentic eligibility is its own change with its own evidence bar.
|
|
1956
|
+
{
|
|
1957
|
+
// Nemotron 3.5 Lightning 30B-A3B — the new free default. blockrun's own
|
|
1958
|
+
// redirect target for the retired step-3.7-flash, so following it keeps the
|
|
1959
|
+
// proxy and the gateway naming the same model. Served from OpenRouter's $0
|
|
1960
|
+
// pool (4.9s median vs 16.3s direct) which also publishes a 1M window
|
|
1961
|
+
// against the 131K the NVIDIA NIM path gives; blockrun carries a hidden
|
|
1962
|
+
// "-nim" twin as its fallback. Probed 1.3s with tools.
|
|
1963
|
+
id: "free/nemotron-3.5-lightning",
|
|
1964
|
+
name: "[Free] Nemotron 3.5 Lightning",
|
|
1965
|
+
version: "3.5-lightning",
|
|
1966
|
+
inputPrice: 0,
|
|
1967
|
+
outputPrice: 0,
|
|
1968
|
+
contextWindow: 1e6,
|
|
1969
|
+
maxOutput: 16384,
|
|
1970
|
+
reasoning: true
|
|
1971
|
+
},
|
|
1972
|
+
{
|
|
1973
|
+
// Nemotron 3 Nano 30B-A3B — the fastest free model in the catalog
|
|
1974
|
+
// (~121 tok/s on a realistic workload, not a 16-token ping). Returns
|
|
1975
|
+
// reasoning_content. Also the tertiary rung of blockrun's own free cascade.
|
|
1976
|
+
id: "free/nemotron-3-nano-30b",
|
|
1977
|
+
name: "[Free] Nemotron 3 Nano 30B",
|
|
1978
|
+
version: "3-nano-30b",
|
|
1979
|
+
inputPrice: 0,
|
|
1980
|
+
outputPrice: 0,
|
|
1981
|
+
contextWindow: 131072,
|
|
1982
|
+
maxOutput: 16384,
|
|
1983
|
+
reasoning: true
|
|
1984
|
+
},
|
|
1985
|
+
{
|
|
1986
|
+
// Nemotron 3 Ultra 550B-A55B — the largest free model ever listed, 1M ctx,
|
|
1987
|
+
// reachable ONLY through OpenRouter's $0 pool (build.nvidia.com answers 503).
|
|
1988
|
+
// Deliberately LOW in the cascade: 16.8s on the tools probe, and blockrun
|
|
1989
|
+
// measured 3 of 15 calls coming back as an HTTP 200 carrying an upstream
|
|
1990
|
+
// 502/503 error object instead of choices.
|
|
1991
|
+
id: "free/nemotron-3-ultra-550b",
|
|
1992
|
+
name: "[Free] Nemotron 3 Ultra 550B",
|
|
1993
|
+
version: "3-ultra-550b",
|
|
1994
|
+
inputPrice: 0,
|
|
1995
|
+
outputPrice: 0,
|
|
1996
|
+
contextWindow: 1e6,
|
|
1997
|
+
maxOutput: 16384,
|
|
1998
|
+
reasoning: true
|
|
1999
|
+
},
|
|
2000
|
+
{
|
|
2001
|
+
// Meta Llama 3.2 11B Vision — restores a free Llama after nemotron-super-49b
|
|
2002
|
+
// (Llama-3.3-based) hit NVIDIA's 410 EOL. A 12-model sweep found exactly two
|
|
2003
|
+
// survivors and only the 11B finishes a real completion. Older than the rest
|
|
2004
|
+
// of the tier and deliberately so: it is a real Llama that actually answers.
|
|
2005
|
+
// Slowest in the tier (~18 tok/s) — last rung of the cascade.
|
|
2006
|
+
id: "free/llama-3.2-11b-vision",
|
|
2007
|
+
name: "[Free] Llama 3.2 11B Vision",
|
|
2008
|
+
version: "3.2-11b-vision",
|
|
2009
|
+
inputPrice: 0,
|
|
2010
|
+
outputPrice: 0,
|
|
2011
|
+
contextWindow: 128e3,
|
|
2012
|
+
maxOutput: 16384,
|
|
2013
|
+
vision: true
|
|
2014
|
+
},
|
|
2015
|
+
{
|
|
2016
|
+
// Cohere North Mini Code, on OpenRouter's $0 pool — 607ms median, the
|
|
2017
|
+
// fastest thing in the tier. Emits reasoning_content (content is clean once
|
|
2018
|
+
// the budget is large enough to finish, verified live).
|
|
2019
|
+
// NOTE: NOT an nvidia/* id upstream — see FREE_UPSTREAM_OVERRIDES in proxy.ts.
|
|
2020
|
+
id: "free/north-mini-code",
|
|
2021
|
+
name: "[Free] Cohere North Mini Code",
|
|
2022
|
+
version: "north-mini-code",
|
|
2023
|
+
inputPrice: 0,
|
|
2024
|
+
outputPrice: 0,
|
|
2025
|
+
contextWindow: 256e3,
|
|
2026
|
+
maxOutput: 16384,
|
|
2027
|
+
reasoning: true
|
|
2028
|
+
},
|
|
2029
|
+
{
|
|
2030
|
+
// Poolside Laguna XS 2.1 on OUR NVIDIA key (~161 tok/s). Deliberately not
|
|
2031
|
+
// the OpenRouter twin, which 429s on every attempt — so this rung and
|
|
2032
|
+
// north-mini-code sit on DIFFERENT capacity pools, which is why they are
|
|
2033
|
+
// adjacent in the cascade.
|
|
2034
|
+
// NOTE: NOT an nvidia/* id upstream — see FREE_UPSTREAM_OVERRIDES in proxy.ts.
|
|
2035
|
+
id: "free/laguna-xs-2.1",
|
|
2036
|
+
name: "[Free] Poolside Laguna XS 2.1",
|
|
2037
|
+
version: "xs-2.1",
|
|
2038
|
+
inputPrice: 0,
|
|
2039
|
+
outputPrice: 0,
|
|
2040
|
+
contextWindow: 131072,
|
|
2041
|
+
maxOutput: 16384
|
|
2042
|
+
},
|
|
1864
2043
|
// Z.AI GLM-5 Models
|
|
1865
2044
|
{
|
|
1866
|
-
//
|
|
2045
|
+
// Z.AI's flagship, live-probed by blockrun 2026-08-19 against api.z.ai
|
|
2046
|
+
// (real completion in 2s, content alongside reasoning tokens). $1.40/$4.40,
|
|
2047
|
+
// cached input $0.26, off the international USD price list.
|
|
2048
|
+
// maxOutput is 131072, NOT the 1M context: that is the hard ceiling the API
|
|
2049
|
+
// enforces (error 1210 above it), the same on every GLM-5 SKU.
|
|
2050
|
+
// Thinking is ALWAYS ON here and cannot be disabled.
|
|
2051
|
+
id: "zai/glm-5.3",
|
|
2052
|
+
name: "GLM-5.3",
|
|
2053
|
+
version: "5.3",
|
|
2054
|
+
inputPrice: 1.4,
|
|
2055
|
+
outputPrice: 4.4,
|
|
2056
|
+
contextWindow: 1e6,
|
|
2057
|
+
maxOutput: 131072,
|
|
2058
|
+
reasoning: true,
|
|
2059
|
+
toolCalling: true
|
|
2060
|
+
},
|
|
2061
|
+
{
|
|
2062
|
+
// Z.AI's first natively multimodal GLM-5 — 320B/18B MoE. blockrun probed
|
|
2063
|
+
// text, vision (base64 data URL → correct answer), tools
|
|
2064
|
+
// (finish_reason=tool_calls with well-formed arguments) and streaming live
|
|
2065
|
+
// on 2026-08-27 before listing it.
|
|
2066
|
+
//
|
|
2067
|
+
// MUST be in this catalog, not just router-core's: it is router-core's eco
|
|
2068
|
+
// MEDIUM and COMPLEX primary, and estimateAmount() returns undefined for an
|
|
2069
|
+
// id we do not carry — which makes the request skip the maxCostPerRun filter
|
|
2070
|
+
// AND never accumulate into session cost. An uncatalogued routing target is
|
|
2071
|
+
// a cost-cap hole, not a logging gap.
|
|
2072
|
+
//
|
|
2073
|
+
// Price is the LIST rate. Z.AI is running a 50% launch promo ($0.075/$0.25)
|
|
2074
|
+
// that ENDS 2026-09-09; listing the promo rate would put us under COGS the
|
|
2075
|
+
// morning it lapses. Thinking is always on, as on glm-5.3.
|
|
2076
|
+
id: "zai/glm-5.3-flash",
|
|
2077
|
+
name: "GLM-5.3 Flash",
|
|
2078
|
+
version: "5.3-flash",
|
|
2079
|
+
inputPrice: 0.15,
|
|
2080
|
+
outputPrice: 0.5,
|
|
2081
|
+
contextWindow: 1e6,
|
|
2082
|
+
maxOutput: 131072,
|
|
2083
|
+
reasoning: true,
|
|
2084
|
+
vision: true,
|
|
2085
|
+
toolCalling: true
|
|
2086
|
+
},
|
|
2087
|
+
{
|
|
2088
|
+
// Launched 2026-06-16. Was Z.AI's flagship until glm-5.3 (above) took the
|
|
2089
|
+
// slot on 2026-08-19. 1M-token context,
|
|
1867
2090
|
// beats GPT-5.5 on long-horizon coding at a fraction of the cost.
|
|
1868
2091
|
// Paid per-token at $1.40/$4.40 (same as glm-5.1, cached $0.26).
|
|
1869
2092
|
id: "zai/glm-5.2",
|
|
@@ -1872,7 +2095,7 @@ var init_models = __esm({
|
|
|
1872
2095
|
inputPrice: 1.4,
|
|
1873
2096
|
outputPrice: 4.4,
|
|
1874
2097
|
contextWindow: 1e6,
|
|
1875
|
-
maxOutput:
|
|
2098
|
+
maxOutput: 131072,
|
|
1876
2099
|
reasoning: true,
|
|
1877
2100
|
toolCalling: true
|
|
1878
2101
|
},
|
|
@@ -29310,8 +29533,8 @@ var init_parseUtil = __esm({
|
|
|
29310
29533
|
init_errors4();
|
|
29311
29534
|
init_en();
|
|
29312
29535
|
makeIssue = (params) => {
|
|
29313
|
-
const { data, path:
|
|
29314
|
-
const fullPath = [...
|
|
29536
|
+
const { data, path: path5, errorMaps, issueData } = params;
|
|
29537
|
+
const fullPath = [...path5, ...issueData.path || []];
|
|
29315
29538
|
const fullIssue = {
|
|
29316
29539
|
...issueData,
|
|
29317
29540
|
path: fullPath
|
|
@@ -29622,11 +29845,11 @@ var init_types = __esm({
|
|
|
29622
29845
|
init_parseUtil();
|
|
29623
29846
|
init_util();
|
|
29624
29847
|
ParseInputLazyPath = class {
|
|
29625
|
-
constructor(parent, value,
|
|
29848
|
+
constructor(parent, value, path5, key2) {
|
|
29626
29849
|
this._cachedPath = [];
|
|
29627
29850
|
this.parent = parent;
|
|
29628
29851
|
this.data = value;
|
|
29629
|
-
this._path =
|
|
29852
|
+
this._path = path5;
|
|
29630
29853
|
this._key = key2;
|
|
29631
29854
|
}
|
|
29632
29855
|
get path() {
|
|
@@ -34035,6 +34258,613 @@ var init_max_tokens = __esm({
|
|
|
34035
34258
|
}
|
|
34036
34259
|
});
|
|
34037
34260
|
|
|
34261
|
+
// src/fs-read.ts
|
|
34262
|
+
import { open } from "fs/promises";
|
|
34263
|
+
import { openSync, readSync, closeSync, fstatSync } from "fs";
|
|
34264
|
+
async function readTextFile(filePath) {
|
|
34265
|
+
const fh = await open(filePath, "r");
|
|
34266
|
+
try {
|
|
34267
|
+
const size5 = (await fh.stat()).size;
|
|
34268
|
+
const buf = Buffer.alloc(size5);
|
|
34269
|
+
let offset = 0;
|
|
34270
|
+
while (offset < size5) {
|
|
34271
|
+
const { bytesRead } = await fh.read(buf, offset, size5 - offset, offset);
|
|
34272
|
+
if (bytesRead === 0) break;
|
|
34273
|
+
offset += bytesRead;
|
|
34274
|
+
}
|
|
34275
|
+
return buf.subarray(0, offset).toString("utf-8");
|
|
34276
|
+
} finally {
|
|
34277
|
+
await fh.close();
|
|
34278
|
+
}
|
|
34279
|
+
}
|
|
34280
|
+
function readTextFileSync(filePath) {
|
|
34281
|
+
const fd = openSync(filePath, "r");
|
|
34282
|
+
try {
|
|
34283
|
+
const size5 = fstatSync(fd).size;
|
|
34284
|
+
const buf = Buffer.alloc(size5);
|
|
34285
|
+
let offset = 0;
|
|
34286
|
+
while (offset < size5) {
|
|
34287
|
+
const bytesRead = readSync(fd, buf, offset, size5 - offset, offset);
|
|
34288
|
+
if (bytesRead === 0) break;
|
|
34289
|
+
offset += bytesRead;
|
|
34290
|
+
}
|
|
34291
|
+
return buf.subarray(0, offset).toString("utf-8");
|
|
34292
|
+
} finally {
|
|
34293
|
+
closeSync(fd);
|
|
34294
|
+
}
|
|
34295
|
+
}
|
|
34296
|
+
var init_fs_read = __esm({
|
|
34297
|
+
"src/fs-read.ts"() {
|
|
34298
|
+
"use strict";
|
|
34299
|
+
}
|
|
34300
|
+
});
|
|
34301
|
+
|
|
34302
|
+
// src/spend-control.ts
|
|
34303
|
+
import * as fs from "fs";
|
|
34304
|
+
import * as path from "path";
|
|
34305
|
+
import { homedir } from "os";
|
|
34306
|
+
function normalizePayee(value) {
|
|
34307
|
+
return EVM_ADDRESS.test(value) ? value.toLowerCase() : value;
|
|
34308
|
+
}
|
|
34309
|
+
function isAddressList(list) {
|
|
34310
|
+
return ADDRESS_LISTS.includes(list);
|
|
34311
|
+
}
|
|
34312
|
+
function normalizePolicyValues(list, values) {
|
|
34313
|
+
return isAddressList(list) ? values.map(normalizePayee) : [...values];
|
|
34314
|
+
}
|
|
34315
|
+
function isValidPolicyValues(values) {
|
|
34316
|
+
return Array.isArray(values) && values.every((v) => typeof v === "string" && v.length > 0);
|
|
34317
|
+
}
|
|
34318
|
+
function isPolicyList(value) {
|
|
34319
|
+
return POLICY_LISTS.includes(value);
|
|
34320
|
+
}
|
|
34321
|
+
function cloneLimits(limits) {
|
|
34322
|
+
const clone = { ...limits };
|
|
34323
|
+
for (const key2 of POLICY_LISTS) {
|
|
34324
|
+
const val = limits[key2];
|
|
34325
|
+
if (val !== void 0) {
|
|
34326
|
+
clone[key2] = [...val];
|
|
34327
|
+
}
|
|
34328
|
+
}
|
|
34329
|
+
return clone;
|
|
34330
|
+
}
|
|
34331
|
+
function parseQuotedAmountUsd(selected) {
|
|
34332
|
+
const raw = selected.amount ?? selected.maxAmountRequired;
|
|
34333
|
+
if (typeof raw !== "string" || !CANONICAL_AMOUNT.test(raw)) {
|
|
34334
|
+
return void 0;
|
|
34335
|
+
}
|
|
34336
|
+
const micros = Number(raw);
|
|
34337
|
+
if (!Number.isSafeInteger(micros)) {
|
|
34338
|
+
return void 0;
|
|
34339
|
+
}
|
|
34340
|
+
return micros / 1e6;
|
|
34341
|
+
}
|
|
34342
|
+
function assertSpendPolicyAllows(control, selected) {
|
|
34343
|
+
const quoted = parseQuotedAmountUsd(selected);
|
|
34344
|
+
if (quoted === void 0 && control.hasAmountLimits()) {
|
|
34345
|
+
throw new SpendPolicyError(
|
|
34346
|
+
`Payment quote carries no usable amount (${JSON.stringify(
|
|
34347
|
+
selected.amount ?? selected.maxAmountRequired
|
|
34348
|
+
)}); refusing to sign against a configured spend limit`
|
|
34349
|
+
);
|
|
34350
|
+
}
|
|
34351
|
+
const estimatedCost2 = quoted ?? 0;
|
|
34352
|
+
const result = control.check(estimatedCost2, {
|
|
34353
|
+
payTo: selected.payTo,
|
|
34354
|
+
network: selected.network,
|
|
34355
|
+
asset: selected.asset
|
|
34356
|
+
});
|
|
34357
|
+
if (!result.allowed) {
|
|
34358
|
+
throw new SpendPolicyError(result.reason ?? "blocked by spend policy", {
|
|
34359
|
+
blockedBy: result.blockedBy,
|
|
34360
|
+
blockedByPolicy: result.blockedByPolicy
|
|
34361
|
+
});
|
|
34362
|
+
}
|
|
34363
|
+
if (!control.hasAggregateLimits()) {
|
|
34364
|
+
return void 0;
|
|
34365
|
+
}
|
|
34366
|
+
return control.reserve(estimatedCost2);
|
|
34367
|
+
}
|
|
34368
|
+
function registerSpendPolicyHook(x402, control) {
|
|
34369
|
+
const reservations = /* @__PURE__ */ new WeakMap();
|
|
34370
|
+
x402.onBeforePaymentCreation(async (ctx) => {
|
|
34371
|
+
const selected = ctx.selectedRequirements;
|
|
34372
|
+
const reservationId = assertSpendPolicyAllows(control, selected);
|
|
34373
|
+
if (reservationId !== void 0) {
|
|
34374
|
+
reservations.set(ctx.selectedRequirements, reservationId);
|
|
34375
|
+
}
|
|
34376
|
+
});
|
|
34377
|
+
x402.onAfterPaymentCreation(async (ctx) => {
|
|
34378
|
+
const key2 = ctx.selectedRequirements;
|
|
34379
|
+
const id2 = reservations.get(key2);
|
|
34380
|
+
if (id2 !== void 0) {
|
|
34381
|
+
reservations.delete(key2);
|
|
34382
|
+
control.settleReservation(id2, { action: "x402 payment" });
|
|
34383
|
+
}
|
|
34384
|
+
});
|
|
34385
|
+
x402.onPaymentCreationFailure(async (ctx) => {
|
|
34386
|
+
const key2 = ctx.selectedRequirements;
|
|
34387
|
+
const id2 = reservations.get(key2);
|
|
34388
|
+
if (id2 !== void 0) {
|
|
34389
|
+
reservations.delete(key2);
|
|
34390
|
+
control.releaseReservation(id2);
|
|
34391
|
+
}
|
|
34392
|
+
});
|
|
34393
|
+
}
|
|
34394
|
+
function formatDuration(seconds) {
|
|
34395
|
+
if (seconds < 60) {
|
|
34396
|
+
return `${seconds}s`;
|
|
34397
|
+
} else if (seconds < 3600) {
|
|
34398
|
+
const mins = Math.ceil(seconds / 60);
|
|
34399
|
+
return `${mins} min`;
|
|
34400
|
+
} else {
|
|
34401
|
+
const hours = Math.floor(seconds / 3600);
|
|
34402
|
+
const mins = Math.ceil(seconds % 3600 / 60);
|
|
34403
|
+
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
34404
|
+
}
|
|
34405
|
+
}
|
|
34406
|
+
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;
|
|
34407
|
+
var init_spend_control = __esm({
|
|
34408
|
+
"src/spend-control.ts"() {
|
|
34409
|
+
"use strict";
|
|
34410
|
+
init_fs_read();
|
|
34411
|
+
WALLET_DIR = path.join(homedir(), ".openclaw", "blockrun");
|
|
34412
|
+
HOUR_MS = 60 * 60 * 1e3;
|
|
34413
|
+
DAY_MS = 24 * HOUR_MS;
|
|
34414
|
+
CAIP2_BASE = "eip155:8453";
|
|
34415
|
+
CAIP2_SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d";
|
|
34416
|
+
POLICY_LISTS = [
|
|
34417
|
+
"allowedPayees",
|
|
34418
|
+
"blockedPayees",
|
|
34419
|
+
"allowedNetworks",
|
|
34420
|
+
"allowedAssets"
|
|
34421
|
+
];
|
|
34422
|
+
ADDRESS_LISTS = ["allowedPayees", "blockedPayees", "allowedAssets"];
|
|
34423
|
+
EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
34424
|
+
MalformedSpendPolicyError = class extends Error {
|
|
34425
|
+
constructor(key2) {
|
|
34426
|
+
super(
|
|
34427
|
+
`[ClawRouter] refusing to load spending.json: ${key2} is malformed; a corrupted policy file must not widen what the agent may pay`
|
|
34428
|
+
);
|
|
34429
|
+
this.name = "MalformedSpendPolicyError";
|
|
34430
|
+
}
|
|
34431
|
+
};
|
|
34432
|
+
FileSpendControlStorage = class {
|
|
34433
|
+
spendingFile;
|
|
34434
|
+
constructor() {
|
|
34435
|
+
this.spendingFile = path.join(WALLET_DIR, "spending.json");
|
|
34436
|
+
}
|
|
34437
|
+
load() {
|
|
34438
|
+
try {
|
|
34439
|
+
if (fs.existsSync(this.spendingFile)) {
|
|
34440
|
+
const data = JSON.parse(readTextFileSync(this.spendingFile));
|
|
34441
|
+
const rawLimits = data.limits ?? {};
|
|
34442
|
+
const rawHistory = data.history ?? [];
|
|
34443
|
+
const limits = {};
|
|
34444
|
+
for (const key2 of ["perRequest", "hourly", "daily", "session"]) {
|
|
34445
|
+
const val = rawLimits[key2];
|
|
34446
|
+
if (typeof val === "number" && val > 0 && Number.isFinite(val)) {
|
|
34447
|
+
limits[key2] = val;
|
|
34448
|
+
}
|
|
34449
|
+
}
|
|
34450
|
+
for (const key2 of POLICY_LISTS) {
|
|
34451
|
+
if (!Object.prototype.hasOwnProperty.call(rawLimits, key2)) continue;
|
|
34452
|
+
const val = rawLimits[key2];
|
|
34453
|
+
if (!isValidPolicyValues(val)) {
|
|
34454
|
+
throw new MalformedSpendPolicyError(key2);
|
|
34455
|
+
}
|
|
34456
|
+
if (val.length === 0) continue;
|
|
34457
|
+
limits[key2] = normalizePolicyValues(key2, val);
|
|
34458
|
+
}
|
|
34459
|
+
const history = [];
|
|
34460
|
+
if (Array.isArray(rawHistory)) {
|
|
34461
|
+
for (const r2 of rawHistory) {
|
|
34462
|
+
if (typeof r2?.timestamp === "number" && typeof r2?.amount === "number" && Number.isFinite(r2.timestamp) && Number.isFinite(r2.amount) && r2.amount >= 0) {
|
|
34463
|
+
history.push({
|
|
34464
|
+
timestamp: r2.timestamp,
|
|
34465
|
+
amount: r2.amount,
|
|
34466
|
+
model: typeof r2.model === "string" ? r2.model : void 0,
|
|
34467
|
+
action: typeof r2.action === "string" ? r2.action : void 0
|
|
34468
|
+
});
|
|
34469
|
+
}
|
|
34470
|
+
}
|
|
34471
|
+
}
|
|
34472
|
+
return { limits, history };
|
|
34473
|
+
}
|
|
34474
|
+
} catch (err) {
|
|
34475
|
+
if (err instanceof MalformedSpendPolicyError) {
|
|
34476
|
+
throw err;
|
|
34477
|
+
}
|
|
34478
|
+
console.error(
|
|
34479
|
+
`[ClawRouter] Failed to load spending data, starting fresh (any configured spend policy is NOT in effect until this file is repaired): ${err}`
|
|
34480
|
+
);
|
|
34481
|
+
}
|
|
34482
|
+
return null;
|
|
34483
|
+
}
|
|
34484
|
+
save(data) {
|
|
34485
|
+
try {
|
|
34486
|
+
if (!fs.existsSync(WALLET_DIR)) {
|
|
34487
|
+
fs.mkdirSync(WALLET_DIR, { recursive: true, mode: 448 });
|
|
34488
|
+
}
|
|
34489
|
+
const tmp = `${this.spendingFile}.${process.pid}.tmp`;
|
|
34490
|
+
fs.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
34491
|
+
fs.renameSync(tmp, this.spendingFile);
|
|
34492
|
+
} catch (err) {
|
|
34493
|
+
console.error(`[ClawRouter] Failed to save spending data: ${err}`);
|
|
34494
|
+
}
|
|
34495
|
+
}
|
|
34496
|
+
/**
|
|
34497
|
+
* Persist history while leaving the stored limits exactly as they are on
|
|
34498
|
+
* disk. Recording spend must not rewrite policy: the proxy reads limits once
|
|
34499
|
+
* at startup, so writing its in-memory copy back on every payment would
|
|
34500
|
+
* erase an operator's hand-edit to spending.json seconds after they made it.
|
|
34501
|
+
*/
|
|
34502
|
+
saveHistory(history) {
|
|
34503
|
+
let storedLimits = {};
|
|
34504
|
+
try {
|
|
34505
|
+
const current = this.load();
|
|
34506
|
+
if (current) storedLimits = current.limits;
|
|
34507
|
+
} catch {
|
|
34508
|
+
return;
|
|
34509
|
+
}
|
|
34510
|
+
this.save({ limits: storedLimits, history });
|
|
34511
|
+
}
|
|
34512
|
+
};
|
|
34513
|
+
InMemorySpendControlStorage = class {
|
|
34514
|
+
data = null;
|
|
34515
|
+
load() {
|
|
34516
|
+
return this.data ? {
|
|
34517
|
+
limits: cloneLimits(this.data.limits),
|
|
34518
|
+
history: this.data.history.map((r2) => ({ ...r2 }))
|
|
34519
|
+
} : null;
|
|
34520
|
+
}
|
|
34521
|
+
save(data) {
|
|
34522
|
+
this.data = {
|
|
34523
|
+
limits: cloneLimits(data.limits),
|
|
34524
|
+
history: data.history.map((r2) => ({ ...r2 }))
|
|
34525
|
+
};
|
|
34526
|
+
}
|
|
34527
|
+
};
|
|
34528
|
+
RESERVATION_TTL_MS = 2 * 60 * 1e3;
|
|
34529
|
+
SpendControl = class {
|
|
34530
|
+
limits = {};
|
|
34531
|
+
history = [];
|
|
34532
|
+
sessionSpent = 0;
|
|
34533
|
+
sessionCalls = 0;
|
|
34534
|
+
pending = /* @__PURE__ */ new Map();
|
|
34535
|
+
reservationSeq = 0;
|
|
34536
|
+
/** Limits we loaded and have not changed; history-only saves must not clobber operator edits. */
|
|
34537
|
+
limitsDirty = false;
|
|
34538
|
+
/** Set when spending.json held an unusable policy list: refuse every payment. */
|
|
34539
|
+
policyFileBroken;
|
|
34540
|
+
storage;
|
|
34541
|
+
now;
|
|
34542
|
+
constructor(options) {
|
|
34543
|
+
this.storage = options?.storage ?? new FileSpendControlStorage();
|
|
34544
|
+
this.now = options?.now ?? (() => Date.now());
|
|
34545
|
+
this.load();
|
|
34546
|
+
}
|
|
34547
|
+
setLimit(window2, amount) {
|
|
34548
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
34549
|
+
throw new Error("Limit must be a finite positive number");
|
|
34550
|
+
}
|
|
34551
|
+
this.limits[window2] = amount;
|
|
34552
|
+
this.limitsDirty = true;
|
|
34553
|
+
this.save();
|
|
34554
|
+
}
|
|
34555
|
+
clearLimit(window2) {
|
|
34556
|
+
delete this.limits[window2];
|
|
34557
|
+
this.limitsDirty = true;
|
|
34558
|
+
this.save();
|
|
34559
|
+
}
|
|
34560
|
+
setPolicy(list, values) {
|
|
34561
|
+
if (!isPolicyList(list)) {
|
|
34562
|
+
throw new Error(`Unknown policy list: ${String(list)}`);
|
|
34563
|
+
}
|
|
34564
|
+
if (!isValidPolicyValues(values) || values.length === 0) {
|
|
34565
|
+
throw new Error("Policy list must be a non-empty array of non-empty strings");
|
|
34566
|
+
}
|
|
34567
|
+
this.limits[list] = normalizePolicyValues(list, values);
|
|
34568
|
+
this.limitsDirty = true;
|
|
34569
|
+
this.save();
|
|
34570
|
+
}
|
|
34571
|
+
clearPolicy(list) {
|
|
34572
|
+
if (!isPolicyList(list)) {
|
|
34573
|
+
throw new Error(`Unknown policy list: ${String(list)}`);
|
|
34574
|
+
}
|
|
34575
|
+
delete this.limits[list];
|
|
34576
|
+
this.limitsDirty = true;
|
|
34577
|
+
this.save();
|
|
34578
|
+
}
|
|
34579
|
+
getLimits() {
|
|
34580
|
+
return cloneLimits(this.limits);
|
|
34581
|
+
}
|
|
34582
|
+
check(estimatedCost2, counterparty) {
|
|
34583
|
+
if (this.policyFileBroken !== void 0) {
|
|
34584
|
+
return {
|
|
34585
|
+
allowed: false,
|
|
34586
|
+
reason: `Spend policy is unreadable, refusing all payments: ${this.policyFileBroken}`
|
|
34587
|
+
};
|
|
34588
|
+
}
|
|
34589
|
+
const payeePolicySet = this.limits.blockedPayees && this.limits.blockedPayees.length > 0 || this.limits.allowedPayees && this.limits.allowedPayees.length > 0;
|
|
34590
|
+
if (payeePolicySet) {
|
|
34591
|
+
if (counterparty?.payTo === void 0) {
|
|
34592
|
+
return {
|
|
34593
|
+
allowed: false,
|
|
34594
|
+
blockedByPolicy: this.limits.blockedPayees?.length ? "blockedPayees" : "allowedPayees",
|
|
34595
|
+
reason: "Payee policy is configured but no payTo was provided to check()"
|
|
34596
|
+
};
|
|
34597
|
+
}
|
|
34598
|
+
const payTo = normalizePayee(counterparty.payTo);
|
|
34599
|
+
if (this.limits.blockedPayees?.includes(payTo)) {
|
|
34600
|
+
return {
|
|
34601
|
+
allowed: false,
|
|
34602
|
+
blockedByPolicy: "blockedPayees",
|
|
34603
|
+
reason: `Payee is blocked by policy: ${counterparty.payTo}`
|
|
34604
|
+
};
|
|
34605
|
+
}
|
|
34606
|
+
if (this.limits.allowedPayees && this.limits.allowedPayees.length > 0 && !this.limits.allowedPayees.includes(payTo)) {
|
|
34607
|
+
return {
|
|
34608
|
+
allowed: false,
|
|
34609
|
+
blockedByPolicy: "allowedPayees",
|
|
34610
|
+
reason: `Payee is not in the configured allowlist: ${counterparty.payTo}`
|
|
34611
|
+
};
|
|
34612
|
+
}
|
|
34613
|
+
}
|
|
34614
|
+
if (this.limits.allowedNetworks && this.limits.allowedNetworks.length > 0) {
|
|
34615
|
+
if (counterparty?.network === void 0) {
|
|
34616
|
+
return {
|
|
34617
|
+
allowed: false,
|
|
34618
|
+
blockedByPolicy: "allowedNetworks",
|
|
34619
|
+
reason: "Network policy is configured but no network was provided to check()"
|
|
34620
|
+
};
|
|
34621
|
+
}
|
|
34622
|
+
if (!this.limits.allowedNetworks.includes(counterparty.network)) {
|
|
34623
|
+
return {
|
|
34624
|
+
allowed: false,
|
|
34625
|
+
blockedByPolicy: "allowedNetworks",
|
|
34626
|
+
reason: `Network is not in the configured allowlist: ${counterparty.network}`
|
|
34627
|
+
};
|
|
34628
|
+
}
|
|
34629
|
+
}
|
|
34630
|
+
if (this.limits.allowedAssets && this.limits.allowedAssets.length > 0) {
|
|
34631
|
+
if (counterparty?.asset === void 0) {
|
|
34632
|
+
return {
|
|
34633
|
+
allowed: false,
|
|
34634
|
+
blockedByPolicy: "allowedAssets",
|
|
34635
|
+
reason: "Asset policy is configured but no asset was provided to check()"
|
|
34636
|
+
};
|
|
34637
|
+
}
|
|
34638
|
+
if (!this.limits.allowedAssets.includes(normalizePayee(counterparty.asset))) {
|
|
34639
|
+
return {
|
|
34640
|
+
allowed: false,
|
|
34641
|
+
blockedByPolicy: "allowedAssets",
|
|
34642
|
+
reason: `Asset is not in the configured allowlist: ${counterparty.asset}`
|
|
34643
|
+
};
|
|
34644
|
+
}
|
|
34645
|
+
}
|
|
34646
|
+
const now2 = this.now();
|
|
34647
|
+
if (this.limits.perRequest !== void 0) {
|
|
34648
|
+
if (estimatedCost2 > this.limits.perRequest) {
|
|
34649
|
+
return {
|
|
34650
|
+
allowed: false,
|
|
34651
|
+
blockedBy: "perRequest",
|
|
34652
|
+
remaining: this.limits.perRequest,
|
|
34653
|
+
reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
|
|
34654
|
+
};
|
|
34655
|
+
}
|
|
34656
|
+
}
|
|
34657
|
+
if (this.limits.hourly !== void 0) {
|
|
34658
|
+
const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
34659
|
+
const remaining = this.limits.hourly - hourlySpent;
|
|
34660
|
+
if (estimatedCost2 > remaining) {
|
|
34661
|
+
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
|
|
34662
|
+
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
|
|
34663
|
+
return {
|
|
34664
|
+
allowed: false,
|
|
34665
|
+
blockedBy: "hourly",
|
|
34666
|
+
remaining,
|
|
34667
|
+
reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
|
|
34668
|
+
resetIn
|
|
34669
|
+
};
|
|
34670
|
+
}
|
|
34671
|
+
}
|
|
34672
|
+
if (this.limits.daily !== void 0) {
|
|
34673
|
+
const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
34674
|
+
const remaining = this.limits.daily - dailySpent;
|
|
34675
|
+
if (estimatedCost2 > remaining) {
|
|
34676
|
+
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
|
|
34677
|
+
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
|
|
34678
|
+
return {
|
|
34679
|
+
allowed: false,
|
|
34680
|
+
blockedBy: "daily",
|
|
34681
|
+
remaining,
|
|
34682
|
+
reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
|
|
34683
|
+
resetIn
|
|
34684
|
+
};
|
|
34685
|
+
}
|
|
34686
|
+
}
|
|
34687
|
+
if (this.limits.session !== void 0) {
|
|
34688
|
+
const sessionSpent = this.sessionSpent + this.pendingTotal();
|
|
34689
|
+
const remaining = this.limits.session - sessionSpent;
|
|
34690
|
+
if (estimatedCost2 > remaining) {
|
|
34691
|
+
return {
|
|
34692
|
+
allowed: false,
|
|
34693
|
+
blockedBy: "session",
|
|
34694
|
+
remaining,
|
|
34695
|
+
reason: `Session limit exceeded: $${(sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
|
|
34696
|
+
};
|
|
34697
|
+
}
|
|
34698
|
+
}
|
|
34699
|
+
return { allowed: true };
|
|
34700
|
+
}
|
|
34701
|
+
record(amount, metadata) {
|
|
34702
|
+
if (!Number.isFinite(amount) || amount < 0) {
|
|
34703
|
+
throw new Error("Record amount must be a non-negative finite number");
|
|
34704
|
+
}
|
|
34705
|
+
const record = {
|
|
34706
|
+
timestamp: this.now(),
|
|
34707
|
+
amount,
|
|
34708
|
+
model: metadata?.model,
|
|
34709
|
+
action: metadata?.action
|
|
34710
|
+
};
|
|
34711
|
+
this.history.push(record);
|
|
34712
|
+
this.sessionSpent += amount;
|
|
34713
|
+
this.sessionCalls += 1;
|
|
34714
|
+
this.cleanup();
|
|
34715
|
+
this.save();
|
|
34716
|
+
}
|
|
34717
|
+
/** True when any window that this module can compare an amount against is set. */
|
|
34718
|
+
hasAmountLimits() {
|
|
34719
|
+
return this.limits.perRequest !== void 0 || this.limits.hourly !== void 0 || this.limits.daily !== void 0 || this.limits.session !== void 0;
|
|
34720
|
+
}
|
|
34721
|
+
/** True when a window spans more than one request, so reservations matter. */
|
|
34722
|
+
hasAggregateLimits() {
|
|
34723
|
+
return this.limits.hourly !== void 0 || this.limits.daily !== void 0 || this.limits.session !== void 0;
|
|
34724
|
+
}
|
|
34725
|
+
/**
|
|
34726
|
+
* Hold `amount` against the aggregate windows before a payment is signed.
|
|
34727
|
+
*
|
|
34728
|
+
* Reservations live in memory only and are never persisted: an unsettled
|
|
34729
|
+
* reservation is not spend, and writing it to disk is what made a failed
|
|
34730
|
+
* signer permanently consume budget. They expire on their own so a caller
|
|
34731
|
+
* that never settles or releases (process killed mid-payment, a transport
|
|
34732
|
+
* that hangs past the payment timeout) cannot wedge the window shut.
|
|
34733
|
+
*/
|
|
34734
|
+
reserve(amount) {
|
|
34735
|
+
if (!Number.isFinite(amount) || amount < 0) {
|
|
34736
|
+
throw new Error("Reservation amount must be a non-negative finite number");
|
|
34737
|
+
}
|
|
34738
|
+
const id2 = `${this.now()}-${this.reservationSeq += 1}`;
|
|
34739
|
+
this.pending.set(id2, { amount, expiresAt: this.now() + RESERVATION_TTL_MS });
|
|
34740
|
+
return id2;
|
|
34741
|
+
}
|
|
34742
|
+
/** Convert a reservation into recorded spend (the payment was signed). */
|
|
34743
|
+
settleReservation(id2, metadata) {
|
|
34744
|
+
const held = this.pending.get(id2);
|
|
34745
|
+
if (!held) return;
|
|
34746
|
+
this.pending.delete(id2);
|
|
34747
|
+
this.record(held.amount, metadata);
|
|
34748
|
+
}
|
|
34749
|
+
/** Drop a reservation without recording spend (the payment was never signed). */
|
|
34750
|
+
releaseReservation(id2) {
|
|
34751
|
+
this.pending.delete(id2);
|
|
34752
|
+
}
|
|
34753
|
+
/** Total currently held but not yet settled. */
|
|
34754
|
+
pendingTotal() {
|
|
34755
|
+
this.expireReservations();
|
|
34756
|
+
let total = 0;
|
|
34757
|
+
for (const held of this.pending.values()) {
|
|
34758
|
+
total += held.amount;
|
|
34759
|
+
}
|
|
34760
|
+
return total;
|
|
34761
|
+
}
|
|
34762
|
+
expireReservations() {
|
|
34763
|
+
const now2 = this.now();
|
|
34764
|
+
for (const [id2, held] of this.pending) {
|
|
34765
|
+
if (held.expiresAt <= now2) {
|
|
34766
|
+
this.pending.delete(id2);
|
|
34767
|
+
}
|
|
34768
|
+
}
|
|
34769
|
+
}
|
|
34770
|
+
getSpendingInWindow(from15, to) {
|
|
34771
|
+
const recorded = this.history.filter((r2) => r2.timestamp >= from15 && r2.timestamp <= to).reduce((sum, r2) => sum + r2.amount, 0);
|
|
34772
|
+
return recorded + (to >= this.now() ? this.pendingTotal() : 0);
|
|
34773
|
+
}
|
|
34774
|
+
getSpending(window2) {
|
|
34775
|
+
const now2 = this.now();
|
|
34776
|
+
switch (window2) {
|
|
34777
|
+
case "hourly":
|
|
34778
|
+
return this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
34779
|
+
case "daily":
|
|
34780
|
+
return this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
34781
|
+
case "session":
|
|
34782
|
+
return this.sessionSpent + this.pendingTotal();
|
|
34783
|
+
}
|
|
34784
|
+
}
|
|
34785
|
+
getRemaining(window2) {
|
|
34786
|
+
const limit = this.limits[window2];
|
|
34787
|
+
if (limit === void 0) return null;
|
|
34788
|
+
return Math.max(0, limit - this.getSpending(window2));
|
|
34789
|
+
}
|
|
34790
|
+
getStatus() {
|
|
34791
|
+
const now2 = this.now();
|
|
34792
|
+
const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
34793
|
+
const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
34794
|
+
return {
|
|
34795
|
+
limits: cloneLimits(this.limits),
|
|
34796
|
+
spending: {
|
|
34797
|
+
hourly: hourlySpent,
|
|
34798
|
+
daily: dailySpent,
|
|
34799
|
+
session: this.sessionSpent
|
|
34800
|
+
},
|
|
34801
|
+
remaining: {
|
|
34802
|
+
hourly: this.limits.hourly !== void 0 ? this.limits.hourly - hourlySpent : null,
|
|
34803
|
+
daily: this.limits.daily !== void 0 ? this.limits.daily - dailySpent : null,
|
|
34804
|
+
session: this.limits.session !== void 0 ? this.limits.session - (this.sessionSpent + this.pendingTotal()) : null
|
|
34805
|
+
},
|
|
34806
|
+
calls: this.sessionCalls
|
|
34807
|
+
};
|
|
34808
|
+
}
|
|
34809
|
+
getHistory(limit) {
|
|
34810
|
+
const records = [...this.history].reverse();
|
|
34811
|
+
return limit ? records.slice(0, limit) : records;
|
|
34812
|
+
}
|
|
34813
|
+
resetSession() {
|
|
34814
|
+
this.sessionSpent = 0;
|
|
34815
|
+
this.sessionCalls = 0;
|
|
34816
|
+
}
|
|
34817
|
+
cleanup() {
|
|
34818
|
+
const cutoff = this.now() - DAY_MS;
|
|
34819
|
+
this.history = this.history.filter((r2) => r2.timestamp >= cutoff);
|
|
34820
|
+
}
|
|
34821
|
+
save() {
|
|
34822
|
+
if (this.policyFileBroken !== void 0) {
|
|
34823
|
+
return;
|
|
34824
|
+
}
|
|
34825
|
+
if (!this.limitsDirty && this.storage.saveHistory) {
|
|
34826
|
+
this.storage.saveHistory([...this.history]);
|
|
34827
|
+
return;
|
|
34828
|
+
}
|
|
34829
|
+
this.storage.save({
|
|
34830
|
+
limits: cloneLimits(this.limits),
|
|
34831
|
+
history: [...this.history]
|
|
34832
|
+
});
|
|
34833
|
+
}
|
|
34834
|
+
load() {
|
|
34835
|
+
let data;
|
|
34836
|
+
try {
|
|
34837
|
+
data = this.storage.load();
|
|
34838
|
+
} catch (err) {
|
|
34839
|
+
if (!(err instanceof MalformedSpendPolicyError)) throw err;
|
|
34840
|
+
this.policyFileBroken = err.message;
|
|
34841
|
+
console.error(`[ClawRouter] ${err.message}`);
|
|
34842
|
+
console.error(
|
|
34843
|
+
"[ClawRouter] All paid requests will be refused until spending.json is repaired. Free models are unaffected."
|
|
34844
|
+
);
|
|
34845
|
+
return;
|
|
34846
|
+
}
|
|
34847
|
+
if (data) {
|
|
34848
|
+
this.limits = cloneLimits(data.limits);
|
|
34849
|
+
this.history = data.history;
|
|
34850
|
+
this.cleanup();
|
|
34851
|
+
}
|
|
34852
|
+
}
|
|
34853
|
+
};
|
|
34854
|
+
SpendPolicyError = class extends Error {
|
|
34855
|
+
blockedBy;
|
|
34856
|
+
blockedByPolicy;
|
|
34857
|
+
constructor(reason, blocked) {
|
|
34858
|
+
super(`Payment creation aborted: ${reason}`);
|
|
34859
|
+
this.name = "SpendPolicyError";
|
|
34860
|
+
this.blockedBy = blocked?.blockedBy;
|
|
34861
|
+
this.blockedByPolicy = blocked?.blockedByPolicy;
|
|
34862
|
+
}
|
|
34863
|
+
};
|
|
34864
|
+
CANONICAL_AMOUNT = /^\d+$/;
|
|
34865
|
+
}
|
|
34866
|
+
});
|
|
34867
|
+
|
|
34038
34868
|
// src/payment-preauth.ts
|
|
34039
34869
|
function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, options) {
|
|
34040
34870
|
const httpClient = new x402HTTPClient(client);
|
|
@@ -34079,8 +34909,11 @@ function createPayFetchWithPreAuth(baseFetch, client, ttlMs = DEFAULT_TTL_MS, op
|
|
|
34079
34909
|
return response2;
|
|
34080
34910
|
}
|
|
34081
34911
|
cache2.delete(cacheKey2);
|
|
34082
|
-
} catch {
|
|
34912
|
+
} catch (err) {
|
|
34083
34913
|
cache2.delete(cacheKey2);
|
|
34914
|
+
if (err instanceof SpendPolicyError) {
|
|
34915
|
+
throw err;
|
|
34916
|
+
}
|
|
34084
34917
|
}
|
|
34085
34918
|
}
|
|
34086
34919
|
const clonedRequest = request2.clone();
|
|
@@ -34124,6 +34957,7 @@ var init_payment_preauth = __esm({
|
|
|
34124
34957
|
"use strict";
|
|
34125
34958
|
init_esm4();
|
|
34126
34959
|
init_max_tokens();
|
|
34960
|
+
init_spend_control();
|
|
34127
34961
|
DEFAULT_TTL_MS = 36e5;
|
|
34128
34962
|
}
|
|
34129
34963
|
});
|
|
@@ -36222,6 +37056,13 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
36222
37056
|
supportsTools: true,
|
|
36223
37057
|
supportsVision: true
|
|
36224
37058
|
},
|
|
37059
|
+
"cohere/north-mini-code": {
|
|
37060
|
+
// supportsTools: not probed — fails closed
|
|
37061
|
+
contextWindow: 256e3,
|
|
37062
|
+
maxOutputTokens: 16384,
|
|
37063
|
+
supportsTools: false,
|
|
37064
|
+
supportsVision: false
|
|
37065
|
+
},
|
|
36225
37066
|
"deepseek/deepseek-chat": {
|
|
36226
37067
|
contextWindow: 1048576,
|
|
36227
37068
|
maxOutputTokens: 65536,
|
|
@@ -36312,8 +37153,15 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
36312
37153
|
supportsTools: true,
|
|
36313
37154
|
supportsVision: true
|
|
36314
37155
|
},
|
|
36315
|
-
"nvidia/
|
|
36316
|
-
// supportsTools:
|
|
37156
|
+
"nvidia/llama-3.2-11b-vision": {
|
|
37157
|
+
// supportsTools: not probed — fails closed
|
|
37158
|
+
contextWindow: 128e3,
|
|
37159
|
+
maxOutputTokens: 16384,
|
|
37160
|
+
supportsTools: false,
|
|
37161
|
+
supportsVision: true
|
|
37162
|
+
},
|
|
37163
|
+
"nvidia/nemotron-3-nano-30b": {
|
|
37164
|
+
// supportsTools: not probed — fails closed
|
|
36317
37165
|
contextWindow: 131072,
|
|
36318
37166
|
maxOutputTokens: 16384,
|
|
36319
37167
|
supportsTools: false,
|
|
@@ -36325,21 +37173,16 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
36325
37173
|
supportsTools: false,
|
|
36326
37174
|
supportsVision: true
|
|
36327
37175
|
},
|
|
36328
|
-
"nvidia/nemotron-
|
|
36329
|
-
// supportsTools:
|
|
36330
|
-
contextWindow:
|
|
36331
|
-
maxOutputTokens: 16384,
|
|
36332
|
-
supportsTools: false,
|
|
36333
|
-
supportsVision: true
|
|
36334
|
-
},
|
|
36335
|
-
"nvidia/nemotron-nano-9b-v2": {
|
|
36336
|
-
contextWindow: 131072,
|
|
37176
|
+
"nvidia/nemotron-3-ultra-550b": {
|
|
37177
|
+
// supportsTools: not probed — fails closed
|
|
37178
|
+
contextWindow: 1e6,
|
|
36337
37179
|
maxOutputTokens: 16384,
|
|
36338
37180
|
supportsTools: false,
|
|
36339
37181
|
supportsVision: false
|
|
36340
37182
|
},
|
|
36341
|
-
"nvidia/
|
|
36342
|
-
|
|
37183
|
+
"nvidia/nemotron-3.5-lightning": {
|
|
37184
|
+
// supportsTools: not probed — fails closed
|
|
37185
|
+
contextWindow: 1e6,
|
|
36343
37186
|
maxOutputTokens: 16384,
|
|
36344
37187
|
supportsTools: false,
|
|
36345
37188
|
supportsVision: false
|
|
@@ -36399,13 +37242,6 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
36399
37242
|
supportsTools: false,
|
|
36400
37243
|
supportsVision: true
|
|
36401
37244
|
},
|
|
36402
|
-
"openai/gpt-5.3": {
|
|
36403
|
-
// supportsTools: gateway unavailable at probe time — fails closed
|
|
36404
|
-
contextWindow: 128e3,
|
|
36405
|
-
maxOutputTokens: 128e3,
|
|
36406
|
-
supportsTools: false,
|
|
36407
|
-
supportsVision: true
|
|
36408
|
-
},
|
|
36409
37245
|
"openai/gpt-5.3-codex": {
|
|
36410
37246
|
// supportsTools: gateway unavailable at probe time — fails closed; override: 2026-08-29 probe: every request (6 plain + 3 tool attempts) returned a gateway 500, so the probe measured an incident, not the model. Codex's function calling is established by the 2026-07 Terminal-Bench / tau2 calibration trajectories in portfolio.ts. Hosts observing the 500s should drop it with RouterOptions.unavailableModels rather than this snapshot claiming the model cannot call tools.
|
|
36411
37247
|
contextWindow: 4e5,
|
|
@@ -36511,6 +37347,13 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
36511
37347
|
supportsTools: true,
|
|
36512
37348
|
supportsVision: false
|
|
36513
37349
|
},
|
|
37350
|
+
"poolside/laguna-xs-2.1": {
|
|
37351
|
+
// supportsTools: not probed — fails closed
|
|
37352
|
+
contextWindow: 131072,
|
|
37353
|
+
maxOutputTokens: 16384,
|
|
37354
|
+
supportsTools: false,
|
|
37355
|
+
supportsVision: false
|
|
37356
|
+
},
|
|
36514
37357
|
"qwen/qwen3.7-flash": {
|
|
36515
37358
|
contextWindow: 1e6,
|
|
36516
37359
|
maxOutputTokens: 65536,
|
|
@@ -38426,8 +39269,8 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
38426
39269
|
// $0.20/$1.25, 1M ctx
|
|
38427
39270
|
"google/gemini-2.5-flash-lite",
|
|
38428
39271
|
// $0.10/$0.40
|
|
38429
|
-
"nvidia/
|
|
38430
|
-
// FREE backstop — NVIDIA free tier (probed 2026-08-
|
|
39272
|
+
"nvidia/nemotron-3.5-lightning"
|
|
39273
|
+
// FREE backstop — NVIDIA free tier (probed 2026-08-30)
|
|
38431
39274
|
]
|
|
38432
39275
|
},
|
|
38433
39276
|
MEDIUM: {
|
|
@@ -38516,15 +39359,19 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
38516
39359
|
// Eco tier configs - absolute cheapest (blockrun/eco)
|
|
38517
39360
|
ecoTiers: {
|
|
38518
39361
|
SIMPLE: {
|
|
38519
|
-
primary: "nvidia/
|
|
38520
|
-
// FREE — NVIDIA free tier flagship
|
|
39362
|
+
primary: "nvidia/nemotron-3.5-lightning",
|
|
39363
|
+
// FREE — NVIDIA free tier flagship, 1M ctx
|
|
38521
39364
|
fallback: [
|
|
38522
|
-
"nvidia/nemotron-nano-
|
|
38523
|
-
// FREE —
|
|
39365
|
+
"nvidia/nemotron-3-nano-30b",
|
|
39366
|
+
// FREE — fastest free model (~121 tok/s)
|
|
38524
39367
|
// The free head keeps rotting with NVIDIA's hosting (deepseek-v4-flash
|
|
38525
39368
|
// 410 2026-08-12, seed-oss-36b 410 2026-08-03, gpt-oss-120b/20b 400
|
|
38526
|
-
// 2026-08-21
|
|
38527
|
-
//
|
|
39369
|
+
// 2026-08-21, and on 2026-08-30 FOUR of the five visible free models at
|
|
39370
|
+
// once — step-3.7-flash, nemotron-nano-9b-v2 and nemotron-nano-12b-v2-vl
|
|
39371
|
+
// all 410, mistral-nemotron hung). Each retirement retargets the two
|
|
39372
|
+
// free rungs to the current free tier; the paid rungs below never move.
|
|
39373
|
+
// The head follows blockrun's own redirect of the model it replaces, so
|
|
39374
|
+
// the router and the gateway never name different models.
|
|
38528
39375
|
"google/gemini-2.5-flash-lite",
|
|
38529
39376
|
// $0.10/$0.40 — cheapest paid rung
|
|
38530
39377
|
"zai/glm-5.3-flash",
|
|
@@ -38668,7 +39515,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
38668
39515
|
// strongest open-weight reasoner
|
|
38669
39516
|
"deepseek/deepseek-chat",
|
|
38670
39517
|
// Cheap, reliable
|
|
38671
|
-
"nvidia/
|
|
39518
|
+
"nvidia/nemotron-3.5-lightning"
|
|
38672
39519
|
// NVIDIA free ultimate backstop
|
|
38673
39520
|
]
|
|
38674
39521
|
},
|
|
@@ -38772,7 +39619,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
38772
39619
|
// retail high-risk 3/3
|
|
38773
39620
|
"deepseek/deepseek-chat",
|
|
38774
39621
|
// cheap, reliable
|
|
38775
|
-
"nvidia/
|
|
39622
|
+
"nvidia/nemotron-3.5-lightning"
|
|
38776
39623
|
// NVIDIA free ultimate backstop
|
|
38777
39624
|
]
|
|
38778
39625
|
},
|
|
@@ -38823,8 +39670,8 @@ var init_router = __esm({
|
|
|
38823
39670
|
|
|
38824
39671
|
// src/logger.ts
|
|
38825
39672
|
import { appendFile, mkdir } from "fs/promises";
|
|
38826
|
-
import { join as
|
|
38827
|
-
import { homedir } from "os";
|
|
39673
|
+
import { join as join3 } from "path";
|
|
39674
|
+
import { homedir as homedir2 } from "os";
|
|
38828
39675
|
async function ensureDir() {
|
|
38829
39676
|
if (dirReady) return;
|
|
38830
39677
|
await mkdir(LOG_DIR, { recursive: true });
|
|
@@ -38834,7 +39681,7 @@ async function logUsage(entry) {
|
|
|
38834
39681
|
try {
|
|
38835
39682
|
await ensureDir();
|
|
38836
39683
|
const date = entry.timestamp.slice(0, 10);
|
|
38837
|
-
const file =
|
|
39684
|
+
const file = join3(LOG_DIR, `usage-${date}.jsonl`);
|
|
38838
39685
|
await appendFile(file, JSON.stringify(entry) + "\n");
|
|
38839
39686
|
} catch {
|
|
38840
39687
|
}
|
|
@@ -38843,56 +39690,15 @@ var LOG_DIR, dirReady;
|
|
|
38843
39690
|
var init_logger = __esm({
|
|
38844
39691
|
"src/logger.ts"() {
|
|
38845
39692
|
"use strict";
|
|
38846
|
-
LOG_DIR =
|
|
39693
|
+
LOG_DIR = join3(homedir2(), ".openclaw", "blockrun", "logs");
|
|
38847
39694
|
dirReady = false;
|
|
38848
39695
|
}
|
|
38849
39696
|
});
|
|
38850
39697
|
|
|
38851
|
-
// src/fs-read.ts
|
|
38852
|
-
import { open } from "fs/promises";
|
|
38853
|
-
import { openSync, readSync, closeSync, fstatSync } from "fs";
|
|
38854
|
-
async function readTextFile(filePath) {
|
|
38855
|
-
const fh = await open(filePath, "r");
|
|
38856
|
-
try {
|
|
38857
|
-
const size5 = (await fh.stat()).size;
|
|
38858
|
-
const buf = Buffer.alloc(size5);
|
|
38859
|
-
let offset = 0;
|
|
38860
|
-
while (offset < size5) {
|
|
38861
|
-
const { bytesRead } = await fh.read(buf, offset, size5 - offset, offset);
|
|
38862
|
-
if (bytesRead === 0) break;
|
|
38863
|
-
offset += bytesRead;
|
|
38864
|
-
}
|
|
38865
|
-
return buf.subarray(0, offset).toString("utf-8");
|
|
38866
|
-
} finally {
|
|
38867
|
-
await fh.close();
|
|
38868
|
-
}
|
|
38869
|
-
}
|
|
38870
|
-
function readTextFileSync(filePath) {
|
|
38871
|
-
const fd = openSync(filePath, "r");
|
|
38872
|
-
try {
|
|
38873
|
-
const size5 = fstatSync(fd).size;
|
|
38874
|
-
const buf = Buffer.alloc(size5);
|
|
38875
|
-
let offset = 0;
|
|
38876
|
-
while (offset < size5) {
|
|
38877
|
-
const bytesRead = readSync(fd, buf, offset, size5 - offset, offset);
|
|
38878
|
-
if (bytesRead === 0) break;
|
|
38879
|
-
offset += bytesRead;
|
|
38880
|
-
}
|
|
38881
|
-
return buf.subarray(0, offset).toString("utf-8");
|
|
38882
|
-
} finally {
|
|
38883
|
-
closeSync(fd);
|
|
38884
|
-
}
|
|
38885
|
-
}
|
|
38886
|
-
var init_fs_read = __esm({
|
|
38887
|
-
"src/fs-read.ts"() {
|
|
38888
|
-
"use strict";
|
|
38889
|
-
}
|
|
38890
|
-
});
|
|
38891
|
-
|
|
38892
39698
|
// src/version.ts
|
|
38893
39699
|
import { createRequire } from "module";
|
|
38894
39700
|
import { fileURLToPath } from "url";
|
|
38895
|
-
import { dirname, join as
|
|
39701
|
+
import { dirname, join as join4 } from "path";
|
|
38896
39702
|
function clientTag() {
|
|
38897
39703
|
const raw = (process.env.CLAWROUTER_CLIENT ?? "").trim();
|
|
38898
39704
|
if (!raw) return "";
|
|
@@ -38906,7 +39712,7 @@ var init_version4 = __esm({
|
|
|
38906
39712
|
__filename2 = fileURLToPath(import.meta.url);
|
|
38907
39713
|
__dirname = dirname(__filename2);
|
|
38908
39714
|
require2 = createRequire(import.meta.url);
|
|
38909
|
-
pkg = require2(
|
|
39715
|
+
pkg = require2(join4(__dirname, "..", "package.json"));
|
|
38910
39716
|
VERSION = pkg.version;
|
|
38911
39717
|
USER_AGENT = `clawrouter/${VERSION}${clientTag()}`;
|
|
38912
39718
|
}
|
|
@@ -38914,8 +39720,8 @@ var init_version4 = __esm({
|
|
|
38914
39720
|
|
|
38915
39721
|
// src/stats.ts
|
|
38916
39722
|
import { readdir, unlink } from "fs/promises";
|
|
38917
|
-
import { join as
|
|
38918
|
-
import { homedir as
|
|
39723
|
+
import { join as join5 } from "path";
|
|
39724
|
+
import { homedir as homedir3 } from "os";
|
|
38919
39725
|
async function parseLogFile(filePath) {
|
|
38920
39726
|
try {
|
|
38921
39727
|
const content = await readTextFile(filePath);
|
|
@@ -38987,7 +39793,7 @@ async function getStats(days = 7) {
|
|
|
38987
39793
|
let totalLatency = 0;
|
|
38988
39794
|
for (const file of filesToRead) {
|
|
38989
39795
|
const date = file.replace("usage-", "").replace(".jsonl", "");
|
|
38990
|
-
const filePath =
|
|
39796
|
+
const filePath = join5(LOG_DIR2, file);
|
|
38991
39797
|
const entries = await parseLogFile(filePath);
|
|
38992
39798
|
if (entries.length === 0) continue;
|
|
38993
39799
|
const dayStats = aggregateDay(date, entries);
|
|
@@ -39105,7 +39911,7 @@ async function clearStats() {
|
|
|
39105
39911
|
try {
|
|
39106
39912
|
const files = await readdir(LOG_DIR2);
|
|
39107
39913
|
const logFiles = files.filter((f) => f.startsWith("usage-") && f.endsWith(".jsonl"));
|
|
39108
|
-
await Promise.all(logFiles.map((f) => unlink(
|
|
39914
|
+
await Promise.all(logFiles.map((f) => unlink(join5(LOG_DIR2, f))));
|
|
39109
39915
|
return { deletedFiles: logFiles.length };
|
|
39110
39916
|
} catch {
|
|
39111
39917
|
return { deletedFiles: 0 };
|
|
@@ -39117,7 +39923,7 @@ var init_stats = __esm({
|
|
|
39117
39923
|
"use strict";
|
|
39118
39924
|
init_fs_read();
|
|
39119
39925
|
init_version4();
|
|
39120
|
-
LOG_DIR2 =
|
|
39926
|
+
LOG_DIR2 = join5(homedir3(), ".openclaw", "blockrun", "logs");
|
|
39121
39927
|
}
|
|
39122
39928
|
});
|
|
39123
39929
|
|
|
@@ -42936,7 +43742,7 @@ function alphabet2(letters) {
|
|
|
42936
43742
|
};
|
|
42937
43743
|
}
|
|
42938
43744
|
// @__NO_SIDE_EFFECTS__
|
|
42939
|
-
function
|
|
43745
|
+
function join6(separator = "") {
|
|
42940
43746
|
astr2("join", separator);
|
|
42941
43747
|
return {
|
|
42942
43748
|
encode: (from15) => {
|
|
@@ -43046,7 +43852,7 @@ var genBase58, base58, createBase58check;
|
|
|
43046
43852
|
var init_base3 = __esm({
|
|
43047
43853
|
"node_modules/@scure/base/index.js"() {
|
|
43048
43854
|
"use strict";
|
|
43049
|
-
genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain2(/* @__PURE__ */ radix3(58), /* @__PURE__ */ alphabet2(abc), /* @__PURE__ */
|
|
43855
|
+
genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain2(/* @__PURE__ */ radix3(58), /* @__PURE__ */ alphabet2(abc), /* @__PURE__ */ join6(""));
|
|
43050
43856
|
base58 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"));
|
|
43051
43857
|
createBase58check = (sha25610) => {
|
|
43052
43858
|
afn2(sha25610);
|
|
@@ -43195,14 +44001,14 @@ var init_bip32 = __esm({
|
|
|
43195
44001
|
}
|
|
43196
44002
|
this.pubHash = hash160(this._publicKey);
|
|
43197
44003
|
}
|
|
43198
|
-
derive(
|
|
43199
|
-
if (!/^[mM]'?/.test(
|
|
44004
|
+
derive(path5) {
|
|
44005
|
+
if (!/^[mM]'?/.test(path5)) {
|
|
43200
44006
|
throw new Error('Path must start with "m" or "M"');
|
|
43201
44007
|
}
|
|
43202
|
-
if (/^[mM]'?$/.test(
|
|
44008
|
+
if (/^[mM]'?$/.test(path5)) {
|
|
43203
44009
|
return this;
|
|
43204
44010
|
}
|
|
43205
|
-
const parts =
|
|
44011
|
+
const parts = path5.replace(/^[mM]'?\//, "").split("/");
|
|
43206
44012
|
let child = this;
|
|
43207
44013
|
for (const c of parts) {
|
|
43208
44014
|
const m = /^(\d+)('?)$/.exec(c);
|
|
@@ -51492,14 +52298,14 @@ function createSolanaJsonRpcIntegerOverflowError(methodName, keyPath, value) {
|
|
|
51492
52298
|
} else {
|
|
51493
52299
|
argumentLabel = `\`${keyPath[0].toString()}\``;
|
|
51494
52300
|
}
|
|
51495
|
-
const
|
|
52301
|
+
const path5 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
|
|
51496
52302
|
const error = new SolanaError(SOLANA_ERROR__RPC__INTEGER_OVERFLOW, {
|
|
51497
52303
|
argumentLabel,
|
|
51498
52304
|
keyPath,
|
|
51499
52305
|
methodName,
|
|
51500
|
-
optionalPathLabel:
|
|
52306
|
+
optionalPathLabel: path5 ? ` at path \`${path5}\`` : "",
|
|
51501
52307
|
value,
|
|
51502
|
-
...
|
|
52308
|
+
...path5 !== void 0 ? { path: path5 } : void 0
|
|
51503
52309
|
});
|
|
51504
52310
|
safeCaptureStackTrace(error, createSolanaJsonRpcIntegerOverflowError);
|
|
51505
52311
|
return error;
|
|
@@ -56163,14 +56969,14 @@ function createSolanaJsonRpcIntegerOverflowError2(methodName, keyPath, value) {
|
|
|
56163
56969
|
} else {
|
|
56164
56970
|
argumentLabel = `\`${keyPath[0].toString()}\``;
|
|
56165
56971
|
}
|
|
56166
|
-
const
|
|
56972
|
+
const path5 = keyPath.length > 1 ? keyPath.slice(1).map((pathPart) => typeof pathPart === "number" ? `[${pathPart}]` : pathPart).join(".") : void 0;
|
|
56167
56973
|
const error = new SolanaError(SOLANA_ERROR__RPC__INTEGER_OVERFLOW, {
|
|
56168
56974
|
argumentLabel,
|
|
56169
56975
|
keyPath,
|
|
56170
56976
|
methodName,
|
|
56171
|
-
optionalPathLabel:
|
|
56977
|
+
optionalPathLabel: path5 ? ` at path \`${path5}\`` : "",
|
|
56172
56978
|
value,
|
|
56173
|
-
...
|
|
56979
|
+
...path5 !== void 0 ? { path: path5 } : void 0
|
|
56174
56980
|
});
|
|
56175
56981
|
safeCaptureStackTrace(error, createSolanaJsonRpcIntegerOverflowError2);
|
|
56176
56982
|
return error;
|
|
@@ -58238,8 +59044,8 @@ var init_wallet2 = __esm({
|
|
|
58238
59044
|
|
|
58239
59045
|
// src/auth.ts
|
|
58240
59046
|
import { writeFile, mkdir as mkdir2 } from "fs/promises";
|
|
58241
|
-
import { join as
|
|
58242
|
-
import { homedir as
|
|
59047
|
+
import { join as join7 } from "path";
|
|
59048
|
+
import { homedir as homedir4 } from "os";
|
|
58243
59049
|
async function loadSavedWallet() {
|
|
58244
59050
|
try {
|
|
58245
59051
|
const key2 = (await readTextFile(WALLET_FILE)).trim();
|
|
@@ -58288,7 +59094,7 @@ async function loadMnemonic() {
|
|
|
58288
59094
|
return void 0;
|
|
58289
59095
|
}
|
|
58290
59096
|
async function saveMnemonic(mnemonic) {
|
|
58291
|
-
await mkdir2(
|
|
59097
|
+
await mkdir2(WALLET_DIR2, { recursive: true });
|
|
58292
59098
|
await writeFile(MNEMONIC_FILE, mnemonic + "\n", { mode: 384 });
|
|
58293
59099
|
}
|
|
58294
59100
|
async function generateAndSaveWallet() {
|
|
@@ -58307,7 +59113,7 @@ Then run: npx @blockrun/clawrouter`
|
|
|
58307
59113
|
}
|
|
58308
59114
|
const mnemonic = generateWalletMnemonic();
|
|
58309
59115
|
const derived = deriveAllKeys(mnemonic);
|
|
58310
|
-
await mkdir2(
|
|
59116
|
+
await mkdir2(WALLET_DIR2, { recursive: true });
|
|
58311
59117
|
await writeFile(WALLET_FILE, derived.evmPrivateKey + "\n", { mode: 384 });
|
|
58312
59118
|
await writeFile(MNEMONIC_FILE, mnemonic + "\n", { mode: 384 });
|
|
58313
59119
|
try {
|
|
@@ -58429,7 +59235,7 @@ async function setupSolana() {
|
|
|
58429
59235
|
return { mnemonic, solanaPrivateKeyBytes: solanaKeyBytes };
|
|
58430
59236
|
}
|
|
58431
59237
|
async function savePaymentChain(chain3) {
|
|
58432
|
-
await mkdir2(
|
|
59238
|
+
await mkdir2(WALLET_DIR2, { recursive: true });
|
|
58433
59239
|
await writeFile(CHAIN_FILE, chain3 + "\n", { mode: 384 });
|
|
58434
59240
|
}
|
|
58435
59241
|
async function loadPaymentChain() {
|
|
@@ -58446,17 +59252,17 @@ async function resolvePaymentChain() {
|
|
|
58446
59252
|
if (process["env"].CLAWROUTER_PAYMENT_CHAIN === "base") return "base";
|
|
58447
59253
|
return loadPaymentChain();
|
|
58448
59254
|
}
|
|
58449
|
-
var
|
|
59255
|
+
var WALLET_DIR2, WALLET_FILE, MNEMONIC_FILE, CHAIN_FILE;
|
|
58450
59256
|
var init_auth = __esm({
|
|
58451
59257
|
"src/auth.ts"() {
|
|
58452
59258
|
"use strict";
|
|
58453
59259
|
init_fs_read();
|
|
58454
59260
|
init_accounts();
|
|
58455
59261
|
init_wallet2();
|
|
58456
|
-
|
|
58457
|
-
WALLET_FILE =
|
|
58458
|
-
MNEMONIC_FILE =
|
|
58459
|
-
CHAIN_FILE =
|
|
59262
|
+
WALLET_DIR2 = join7(homedir4(), ".openclaw", "blockrun");
|
|
59263
|
+
WALLET_FILE = join7(WALLET_DIR2, "wallet.key");
|
|
59264
|
+
MNEMONIC_FILE = join7(WALLET_DIR2, "mnemonic");
|
|
59265
|
+
CHAIN_FILE = join7(WALLET_DIR2, "payment-chain");
|
|
58460
59266
|
}
|
|
58461
59267
|
});
|
|
58462
59268
|
|
|
@@ -58615,7 +59421,7 @@ function generateCodebookHeader(usedCodes, pathMap = {}) {
|
|
|
58615
59421
|
parts.push(`[Dict: ${codeEntries}]`);
|
|
58616
59422
|
}
|
|
58617
59423
|
if (Object.keys(pathMap).length > 0) {
|
|
58618
|
-
const pathEntries = Object.entries(pathMap).map(([code,
|
|
59424
|
+
const pathEntries = Object.entries(pathMap).map(([code, path5]) => `${code}=${path5}`).join(", ");
|
|
58619
59425
|
parts.push(`[Paths: ${pathEntries}]`);
|
|
58620
59426
|
}
|
|
58621
59427
|
return parts.join("\n");
|
|
@@ -58763,8 +59569,8 @@ function extractPaths(messages) {
|
|
|
58763
59569
|
}
|
|
58764
59570
|
function findFrequentPrefixes(paths) {
|
|
58765
59571
|
const prefixCounts = /* @__PURE__ */ new Map();
|
|
58766
|
-
for (const
|
|
58767
|
-
const parts =
|
|
59572
|
+
for (const path5 of paths) {
|
|
59573
|
+
const parts = path5.split("/").filter(Boolean);
|
|
58768
59574
|
for (let i = 2; i < parts.length; i++) {
|
|
58769
59575
|
const prefix = "/" + parts.slice(0, i).join("/") + "/";
|
|
58770
59576
|
prefixCounts.set(prefix, (prefixCounts.get(prefix) || 0) + 1);
|
|
@@ -59548,9 +60354,9 @@ var init_updater = __esm({
|
|
|
59548
60354
|
});
|
|
59549
60355
|
|
|
59550
60356
|
// src/exclude-models.ts
|
|
59551
|
-
import { readFileSync, writeFileSync, mkdirSync, statSync } from "fs";
|
|
59552
|
-
import { join as
|
|
59553
|
-
import { homedir as
|
|
60357
|
+
import { readFileSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, statSync } from "fs";
|
|
60358
|
+
import { join as join8, dirname as dirname2 } from "path";
|
|
60359
|
+
import { homedir as homedir5 } from "os";
|
|
59554
60360
|
function loadExcludeList(filePath = DEFAULT_FILE_PATH) {
|
|
59555
60361
|
try {
|
|
59556
60362
|
const mtimeMs = statSync(filePath).mtimeMs;
|
|
@@ -59571,8 +60377,8 @@ function loadExcludeList(filePath = DEFAULT_FILE_PATH) {
|
|
|
59571
60377
|
function saveExcludeList(set, filePath) {
|
|
59572
60378
|
const sorted = [...set].sort();
|
|
59573
60379
|
const dir = dirname2(filePath);
|
|
59574
|
-
|
|
59575
|
-
|
|
60380
|
+
mkdirSync2(dir, { recursive: true });
|
|
60381
|
+
writeFileSync2(filePath, JSON.stringify(sorted, null, 2) + "\n", "utf-8");
|
|
59576
60382
|
loadCache.delete(filePath);
|
|
59577
60383
|
}
|
|
59578
60384
|
function addExclusion(model, filePath = DEFAULT_FILE_PATH) {
|
|
@@ -59599,7 +60405,7 @@ var init_exclude_models = __esm({
|
|
|
59599
60405
|
"src/exclude-models.ts"() {
|
|
59600
60406
|
"use strict";
|
|
59601
60407
|
init_models();
|
|
59602
|
-
DEFAULT_FILE_PATH =
|
|
60408
|
+
DEFAULT_FILE_PATH = join8(homedir5(), ".openclaw", "blockrun", "exclude-models.json");
|
|
59603
60409
|
loadCache = /* @__PURE__ */ new Map();
|
|
59604
60410
|
}
|
|
59605
60411
|
});
|
|
@@ -60904,14 +61710,14 @@ var require_util = __commonJS({
|
|
|
60904
61710
|
}
|
|
60905
61711
|
const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
|
|
60906
61712
|
let origin2 = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
|
|
60907
|
-
let
|
|
61713
|
+
let path5 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
|
|
60908
61714
|
if (origin2[origin2.length - 1] === "/") {
|
|
60909
61715
|
origin2 = origin2.slice(0, origin2.length - 1);
|
|
60910
61716
|
}
|
|
60911
|
-
if (
|
|
60912
|
-
|
|
61717
|
+
if (path5 && path5[0] !== "/") {
|
|
61718
|
+
path5 = `/${path5}`;
|
|
60913
61719
|
}
|
|
60914
|
-
return new URL(`${origin2}${
|
|
61720
|
+
return new URL(`${origin2}${path5}`);
|
|
60915
61721
|
}
|
|
60916
61722
|
if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
|
|
60917
61723
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -61782,9 +62588,9 @@ var require_diagnostics = __commonJS({
|
|
|
61782
62588
|
"undici:client:sendHeaders",
|
|
61783
62589
|
(evt) => {
|
|
61784
62590
|
const {
|
|
61785
|
-
request: { method, path:
|
|
62591
|
+
request: { method, path: path5, origin: origin2 }
|
|
61786
62592
|
} = evt;
|
|
61787
|
-
debugLog("sending request to %s %s%s", method, origin2,
|
|
62593
|
+
debugLog("sending request to %s %s%s", method, origin2, path5);
|
|
61788
62594
|
}
|
|
61789
62595
|
);
|
|
61790
62596
|
}
|
|
@@ -61802,14 +62608,14 @@ var require_diagnostics = __commonJS({
|
|
|
61802
62608
|
"undici:request:headers",
|
|
61803
62609
|
(evt) => {
|
|
61804
62610
|
const {
|
|
61805
|
-
request: { method, path:
|
|
62611
|
+
request: { method, path: path5, origin: origin2 },
|
|
61806
62612
|
response: { statusCode }
|
|
61807
62613
|
} = evt;
|
|
61808
62614
|
debugLog(
|
|
61809
62615
|
"received response to %s %s%s - HTTP %d",
|
|
61810
62616
|
method,
|
|
61811
62617
|
origin2,
|
|
61812
|
-
|
|
62618
|
+
path5,
|
|
61813
62619
|
statusCode
|
|
61814
62620
|
);
|
|
61815
62621
|
}
|
|
@@ -61818,23 +62624,23 @@ var require_diagnostics = __commonJS({
|
|
|
61818
62624
|
"undici:request:trailers",
|
|
61819
62625
|
(evt) => {
|
|
61820
62626
|
const {
|
|
61821
|
-
request: { method, path:
|
|
62627
|
+
request: { method, path: path5, origin: origin2 }
|
|
61822
62628
|
} = evt;
|
|
61823
|
-
debugLog("trailers received from %s %s%s", method, origin2,
|
|
62629
|
+
debugLog("trailers received from %s %s%s", method, origin2, path5);
|
|
61824
62630
|
}
|
|
61825
62631
|
);
|
|
61826
62632
|
diagnosticsChannel.subscribe(
|
|
61827
62633
|
"undici:request:error",
|
|
61828
62634
|
(evt) => {
|
|
61829
62635
|
const {
|
|
61830
|
-
request: { method, path:
|
|
62636
|
+
request: { method, path: path5, origin: origin2 },
|
|
61831
62637
|
error
|
|
61832
62638
|
} = evt;
|
|
61833
62639
|
debugLog(
|
|
61834
62640
|
"request to %s %s%s errored - %s",
|
|
61835
62641
|
method,
|
|
61836
62642
|
origin2,
|
|
61837
|
-
|
|
62643
|
+
path5,
|
|
61838
62644
|
error.message
|
|
61839
62645
|
);
|
|
61840
62646
|
}
|
|
@@ -61989,7 +62795,7 @@ var require_request = __commonJS({
|
|
|
61989
62795
|
};
|
|
61990
62796
|
var Request2 = class {
|
|
61991
62797
|
constructor(origin2, {
|
|
61992
|
-
path:
|
|
62798
|
+
path: path5,
|
|
61993
62799
|
method,
|
|
61994
62800
|
body,
|
|
61995
62801
|
headers,
|
|
@@ -62006,11 +62812,11 @@ var require_request = __commonJS({
|
|
|
62006
62812
|
maxRedirections,
|
|
62007
62813
|
typeOfService
|
|
62008
62814
|
}, handler) {
|
|
62009
|
-
if (typeof
|
|
62815
|
+
if (typeof path5 !== "string") {
|
|
62010
62816
|
throw new InvalidArgumentError("path must be a string");
|
|
62011
|
-
} else if (
|
|
62817
|
+
} else if (path5[0] !== "/" && !(path5.startsWith("http://") || path5.startsWith("https://")) && method !== "CONNECT") {
|
|
62012
62818
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
62013
|
-
} else if (invalidPathRegex.test(
|
|
62819
|
+
} else if (invalidPathRegex.test(path5)) {
|
|
62014
62820
|
throw new InvalidArgumentError("invalid request path");
|
|
62015
62821
|
}
|
|
62016
62822
|
if (typeof method !== "string") {
|
|
@@ -62085,7 +62891,7 @@ var require_request = __commonJS({
|
|
|
62085
62891
|
this.completed = false;
|
|
62086
62892
|
this.aborted = false;
|
|
62087
62893
|
this.upgrade = upgrade || null;
|
|
62088
|
-
this.path = query ? serializePathWithQuery(
|
|
62894
|
+
this.path = query ? serializePathWithQuery(path5, query) : path5;
|
|
62089
62895
|
this.origin = origin2;
|
|
62090
62896
|
this.protocol = getProtocolFromUrlString(origin2);
|
|
62091
62897
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" || method === "QUERY" : idempotent;
|
|
@@ -67171,7 +67977,7 @@ var require_client_h1 = __commonJS({
|
|
|
67171
67977
|
}
|
|
67172
67978
|
}
|
|
67173
67979
|
function writeH1(client, request2) {
|
|
67174
|
-
const { method, path:
|
|
67980
|
+
const { method, path: path5, host, upgrade, blocking, reset } = request2;
|
|
67175
67981
|
let { body, headers, contentLength } = request2;
|
|
67176
67982
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
67177
67983
|
if (util5.isFormDataLike(body)) {
|
|
@@ -67247,7 +68053,7 @@ var require_client_h1 = __commonJS({
|
|
|
67247
68053
|
socket[kBlocking] = true;
|
|
67248
68054
|
}
|
|
67249
68055
|
setTypeOfService(socket, request2);
|
|
67250
|
-
let header = `${method} ${
|
|
68056
|
+
let header = `${method} ${path5} HTTP/1.1\r
|
|
67251
68057
|
`;
|
|
67252
68058
|
if (typeof host === "string") {
|
|
67253
68059
|
header += `host: ${host}\r
|
|
@@ -68328,7 +69134,7 @@ var require_client_h2 = __commonJS({
|
|
|
68328
69134
|
const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
|
|
68329
69135
|
const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
68330
69136
|
const session = client[kHTTP2Session];
|
|
68331
|
-
const { method, path:
|
|
69137
|
+
const { method, path: path5, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
68332
69138
|
if (upgrade != null && upgrade !== "websocket") {
|
|
68333
69139
|
util5.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
68334
69140
|
return false;
|
|
@@ -68391,7 +69197,7 @@ var require_client_h2 = __commonJS({
|
|
|
68391
69197
|
}
|
|
68392
69198
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
68393
69199
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
68394
|
-
headers[HTTP2_HEADER_PATH] =
|
|
69200
|
+
headers[HTTP2_HEADER_PATH] = path5;
|
|
68395
69201
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
68396
69202
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
68397
69203
|
} else {
|
|
@@ -68413,7 +69219,7 @@ var require_client_h2 = __commonJS({
|
|
|
68413
69219
|
setupUpgradeStream(stream4, state);
|
|
68414
69220
|
return true;
|
|
68415
69221
|
}
|
|
68416
|
-
headers[HTTP2_HEADER_PATH] =
|
|
69222
|
+
headers[HTTP2_HEADER_PATH] = path5;
|
|
68417
69223
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
68418
69224
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
68419
69225
|
let body = state.body;
|
|
@@ -71083,10 +71889,10 @@ var require_proxy_agent = __commonJS({
|
|
|
71083
71889
|
};
|
|
71084
71890
|
const {
|
|
71085
71891
|
origin: origin2,
|
|
71086
|
-
path:
|
|
71892
|
+
path: path5 = "/",
|
|
71087
71893
|
headers = {}
|
|
71088
71894
|
} = opts;
|
|
71089
|
-
opts.path = origin2 +
|
|
71895
|
+
opts.path = origin2 + path5;
|
|
71090
71896
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
71091
71897
|
const { host } = new URL(origin2);
|
|
71092
71898
|
headers.host = host;
|
|
@@ -73351,20 +74157,20 @@ var require_mock_utils = __commonJS({
|
|
|
73351
74157
|
}
|
|
73352
74158
|
return normalizedQp;
|
|
73353
74159
|
}
|
|
73354
|
-
function safeUrl(
|
|
73355
|
-
if (typeof
|
|
73356
|
-
return
|
|
74160
|
+
function safeUrl(path5) {
|
|
74161
|
+
if (typeof path5 !== "string") {
|
|
74162
|
+
return path5;
|
|
73357
74163
|
}
|
|
73358
|
-
const pathSegments =
|
|
74164
|
+
const pathSegments = path5.split("?", 3);
|
|
73359
74165
|
if (pathSegments.length !== 2) {
|
|
73360
|
-
return
|
|
74166
|
+
return path5;
|
|
73361
74167
|
}
|
|
73362
74168
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
73363
74169
|
qp.sort();
|
|
73364
74170
|
return [...pathSegments, qp.toString()].join("?");
|
|
73365
74171
|
}
|
|
73366
|
-
function matchKey(mockDispatch2, { path:
|
|
73367
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
74172
|
+
function matchKey(mockDispatch2, { path: path5, method, body, headers }) {
|
|
74173
|
+
const pathMatch = matchValue(mockDispatch2.path, path5);
|
|
73368
74174
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
73369
74175
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
73370
74176
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -73391,8 +74197,8 @@ var require_mock_utils = __commonJS({
|
|
|
73391
74197
|
const basePath = key2.query ? serializePathWithQuery(key2.path, key2.query) : key2.path;
|
|
73392
74198
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
73393
74199
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
73394
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
73395
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
74200
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path5, ignoreTrailingSlash }) => {
|
|
74201
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path5)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path5), resolvedPath);
|
|
73396
74202
|
});
|
|
73397
74203
|
if (matchedMockDispatches.length === 0) {
|
|
73398
74204
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -73431,22 +74237,22 @@ var require_mock_utils = __commonJS({
|
|
|
73431
74237
|
mockDispatches.splice(index2, 1);
|
|
73432
74238
|
}
|
|
73433
74239
|
}
|
|
73434
|
-
function removeTrailingSlash(
|
|
73435
|
-
if (typeof
|
|
73436
|
-
return
|
|
74240
|
+
function removeTrailingSlash(path5) {
|
|
74241
|
+
if (typeof path5 !== "string") {
|
|
74242
|
+
return path5;
|
|
73437
74243
|
}
|
|
73438
|
-
while (
|
|
73439
|
-
|
|
74244
|
+
while (path5.endsWith("/")) {
|
|
74245
|
+
path5 = path5.slice(0, -1);
|
|
73440
74246
|
}
|
|
73441
|
-
if (
|
|
73442
|
-
|
|
74247
|
+
if (path5.length === 0) {
|
|
74248
|
+
path5 = "/";
|
|
73443
74249
|
}
|
|
73444
|
-
return
|
|
74250
|
+
return path5;
|
|
73445
74251
|
}
|
|
73446
74252
|
function buildKey(opts) {
|
|
73447
|
-
const { path:
|
|
74253
|
+
const { path: path5, method, body, headers, query } = opts;
|
|
73448
74254
|
return {
|
|
73449
|
-
path:
|
|
74255
|
+
path: path5,
|
|
73450
74256
|
method,
|
|
73451
74257
|
body,
|
|
73452
74258
|
headers,
|
|
@@ -74317,10 +75123,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
74317
75123
|
}
|
|
74318
75124
|
format(pendingInterceptors) {
|
|
74319
75125
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
74320
|
-
({ method, path:
|
|
75126
|
+
({ method, path: path5, data: { statusCode }, persist, times, timesInvoked, origin: origin2 }) => ({
|
|
74321
75127
|
Method: method,
|
|
74322
75128
|
Origin: origin2,
|
|
74323
|
-
Path:
|
|
75129
|
+
Path: path5,
|
|
74324
75130
|
"Status code": statusCode,
|
|
74325
75131
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
74326
75132
|
Invocations: timesInvoked,
|
|
@@ -74402,9 +75208,9 @@ var require_mock_agent = __commonJS({
|
|
|
74402
75208
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
74403
75209
|
const dispatchOpts = { ...opts };
|
|
74404
75210
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
74405
|
-
const [
|
|
75211
|
+
const [path5, searchParams] = dispatchOpts.path.split("?");
|
|
74406
75212
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
74407
|
-
dispatchOpts.path = `${
|
|
75213
|
+
dispatchOpts.path = `${path5}?${normalizedSearchParams}`;
|
|
74408
75214
|
}
|
|
74409
75215
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
74410
75216
|
}
|
|
@@ -74820,12 +75626,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
74820
75626
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
74821
75627
|
*/
|
|
74822
75628
|
async loadSnapshots(filePath) {
|
|
74823
|
-
const
|
|
74824
|
-
if (!
|
|
75629
|
+
const path5 = filePath || this.#snapshotPath;
|
|
75630
|
+
if (!path5) {
|
|
74825
75631
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
74826
75632
|
}
|
|
74827
75633
|
try {
|
|
74828
|
-
const data = await readFile3(resolve(
|
|
75634
|
+
const data = await readFile3(resolve(path5), "utf8");
|
|
74829
75635
|
const parsed = JSON.parse(data);
|
|
74830
75636
|
if (Array.isArray(parsed)) {
|
|
74831
75637
|
this.#snapshots.clear();
|
|
@@ -74839,7 +75645,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
74839
75645
|
if (error.code === "ENOENT") {
|
|
74840
75646
|
this.#snapshots.clear();
|
|
74841
75647
|
} else {
|
|
74842
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
75648
|
+
throw new UndiciError(`Failed to load snapshots from ${path5}`, { cause: error });
|
|
74843
75649
|
}
|
|
74844
75650
|
}
|
|
74845
75651
|
}
|
|
@@ -74850,11 +75656,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
74850
75656
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
74851
75657
|
*/
|
|
74852
75658
|
async saveSnapshots(filePath) {
|
|
74853
|
-
const
|
|
74854
|
-
if (!
|
|
75659
|
+
const path5 = filePath || this.#snapshotPath;
|
|
75660
|
+
if (!path5) {
|
|
74855
75661
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
74856
75662
|
}
|
|
74857
|
-
const resolvedPath = resolve(
|
|
75663
|
+
const resolvedPath = resolve(path5);
|
|
74858
75664
|
await mkdir5(dirname5(resolvedPath), { recursive: true });
|
|
74859
75665
|
const data = Array.from(this.#snapshots.entries()).map(([hash5, snapshot]) => ({
|
|
74860
75666
|
hash: hash5,
|
|
@@ -75491,15 +76297,15 @@ var require_redirect_handler = __commonJS({
|
|
|
75491
76297
|
return;
|
|
75492
76298
|
}
|
|
75493
76299
|
const { origin: origin2, pathname, search } = util5.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
75494
|
-
const
|
|
75495
|
-
const redirectUrlString = `${origin2}${
|
|
76300
|
+
const path5 = search ? `${pathname}${search}` : pathname;
|
|
76301
|
+
const redirectUrlString = `${origin2}${path5}`;
|
|
75496
76302
|
for (const historyUrl of this.history) {
|
|
75497
76303
|
if (historyUrl.toString() === redirectUrlString) {
|
|
75498
76304
|
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.`);
|
|
75499
76305
|
}
|
|
75500
76306
|
}
|
|
75501
76307
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, removeContentHeaders, this.opts.origin !== origin2, this.stripHeadersOnRedirect, this.stripHeadersOnCrossOriginRedirect);
|
|
75502
|
-
this.opts.path =
|
|
76308
|
+
this.opts.path = path5;
|
|
75503
76309
|
this.opts.origin = origin2;
|
|
75504
76310
|
this.opts.query = null;
|
|
75505
76311
|
}
|
|
@@ -77327,10 +78133,10 @@ var require_cache_handler = __commonJS({
|
|
|
77327
78133
|
}
|
|
77328
78134
|
return locationUrl.pathname + locationUrl.search;
|
|
77329
78135
|
}
|
|
77330
|
-
function deleteCachedUri(store, cacheKey2,
|
|
78136
|
+
function deleteCachedUri(store, cacheKey2, path5) {
|
|
77331
78137
|
deleteCachedValue(store, {
|
|
77332
78138
|
...cacheKey2,
|
|
77333
|
-
path:
|
|
78139
|
+
path: path5
|
|
77334
78140
|
});
|
|
77335
78141
|
for (let i = 0; i < util5.safeHTTPMethods.length; i++) {
|
|
77336
78142
|
const method = util5.safeHTTPMethods[i];
|
|
@@ -77338,7 +78144,7 @@ var require_cache_handler = __commonJS({
|
|
|
77338
78144
|
deleteCachedValue(store, {
|
|
77339
78145
|
...cacheKey2,
|
|
77340
78146
|
method,
|
|
77341
|
-
path:
|
|
78147
|
+
path: path5
|
|
77342
78148
|
});
|
|
77343
78149
|
}
|
|
77344
78150
|
}
|
|
@@ -77349,9 +78155,9 @@ var require_cache_handler = __commonJS({
|
|
|
77349
78155
|
}
|
|
77350
78156
|
const values = Array.isArray(headerValue) ? headerValue : [headerValue];
|
|
77351
78157
|
for (let i = 0; i < values.length; i++) {
|
|
77352
|
-
const
|
|
77353
|
-
if (
|
|
77354
|
-
deleteCachedUri(store, cacheKey2,
|
|
78158
|
+
const path5 = getSameOriginPath(cacheKey2, values[i]);
|
|
78159
|
+
if (path5 !== void 0) {
|
|
78160
|
+
deleteCachedUri(store, cacheKey2, path5);
|
|
77355
78161
|
}
|
|
77356
78162
|
}
|
|
77357
78163
|
}
|
|
@@ -82348,13 +83154,13 @@ var require_fetch = __commonJS({
|
|
|
82348
83154
|
function dispatch({ body }) {
|
|
82349
83155
|
const url2 = requestCurrentURL(request2);
|
|
82350
83156
|
const agent = fetchParams.controller.dispatcher;
|
|
82351
|
-
const
|
|
83157
|
+
const path5 = url2.pathname + url2.search;
|
|
82352
83158
|
const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
|
|
82353
83159
|
return dispatchWithProtocolPreference(body);
|
|
82354
83160
|
function dispatchWithProtocolPreference(body2, allowH2) {
|
|
82355
83161
|
return new Promise((resolve, reject) => agent.dispatch(
|
|
82356
83162
|
{
|
|
82357
|
-
path: hasTrailingQuestionMark ? `${
|
|
83163
|
+
path: hasTrailingQuestionMark ? `${path5}?` : path5,
|
|
82358
83164
|
origin: url2.origin,
|
|
82359
83165
|
method: request2.method,
|
|
82360
83166
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body2,
|
|
@@ -83266,9 +84072,9 @@ var require_util4 = __commonJS({
|
|
|
83266
84072
|
}
|
|
83267
84073
|
}
|
|
83268
84074
|
}
|
|
83269
|
-
function validateCookiePath(
|
|
83270
|
-
for (let i = 0; i <
|
|
83271
|
-
const code =
|
|
84075
|
+
function validateCookiePath(path5) {
|
|
84076
|
+
for (let i = 0; i < path5.length; ++i) {
|
|
84077
|
+
const code = path5.charCodeAt(i);
|
|
83272
84078
|
if (code < 32 || // exclude CTLs (0-31)
|
|
83273
84079
|
code > 126 || // exclude non-ascii and DEL
|
|
83274
84080
|
code === 59) {
|
|
@@ -86640,11 +87446,11 @@ var require_undici = __commonJS({
|
|
|
86640
87446
|
if (typeof opts.path !== "string") {
|
|
86641
87447
|
throw new InvalidArgumentError("invalid opts.path");
|
|
86642
87448
|
}
|
|
86643
|
-
let
|
|
87449
|
+
let path5 = opts.path;
|
|
86644
87450
|
if (!opts.path.startsWith("/")) {
|
|
86645
|
-
|
|
87451
|
+
path5 = `/${path5}`;
|
|
86646
87452
|
}
|
|
86647
|
-
url2 = new URL(util5.parseOrigin(url2).origin +
|
|
87453
|
+
url2 = new URL(util5.parseOrigin(url2).origin + path5);
|
|
86648
87454
|
} else {
|
|
86649
87455
|
if (!opts) {
|
|
86650
87456
|
opts = typeof url2 === "object" ? url2 : {};
|
|
@@ -87190,8 +87996,8 @@ var init_textual_tool_calls = __esm({
|
|
|
87190
87996
|
|
|
87191
87997
|
// src/response-store.ts
|
|
87192
87998
|
import { appendFile as appendFile2, mkdir as mkdir3, readFile, readdir as readdir2 } from "fs/promises";
|
|
87193
|
-
import { homedir as
|
|
87194
|
-
import { join as
|
|
87999
|
+
import { homedir as homedir6 } from "os";
|
|
88000
|
+
import { join as join9 } from "path";
|
|
87195
88001
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
87196
88002
|
function isEnabled() {
|
|
87197
88003
|
const v = process.env.BLOCKRUN_RESPONSE_STORE;
|
|
@@ -87204,7 +88010,7 @@ async function ensureDir2() {
|
|
|
87204
88010
|
}
|
|
87205
88011
|
function dailyFile(date = /* @__PURE__ */ new Date()) {
|
|
87206
88012
|
const iso = date.toISOString().slice(0, 10);
|
|
87207
|
-
return
|
|
88013
|
+
return join9(STORE_DIR, `responses-${iso}.jsonl`);
|
|
87208
88014
|
}
|
|
87209
88015
|
function genId() {
|
|
87210
88016
|
return `resp_${Date.now()}_${randomBytes7(3).toString("hex")}`;
|
|
@@ -87254,7 +88060,7 @@ async function listRecent(limit = 20, daysBack = 7) {
|
|
|
87254
88060
|
d.setUTCDate(d.getUTCDate() - i);
|
|
87255
88061
|
const iso = d.toISOString().slice(0, 10);
|
|
87256
88062
|
const name = `responses-${iso}.jsonl`;
|
|
87257
|
-
if (files.includes(name)) candidateFiles.push(
|
|
88063
|
+
if (files.includes(name)) candidateFiles.push(join9(STORE_DIR, name));
|
|
87258
88064
|
}
|
|
87259
88065
|
const all3 = [];
|
|
87260
88066
|
for (const f of candidateFiles) {
|
|
@@ -87283,7 +88089,7 @@ var STORE_DIR, dirReady2;
|
|
|
87283
88089
|
var init_response_store = __esm({
|
|
87284
88090
|
"src/response-store.ts"() {
|
|
87285
88091
|
"use strict";
|
|
87286
|
-
STORE_DIR =
|
|
88092
|
+
STORE_DIR = join9(homedir6(), ".openclaw", "blockrun", "responses");
|
|
87287
88093
|
dirReady2 = false;
|
|
87288
88094
|
}
|
|
87289
88095
|
});
|
|
@@ -88933,10 +89739,10 @@ var init_client3 = __esm({
|
|
|
88933
89739
|
import { AsyncLocalStorage } from "async_hooks";
|
|
88934
89740
|
import { createServer } from "http";
|
|
88935
89741
|
import { finished } from "stream";
|
|
88936
|
-
import { homedir as
|
|
88937
|
-
import { join as
|
|
89742
|
+
import { homedir as homedir7 } from "os";
|
|
89743
|
+
import { join as join10 } from "path";
|
|
88938
89744
|
import { mkdir as mkdir4, writeFile as writeFile2, readFile as readFile2, stat as fsStat } from "fs/promises";
|
|
88939
|
-
import { readFileSync as readFileSync2, existsSync } from "fs";
|
|
89745
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
88940
89746
|
function pickFreeModel(excludeList) {
|
|
88941
89747
|
for (const m of FREE_MODELS) {
|
|
88942
89748
|
if (!excludeList?.has(m)) return m;
|
|
@@ -88944,6 +89750,8 @@ function pickFreeModel(excludeList) {
|
|
|
88944
89750
|
return void 0;
|
|
88945
89751
|
}
|
|
88946
89752
|
function toUpstreamModelId(modelId) {
|
|
89753
|
+
const override = FREE_UPSTREAM_OVERRIDES[modelId];
|
|
89754
|
+
if (override) return override;
|
|
88947
89755
|
if (modelId.startsWith("free/")) {
|
|
88948
89756
|
return "nvidia/" + modelId.slice("free/".length);
|
|
88949
89757
|
}
|
|
@@ -89702,8 +90510,8 @@ async function proxyPaidApiRequest(req, res, apiBase, payFetch, getActualPayment
|
|
|
89702
90510
|
});
|
|
89703
90511
|
}
|
|
89704
90512
|
function readImageFileAsDataUri(filePath) {
|
|
89705
|
-
const resolved = filePath.startsWith("~/") ?
|
|
89706
|
-
if (!
|
|
90513
|
+
const resolved = filePath.startsWith("~/") ? join10(homedir7(), filePath.slice(2)) : filePath;
|
|
90514
|
+
if (!existsSync2(resolved)) {
|
|
89707
90515
|
throw new Error(`Image file not found: ${resolved}`);
|
|
89708
90516
|
}
|
|
89709
90517
|
const ext = resolved.split(".").pop()?.toLowerCase() ?? "png";
|
|
@@ -89817,6 +90625,8 @@ async function startProxy(options) {
|
|
|
89817
90625
|
const evmPublicClient = createPublicClient({ chain: base, transport: http() });
|
|
89818
90626
|
const evmSigner = toClientEvmSigner(account, evmPublicClient);
|
|
89819
90627
|
const x402 = new x402Client();
|
|
90628
|
+
const spendControl = options.spendControl ?? new SpendControl();
|
|
90629
|
+
registerSpendPolicyHook(x402, spendControl);
|
|
89820
90630
|
registerExactEvmScheme(x402, { signer: evmSigner });
|
|
89821
90631
|
let solanaAddress;
|
|
89822
90632
|
if (solanaPrivateKeyBytes) {
|
|
@@ -89985,8 +90795,8 @@ async function startProxy(options) {
|
|
|
89985
90795
|
if (req.url?.startsWith("/share") && req.method === "GET") {
|
|
89986
90796
|
try {
|
|
89987
90797
|
const url2 = new URL(req.url, "http://localhost");
|
|
89988
|
-
const
|
|
89989
|
-
if (
|
|
90798
|
+
const path5 = url2.pathname;
|
|
90799
|
+
if (path5 === "/share/list") {
|
|
89990
90800
|
const limit = Math.min(parseInt(url2.searchParams.get("limit") || "20", 10), 100);
|
|
89991
90801
|
const entries = await listRecent(limit);
|
|
89992
90802
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -90004,7 +90814,7 @@ async function startProxy(options) {
|
|
|
90004
90814
|
);
|
|
90005
90815
|
return;
|
|
90006
90816
|
}
|
|
90007
|
-
if (
|
|
90817
|
+
if (path5 === "/share/last") {
|
|
90008
90818
|
const sessionId = url2.searchParams.get("sessionId") || void 0;
|
|
90009
90819
|
const entry = await getLast(sessionId);
|
|
90010
90820
|
if (!entry) {
|
|
@@ -90033,7 +90843,7 @@ async function startProxy(options) {
|
|
|
90033
90843
|
res.end(JSON.stringify(entry));
|
|
90034
90844
|
return;
|
|
90035
90845
|
}
|
|
90036
|
-
const idMatch =
|
|
90846
|
+
const idMatch = path5.match(/^\/share\/(resp_[A-Za-z0-9_]+)(?:\/render)?$/);
|
|
90037
90847
|
if (idMatch) {
|
|
90038
90848
|
const id2 = idMatch[1];
|
|
90039
90849
|
const entry = await getById(id2);
|
|
@@ -90079,7 +90889,7 @@ async function startProxy(options) {
|
|
|
90079
90889
|
res.end("Bad request");
|
|
90080
90890
|
return;
|
|
90081
90891
|
}
|
|
90082
|
-
const filePath =
|
|
90892
|
+
const filePath = join10(IMAGE_DIR, filename);
|
|
90083
90893
|
try {
|
|
90084
90894
|
const s3 = await fsStat(filePath);
|
|
90085
90895
|
if (!s3.isFile()) throw new Error("not a file");
|
|
@@ -90110,7 +90920,7 @@ async function startProxy(options) {
|
|
|
90110
90920
|
res.end("Bad request");
|
|
90111
90921
|
return;
|
|
90112
90922
|
}
|
|
90113
|
-
const filePath =
|
|
90923
|
+
const filePath = join10(AUDIO_DIR, filename);
|
|
90114
90924
|
try {
|
|
90115
90925
|
const s3 = await fsStat(filePath);
|
|
90116
90926
|
if (!s3.isFile()) throw new Error("not a file");
|
|
@@ -90140,7 +90950,7 @@ async function startProxy(options) {
|
|
|
90140
90950
|
res.end("Bad request");
|
|
90141
90951
|
return;
|
|
90142
90952
|
}
|
|
90143
|
-
const filePath =
|
|
90953
|
+
const filePath = join10(VIDEO_DIR, filename);
|
|
90144
90954
|
try {
|
|
90145
90955
|
const s3 = await fsStat(filePath);
|
|
90146
90956
|
if (!s3.isFile()) throw new Error("not a file");
|
|
@@ -90281,7 +91091,7 @@ async function startProxy(options) {
|
|
|
90281
91091
|
const [, mimeType, b64] = dataUriMatch;
|
|
90282
91092
|
const ext = mimeType === "image/jpeg" ? "jpg" : mimeType.split("/")[1] ?? "png";
|
|
90283
91093
|
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
|
|
90284
|
-
await writeFile2(
|
|
91094
|
+
await writeFile2(join10(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
|
|
90285
91095
|
img.url = `http://localhost:${port2}/images/${filename}`;
|
|
90286
91096
|
console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
|
|
90287
91097
|
} else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
|
|
@@ -90292,7 +91102,7 @@ async function startProxy(options) {
|
|
|
90292
91102
|
const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
|
|
90293
91103
|
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
|
|
90294
91104
|
const buf = Buffer.from(await imgResp.arrayBuffer());
|
|
90295
|
-
await writeFile2(
|
|
91105
|
+
await writeFile2(join10(IMAGE_DIR, filename), buf);
|
|
90296
91106
|
img.url = `http://localhost:${port2}/images/${filename}`;
|
|
90297
91107
|
console.log(`[ClawRouter] Image downloaded & saved \u2192 ${img.url}`);
|
|
90298
91108
|
}
|
|
@@ -90404,7 +91214,7 @@ async function startProxy(options) {
|
|
|
90404
91214
|
const [, mimeType, b64] = dataUriMatch;
|
|
90405
91215
|
const ext = mimeType === "image/jpeg" ? "jpg" : mimeType.split("/")[1] ?? "png";
|
|
90406
91216
|
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
|
|
90407
|
-
await writeFile2(
|
|
91217
|
+
await writeFile2(join10(IMAGE_DIR, filename), Buffer.from(b64, "base64"));
|
|
90408
91218
|
img.url = `http://localhost:${port2}/images/${filename}`;
|
|
90409
91219
|
console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
|
|
90410
91220
|
} else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
|
|
@@ -90415,7 +91225,7 @@ async function startProxy(options) {
|
|
|
90415
91225
|
const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
|
|
90416
91226
|
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
|
|
90417
91227
|
const buf = Buffer.from(await imgResp.arrayBuffer());
|
|
90418
|
-
await writeFile2(
|
|
91228
|
+
await writeFile2(join10(IMAGE_DIR, filename), buf);
|
|
90419
91229
|
img.url = `http://localhost:${port2}/images/${filename}`;
|
|
90420
91230
|
console.log(`[ClawRouter] Image downloaded & saved \u2192 ${img.url}`);
|
|
90421
91231
|
}
|
|
@@ -90501,7 +91311,7 @@ async function startProxy(options) {
|
|
|
90501
91311
|
const ext = contentType.includes("wav") ? "wav" : "mp3";
|
|
90502
91312
|
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
|
|
90503
91313
|
const buf = Buffer.from(await audioResp.arrayBuffer());
|
|
90504
|
-
await writeFile2(
|
|
91314
|
+
await writeFile2(join10(AUDIO_DIR, filename), buf);
|
|
90505
91315
|
track.url = `http://localhost:${port2}/audio/${filename}`;
|
|
90506
91316
|
console.log(`[ClawRouter] Audio saved \u2192 ${track.url}`);
|
|
90507
91317
|
}
|
|
@@ -90661,7 +91471,7 @@ async function startProxy(options) {
|
|
|
90661
91471
|
const ext = contentType.includes("webm") ? "webm" : contentType.includes("quicktime") ? "mov" : "mp4";
|
|
90662
91472
|
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;
|
|
90663
91473
|
const buf = Buffer.from(await videoResp.arrayBuffer());
|
|
90664
|
-
await writeFile2(
|
|
91474
|
+
await writeFile2(join10(VIDEO_DIR, filename), buf);
|
|
90665
91475
|
clip.url = `http://localhost:${port2}/videos/${filename}`;
|
|
90666
91476
|
console.log(`[ClawRouter] Video saved \u2192 ${clip.url}`);
|
|
90667
91477
|
}
|
|
@@ -91001,6 +91811,17 @@ async function tryModelRequest(upstreamUrl, method, headers, body, modelId, maxT
|
|
|
91001
91811
|
return { success: true, response };
|
|
91002
91812
|
} catch (err) {
|
|
91003
91813
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
91814
|
+
if (err instanceof SpendPolicyError) {
|
|
91815
|
+
return {
|
|
91816
|
+
success: false,
|
|
91817
|
+
errorBody: JSON.stringify({
|
|
91818
|
+
error: { message: errorMsg, type: "spend_policy_denied", status: 403 }
|
|
91819
|
+
}),
|
|
91820
|
+
errorStatus: 403,
|
|
91821
|
+
isProviderError: false,
|
|
91822
|
+
errorCategory: "payment_error"
|
|
91823
|
+
};
|
|
91824
|
+
}
|
|
91004
91825
|
return {
|
|
91005
91826
|
success: false,
|
|
91006
91827
|
errorBody: errorMsg,
|
|
@@ -93165,7 +93986,7 @@ data: [DONE]
|
|
|
93165
93986
|
});
|
|
93166
93987
|
}
|
|
93167
93988
|
}
|
|
93168
|
-
var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, FREE_MODEL, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, ClientDisconnectedError, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING;
|
|
93989
|
+
var paymentStore, BLOCKRUN_API, BLOCKRUN_SOLANA_API, IMAGE_DIR, AUDIO_DIR, VIDEO_DIR, AUTO_MODEL, ROUTING_PROFILES, FREE_MODELS, FREE_MODEL, FREE_UPSTREAM_OVERRIDES, MAX_MESSAGES, CONTEXT_LIMIT_KB, HEARTBEAT_INTERVAL_MS, BALANCE_CHECK_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, PER_MODEL_TIMEOUT_MS, REASONING_MODEL_TIMEOUT_MS, REASONING_MODEL_IDS, MAX_FALLBACK_ATTEMPTS, HEALTH_CHECK_TIMEOUT_MS, RATE_LIMIT_COOLDOWN_MS, OVERLOAD_COOLDOWN_MS, PORT_RETRY_ATTEMPTS, PORT_RETRY_DELAY_MS, MODEL_BODY_READ_TIMEOUT_MS, ERROR_BODY_READ_TIMEOUT_MS, ClientDisconnectedError, rateLimitedModels, overloadedModels, perProviderErrors, BALANCE_CHECK_BUFFER, BALANCE_PREFLIGHT_OUTPUT_TOKEN_CAP, PROVIDER_ERROR_PATTERNS, DEGRADED_RESPONSE_PATTERNS, DEGRADED_LOOP_PATTERNS, VALID_ROLES, ROLE_MAPPINGS, VALID_TOOL_ID_PATTERN, KIMI_BLOCK_RE, KIMI_TOKEN_RE, THINKING_TAG_RE, THINKING_BLOCK_RE, BLOCKRUN_MODEL_BY_ID, IMAGE_PRICING, IMAGE_MODEL_IDS, IMAGE_MODEL_SIZES, IMAGE_MODEL_ALIASES, VIDEO_PRICING, PHONE_PRICING;
|
|
93169
93990
|
var init_proxy = __esm({
|
|
93170
93991
|
"src/proxy.ts"() {
|
|
93171
93992
|
"use strict";
|
|
@@ -93187,6 +94008,7 @@ var init_proxy = __esm({
|
|
|
93187
94008
|
init_response_cache();
|
|
93188
94009
|
init_balance();
|
|
93189
94010
|
init_auth();
|
|
94011
|
+
init_spend_control();
|
|
93190
94012
|
init_compression();
|
|
93191
94013
|
init_version4();
|
|
93192
94014
|
init_session();
|
|
@@ -93202,9 +94024,9 @@ var init_proxy = __esm({
|
|
|
93202
94024
|
paymentStore = new AsyncLocalStorage();
|
|
93203
94025
|
BLOCKRUN_API = "https://blockrun.ai/api";
|
|
93204
94026
|
BLOCKRUN_SOLANA_API = "https://sol.blockrun.ai/api";
|
|
93205
|
-
IMAGE_DIR =
|
|
93206
|
-
AUDIO_DIR =
|
|
93207
|
-
VIDEO_DIR =
|
|
94027
|
+
IMAGE_DIR = join10(homedir7(), ".openclaw", "blockrun", "images");
|
|
94028
|
+
AUDIO_DIR = join10(homedir7(), ".openclaw", "blockrun", "audio");
|
|
94029
|
+
VIDEO_DIR = join10(homedir7(), ".openclaw", "blockrun", "videos");
|
|
93208
94030
|
AUTO_MODEL = "blockrun/auto";
|
|
93209
94031
|
ROUTING_PROFILES = /* @__PURE__ */ new Set([
|
|
93210
94032
|
"blockrun/eco",
|
|
@@ -93215,18 +94037,26 @@ var init_proxy = __esm({
|
|
|
93215
94037
|
"premium"
|
|
93216
94038
|
]);
|
|
93217
94039
|
FREE_MODELS = /* @__PURE__ */ new Set([
|
|
93218
|
-
"free/
|
|
93219
|
-
//
|
|
93220
|
-
"free/nemotron-nano-
|
|
93221
|
-
//
|
|
93222
|
-
"free/
|
|
93223
|
-
//
|
|
94040
|
+
"free/nemotron-3.5-lightning",
|
|
94041
|
+
// free-tier default — 1M ctx, thinking mode
|
|
94042
|
+
"free/nemotron-3-nano-30b",
|
|
94043
|
+
// fastest free model (~121 tok/s)
|
|
94044
|
+
"free/laguna-xs-2.1",
|
|
94045
|
+
// coding, ~161 tok/s — on our NVIDIA key
|
|
94046
|
+
"free/north-mini-code",
|
|
94047
|
+
// coding, 607ms median — OpenRouter $0 pool
|
|
93224
94048
|
"free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
93225
94049
|
// vision (text/image/video/audio)
|
|
93226
|
-
"free/nemotron-
|
|
93227
|
-
//
|
|
94050
|
+
"free/nemotron-3-ultra-550b",
|
|
94051
|
+
// largest free model, 1M ctx — but slow + flaky
|
|
94052
|
+
"free/llama-3.2-11b-vision"
|
|
94053
|
+
// only free Llama left; slowest, so last
|
|
93228
94054
|
]);
|
|
93229
|
-
FREE_MODEL = "free/
|
|
94055
|
+
FREE_MODEL = "free/nemotron-3.5-lightning";
|
|
94056
|
+
FREE_UPSTREAM_OVERRIDES = {
|
|
94057
|
+
"free/north-mini-code": "cohere/north-mini-code",
|
|
94058
|
+
"free/laguna-xs-2.1": "poolside/laguna-xs-2.1"
|
|
94059
|
+
};
|
|
93230
94060
|
MAX_MESSAGES = 200;
|
|
93231
94061
|
CONTEXT_LIMIT_KB = 5120;
|
|
93232
94062
|
HEARTBEAT_INTERVAL_MS = 2e3;
|
|
@@ -94540,7 +95370,7 @@ function buildTool(service, proxyBaseUrl) {
|
|
|
94540
95370
|
required
|
|
94541
95371
|
},
|
|
94542
95372
|
execute: async (_toolCallId, params) => {
|
|
94543
|
-
let
|
|
95373
|
+
let path5;
|
|
94544
95374
|
const leftoverParams = {};
|
|
94545
95375
|
let dynamicMethod = "GET";
|
|
94546
95376
|
let dynamicBody = void 0;
|
|
@@ -94552,7 +95382,7 @@ function buildTool(service, proxyBaseUrl) {
|
|
|
94552
95382
|
`predexon_endpoint_call: invalid path '${rawPath}' \u2014 must begin with '/pm/' and contain no '..'`
|
|
94553
95383
|
);
|
|
94554
95384
|
}
|
|
94555
|
-
|
|
95385
|
+
path5 = `/v1${normalized}`;
|
|
94556
95386
|
if (typeof params.method === "string") {
|
|
94557
95387
|
const upper = params.method.toUpperCase();
|
|
94558
95388
|
if (upper !== "GET" && upper !== "POST") {
|
|
@@ -94601,19 +95431,19 @@ function buildTool(service, proxyBaseUrl) {
|
|
|
94601
95431
|
}
|
|
94602
95432
|
}
|
|
94603
95433
|
} else {
|
|
94604
|
-
|
|
95434
|
+
path5 = `/v1${service.proxyPath}`;
|
|
94605
95435
|
for (const [key2, value] of Object.entries(params)) {
|
|
94606
95436
|
if (value === void 0 || value === null) continue;
|
|
94607
95437
|
const placeholder = `:${key2}`;
|
|
94608
|
-
if (
|
|
94609
|
-
|
|
95438
|
+
if (path5.includes(placeholder)) {
|
|
95439
|
+
path5 = path5.replace(placeholder, encodeURIComponent(String(value)));
|
|
94610
95440
|
} else {
|
|
94611
95441
|
leftoverParams[key2] = value;
|
|
94612
95442
|
}
|
|
94613
95443
|
}
|
|
94614
95444
|
}
|
|
94615
95445
|
const effectiveMethod = service.proxyPath === "/pm/__dynamic__" ? dynamicMethod : service.method;
|
|
94616
|
-
let url2 = `${proxyBaseUrl}${
|
|
95446
|
+
let url2 = `${proxyBaseUrl}${path5}`;
|
|
94617
95447
|
if (effectiveMethod === "GET" && Object.keys(leftoverParams).length > 0) {
|
|
94618
95448
|
const qs = new URLSearchParams();
|
|
94619
95449
|
for (const [key2, value] of Object.entries(leftoverParams)) {
|
|
@@ -106021,11 +106851,11 @@ var require_mime_types = __commonJS({
|
|
|
106021
106851
|
}
|
|
106022
106852
|
return exts[0];
|
|
106023
106853
|
}
|
|
106024
|
-
function lookup(
|
|
106025
|
-
if (!
|
|
106854
|
+
function lookup(path5) {
|
|
106855
|
+
if (!path5 || typeof path5 !== "string") {
|
|
106026
106856
|
return false;
|
|
106027
106857
|
}
|
|
106028
|
-
var extension3 = extname("x." +
|
|
106858
|
+
var extension3 = extname("x." + path5).toLowerCase().substr(1);
|
|
106029
106859
|
if (!extension3) {
|
|
106030
106860
|
return false;
|
|
106031
106861
|
}
|
|
@@ -107140,7 +107970,7 @@ var require_form_data = __commonJS({
|
|
|
107140
107970
|
"use strict";
|
|
107141
107971
|
var CombinedStream = require_combined_stream();
|
|
107142
107972
|
var util5 = __require("util");
|
|
107143
|
-
var
|
|
107973
|
+
var path5 = __require("path");
|
|
107144
107974
|
var http5 = __require("http");
|
|
107145
107975
|
var https2 = __require("https");
|
|
107146
107976
|
var parseUrl3 = __require("url").parse;
|
|
@@ -107271,11 +108101,11 @@ var require_form_data = __commonJS({
|
|
|
107271
108101
|
FormData3.prototype._getContentDisposition = function(value, options) {
|
|
107272
108102
|
var filename;
|
|
107273
108103
|
if (typeof options.filepath === "string") {
|
|
107274
|
-
filename =
|
|
108104
|
+
filename = path5.normalize(options.filepath).replace(/\\/g, "/");
|
|
107275
108105
|
} else if (options.filename || value && (value.name || value.path)) {
|
|
107276
|
-
filename =
|
|
108106
|
+
filename = path5.basename(options.filename || value && (value.name || value.path));
|
|
107277
108107
|
} else if (value && value.readable && hasOwn(value, "httpVersion")) {
|
|
107278
|
-
filename =
|
|
108108
|
+
filename = path5.basename(value.client._httpMessage.path || "");
|
|
107279
108109
|
}
|
|
107280
108110
|
if (filename) {
|
|
107281
108111
|
return 'filename="' + escapeHeaderParam(filename) + '"';
|
|
@@ -107489,9 +108319,9 @@ function isVisitable(thing) {
|
|
|
107489
108319
|
function removeBrackets(key2) {
|
|
107490
108320
|
return utils_default.endsWith(key2, "[]") ? key2.slice(0, -2) : key2;
|
|
107491
108321
|
}
|
|
107492
|
-
function renderKey(
|
|
107493
|
-
if (!
|
|
107494
|
-
return
|
|
108322
|
+
function renderKey(path5, key2, dots) {
|
|
108323
|
+
if (!path5) return key2;
|
|
108324
|
+
return path5.concat(key2).map(function each(token, i) {
|
|
107495
108325
|
token = removeBrackets(token);
|
|
107496
108326
|
return !dots && i ? "[" + token + "]" : token;
|
|
107497
108327
|
}).join(dots ? "." : "");
|
|
@@ -107574,13 +108404,13 @@ function toFormData(obj, formData, options) {
|
|
|
107574
108404
|
return currentValue;
|
|
107575
108405
|
});
|
|
107576
108406
|
}
|
|
107577
|
-
function defaultVisitor(value, key2,
|
|
108407
|
+
function defaultVisitor(value, key2, path5) {
|
|
107578
108408
|
let arr = value;
|
|
107579
108409
|
if (utils_default.isReactNative(formData) && utils_default.isReactNativeBlob(value)) {
|
|
107580
|
-
formData.append(renderKey(
|
|
108410
|
+
formData.append(renderKey(path5, key2, dots), convertValue(value));
|
|
107581
108411
|
return false;
|
|
107582
108412
|
}
|
|
107583
|
-
if (value && !
|
|
108413
|
+
if (value && !path5 && typeof value === "object") {
|
|
107584
108414
|
if (utils_default.endsWith(key2, "{}")) {
|
|
107585
108415
|
key2 = metaTokens ? key2 : key2.slice(0, -2);
|
|
107586
108416
|
value = stringifyWithDepthLimit(value, 1);
|
|
@@ -107599,7 +108429,7 @@ function toFormData(obj, formData, options) {
|
|
|
107599
108429
|
if (isVisitable(value)) {
|
|
107600
108430
|
return true;
|
|
107601
108431
|
}
|
|
107602
|
-
formData.append(renderKey(
|
|
108432
|
+
formData.append(renderKey(path5, key2, dots), convertValue(value));
|
|
107603
108433
|
return false;
|
|
107604
108434
|
}
|
|
107605
108435
|
const exposedHelpers = Object.assign(predicates, {
|
|
@@ -107607,17 +108437,17 @@ function toFormData(obj, formData, options) {
|
|
|
107607
108437
|
convertValue,
|
|
107608
108438
|
isVisitable
|
|
107609
108439
|
});
|
|
107610
|
-
function build(value,
|
|
108440
|
+
function build(value, path5, depth = 0) {
|
|
107611
108441
|
if (utils_default.isUndefined(value)) return;
|
|
107612
108442
|
throwIfMaxDepthExceeded(depth);
|
|
107613
108443
|
if (stack.indexOf(value) !== -1) {
|
|
107614
|
-
throw new Error("Circular reference detected in " +
|
|
108444
|
+
throw new Error("Circular reference detected in " + path5.join("."));
|
|
107615
108445
|
}
|
|
107616
108446
|
stack.push(value);
|
|
107617
108447
|
utils_default.forEach(value, function each(el, key2) {
|
|
107618
|
-
const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key2) ? key2.trim() : key2,
|
|
108448
|
+
const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key2) ? key2.trim() : key2, path5, exposedHelpers);
|
|
107619
108449
|
if (result === true) {
|
|
107620
|
-
build(el,
|
|
108450
|
+
build(el, path5 ? path5.concat(key2) : [key2], depth + 1);
|
|
107621
108451
|
}
|
|
107622
108452
|
});
|
|
107623
108453
|
stack.pop();
|
|
@@ -107896,7 +108726,7 @@ var init_platform = __esm({
|
|
|
107896
108726
|
// node_modules/axios/lib/helpers/toURLEncodedForm.js
|
|
107897
108727
|
function toURLEncodedForm(data, options) {
|
|
107898
108728
|
return toFormData_default(data, new platform_default.classes.URLSearchParams(), {
|
|
107899
|
-
visitor: function(value, key2,
|
|
108729
|
+
visitor: function(value, key2, path5, helpers) {
|
|
107900
108730
|
if (platform_default.isNode && utils_default.isBuffer(value)) {
|
|
107901
108731
|
this.append(key2, value.toString("base64"));
|
|
107902
108732
|
return false;
|
|
@@ -107925,14 +108755,14 @@ function throwIfDepthExceeded(index2) {
|
|
|
107925
108755
|
}
|
|
107926
108756
|
}
|
|
107927
108757
|
function parsePropPath(name) {
|
|
107928
|
-
const
|
|
108758
|
+
const path5 = [];
|
|
107929
108759
|
const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
|
|
107930
108760
|
let match;
|
|
107931
108761
|
while ((match = pattern.exec(name)) !== null) {
|
|
107932
|
-
throwIfDepthExceeded(
|
|
107933
|
-
|
|
108762
|
+
throwIfDepthExceeded(path5.length);
|
|
108763
|
+
path5.push(match[0] === "[]" ? "" : match[1] || match[0]);
|
|
107934
108764
|
}
|
|
107935
|
-
return
|
|
108765
|
+
return path5;
|
|
107936
108766
|
}
|
|
107937
108767
|
function arrayToObject(arr) {
|
|
107938
108768
|
const obj = {};
|
|
@@ -107947,12 +108777,12 @@ function arrayToObject(arr) {
|
|
|
107947
108777
|
return obj;
|
|
107948
108778
|
}
|
|
107949
108779
|
function formDataToJSON(formData) {
|
|
107950
|
-
function buildPath(
|
|
108780
|
+
function buildPath(path5, value, target, index2) {
|
|
107951
108781
|
throwIfDepthExceeded(index2);
|
|
107952
|
-
let name =
|
|
108782
|
+
let name = path5[index2++];
|
|
107953
108783
|
if (name === "__proto__") return true;
|
|
107954
108784
|
const isNumericKey = Number.isFinite(+name);
|
|
107955
|
-
const isLast = index2 >=
|
|
108785
|
+
const isLast = index2 >= path5.length;
|
|
107956
108786
|
name = !name && utils_default.isArray(target) ? target.length : name;
|
|
107957
108787
|
if (isLast) {
|
|
107958
108788
|
if (utils_default.hasOwnProp(target, name)) {
|
|
@@ -107965,7 +108795,7 @@ function formDataToJSON(formData) {
|
|
|
107965
108795
|
if (!utils_default.hasOwnProp(target, name) || !utils_default.isObject(target[name])) {
|
|
107966
108796
|
target[name] = [];
|
|
107967
108797
|
}
|
|
107968
|
-
const result = buildPath(
|
|
108798
|
+
const result = buildPath(path5, value, target[name], index2);
|
|
107969
108799
|
if (result && utils_default.isArray(target[name])) {
|
|
107970
108800
|
target[name] = arrayToObject(target[name]);
|
|
107971
108801
|
}
|
|
@@ -111512,9 +112342,9 @@ var init_http4 = __esm({
|
|
|
111512
112342
|
auth = urlUsername + ":" + urlPassword;
|
|
111513
112343
|
}
|
|
111514
112344
|
auth && headers.delete("authorization");
|
|
111515
|
-
let
|
|
112345
|
+
let path5;
|
|
111516
112346
|
try {
|
|
111517
|
-
|
|
112347
|
+
path5 = buildURL(
|
|
111518
112348
|
parsed.pathname + parsed.search,
|
|
111519
112349
|
own2("params"),
|
|
111520
112350
|
own2("paramsSerializer")
|
|
@@ -111533,7 +112363,7 @@ var init_http4 = __esm({
|
|
|
111533
112363
|
false
|
|
111534
112364
|
);
|
|
111535
112365
|
const options = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
111536
|
-
path:
|
|
112366
|
+
path: path5,
|
|
111537
112367
|
method,
|
|
111538
112368
|
headers: toByteStringHeaderObject(headers),
|
|
111539
112369
|
agents: { http: httpAgent, https: httpsAgent },
|
|
@@ -111950,14 +112780,14 @@ var init_cookies = __esm({
|
|
|
111950
112780
|
cookies_default = platform_default.hasStandardBrowserEnv ? (
|
|
111951
112781
|
// Standard browser envs support document.cookie
|
|
111952
112782
|
{
|
|
111953
|
-
write(name, value, expires,
|
|
112783
|
+
write(name, value, expires, path5, domain, secure, sameSite) {
|
|
111954
112784
|
if (typeof document === "undefined") return;
|
|
111955
112785
|
const cookie = [`${name}=${encodeURIComponent(value)}`];
|
|
111956
112786
|
if (utils_default.isNumber(expires)) {
|
|
111957
112787
|
cookie.push(`expires=${new Date(expires).toUTCString()}`);
|
|
111958
112788
|
}
|
|
111959
|
-
if (utils_default.isString(
|
|
111960
|
-
cookie.push(`path=${
|
|
112789
|
+
if (utils_default.isString(path5)) {
|
|
112790
|
+
cookie.push(`path=${path5}`);
|
|
111961
112791
|
}
|
|
111962
112792
|
if (utils_default.isString(domain)) {
|
|
111963
112793
|
cookie.push(`domain=${domain}`);
|
|
@@ -115386,15 +116216,15 @@ var init_constants3 = __esm({
|
|
|
115386
116216
|
});
|
|
115387
116217
|
|
|
115388
116218
|
// src/polymarket/wallet-adapter.ts
|
|
115389
|
-
import
|
|
115390
|
-
import { homedir as
|
|
115391
|
-
import { join as
|
|
116219
|
+
import fs2 from "fs";
|
|
116220
|
+
import { homedir as homedir8 } from "os";
|
|
116221
|
+
import { join as join11 } from "path";
|
|
115392
116222
|
function getOrCreateWalletKey() {
|
|
115393
116223
|
const envKey = process.env.BLOCKRUN_WALLET_KEY?.trim();
|
|
115394
116224
|
if (envKey && /^0x[0-9a-fA-F]{64}$/.test(envKey)) return envKey;
|
|
115395
116225
|
let key2;
|
|
115396
116226
|
try {
|
|
115397
|
-
key2 =
|
|
116227
|
+
key2 = fs2.readFileSync(WALLET_FILE2, "utf-8").trim();
|
|
115398
116228
|
} catch (err) {
|
|
115399
116229
|
if (err.code === "ENOENT") {
|
|
115400
116230
|
throw new Error(
|
|
@@ -115436,7 +116266,7 @@ var init_wallet_adapter = __esm({
|
|
|
115436
116266
|
init_esm();
|
|
115437
116267
|
init_chains();
|
|
115438
116268
|
init_constants3();
|
|
115439
|
-
WALLET_FILE2 =
|
|
116269
|
+
WALLET_FILE2 = join11(homedir8(), ".openclaw", "blockrun", "wallet.key");
|
|
115440
116270
|
BASE_RPC_URLS = [
|
|
115441
116271
|
"https://mainnet.base.org",
|
|
115442
116272
|
"https://base.llamarpc.com",
|
|
@@ -115447,21 +116277,21 @@ var init_wallet_adapter = __esm({
|
|
|
115447
116277
|
});
|
|
115448
116278
|
|
|
115449
116279
|
// src/polymarket/creds.ts
|
|
115450
|
-
import
|
|
115451
|
-
import
|
|
116280
|
+
import fs3 from "fs";
|
|
116281
|
+
import path2 from "path";
|
|
115452
116282
|
import os from "os";
|
|
115453
116283
|
function readJsonFile(file) {
|
|
115454
116284
|
try {
|
|
115455
|
-
if (!
|
|
115456
|
-
const raw =
|
|
116285
|
+
if (!fs3.existsSync(file)) return null;
|
|
116286
|
+
const raw = fs3.readFileSync(file, "utf-8").trim();
|
|
115457
116287
|
return raw ? JSON.parse(raw) : null;
|
|
115458
116288
|
} catch {
|
|
115459
116289
|
return null;
|
|
115460
116290
|
}
|
|
115461
116291
|
}
|
|
115462
116292
|
function writeJsonFile(file, value) {
|
|
115463
|
-
|
|
115464
|
-
|
|
116293
|
+
fs3.mkdirSync(BLOCKRUN_DIR, { recursive: true });
|
|
116294
|
+
fs3.writeFileSync(file, JSON.stringify(value, null, 2), { mode: 384 });
|
|
115465
116295
|
}
|
|
115466
116296
|
function credsKey(address2, sigType) {
|
|
115467
116297
|
return `${address2.toLowerCase()}:${sigType}`;
|
|
@@ -115513,10 +116343,10 @@ var BLOCKRUN_DIR, CREDS_FILE, BUILDER_CREDS_FILE, STATE_FILE;
|
|
|
115513
116343
|
var init_creds = __esm({
|
|
115514
116344
|
"src/polymarket/creds.ts"() {
|
|
115515
116345
|
"use strict";
|
|
115516
|
-
BLOCKRUN_DIR =
|
|
115517
|
-
CREDS_FILE =
|
|
115518
|
-
BUILDER_CREDS_FILE =
|
|
115519
|
-
STATE_FILE =
|
|
116346
|
+
BLOCKRUN_DIR = path2.join(os.homedir(), ".openclaw", "blockrun");
|
|
116347
|
+
CREDS_FILE = path2.join(BLOCKRUN_DIR, ".polymarket-creds");
|
|
116348
|
+
BUILDER_CREDS_FILE = path2.join(BLOCKRUN_DIR, ".polymarket-builder-creds");
|
|
116349
|
+
STATE_FILE = path2.join(BLOCKRUN_DIR, ".polymarket.json");
|
|
115520
116350
|
}
|
|
115521
116351
|
});
|
|
115522
116352
|
|
|
@@ -116698,13 +117528,13 @@ function __disposeResources(env) {
|
|
|
116698
117528
|
}
|
|
116699
117529
|
return next();
|
|
116700
117530
|
}
|
|
116701
|
-
function __rewriteRelativeImportExtension(
|
|
116702
|
-
if (typeof
|
|
116703
|
-
return
|
|
117531
|
+
function __rewriteRelativeImportExtension(path5, preserveJsx) {
|
|
117532
|
+
if (typeof path5 === "string" && /^\.\.?\//.test(path5)) {
|
|
117533
|
+
return path5.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
116704
117534
|
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
116705
117535
|
});
|
|
116706
117536
|
}
|
|
116707
|
-
return
|
|
117537
|
+
return path5;
|
|
116708
117538
|
}
|
|
116709
117539
|
var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
|
|
116710
117540
|
var init_tslib_es6 = __esm({
|
|
@@ -149001,9 +149831,9 @@ var require_setupKzg = __commonJS({
|
|
|
149001
149831
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
149002
149832
|
exports.setupKzg = setupKzg;
|
|
149003
149833
|
var defineKzg_js_1 = require_defineKzg();
|
|
149004
|
-
function setupKzg(parameters,
|
|
149834
|
+
function setupKzg(parameters, path5) {
|
|
149005
149835
|
try {
|
|
149006
|
-
parameters.loadTrustedSetup(
|
|
149836
|
+
parameters.loadTrustedSetup(path5);
|
|
149007
149837
|
} catch (e7) {
|
|
149008
149838
|
const error = e7;
|
|
149009
149839
|
if (!error.message.includes("trusted setup is already loaded"))
|
|
@@ -197088,12 +197918,12 @@ var init_fragments = __esm({
|
|
|
197088
197918
|
// node_modules/@ethersproject/abi/lib.esm/coders/abstract-coder.js
|
|
197089
197919
|
function checkResultErrors(result) {
|
|
197090
197920
|
const errors = [];
|
|
197091
|
-
const checkErrors = function(
|
|
197921
|
+
const checkErrors = function(path5, object) {
|
|
197092
197922
|
if (!Array.isArray(object)) {
|
|
197093
197923
|
return;
|
|
197094
197924
|
}
|
|
197095
197925
|
for (let key2 in object) {
|
|
197096
|
-
const childPath =
|
|
197926
|
+
const childPath = path5.slice();
|
|
197097
197927
|
childPath.push(key2);
|
|
197098
197928
|
try {
|
|
197099
197929
|
checkErrors(childPath, object[key2]);
|
|
@@ -202911,8 +203741,8 @@ function createCommonjsModule(fn, basedir, module) {
|
|
|
202911
203741
|
return module = {
|
|
202912
203742
|
path: basedir,
|
|
202913
203743
|
exports: {},
|
|
202914
|
-
require: function(
|
|
202915
|
-
return commonjsRequire(
|
|
203744
|
+
require: function(path5, base3) {
|
|
203745
|
+
return commonjsRequire(path5, base3 === void 0 || base3 === null ? module.path : base3);
|
|
202916
203746
|
}
|
|
202917
203747
|
}, fn(module, module.exports), module.exports;
|
|
202918
203748
|
}
|
|
@@ -206762,9 +207592,9 @@ var init_lib23 = __esm({
|
|
|
206762
207592
|
if (index2 > 4294967295) {
|
|
206763
207593
|
throw new Error("invalid index - " + String(index2));
|
|
206764
207594
|
}
|
|
206765
|
-
let
|
|
206766
|
-
if (
|
|
206767
|
-
|
|
207595
|
+
let path5 = this.path;
|
|
207596
|
+
if (path5) {
|
|
207597
|
+
path5 += "/" + (index2 & ~HardenedBit);
|
|
206768
207598
|
}
|
|
206769
207599
|
const data = new Uint8Array(37);
|
|
206770
207600
|
if (index2 & HardenedBit) {
|
|
@@ -206772,8 +207602,8 @@ var init_lib23 = __esm({
|
|
|
206772
207602
|
throw new Error("cannot derive child of neutered node");
|
|
206773
207603
|
}
|
|
206774
207604
|
data.set(arrayify(this.privateKey), 1);
|
|
206775
|
-
if (
|
|
206776
|
-
|
|
207605
|
+
if (path5) {
|
|
207606
|
+
path5 += "'";
|
|
206777
207607
|
}
|
|
206778
207608
|
} else {
|
|
206779
207609
|
data.set(arrayify(this.publicKey));
|
|
@@ -206792,21 +207622,21 @@ var init_lib23 = __esm({
|
|
|
206792
207622
|
const ek = new SigningKey(hexlify(IL));
|
|
206793
207623
|
Ki = ek._addPoint(this.publicKey);
|
|
206794
207624
|
}
|
|
206795
|
-
let mnemonicOrPath =
|
|
207625
|
+
let mnemonicOrPath = path5;
|
|
206796
207626
|
const srcMnemonic = this.mnemonic;
|
|
206797
207627
|
if (srcMnemonic) {
|
|
206798
207628
|
mnemonicOrPath = Object.freeze({
|
|
206799
207629
|
phrase: srcMnemonic.phrase,
|
|
206800
|
-
path:
|
|
207630
|
+
path: path5,
|
|
206801
207631
|
locale: srcMnemonic.locale || "en"
|
|
206802
207632
|
});
|
|
206803
207633
|
}
|
|
206804
207634
|
return new _HDNode(_constructorGuard4, ki, Ki, this.fingerprint, bytes32(IR), index2, this.depth + 1, mnemonicOrPath);
|
|
206805
207635
|
}
|
|
206806
|
-
derivePath(
|
|
206807
|
-
const components =
|
|
207636
|
+
derivePath(path5) {
|
|
207637
|
+
const components = path5.split("/");
|
|
206808
207638
|
if (components.length === 0 || components[0] === "m" && this.depth !== 0) {
|
|
206809
|
-
throw new Error("invalid path - " +
|
|
207639
|
+
throw new Error("invalid path - " + path5);
|
|
206810
207640
|
}
|
|
206811
207641
|
if (components[0] === "m") {
|
|
206812
207642
|
components.shift();
|
|
@@ -207541,9 +208371,9 @@ function getPassword(password) {
|
|
|
207541
208371
|
}
|
|
207542
208372
|
return arrayify(password);
|
|
207543
208373
|
}
|
|
207544
|
-
function searchPath(object,
|
|
208374
|
+
function searchPath(object, path5) {
|
|
207545
208375
|
let currentChild = object;
|
|
207546
|
-
const comps =
|
|
208376
|
+
const comps = path5.toLowerCase().split("/");
|
|
207547
208377
|
for (let i = 0; i < comps.length; i++) {
|
|
207548
208378
|
let matchingChild = null;
|
|
207549
208379
|
for (const key2 in currentChild) {
|
|
@@ -208192,12 +209022,12 @@ function _getAccount(data, key2) {
|
|
|
208192
209022
|
const mnemonicIv = looseArrayify(searchPath(data, "x-ethers/mnemonicCounter"));
|
|
208193
209023
|
const mnemonicCounter = new import_aes_js2.default.Counter(mnemonicIv);
|
|
208194
209024
|
const mnemonicAesCtr = new import_aes_js2.default.ModeOfOperation.ctr(mnemonicKey, mnemonicCounter);
|
|
208195
|
-
const
|
|
209025
|
+
const path5 = searchPath(data, "x-ethers/path") || defaultPath;
|
|
208196
209026
|
const locale = searchPath(data, "x-ethers/locale") || "en";
|
|
208197
209027
|
const entropy = arrayify(mnemonicAesCtr.decrypt(mnemonicCiphertext));
|
|
208198
209028
|
try {
|
|
208199
209029
|
const mnemonic = entropyToMnemonic2(entropy, locale);
|
|
208200
|
-
const node = HDNode.fromMnemonic(mnemonic, null, locale).derivePath(
|
|
209030
|
+
const node = HDNode.fromMnemonic(mnemonic, null, locale).derivePath(path5);
|
|
208201
209031
|
if (node.privateKey != account.privateKey) {
|
|
208202
209032
|
throw new Error("mnemonic mismatch");
|
|
208203
209033
|
}
|
|
@@ -208297,12 +209127,12 @@ function encrypt(account, password, options, progressCallback) {
|
|
|
208297
209127
|
const privateKey = arrayify(account.privateKey);
|
|
208298
209128
|
const passwordBytes = getPassword(password);
|
|
208299
209129
|
let entropy = null;
|
|
208300
|
-
let
|
|
209130
|
+
let path5 = null;
|
|
208301
209131
|
let locale = null;
|
|
208302
209132
|
if (hasMnemonic(account)) {
|
|
208303
209133
|
const srcMnemonic = account.mnemonic;
|
|
208304
209134
|
entropy = arrayify(mnemonicToEntropy2(srcMnemonic.phrase, srcMnemonic.locale || "en"));
|
|
208305
|
-
|
|
209135
|
+
path5 = srcMnemonic.path || defaultPath;
|
|
208306
209136
|
locale = srcMnemonic.locale || "en";
|
|
208307
209137
|
}
|
|
208308
209138
|
let client = options.client;
|
|
@@ -208388,7 +209218,7 @@ function encrypt(account, password, options, progressCallback) {
|
|
|
208388
209218
|
gethFilename: "UTC--" + timestamp + "--" + data.address,
|
|
208389
209219
|
mnemonicCounter: hexlify(mnemonicIv).substring(2),
|
|
208390
209220
|
mnemonicCiphertext: hexlify(mnemonicCiphertext).substring(2),
|
|
208391
|
-
path:
|
|
209221
|
+
path: path5,
|
|
208392
209222
|
locale,
|
|
208393
209223
|
version: "0.1"
|
|
208394
209224
|
};
|
|
@@ -208682,11 +209512,11 @@ var init_lib26 = __esm({
|
|
|
208682
209512
|
static fromEncryptedJsonSync(json, password) {
|
|
208683
209513
|
return new _Wallet(decryptJsonWalletSync(json, password));
|
|
208684
209514
|
}
|
|
208685
|
-
static fromMnemonic(mnemonic,
|
|
208686
|
-
if (!
|
|
208687
|
-
|
|
209515
|
+
static fromMnemonic(mnemonic, path5, wordlist3) {
|
|
209516
|
+
if (!path5) {
|
|
209517
|
+
path5 = defaultPath;
|
|
208688
209518
|
}
|
|
208689
|
-
return new _Wallet(HDNode.fromMnemonic(mnemonic, null, wordlist3).derivePath(
|
|
209519
|
+
return new _Wallet(HDNode.fromMnemonic(mnemonic, null, wordlist3).derivePath(path5));
|
|
208690
209520
|
}
|
|
208691
209521
|
};
|
|
208692
209522
|
}
|
|
@@ -214682,21 +215512,21 @@ var init_web3_provider = __esm({
|
|
|
214682
215512
|
if (provider == null) {
|
|
214683
215513
|
logger43.throwArgumentError("missing provider", "provider", provider);
|
|
214684
215514
|
}
|
|
214685
|
-
let
|
|
215515
|
+
let path5 = null;
|
|
214686
215516
|
let jsonRpcFetchFunc = null;
|
|
214687
215517
|
let subprovider = null;
|
|
214688
215518
|
if (typeof provider === "function") {
|
|
214689
|
-
|
|
215519
|
+
path5 = "unknown:";
|
|
214690
215520
|
jsonRpcFetchFunc = provider;
|
|
214691
215521
|
} else {
|
|
214692
|
-
|
|
214693
|
-
if (!
|
|
214694
|
-
|
|
215522
|
+
path5 = provider.host || provider.path || "";
|
|
215523
|
+
if (!path5 && provider.isMetaMask) {
|
|
215524
|
+
path5 = "metamask";
|
|
214695
215525
|
}
|
|
214696
215526
|
subprovider = provider;
|
|
214697
215527
|
if (provider.request) {
|
|
214698
|
-
if (
|
|
214699
|
-
|
|
215528
|
+
if (path5 === "") {
|
|
215529
|
+
path5 = "eip-1193:";
|
|
214700
215530
|
}
|
|
214701
215531
|
jsonRpcFetchFunc = buildEip1193Fetcher(provider);
|
|
214702
215532
|
} else if (provider.sendAsync) {
|
|
@@ -214706,11 +215536,11 @@ var init_web3_provider = __esm({
|
|
|
214706
215536
|
} else {
|
|
214707
215537
|
logger43.throwArgumentError("unsupported provider", "provider", provider);
|
|
214708
215538
|
}
|
|
214709
|
-
if (!
|
|
214710
|
-
|
|
215539
|
+
if (!path5) {
|
|
215540
|
+
path5 = "unknown:";
|
|
214711
215541
|
}
|
|
214712
215542
|
}
|
|
214713
|
-
super(
|
|
215543
|
+
super(path5, network);
|
|
214714
215544
|
defineReadOnly(this, "jsonRpcFetchFunc", jsonRpcFetchFunc);
|
|
214715
215545
|
defineReadOnly(this, "provider", subprovider);
|
|
214716
215546
|
}
|
|
@@ -215548,7 +216378,7 @@ var require_axios = __commonJS({
|
|
|
215548
216378
|
var https2 = __require("https");
|
|
215549
216379
|
var http23 = __require("http2");
|
|
215550
216380
|
var util5 = __require("util");
|
|
215551
|
-
var
|
|
216381
|
+
var path5 = __require("path");
|
|
215552
216382
|
var followRedirects2 = require_follow_redirects();
|
|
215553
216383
|
var zlib2 = __require("zlib");
|
|
215554
216384
|
var stream4 = __require("stream");
|
|
@@ -216616,9 +217446,9 @@ var require_axios = __commonJS({
|
|
|
216616
217446
|
function removeBrackets2(key2) {
|
|
216617
217447
|
return utils$1.endsWith(key2, "[]") ? key2.slice(0, -2) : key2;
|
|
216618
217448
|
}
|
|
216619
|
-
function renderKey2(
|
|
216620
|
-
if (!
|
|
216621
|
-
return
|
|
217449
|
+
function renderKey2(path6, key2, dots) {
|
|
217450
|
+
if (!path6) return key2;
|
|
217451
|
+
return path6.concat(key2).map(function each(token, i) {
|
|
216622
217452
|
token = removeBrackets2(token);
|
|
216623
217453
|
return !dots && i ? "[" + token + "]" : token;
|
|
216624
217454
|
}).join(dots ? "." : "");
|
|
@@ -216696,13 +217526,13 @@ var require_axios = __commonJS({
|
|
|
216696
217526
|
return currentValue;
|
|
216697
217527
|
});
|
|
216698
217528
|
}
|
|
216699
|
-
function defaultVisitor(value, key2,
|
|
217529
|
+
function defaultVisitor(value, key2, path6) {
|
|
216700
217530
|
let arr = value;
|
|
216701
217531
|
if (utils$1.isReactNative(formData) && utils$1.isReactNativeBlob(value)) {
|
|
216702
|
-
formData.append(renderKey2(
|
|
217532
|
+
formData.append(renderKey2(path6, key2, dots), convertValue(value));
|
|
216703
217533
|
return false;
|
|
216704
217534
|
}
|
|
216705
|
-
if (value && !
|
|
217535
|
+
if (value && !path6 && typeof value === "object") {
|
|
216706
217536
|
if (utils$1.endsWith(key2, "{}")) {
|
|
216707
217537
|
key2 = metaTokens ? key2 : key2.slice(0, -2);
|
|
216708
217538
|
value = stringifyWithDepthLimit(value, 1);
|
|
@@ -216721,7 +217551,7 @@ var require_axios = __commonJS({
|
|
|
216721
217551
|
if (isVisitable2(value)) {
|
|
216722
217552
|
return true;
|
|
216723
217553
|
}
|
|
216724
|
-
formData.append(renderKey2(
|
|
217554
|
+
formData.append(renderKey2(path6, key2, dots), convertValue(value));
|
|
216725
217555
|
return false;
|
|
216726
217556
|
}
|
|
216727
217557
|
const exposedHelpers = Object.assign(predicates2, {
|
|
@@ -216729,17 +217559,17 @@ var require_axios = __commonJS({
|
|
|
216729
217559
|
convertValue,
|
|
216730
217560
|
isVisitable: isVisitable2
|
|
216731
217561
|
});
|
|
216732
|
-
function build(value,
|
|
217562
|
+
function build(value, path6, depth = 0) {
|
|
216733
217563
|
if (utils$1.isUndefined(value)) return;
|
|
216734
217564
|
throwIfMaxDepthExceeded(depth);
|
|
216735
217565
|
if (stack.indexOf(value) !== -1) {
|
|
216736
|
-
throw new Error("Circular reference detected in " +
|
|
217566
|
+
throw new Error("Circular reference detected in " + path6.join("."));
|
|
216737
217567
|
}
|
|
216738
217568
|
stack.push(value);
|
|
216739
217569
|
utils$1.forEach(value, function each(el, key2) {
|
|
216740
|
-
const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key2) ? key2.trim() : key2,
|
|
217570
|
+
const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key2) ? key2.trim() : key2, path6, exposedHelpers);
|
|
216741
217571
|
if (result === true) {
|
|
216742
|
-
build(el,
|
|
217572
|
+
build(el, path6 ? path6.concat(key2) : [key2], depth + 1);
|
|
216743
217573
|
}
|
|
216744
217574
|
});
|
|
216745
217575
|
stack.pop();
|
|
@@ -216928,7 +217758,7 @@ var require_axios = __commonJS({
|
|
|
216928
217758
|
};
|
|
216929
217759
|
function toURLEncodedForm2(data, options) {
|
|
216930
217760
|
return toFormData3(data, new platform.classes.URLSearchParams(), {
|
|
216931
|
-
visitor: function(value, key2,
|
|
217761
|
+
visitor: function(value, key2, path6, helpers) {
|
|
216932
217762
|
if (platform.isNode && utils$1.isBuffer(value)) {
|
|
216933
217763
|
this.append(key2, value.toString("base64"));
|
|
216934
217764
|
return false;
|
|
@@ -216945,14 +217775,14 @@ var require_axios = __commonJS({
|
|
|
216945
217775
|
}
|
|
216946
217776
|
}
|
|
216947
217777
|
function parsePropPath2(name) {
|
|
216948
|
-
const
|
|
217778
|
+
const path6 = [];
|
|
216949
217779
|
const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
|
|
216950
217780
|
let match;
|
|
216951
217781
|
while ((match = pattern.exec(name)) !== null) {
|
|
216952
|
-
throwIfDepthExceeded2(
|
|
216953
|
-
|
|
217782
|
+
throwIfDepthExceeded2(path6.length);
|
|
217783
|
+
path6.push(match[0] === "[]" ? "" : match[1] || match[0]);
|
|
216954
217784
|
}
|
|
216955
|
-
return
|
|
217785
|
+
return path6;
|
|
216956
217786
|
}
|
|
216957
217787
|
function arrayToObject2(arr) {
|
|
216958
217788
|
const obj = {};
|
|
@@ -216967,12 +217797,12 @@ var require_axios = __commonJS({
|
|
|
216967
217797
|
return obj;
|
|
216968
217798
|
}
|
|
216969
217799
|
function formDataToJSON2(formData) {
|
|
216970
|
-
function buildPath(
|
|
217800
|
+
function buildPath(path6, value, target, index2) {
|
|
216971
217801
|
throwIfDepthExceeded2(index2);
|
|
216972
|
-
let name =
|
|
217802
|
+
let name = path6[index2++];
|
|
216973
217803
|
if (name === "__proto__") return true;
|
|
216974
217804
|
const isNumericKey = Number.isFinite(+name);
|
|
216975
|
-
const isLast = index2 >=
|
|
217805
|
+
const isLast = index2 >= path6.length;
|
|
216976
217806
|
name = !name && utils$1.isArray(target) ? target.length : name;
|
|
216977
217807
|
if (isLast) {
|
|
216978
217808
|
if (utils$1.hasOwnProp(target, name)) {
|
|
@@ -216985,7 +217815,7 @@ var require_axios = __commonJS({
|
|
|
216985
217815
|
if (!utils$1.hasOwnProp(target, name) || !utils$1.isObject(target[name])) {
|
|
216986
217816
|
target[name] = [];
|
|
216987
217817
|
}
|
|
216988
|
-
const result = buildPath(
|
|
217818
|
+
const result = buildPath(path6, value, target[name], index2);
|
|
216989
217819
|
if (result && utils$1.isArray(target[name])) {
|
|
216990
217820
|
target[name] = arrayToObject2(target[name]);
|
|
216991
217821
|
}
|
|
@@ -218596,8 +219426,8 @@ var require_axios = __commonJS({
|
|
|
218596
219426
|
const allowedSocketPaths = own3("allowedSocketPaths");
|
|
218597
219427
|
if (allowedSocketPaths != null) {
|
|
218598
219428
|
const allowed = Array.isArray(allowedSocketPaths) ? allowedSocketPaths : [allowedSocketPaths];
|
|
218599
|
-
const resolvedSocket =
|
|
218600
|
-
const isAllowed = allowed.some((entry) => typeof entry === "string" &&
|
|
219429
|
+
const resolvedSocket = path5.resolve(socketPath);
|
|
219430
|
+
const isAllowed = allowed.some((entry) => typeof entry === "string" && path5.resolve(entry) === resolvedSocket);
|
|
218601
219431
|
if (!isAllowed) {
|
|
218602
219432
|
return reject(new AxiosError3(`socketPath "${socketPath}" is not permitted by allowedSocketPaths`, AxiosError3.ERR_BAD_OPTION_VALUE, config));
|
|
218603
219433
|
}
|
|
@@ -218896,14 +219726,14 @@ var require_axios = __commonJS({
|
|
|
218896
219726
|
var cookies = platform.hasStandardBrowserEnv ? (
|
|
218897
219727
|
// Standard browser envs support document.cookie
|
|
218898
219728
|
{
|
|
218899
|
-
write(name, value, expires,
|
|
219729
|
+
write(name, value, expires, path6, domain, secure, sameSite) {
|
|
218900
219730
|
if (typeof document === "undefined") return;
|
|
218901
219731
|
const cookie = [`${name}=${encodeURIComponent(value)}`];
|
|
218902
219732
|
if (utils$1.isNumber(expires)) {
|
|
218903
219733
|
cookie.push(`expires=${new Date(expires).toUTCString()}`);
|
|
218904
219734
|
}
|
|
218905
|
-
if (utils$1.isString(
|
|
218906
|
-
cookie.push(`path=${
|
|
219735
|
+
if (utils$1.isString(path6)) {
|
|
219736
|
+
cookie.push(`path=${path6}`);
|
|
218907
219737
|
}
|
|
218908
219738
|
if (utils$1.isString(domain)) {
|
|
218909
219739
|
cookie.push(`domain=${domain}`);
|
|
@@ -223392,18 +224222,18 @@ var require_client2 = __commonJS({
|
|
|
223392
224222
|
}
|
|
223393
224223
|
console.log(`Transaction not found or not in given states, timing out!`);
|
|
223394
224224
|
}
|
|
223395
|
-
async sendAuthedRequest(method,
|
|
224225
|
+
async sendAuthedRequest(method, path5, body) {
|
|
223396
224226
|
if (this.canBuilderAuth()) {
|
|
223397
|
-
const builderHeaders = await this._generateBuilderHeaders(method,
|
|
224227
|
+
const builderHeaders = await this._generateBuilderHeaders(method, path5, body);
|
|
223398
224228
|
if (builderHeaders !== void 0) {
|
|
223399
|
-
return this.send(
|
|
224229
|
+
return this.send(path5, method, { headers: builderHeaders, data: body });
|
|
223400
224230
|
}
|
|
223401
224231
|
}
|
|
223402
|
-
return this.send(
|
|
224232
|
+
return this.send(path5, method, { data: body });
|
|
223403
224233
|
}
|
|
223404
|
-
async _generateBuilderHeaders(method,
|
|
224234
|
+
async _generateBuilderHeaders(method, path5, body) {
|
|
223405
224235
|
if (this.builderConfig !== void 0) {
|
|
223406
|
-
const builderHeaders = await this.builderConfig.generateBuilderHeaders(method,
|
|
224236
|
+
const builderHeaders = await this.builderConfig.generateBuilderHeaders(method, path5, body);
|
|
223407
224237
|
if (builderHeaders == void 0) {
|
|
223408
224238
|
return void 0;
|
|
223409
224239
|
}
|
|
@@ -223494,12 +224324,12 @@ var require_signer = __commonJS({
|
|
|
223494
224324
|
constructor(creds) {
|
|
223495
224325
|
this.creds = creds;
|
|
223496
224326
|
}
|
|
223497
|
-
createBuilderHeaderPayload(method,
|
|
224327
|
+
createBuilderHeaderPayload(method, path5, body, timestamp) {
|
|
223498
224328
|
let ts = Math.floor(Date.now() / 1e3);
|
|
223499
224329
|
if (timestamp !== void 0) {
|
|
223500
224330
|
ts = timestamp;
|
|
223501
224331
|
}
|
|
223502
|
-
const builderSig = (0, signing_1.buildHmacSignature)(this.creds.secret, ts, method,
|
|
224332
|
+
const builderSig = (0, signing_1.buildHmacSignature)(this.creds.secret, ts, method, path5, body);
|
|
223503
224333
|
return {
|
|
223504
224334
|
POLY_BUILDER_API_KEY: this.creds.key,
|
|
223505
224335
|
POLY_BUILDER_PASSPHRASE: this.creds.passphrase,
|
|
@@ -223588,17 +224418,17 @@ var require_config2 = __commonJS({
|
|
|
223588
224418
|
* @param path
|
|
223589
224419
|
* @param body
|
|
223590
224420
|
*/
|
|
223591
|
-
async generateBuilderHeaders(method,
|
|
224421
|
+
async generateBuilderHeaders(method, path5, body, timestamp) {
|
|
223592
224422
|
this.ensureValid();
|
|
223593
224423
|
const builderType = this.getBuilderType();
|
|
223594
224424
|
if (builderType == types_1.BuilderType.LOCAL) {
|
|
223595
|
-
return Promise.resolve(this.signer?.createBuilderHeaderPayload(method,
|
|
224425
|
+
return Promise.resolve(this.signer?.createBuilderHeaderPayload(method, path5, body, timestamp));
|
|
223596
224426
|
}
|
|
223597
224427
|
if (builderType == types_1.BuilderType.REMOTE) {
|
|
223598
224428
|
const url2 = this.remoteBuilderConfig.url;
|
|
223599
224429
|
const payload = {
|
|
223600
224430
|
method,
|
|
223601
|
-
path:
|
|
224431
|
+
path: path5,
|
|
223602
224432
|
body,
|
|
223603
224433
|
timestamp
|
|
223604
224434
|
};
|
|
@@ -224380,11 +225210,11 @@ var init_withdraw = __esm({
|
|
|
224380
225210
|
});
|
|
224381
225211
|
|
|
224382
225212
|
// node_modules/@blockrun/llm/dist/index.js
|
|
224383
|
-
import * as
|
|
225213
|
+
import * as path3 from "path";
|
|
224384
225214
|
import * as os2 from "os";
|
|
224385
225215
|
import * as path22 from "path";
|
|
224386
225216
|
import * as os22 from "os";
|
|
224387
|
-
import * as
|
|
225217
|
+
import * as path32 from "path";
|
|
224388
225218
|
import * as os3 from "os";
|
|
224389
225219
|
import * as path4 from "path";
|
|
224390
225220
|
import * as os4 from "os";
|
|
@@ -224558,7 +225388,7 @@ function resolveDefaultTimeout() {
|
|
|
224558
225388
|
function sleep2(ms) {
|
|
224559
225389
|
return new Promise((r2) => setTimeout(r2, ms));
|
|
224560
225390
|
}
|
|
224561
|
-
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,
|
|
225391
|
+
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;
|
|
224562
225392
|
var init_dist7 = __esm({
|
|
224563
225393
|
"node_modules/@blockrun/llm/dist/index.js"() {
|
|
224564
225394
|
"use strict";
|
|
@@ -224606,8 +225436,8 @@ var init_dist7 = __esm({
|
|
|
224606
225436
|
};
|
|
224607
225437
|
BLOCKRUN_SERVICE_CODE2 = "blockrun";
|
|
224608
225438
|
LOCALHOST_DOMAINS = ["localhost", "127.0.0.1"];
|
|
224609
|
-
BLOCKRUN_DIR2 =
|
|
224610
|
-
COST_LOG_FILE =
|
|
225439
|
+
BLOCKRUN_DIR2 = path3.join(os2.homedir(), ".blockrun");
|
|
225440
|
+
COST_LOG_FILE = path3.join(BLOCKRUN_DIR2, "cost_log.jsonl");
|
|
224611
225441
|
SDK_VERSION = "3.10.0";
|
|
224612
225442
|
USER_AGENT2 = `blockrun-ts/${SDK_VERSION}`;
|
|
224613
225443
|
DEFAULT_TIMEOUT = resolveDefaultTimeout();
|
|
@@ -224652,15 +225482,15 @@ var init_dist7 = __esm({
|
|
|
224652
225482
|
* `/api` is tolerated and stripped). Query params are URL-encoded; arrays
|
|
224653
225483
|
* become repeated keys (`?a=1&a=2`); undefined/null are dropped.
|
|
224654
225484
|
*/
|
|
224655
|
-
async get(
|
|
224656
|
-
const url2 = this.buildUrl(
|
|
225485
|
+
async get(path5, params) {
|
|
225486
|
+
const url2 = this.buildUrl(path5, params);
|
|
224657
225487
|
return this.requestWithPayment(url2, "GET");
|
|
224658
225488
|
}
|
|
224659
225489
|
/**
|
|
224660
225490
|
* POST a BlockRun endpoint with a JSON body.
|
|
224661
225491
|
*/
|
|
224662
|
-
async post(
|
|
224663
|
-
const url2 = this.buildUrl(
|
|
225492
|
+
async post(path5, body) {
|
|
225493
|
+
const url2 = this.buildUrl(path5);
|
|
224664
225494
|
return this.requestWithPayment(url2, "POST", body);
|
|
224665
225495
|
}
|
|
224666
225496
|
/**
|
|
@@ -224675,8 +225505,8 @@ var init_dist7 = __esm({
|
|
|
224675
225505
|
* short-circuits and returns the body. Most long-running endpoints (image,
|
|
224676
225506
|
* video, music, voice) return 202 with a poll_url.
|
|
224677
225507
|
*/
|
|
224678
|
-
async poll(
|
|
224679
|
-
const submitUrl = this.buildUrl(
|
|
225508
|
+
async poll(path5, body, options) {
|
|
225509
|
+
const submitUrl = this.buildUrl(path5);
|
|
224680
225510
|
const budgetMs = options?.budgetMs ?? DEFAULT_POLL_BUDGET_MS;
|
|
224681
225511
|
const intervalMs = options?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
224682
225512
|
const resp402 = await this.fetchWithTimeout(submitUrl, {
|
|
@@ -224775,8 +225605,8 @@ var init_dist7 = __esm({
|
|
|
224775
225605
|
* process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
|
|
224776
225606
|
* }
|
|
224777
225607
|
*/
|
|
224778
|
-
async *stream(
|
|
224779
|
-
const url2 = this.buildUrl(
|
|
225608
|
+
async *stream(path5, body) {
|
|
225609
|
+
const url2 = this.buildUrl(path5);
|
|
224780
225610
|
const requestBody = JSON.stringify(body ?? {});
|
|
224781
225611
|
const resp402 = await this.fetchWithTimeout(url2, {
|
|
224782
225612
|
method: "POST",
|
|
@@ -224842,8 +225672,8 @@ var init_dist7 = __esm({
|
|
|
224842
225672
|
// --------------------------------------------------------------------
|
|
224843
225673
|
// Internal: shared infrastructure
|
|
224844
225674
|
// --------------------------------------------------------------------
|
|
224845
|
-
buildUrl(
|
|
224846
|
-
let normalized =
|
|
225675
|
+
buildUrl(path5, params) {
|
|
225676
|
+
let normalized = path5.startsWith("/") ? path5 : `/${path5}`;
|
|
224847
225677
|
if (normalized.startsWith("/api/")) {
|
|
224848
225678
|
normalized = normalized.slice(4);
|
|
224849
225679
|
}
|
|
@@ -224991,10 +225821,10 @@ var init_dist7 = __esm({
|
|
|
224991
225821
|
return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
|
|
224992
225822
|
}
|
|
224993
225823
|
};
|
|
224994
|
-
|
|
224995
|
-
WALLET_FILE3 = path22.join(
|
|
224996
|
-
WALLET_DIR22 =
|
|
224997
|
-
SOLANA_WALLET_FILE =
|
|
225824
|
+
WALLET_DIR3 = path22.join(os22.homedir(), ".blockrun");
|
|
225825
|
+
WALLET_FILE3 = path22.join(WALLET_DIR3, ".session");
|
|
225826
|
+
WALLET_DIR22 = path32.join(os3.homedir(), ".blockrun");
|
|
225827
|
+
SOLANA_WALLET_FILE = path32.join(WALLET_DIR22, ".solana-session");
|
|
224998
225828
|
CACHE_DIR = path4.join(os4.homedir(), ".blockrun", "cache");
|
|
224999
225829
|
DATA_DIR = path4.join(os4.homedir(), ".blockrun", "data");
|
|
225000
225830
|
COST_LOG_FILE2 = path4.join(os4.homedir(), ".blockrun", "cost_log.jsonl");
|
|
@@ -225490,261 +226320,6 @@ var init_mcp_config = __esm({
|
|
|
225490
226320
|
}
|
|
225491
226321
|
});
|
|
225492
226322
|
|
|
225493
|
-
// src/spend-control.ts
|
|
225494
|
-
import * as fs3 from "fs";
|
|
225495
|
-
import * as path5 from "path";
|
|
225496
|
-
import { homedir as homedir12 } from "os";
|
|
225497
|
-
function formatDuration(seconds) {
|
|
225498
|
-
if (seconds < 60) {
|
|
225499
|
-
return `${seconds}s`;
|
|
225500
|
-
} else if (seconds < 3600) {
|
|
225501
|
-
const mins = Math.ceil(seconds / 60);
|
|
225502
|
-
return `${mins} min`;
|
|
225503
|
-
} else {
|
|
225504
|
-
const hours = Math.floor(seconds / 3600);
|
|
225505
|
-
const mins = Math.ceil(seconds % 3600 / 60);
|
|
225506
|
-
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
225507
|
-
}
|
|
225508
|
-
}
|
|
225509
|
-
var WALLET_DIR3, HOUR_MS, DAY_MS, FileSpendControlStorage, InMemorySpendControlStorage, SpendControl;
|
|
225510
|
-
var init_spend_control = __esm({
|
|
225511
|
-
"src/spend-control.ts"() {
|
|
225512
|
-
"use strict";
|
|
225513
|
-
init_fs_read();
|
|
225514
|
-
WALLET_DIR3 = path5.join(homedir12(), ".openclaw", "blockrun");
|
|
225515
|
-
HOUR_MS = 60 * 60 * 1e3;
|
|
225516
|
-
DAY_MS = 24 * HOUR_MS;
|
|
225517
|
-
FileSpendControlStorage = class {
|
|
225518
|
-
spendingFile;
|
|
225519
|
-
constructor() {
|
|
225520
|
-
this.spendingFile = path5.join(WALLET_DIR3, "spending.json");
|
|
225521
|
-
}
|
|
225522
|
-
load() {
|
|
225523
|
-
try {
|
|
225524
|
-
if (fs3.existsSync(this.spendingFile)) {
|
|
225525
|
-
const data = JSON.parse(readTextFileSync(this.spendingFile));
|
|
225526
|
-
const rawLimits = data.limits ?? {};
|
|
225527
|
-
const rawHistory = data.history ?? [];
|
|
225528
|
-
const limits = {};
|
|
225529
|
-
for (const key2 of ["perRequest", "hourly", "daily", "session"]) {
|
|
225530
|
-
const val = rawLimits[key2];
|
|
225531
|
-
if (typeof val === "number" && val > 0 && Number.isFinite(val)) {
|
|
225532
|
-
limits[key2] = val;
|
|
225533
|
-
}
|
|
225534
|
-
}
|
|
225535
|
-
const history = [];
|
|
225536
|
-
if (Array.isArray(rawHistory)) {
|
|
225537
|
-
for (const r2 of rawHistory) {
|
|
225538
|
-
if (typeof r2?.timestamp === "number" && typeof r2?.amount === "number" && Number.isFinite(r2.timestamp) && Number.isFinite(r2.amount) && r2.amount >= 0) {
|
|
225539
|
-
history.push({
|
|
225540
|
-
timestamp: r2.timestamp,
|
|
225541
|
-
amount: r2.amount,
|
|
225542
|
-
model: typeof r2.model === "string" ? r2.model : void 0,
|
|
225543
|
-
action: typeof r2.action === "string" ? r2.action : void 0
|
|
225544
|
-
});
|
|
225545
|
-
}
|
|
225546
|
-
}
|
|
225547
|
-
}
|
|
225548
|
-
return { limits, history };
|
|
225549
|
-
}
|
|
225550
|
-
} catch (err) {
|
|
225551
|
-
console.error(`[ClawRouter] Failed to load spending data, starting fresh: ${err}`);
|
|
225552
|
-
}
|
|
225553
|
-
return null;
|
|
225554
|
-
}
|
|
225555
|
-
save(data) {
|
|
225556
|
-
try {
|
|
225557
|
-
if (!fs3.existsSync(WALLET_DIR3)) {
|
|
225558
|
-
fs3.mkdirSync(WALLET_DIR3, { recursive: true, mode: 448 });
|
|
225559
|
-
}
|
|
225560
|
-
fs3.writeFileSync(this.spendingFile, JSON.stringify(data, null, 2), {
|
|
225561
|
-
mode: 384
|
|
225562
|
-
});
|
|
225563
|
-
} catch (err) {
|
|
225564
|
-
console.error(`[ClawRouter] Failed to save spending data: ${err}`);
|
|
225565
|
-
}
|
|
225566
|
-
}
|
|
225567
|
-
};
|
|
225568
|
-
InMemorySpendControlStorage = class {
|
|
225569
|
-
data = null;
|
|
225570
|
-
load() {
|
|
225571
|
-
return this.data ? {
|
|
225572
|
-
limits: { ...this.data.limits },
|
|
225573
|
-
history: this.data.history.map((r2) => ({ ...r2 }))
|
|
225574
|
-
} : null;
|
|
225575
|
-
}
|
|
225576
|
-
save(data) {
|
|
225577
|
-
this.data = {
|
|
225578
|
-
limits: { ...data.limits },
|
|
225579
|
-
history: data.history.map((r2) => ({ ...r2 }))
|
|
225580
|
-
};
|
|
225581
|
-
}
|
|
225582
|
-
};
|
|
225583
|
-
SpendControl = class {
|
|
225584
|
-
limits = {};
|
|
225585
|
-
history = [];
|
|
225586
|
-
sessionSpent = 0;
|
|
225587
|
-
sessionCalls = 0;
|
|
225588
|
-
storage;
|
|
225589
|
-
now;
|
|
225590
|
-
constructor(options) {
|
|
225591
|
-
this.storage = options?.storage ?? new FileSpendControlStorage();
|
|
225592
|
-
this.now = options?.now ?? (() => Date.now());
|
|
225593
|
-
this.load();
|
|
225594
|
-
}
|
|
225595
|
-
setLimit(window2, amount) {
|
|
225596
|
-
if (!Number.isFinite(amount) || amount <= 0) {
|
|
225597
|
-
throw new Error("Limit must be a finite positive number");
|
|
225598
|
-
}
|
|
225599
|
-
this.limits[window2] = amount;
|
|
225600
|
-
this.save();
|
|
225601
|
-
}
|
|
225602
|
-
clearLimit(window2) {
|
|
225603
|
-
delete this.limits[window2];
|
|
225604
|
-
this.save();
|
|
225605
|
-
}
|
|
225606
|
-
getLimits() {
|
|
225607
|
-
return { ...this.limits };
|
|
225608
|
-
}
|
|
225609
|
-
check(estimatedCost2) {
|
|
225610
|
-
const now2 = this.now();
|
|
225611
|
-
if (this.limits.perRequest !== void 0) {
|
|
225612
|
-
if (estimatedCost2 > this.limits.perRequest) {
|
|
225613
|
-
return {
|
|
225614
|
-
allowed: false,
|
|
225615
|
-
blockedBy: "perRequest",
|
|
225616
|
-
remaining: this.limits.perRequest,
|
|
225617
|
-
reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
|
|
225618
|
-
};
|
|
225619
|
-
}
|
|
225620
|
-
}
|
|
225621
|
-
if (this.limits.hourly !== void 0) {
|
|
225622
|
-
const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
225623
|
-
const remaining = this.limits.hourly - hourlySpent;
|
|
225624
|
-
if (estimatedCost2 > remaining) {
|
|
225625
|
-
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
|
|
225626
|
-
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
|
|
225627
|
-
return {
|
|
225628
|
-
allowed: false,
|
|
225629
|
-
blockedBy: "hourly",
|
|
225630
|
-
remaining,
|
|
225631
|
-
reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
|
|
225632
|
-
resetIn
|
|
225633
|
-
};
|
|
225634
|
-
}
|
|
225635
|
-
}
|
|
225636
|
-
if (this.limits.daily !== void 0) {
|
|
225637
|
-
const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
225638
|
-
const remaining = this.limits.daily - dailySpent;
|
|
225639
|
-
if (estimatedCost2 > remaining) {
|
|
225640
|
-
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
|
|
225641
|
-
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
|
|
225642
|
-
return {
|
|
225643
|
-
allowed: false,
|
|
225644
|
-
blockedBy: "daily",
|
|
225645
|
-
remaining,
|
|
225646
|
-
reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
|
|
225647
|
-
resetIn
|
|
225648
|
-
};
|
|
225649
|
-
}
|
|
225650
|
-
}
|
|
225651
|
-
if (this.limits.session !== void 0) {
|
|
225652
|
-
const remaining = this.limits.session - this.sessionSpent;
|
|
225653
|
-
if (estimatedCost2 > remaining) {
|
|
225654
|
-
return {
|
|
225655
|
-
allowed: false,
|
|
225656
|
-
blockedBy: "session",
|
|
225657
|
-
remaining,
|
|
225658
|
-
reason: `Session limit exceeded: $${(this.sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
|
|
225659
|
-
};
|
|
225660
|
-
}
|
|
225661
|
-
}
|
|
225662
|
-
return { allowed: true };
|
|
225663
|
-
}
|
|
225664
|
-
record(amount, metadata) {
|
|
225665
|
-
if (!Number.isFinite(amount) || amount < 0) {
|
|
225666
|
-
throw new Error("Record amount must be a non-negative finite number");
|
|
225667
|
-
}
|
|
225668
|
-
const record = {
|
|
225669
|
-
timestamp: this.now(),
|
|
225670
|
-
amount,
|
|
225671
|
-
model: metadata?.model,
|
|
225672
|
-
action: metadata?.action
|
|
225673
|
-
};
|
|
225674
|
-
this.history.push(record);
|
|
225675
|
-
this.sessionSpent += amount;
|
|
225676
|
-
this.sessionCalls += 1;
|
|
225677
|
-
this.cleanup();
|
|
225678
|
-
this.save();
|
|
225679
|
-
}
|
|
225680
|
-
getSpendingInWindow(from15, to) {
|
|
225681
|
-
return this.history.filter((r2) => r2.timestamp >= from15 && r2.timestamp <= to).reduce((sum, r2) => sum + r2.amount, 0);
|
|
225682
|
-
}
|
|
225683
|
-
getSpending(window2) {
|
|
225684
|
-
const now2 = this.now();
|
|
225685
|
-
switch (window2) {
|
|
225686
|
-
case "hourly":
|
|
225687
|
-
return this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
225688
|
-
case "daily":
|
|
225689
|
-
return this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
225690
|
-
case "session":
|
|
225691
|
-
return this.sessionSpent;
|
|
225692
|
-
}
|
|
225693
|
-
}
|
|
225694
|
-
getRemaining(window2) {
|
|
225695
|
-
const limit = this.limits[window2];
|
|
225696
|
-
if (limit === void 0) return null;
|
|
225697
|
-
return Math.max(0, limit - this.getSpending(window2));
|
|
225698
|
-
}
|
|
225699
|
-
getStatus() {
|
|
225700
|
-
const now2 = this.now();
|
|
225701
|
-
const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
225702
|
-
const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
225703
|
-
return {
|
|
225704
|
-
limits: { ...this.limits },
|
|
225705
|
-
spending: {
|
|
225706
|
-
hourly: hourlySpent,
|
|
225707
|
-
daily: dailySpent,
|
|
225708
|
-
session: this.sessionSpent
|
|
225709
|
-
},
|
|
225710
|
-
remaining: {
|
|
225711
|
-
hourly: this.limits.hourly !== void 0 ? this.limits.hourly - hourlySpent : null,
|
|
225712
|
-
daily: this.limits.daily !== void 0 ? this.limits.daily - dailySpent : null,
|
|
225713
|
-
session: this.limits.session !== void 0 ? this.limits.session - this.sessionSpent : null
|
|
225714
|
-
},
|
|
225715
|
-
calls: this.sessionCalls
|
|
225716
|
-
};
|
|
225717
|
-
}
|
|
225718
|
-
getHistory(limit) {
|
|
225719
|
-
const records = [...this.history].reverse();
|
|
225720
|
-
return limit ? records.slice(0, limit) : records;
|
|
225721
|
-
}
|
|
225722
|
-
resetSession() {
|
|
225723
|
-
this.sessionSpent = 0;
|
|
225724
|
-
this.sessionCalls = 0;
|
|
225725
|
-
}
|
|
225726
|
-
cleanup() {
|
|
225727
|
-
const cutoff = this.now() - DAY_MS;
|
|
225728
|
-
this.history = this.history.filter((r2) => r2.timestamp >= cutoff);
|
|
225729
|
-
}
|
|
225730
|
-
save() {
|
|
225731
|
-
this.storage.save({
|
|
225732
|
-
limits: { ...this.limits },
|
|
225733
|
-
history: [...this.history]
|
|
225734
|
-
});
|
|
225735
|
-
}
|
|
225736
|
-
load() {
|
|
225737
|
-
const data = this.storage.load();
|
|
225738
|
-
if (data) {
|
|
225739
|
-
this.limits = data.limits;
|
|
225740
|
-
this.history = data.history;
|
|
225741
|
-
this.cleanup();
|
|
225742
|
-
}
|
|
225743
|
-
}
|
|
225744
|
-
};
|
|
225745
|
-
}
|
|
225746
|
-
});
|
|
225747
|
-
|
|
225748
226323
|
// src/retry.ts
|
|
225749
226324
|
function sleep3(ms) {
|
|
225750
226325
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -225814,7 +226389,7 @@ import {
|
|
|
225814
226389
|
readdirSync,
|
|
225815
226390
|
mkdirSync as mkdirSync3,
|
|
225816
226391
|
copyFileSync,
|
|
225817
|
-
renameSync
|
|
226392
|
+
renameSync as renameSync2
|
|
225818
226393
|
} from "fs";
|
|
225819
226394
|
import { readFile as readFileAsync } from "fs/promises";
|
|
225820
226395
|
import { homedir as homedir13 } from "os";
|
|
@@ -226092,7 +226667,7 @@ function injectModelsConfig(logger48, options = {}) {
|
|
|
226092
226667
|
try {
|
|
226093
226668
|
const tmpPath = `${configPath}.tmp.${process.pid}`;
|
|
226094
226669
|
writeFileSync3(tmpPath, JSON.stringify(config, null, 2));
|
|
226095
|
-
|
|
226670
|
+
renameSync2(tmpPath, configPath);
|
|
226096
226671
|
logger48.info("Smart routing enabled (blockrun/auto)");
|
|
226097
226672
|
} catch (err) {
|
|
226098
226673
|
logger48.info(`Failed to write config: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -226128,7 +226703,7 @@ function syncAgentModelCache(logger48, options = {}) {
|
|
|
226128
226703
|
entry.models = VISIBLE_OPENCLAW_MODELS;
|
|
226129
226704
|
const tmpPath = `${cachePath}.tmp.${process.pid}`;
|
|
226130
226705
|
writeFileSync3(tmpPath, JSON.stringify(cache2, null, 2));
|
|
226131
|
-
|
|
226706
|
+
renameSync2(tmpPath, cachePath);
|
|
226132
226707
|
logger48.info(
|
|
226133
226708
|
`Repaired ${agent} model cache: ${staleCount} \u2192 ${expectedIds.length} BlockRun models`
|
|
226134
226709
|
);
|
|
@@ -227491,7 +228066,7 @@ ${errText}`
|
|
|
227491
228066
|
}
|
|
227492
228067
|
const tmpPath = `${configPath}.tmp.${process.pid}`;
|
|
227493
228068
|
writeFileSync3(tmpPath, JSON.stringify(config, null, 2));
|
|
227494
|
-
|
|
228069
|
+
renameSync2(tmpPath, configPath);
|
|
227495
228070
|
api.logger.info("ClawRouter config cleaned up");
|
|
227496
228071
|
}
|
|
227497
228072
|
} catch (err) {
|
|
@@ -227527,6 +228102,8 @@ export {
|
|
|
227527
228102
|
BALANCE_THRESHOLDS,
|
|
227528
228103
|
BLOCKRUN_MODELS,
|
|
227529
228104
|
BalanceMonitor,
|
|
228105
|
+
CAIP2_BASE,
|
|
228106
|
+
CAIP2_SOLANA_MAINNET,
|
|
227530
228107
|
DEFAULT_RETRY_CONFIG,
|
|
227531
228108
|
DEFAULT_ROUTING_CONFIG,
|
|
227532
228109
|
DEFAULT_SESSION_CONFIG,
|
|
@@ -227535,6 +228112,7 @@ export {
|
|
|
227535
228112
|
InMemorySpendControlStorage,
|
|
227536
228113
|
InsufficientFundsError2 as InsufficientFundsError,
|
|
227537
228114
|
MODEL_ALIASES,
|
|
228115
|
+
MalformedSpendPolicyError,
|
|
227538
228116
|
OPENCLAW_MODELS,
|
|
227539
228117
|
PARTNER_SERVICES,
|
|
227540
228118
|
RequestDeduplicator,
|
|
@@ -227543,6 +228121,7 @@ export {
|
|
|
227543
228121
|
SessionStore,
|
|
227544
228122
|
SolanaBalanceMonitor,
|
|
227545
228123
|
SpendControl,
|
|
228124
|
+
SpendPolicyError,
|
|
227546
228125
|
VISIBLE_OPENCLAW_MODELS,
|
|
227547
228126
|
blockrunProvider,
|
|
227548
228127
|
buildImageGenerationProvider,
|
|
@@ -227582,6 +228161,7 @@ export {
|
|
|
227582
228161
|
loadPaymentChain,
|
|
227583
228162
|
logUsage,
|
|
227584
228163
|
parseCallArgs,
|
|
228164
|
+
registerSpendPolicyHook,
|
|
227585
228165
|
resolveModelAlias,
|
|
227586
228166
|
resolvePaymentChain,
|
|
227587
228167
|
route,
|