@blockrun/clawrouter 0.12.95 → 0.12.97

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.
Files changed (282) hide show
  1. package/dist/auth.d.ts +82 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +388 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/balance.d.ts +97 -0
  6. package/dist/balance.d.ts.map +1 -0
  7. package/dist/balance.js +157 -0
  8. package/dist/balance.js.map +1 -0
  9. package/dist/cli.d.ts +15 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +256 -54994
  12. package/dist/cli.js.map +1 -1
  13. package/dist/compression/codebook.d.ts +24 -0
  14. package/dist/compression/codebook.d.ts.map +1 -0
  15. package/dist/compression/codebook.js +119 -0
  16. package/dist/compression/codebook.js.map +1 -0
  17. package/dist/compression/index.d.ts +33 -0
  18. package/dist/compression/index.d.ts.map +1 -0
  19. package/dist/compression/index.js +246 -0
  20. package/dist/compression/index.js.map +1 -0
  21. package/dist/compression/layers/deduplication.d.ts +28 -0
  22. package/dist/compression/layers/deduplication.d.ts.map +1 -0
  23. package/dist/compression/layers/deduplication.js +101 -0
  24. package/dist/compression/layers/deduplication.js.map +1 -0
  25. package/dist/compression/layers/dictionary.d.ts +21 -0
  26. package/dist/compression/layers/dictionary.d.ts.map +1 -0
  27. package/dist/compression/layers/dictionary.js +73 -0
  28. package/dist/compression/layers/dictionary.js.map +1 -0
  29. package/dist/compression/layers/dynamic-codebook.d.ts +26 -0
  30. package/dist/compression/layers/dynamic-codebook.d.ts.map +1 -0
  31. package/dist/compression/layers/dynamic-codebook.js +149 -0
  32. package/dist/compression/layers/dynamic-codebook.js.map +1 -0
  33. package/dist/compression/layers/json-compact.d.ts +23 -0
  34. package/dist/compression/layers/json-compact.d.ts.map +1 -0
  35. package/dist/compression/layers/json-compact.js +79 -0
  36. package/dist/compression/layers/json-compact.js.map +1 -0
  37. package/dist/compression/layers/observation.d.ts +21 -0
  38. package/dist/compression/layers/observation.d.ts.map +1 -0
  39. package/dist/compression/layers/observation.js +130 -0
  40. package/dist/compression/layers/observation.js.map +1 -0
  41. package/dist/compression/layers/paths.d.ts +24 -0
  42. package/dist/compression/layers/paths.d.ts.map +1 -0
  43. package/dist/compression/layers/paths.js +110 -0
  44. package/dist/compression/layers/paths.js.map +1 -0
  45. package/dist/compression/layers/whitespace.d.ts +27 -0
  46. package/dist/compression/layers/whitespace.d.ts.map +1 -0
  47. package/dist/compression/layers/whitespace.js +60 -0
  48. package/dist/compression/layers/whitespace.js.map +1 -0
  49. package/dist/compression/types.d.ts +84 -0
  50. package/dist/compression/types.d.ts.map +1 -0
  51. package/dist/compression/types.js +27 -0
  52. package/dist/compression/types.js.map +1 -0
  53. package/dist/config.d.ts +12 -0
  54. package/dist/config.d.ts.map +1 -0
  55. package/dist/config.js +22 -0
  56. package/dist/config.js.map +1 -0
  57. package/dist/dedup.d.ts +34 -0
  58. package/dist/dedup.d.ts.map +1 -0
  59. package/dist/dedup.js +150 -0
  60. package/dist/dedup.js.map +1 -0
  61. package/dist/doctor.d.ts +8 -0
  62. package/dist/doctor.d.ts.map +1 -0
  63. package/dist/doctor.js +375 -0
  64. package/dist/doctor.js.map +1 -0
  65. package/dist/error-classification.test.d.ts +2 -0
  66. package/dist/error-classification.test.d.ts.map +1 -0
  67. package/dist/error-classification.test.js +59 -0
  68. package/dist/error-classification.test.js.map +1 -0
  69. package/dist/errors.d.ts +54 -0
  70. package/dist/errors.d.ts.map +1 -0
  71. package/dist/errors.js +85 -0
  72. package/dist/errors.js.map +1 -0
  73. package/dist/exclude-models.d.ts +28 -0
  74. package/dist/exclude-models.d.ts.map +1 -0
  75. package/dist/exclude-models.integration.test.d.ts +2 -0
  76. package/dist/exclude-models.integration.test.d.ts.map +1 -0
  77. package/dist/exclude-models.integration.test.js +46 -0
  78. package/dist/exclude-models.integration.test.js.map +1 -0
  79. package/dist/exclude-models.js +70 -0
  80. package/dist/exclude-models.js.map +1 -0
  81. package/dist/exclude-models.test.d.ts +5 -0
  82. package/dist/exclude-models.test.d.ts.map +1 -0
  83. package/dist/exclude-models.test.js +95 -0
  84. package/dist/exclude-models.test.js.map +1 -0
  85. package/dist/fs-read.d.ts +11 -0
  86. package/dist/fs-read.d.ts.map +1 -0
  87. package/dist/fs-read.js +47 -0
  88. package/dist/fs-read.js.map +1 -0
  89. package/dist/index.d.ts +34 -1368
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +1071 -56194
  92. package/dist/index.js.map +1 -1
  93. package/dist/journal.d.ts +67 -0
  94. package/dist/journal.d.ts.map +1 -0
  95. package/dist/journal.js +184 -0
  96. package/dist/journal.js.map +1 -0
  97. package/dist/journal.test.d.ts +2 -0
  98. package/dist/journal.test.d.ts.map +1 -0
  99. package/dist/journal.test.js +201 -0
  100. package/dist/journal.test.js.map +1 -0
  101. package/dist/logger.d.ts +33 -0
  102. package/dist/logger.d.ts.map +1 -0
  103. package/dist/logger.js +35 -0
  104. package/dist/logger.js.map +1 -0
  105. package/dist/models.d.ts +107 -0
  106. package/dist/models.d.ts.map +1 -0
  107. package/dist/models.js +941 -0
  108. package/dist/models.js.map +1 -0
  109. package/dist/models.test.d.ts +2 -0
  110. package/dist/models.test.d.ts.map +1 -0
  111. package/dist/models.test.js +38 -0
  112. package/dist/models.test.js.map +1 -0
  113. package/dist/partners/index.d.ts +8 -0
  114. package/dist/partners/index.d.ts.map +1 -0
  115. package/dist/partners/index.js +6 -0
  116. package/dist/partners/index.js.map +1 -0
  117. package/dist/partners/registry.d.ts +51 -0
  118. package/dist/partners/registry.d.ts.map +1 -0
  119. package/dist/partners/registry.js +256 -0
  120. package/dist/partners/registry.js.map +1 -0
  121. package/dist/partners/tools.d.ts +24 -0
  122. package/dist/partners/tools.d.ts.map +1 -0
  123. package/dist/partners/tools.js +97 -0
  124. package/dist/partners/tools.js.map +1 -0
  125. package/dist/payment-preauth.d.ts +17 -0
  126. package/dist/payment-preauth.d.ts.map +1 -0
  127. package/dist/payment-preauth.js +102 -0
  128. package/dist/payment-preauth.js.map +1 -0
  129. package/dist/provider.d.ts +19 -0
  130. package/dist/provider.d.ts.map +1 -0
  131. package/dist/provider.js +45 -0
  132. package/dist/provider.js.map +1 -0
  133. package/dist/proxy.d.ts +210 -0
  134. package/dist/proxy.d.ts.map +1 -0
  135. package/dist/proxy.debrand.test.d.ts +2 -0
  136. package/dist/proxy.debrand.test.d.ts.map +1 -0
  137. package/dist/proxy.debrand.test.js +101 -0
  138. package/dist/proxy.debrand.test.js.map +1 -0
  139. package/dist/proxy.degraded-response.test.d.ts +2 -0
  140. package/dist/proxy.degraded-response.test.d.ts.map +1 -0
  141. package/dist/proxy.degraded-response.test.js +105 -0
  142. package/dist/proxy.degraded-response.test.js.map +1 -0
  143. package/dist/proxy.image-download.test.d.ts +2 -0
  144. package/dist/proxy.image-download.test.d.ts.map +1 -0
  145. package/dist/proxy.image-download.test.js +92 -0
  146. package/dist/proxy.image-download.test.js.map +1 -0
  147. package/dist/proxy.js +3810 -0
  148. package/dist/proxy.js.map +1 -0
  149. package/dist/proxy.models-endpoint.test.d.ts +2 -0
  150. package/dist/proxy.models-endpoint.test.d.ts.map +1 -0
  151. package/dist/proxy.models-endpoint.test.js +19 -0
  152. package/dist/proxy.models-endpoint.test.js.map +1 -0
  153. package/dist/proxy.multiturn-thinking.test.d.ts +2 -0
  154. package/dist/proxy.multiturn-thinking.test.d.ts.map +1 -0
  155. package/dist/proxy.multiturn-thinking.test.js +82 -0
  156. package/dist/proxy.multiturn-thinking.test.js.map +1 -0
  157. package/dist/proxy.payment-chain-reuse.test.d.ts +2 -0
  158. package/dist/proxy.payment-chain-reuse.test.d.ts.map +1 -0
  159. package/dist/proxy.payment-chain-reuse.test.js +30 -0
  160. package/dist/proxy.payment-chain-reuse.test.js.map +1 -0
  161. package/dist/proxy.solana-resilience.test.d.ts +12 -0
  162. package/dist/proxy.solana-resilience.test.d.ts.map +1 -0
  163. package/dist/proxy.solana-resilience.test.js +39 -0
  164. package/dist/proxy.solana-resilience.test.js.map +1 -0
  165. package/dist/report.d.ts +6 -0
  166. package/dist/report.d.ts.map +1 -0
  167. package/dist/report.js +44 -0
  168. package/dist/report.js.map +1 -0
  169. package/dist/response-cache.advanced.test.d.ts +2 -0
  170. package/dist/response-cache.advanced.test.d.ts.map +1 -0
  171. package/dist/response-cache.advanced.test.js +566 -0
  172. package/dist/response-cache.advanced.test.js.map +1 -0
  173. package/dist/response-cache.d.ts +85 -0
  174. package/dist/response-cache.d.ts.map +1 -0
  175. package/dist/response-cache.edge-cases.test.d.ts +2 -0
  176. package/dist/response-cache.edge-cases.test.d.ts.map +1 -0
  177. package/dist/response-cache.edge-cases.test.js +488 -0
  178. package/dist/response-cache.edge-cases.test.js.map +1 -0
  179. package/dist/response-cache.extreme.test.d.ts +2 -0
  180. package/dist/response-cache.extreme.test.d.ts.map +1 -0
  181. package/dist/response-cache.extreme.test.js +561 -0
  182. package/dist/response-cache.extreme.test.js.map +1 -0
  183. package/dist/response-cache.js +240 -0
  184. package/dist/response-cache.js.map +1 -0
  185. package/dist/response-cache.test.d.ts +2 -0
  186. package/dist/response-cache.test.d.ts.map +1 -0
  187. package/dist/response-cache.test.js +242 -0
  188. package/dist/response-cache.test.js.map +1 -0
  189. package/dist/retry.d.ts +42 -0
  190. package/dist/retry.d.ts.map +1 -0
  191. package/dist/retry.js +99 -0
  192. package/dist/retry.js.map +1 -0
  193. package/dist/router/config.d.ts +11 -0
  194. package/dist/router/config.d.ts.map +1 -0
  195. package/dist/router/config.js +1215 -0
  196. package/dist/router/config.js.map +1 -0
  197. package/dist/router/index.d.ts +18 -0
  198. package/dist/router/index.d.ts.map +1 -0
  199. package/dist/router/index.js +19 -0
  200. package/dist/router/index.js.map +1 -0
  201. package/dist/router/llm-classifier.d.ts +29 -0
  202. package/dist/router/llm-classifier.d.ts.map +1 -0
  203. package/dist/router/llm-classifier.js +99 -0
  204. package/dist/router/llm-classifier.js.map +1 -0
  205. package/dist/router/rules.d.ts +12 -0
  206. package/dist/router/rules.d.ts.map +1 -0
  207. package/dist/router/rules.js +202 -0
  208. package/dist/router/rules.js.map +1 -0
  209. package/dist/router/selector.d.ts +58 -0
  210. package/dist/router/selector.d.ts.map +1 -0
  211. package/dist/router/selector.js +165 -0
  212. package/dist/router/selector.js.map +1 -0
  213. package/dist/router/selector.test.d.ts +2 -0
  214. package/dist/router/selector.test.d.ts.map +1 -0
  215. package/dist/router/selector.test.js +67 -0
  216. package/dist/router/selector.test.js.map +1 -0
  217. package/dist/router/strategy.d.ts +19 -0
  218. package/dist/router/strategy.d.ts.map +1 -0
  219. package/dist/router/strategy.js +138 -0
  220. package/dist/router/strategy.js.map +1 -0
  221. package/dist/router/strategy.test.d.ts +2 -0
  222. package/dist/router/strategy.test.d.ts.map +1 -0
  223. package/dist/router/strategy.test.js +131 -0
  224. package/dist/router/strategy.test.js.map +1 -0
  225. package/dist/router/types.d.ts +127 -0
  226. package/dist/router/types.d.ts.map +1 -0
  227. package/dist/router/types.js +11 -0
  228. package/dist/router/types.js.map +1 -0
  229. package/dist/session.d.ts +124 -0
  230. package/dist/session.d.ts.map +1 -0
  231. package/dist/session.js +256 -0
  232. package/dist/session.js.map +1 -0
  233. package/dist/session.test.d.ts +2 -0
  234. package/dist/session.test.d.ts.map +1 -0
  235. package/dist/session.test.js +163 -0
  236. package/dist/session.test.js.map +1 -0
  237. package/dist/solana-balance.d.ts +48 -0
  238. package/dist/solana-balance.d.ts.map +1 -0
  239. package/dist/solana-balance.js +142 -0
  240. package/dist/solana-balance.js.map +1 -0
  241. package/dist/spend-control.d.ts +112 -0
  242. package/dist/spend-control.d.ts.map +1 -0
  243. package/dist/spend-control.js +278 -0
  244. package/dist/spend-control.js.map +1 -0
  245. package/dist/spend-control.test.d.ts +5 -0
  246. package/dist/spend-control.test.d.ts.map +1 -0
  247. package/dist/spend-control.test.js +210 -0
  248. package/dist/spend-control.test.js.map +1 -0
  249. package/dist/stats.d.ts +64 -0
  250. package/dist/stats.d.ts.map +1 -0
  251. package/dist/stats.js +295 -0
  252. package/dist/stats.js.map +1 -0
  253. package/dist/types.d.ts +150 -0
  254. package/dist/types.d.ts.map +1 -0
  255. package/dist/types.js +9 -0
  256. package/dist/types.js.map +1 -0
  257. package/dist/update-hint.test.d.ts +9 -0
  258. package/dist/update-hint.test.d.ts.map +1 -0
  259. package/dist/update-hint.test.js +156 -0
  260. package/dist/update-hint.test.js.map +1 -0
  261. package/dist/updater.d.ts +10 -0
  262. package/dist/updater.d.ts.map +1 -0
  263. package/dist/updater.js +55 -0
  264. package/dist/updater.js.map +1 -0
  265. package/dist/version.d.ts +3 -0
  266. package/dist/version.d.ts.map +1 -0
  267. package/dist/version.js +16 -0
  268. package/dist/version.js.map +1 -0
  269. package/dist/wallet.d.ts +52 -0
  270. package/dist/wallet.d.ts.map +1 -0
  271. package/dist/wallet.js +93 -0
  272. package/dist/wallet.js.map +1 -0
  273. package/dist/wallet.test.d.ts +6 -0
  274. package/dist/wallet.test.d.ts.map +1 -0
  275. package/dist/wallet.test.js +117 -0
  276. package/dist/wallet.test.js.map +1 -0
  277. package/dist/x402-sdk.test.d.ts +6 -0
  278. package/dist/x402-sdk.test.d.ts.map +1 -0
  279. package/dist/x402-sdk.test.js +161 -0
  280. package/dist/x402-sdk.test.js.map +1 -0
  281. package/package.json +1 -1
  282. package/scripts/e2e-multiturn.mjs +4 -1
package/dist/doctor.js ADDED
@@ -0,0 +1,375 @@
1
+ /**
2
+ * BlockRun Doctor - AI-Powered Diagnostics
3
+ *
4
+ * Collects system diagnostics and sends to Claude Opus 4.6 for analysis.
5
+ * Works independently of OpenClaw - direct x402 payment to BlockRun API.
6
+ */
7
+ import { platform, arch, freemem, totalmem } from "node:os";
8
+ import { createPublicClient, http } from "viem";
9
+ import { base } from "viem/chains";
10
+ import { privateKeyToAccount } from "viem/accounts";
11
+ import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
12
+ import { registerExactEvmScheme } from "@x402/evm/exact/client";
13
+ import { toClientEvmSigner } from "@x402/evm";
14
+ import { resolveOrGenerateWalletKey, resolvePaymentChain, WALLET_FILE } from "./auth.js";
15
+ import { BalanceMonitor } from "./balance.js";
16
+ import { getSolanaAddress } from "./wallet.js";
17
+ import { getStats } from "./stats.js";
18
+ import { getProxyPort } from "./proxy.js";
19
+ import { VERSION } from "./version.js";
20
+ // Helpers
21
+ function formatBytes(bytes) {
22
+ const gb = bytes / (1024 * 1024 * 1024);
23
+ return `${gb.toFixed(1)}GB`;
24
+ }
25
+ function green(text) {
26
+ return `\x1b[32m✓\x1b[0m ${text}`;
27
+ }
28
+ function red(text) {
29
+ return `\x1b[31m✗\x1b[0m ${text}`;
30
+ }
31
+ function yellow(text) {
32
+ return `\x1b[33m⚠\x1b[0m ${text}`;
33
+ }
34
+ // Collect system info
35
+ function collectSystemInfo() {
36
+ return {
37
+ os: `${platform()} ${arch()}`,
38
+ arch: arch(),
39
+ nodeVersion: process.version,
40
+ memoryFree: formatBytes(freemem()),
41
+ memoryTotal: formatBytes(totalmem()),
42
+ };
43
+ }
44
+ // Collect wallet info
45
+ async function collectWalletInfo() {
46
+ try {
47
+ const { key, address, source, solanaPrivateKeyBytes } = await resolveOrGenerateWalletKey();
48
+ if (!key || !address) {
49
+ return {
50
+ exists: false,
51
+ valid: false,
52
+ address: null,
53
+ solanaAddress: null,
54
+ balance: null,
55
+ isLow: false,
56
+ isEmpty: true,
57
+ source: null,
58
+ paymentChain: "base",
59
+ };
60
+ }
61
+ // Derive Solana address if mnemonic-based wallet
62
+ let solanaAddress = null;
63
+ if (solanaPrivateKeyBytes) {
64
+ try {
65
+ solanaAddress = await getSolanaAddress(solanaPrivateKeyBytes);
66
+ }
67
+ catch {
68
+ // Non-fatal
69
+ }
70
+ }
71
+ // Check balance on the active payment chain
72
+ const paymentChain = await resolvePaymentChain();
73
+ try {
74
+ let balanceInfo;
75
+ if (paymentChain === "solana" && solanaAddress) {
76
+ const { SolanaBalanceMonitor } = await import("./solana-balance.js");
77
+ const monitor = new SolanaBalanceMonitor(solanaAddress);
78
+ balanceInfo = await monitor.checkBalance();
79
+ }
80
+ else {
81
+ const monitor = new BalanceMonitor(address);
82
+ balanceInfo = await monitor.checkBalance();
83
+ }
84
+ return {
85
+ exists: true,
86
+ valid: true,
87
+ address,
88
+ solanaAddress,
89
+ balance: balanceInfo.balanceUSD,
90
+ isLow: balanceInfo.isLow,
91
+ isEmpty: balanceInfo.isEmpty,
92
+ source,
93
+ paymentChain,
94
+ };
95
+ }
96
+ catch {
97
+ return {
98
+ exists: true,
99
+ valid: true,
100
+ address,
101
+ solanaAddress,
102
+ balance: null,
103
+ isLow: false,
104
+ isEmpty: false,
105
+ source,
106
+ paymentChain,
107
+ };
108
+ }
109
+ }
110
+ catch {
111
+ return {
112
+ exists: false,
113
+ valid: false,
114
+ address: null,
115
+ solanaAddress: null,
116
+ balance: null,
117
+ isLow: false,
118
+ isEmpty: true,
119
+ source: null,
120
+ paymentChain: "base",
121
+ };
122
+ }
123
+ }
124
+ // Collect network info
125
+ async function collectNetworkInfo() {
126
+ const port = getProxyPort();
127
+ // Check BlockRun API
128
+ let blockrunReachable = false;
129
+ let blockrunLatency = null;
130
+ try {
131
+ const start = Date.now();
132
+ const response = await fetch("https://blockrun.ai/api/v1/models", {
133
+ method: "GET",
134
+ signal: AbortSignal.timeout(10000),
135
+ });
136
+ blockrunLatency = Date.now() - start;
137
+ blockrunReachable = response.ok || response.status === 402;
138
+ }
139
+ catch {
140
+ // blockrunReachable already false
141
+ }
142
+ // Check local proxy
143
+ let proxyRunning = false;
144
+ try {
145
+ const response = await fetch(`http://127.0.0.1:${port}/health`, {
146
+ method: "GET",
147
+ signal: AbortSignal.timeout(3000),
148
+ });
149
+ proxyRunning = response.ok;
150
+ }
151
+ catch {
152
+ // proxyRunning already false
153
+ }
154
+ return {
155
+ blockrunApi: { reachable: blockrunReachable, latencyMs: blockrunLatency },
156
+ localProxy: { running: proxyRunning, port },
157
+ };
158
+ }
159
+ // Collect log info
160
+ async function collectLogInfo() {
161
+ try {
162
+ const stats = await getStats(1); // Last 1 day
163
+ return {
164
+ requestsLast24h: stats.totalRequests,
165
+ costLast24h: `$${stats.totalCost.toFixed(4)}`,
166
+ errorsFound: 0, // TODO: parse error logs
167
+ };
168
+ }
169
+ catch {
170
+ return {
171
+ requestsLast24h: 0,
172
+ costLast24h: "$0.00",
173
+ errorsFound: 0,
174
+ };
175
+ }
176
+ }
177
+ // Identify issues
178
+ function identifyIssues(result) {
179
+ const issues = [];
180
+ if (!result.wallet.exists) {
181
+ issues.push("No wallet found");
182
+ }
183
+ if (result.wallet.isEmpty) {
184
+ const chain = result.wallet.paymentChain === "solana" ? "Solana" : "Base";
185
+ issues.push(`Wallet is empty - need to fund with USDC on ${chain}`);
186
+ if (result.wallet.paymentChain === "base" && result.wallet.solanaAddress) {
187
+ issues.push("Tip: if you funded Solana, run /wallet solana to switch chains");
188
+ }
189
+ }
190
+ else if (result.wallet.isLow) {
191
+ issues.push("Wallet balance is low (< $1.00)");
192
+ }
193
+ if (!result.network.blockrunApi.reachable) {
194
+ issues.push("Cannot reach BlockRun API - check internet connection");
195
+ }
196
+ if (!result.network.localProxy.running) {
197
+ issues.push(`Local proxy not running on port ${result.network.localProxy.port}`);
198
+ }
199
+ return issues;
200
+ }
201
+ // Print diagnostics to terminal
202
+ function printDiagnostics(result) {
203
+ console.log("\n🔍 Collecting diagnostics...\n");
204
+ // System
205
+ console.log("System");
206
+ console.log(` ${green(`OS: ${result.system.os}`)}`);
207
+ console.log(` ${green(`Node: ${result.system.nodeVersion}`)}`);
208
+ console.log(` ${green(`Memory: ${result.system.memoryFree} free / ${result.system.memoryTotal}`)}`);
209
+ // Wallet
210
+ console.log("\nWallet");
211
+ if (result.wallet.exists && result.wallet.valid) {
212
+ console.log(` ${green(`Key: ${WALLET_FILE} (${result.wallet.source})`)}`);
213
+ console.log(` ${green(`EVM Address: ${result.wallet.address}`)}`);
214
+ if (result.wallet.solanaAddress) {
215
+ console.log(` ${green(`Solana Address: ${result.wallet.solanaAddress}`)}`);
216
+ }
217
+ const chainLabel = result.wallet.paymentChain === "solana" ? "Solana" : "Base";
218
+ console.log(` ${green(`Chain: ${chainLabel}`)}`);
219
+ if (result.wallet.isEmpty) {
220
+ console.log(` ${red(`Balance: $0.00 - NEED TO FUND WITH USDC ON ${chainLabel.toUpperCase()}!`)}`);
221
+ if (result.wallet.paymentChain === "base" && result.wallet.solanaAddress) {
222
+ console.log(` ${yellow(`Tip: funded Solana instead? Run /wallet solana to switch`)}`);
223
+ }
224
+ }
225
+ else if (result.wallet.isLow) {
226
+ console.log(` ${yellow(`Balance: ${result.wallet.balance} (low)`)}`);
227
+ }
228
+ else if (result.wallet.balance) {
229
+ console.log(` ${green(`Balance: ${result.wallet.balance}`)}`);
230
+ }
231
+ else {
232
+ console.log(` ${yellow(`Balance: checking...`)}`);
233
+ }
234
+ }
235
+ else {
236
+ console.log(` ${red("No wallet found")}`);
237
+ }
238
+ // Network
239
+ console.log("\nNetwork");
240
+ if (result.network.blockrunApi.reachable) {
241
+ console.log(` ${green(`BlockRun API: reachable (${result.network.blockrunApi.latencyMs}ms)`)}`);
242
+ }
243
+ else {
244
+ console.log(` ${red("BlockRun API: unreachable")}`);
245
+ }
246
+ if (result.network.localProxy.running) {
247
+ console.log(` ${green(`Local proxy: running on :${result.network.localProxy.port}`)}`);
248
+ }
249
+ else {
250
+ console.log(` ${red(`Local proxy: not running on :${result.network.localProxy.port}`)}`);
251
+ }
252
+ // Logs
253
+ console.log("\nLogs");
254
+ console.log(` ${green(`Last 24h: ${result.logs.requestsLast24h} requests, ${result.logs.costLast24h} spent`)}`);
255
+ if (result.logs.errorsFound > 0) {
256
+ console.log(` ${yellow(`${result.logs.errorsFound} errors found in logs`)}`);
257
+ }
258
+ // Issues summary
259
+ if (result.issues.length > 0) {
260
+ console.log("\n⚠️ Issues Found:");
261
+ for (const issue of result.issues) {
262
+ console.log(` • ${issue}`);
263
+ }
264
+ }
265
+ }
266
+ const DOCTOR_MODELS = {
267
+ sonnet: {
268
+ id: "anthropic/claude-sonnet-4.6",
269
+ name: "Claude Sonnet 4.6",
270
+ cost: "~$0.003",
271
+ },
272
+ opus: {
273
+ id: "anthropic/claude-opus-4.6",
274
+ name: "Claude Opus 4.6",
275
+ cost: "~$0.01",
276
+ },
277
+ };
278
+ // Send to AI for analysis
279
+ async function analyzeWithAI(diagnostics, userQuestion, model = "sonnet") {
280
+ // Check if wallet has funds
281
+ if (diagnostics.wallet.isEmpty) {
282
+ console.log("\n💳 Wallet is empty - cannot call AI for analysis.");
283
+ console.log(` Fund your EVM wallet with USDC on Base: ${diagnostics.wallet.address}`);
284
+ if (diagnostics.wallet.solanaAddress) {
285
+ console.log(` Fund your Solana wallet with USDC: ${diagnostics.wallet.solanaAddress}`);
286
+ }
287
+ console.log(" Get USDC: https://www.coinbase.com/price/usd-coin");
288
+ console.log(" Bridge to Base: https://bridge.base.org\n");
289
+ return;
290
+ }
291
+ const modelConfig = DOCTOR_MODELS[model];
292
+ console.log(`\n📤 Sending to ${modelConfig.name} (${modelConfig.cost})...\n`);
293
+ try {
294
+ const { key } = await resolveOrGenerateWalletKey();
295
+ const account = privateKeyToAccount(key);
296
+ const publicClient = createPublicClient({ chain: base, transport: http() });
297
+ const evmSigner = toClientEvmSigner(account, publicClient);
298
+ const x402 = new x402Client();
299
+ registerExactEvmScheme(x402, { signer: evmSigner });
300
+ const paymentFetch = wrapFetchWithPayment(fetch, x402);
301
+ const response = await paymentFetch("https://blockrun.ai/api/v1/chat/completions", {
302
+ method: "POST",
303
+ headers: { "Content-Type": "application/json" },
304
+ body: JSON.stringify({
305
+ model: modelConfig.id,
306
+ stream: false,
307
+ messages: [
308
+ {
309
+ role: "system",
310
+ content: `You are a technical support expert for BlockRun and ClawRouter.
311
+ Analyze the diagnostics and:
312
+ 1. Identify the root cause of any issues
313
+ 2. Provide specific, actionable fix commands (bash)
314
+ 3. Explain why the issue occurred briefly
315
+ 4. Be concise but thorough
316
+ 5. Format commands in code blocks`,
317
+ },
318
+ {
319
+ role: "user",
320
+ content: userQuestion
321
+ ? `Here are my system diagnostics:\n\n${JSON.stringify(diagnostics, null, 2)}\n\nUser's question: ${userQuestion}`
322
+ : `Here are my system diagnostics:\n\n${JSON.stringify(diagnostics, null, 2)}\n\nPlease analyze and help me fix any issues.`,
323
+ },
324
+ ],
325
+ max_tokens: 1000,
326
+ }),
327
+ });
328
+ if (!response.ok) {
329
+ const text = await response.text();
330
+ console.log(`Error: ${response.status} - ${text}`);
331
+ return;
332
+ }
333
+ const data = await response.json();
334
+ const content = data.choices?.[0]?.message?.content;
335
+ if (content) {
336
+ console.log("🤖 AI Analysis:\n");
337
+ console.log(content);
338
+ console.log();
339
+ }
340
+ else {
341
+ console.log("Error: No response from AI");
342
+ }
343
+ }
344
+ catch (err) {
345
+ console.log(`\nError calling AI: ${err instanceof Error ? err.message : String(err)}`);
346
+ console.log("Try again or check your wallet balance.\n");
347
+ }
348
+ }
349
+ // Main entry point
350
+ export async function runDoctor(userQuestion, model = "sonnet") {
351
+ console.log(`\n🩺 BlockRun Doctor v${VERSION}\n`);
352
+ // Collect all diagnostics
353
+ const [system, wallet, network, logs] = await Promise.all([
354
+ collectSystemInfo(),
355
+ collectWalletInfo(),
356
+ collectNetworkInfo(),
357
+ collectLogInfo(),
358
+ ]);
359
+ const result = {
360
+ version: VERSION,
361
+ timestamp: new Date().toISOString(),
362
+ system,
363
+ wallet,
364
+ network,
365
+ logs,
366
+ issues: [],
367
+ };
368
+ // Identify issues
369
+ result.issues = identifyIssues(result);
370
+ // Print to terminal
371
+ printDiagnostics(result);
372
+ // Send to AI for analysis
373
+ await analyzeWithAI(result, userQuestion, model);
374
+ }
375
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=error-classification.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-classification.test.d.ts","sourceRoot":"","sources":["../src/error-classification.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import { describe, it, expect } from "bun:test";
2
+ import { categorizeError } from "./proxy.js";
3
+ describe("categorizeError", () => {
4
+ it("classifies 401 as auth_failure", () => {
5
+ expect(categorizeError(401, "Unauthorized")).toBe("auth_failure");
6
+ expect(categorizeError(401, "api key invalid")).toBe("auth_failure");
7
+ expect(categorizeError(401, "")).toBe("auth_failure");
8
+ });
9
+ it("classifies 403 with quota body as quota_exceeded", () => {
10
+ expect(categorizeError(403, "plan limit reached")).toBe("quota_exceeded");
11
+ expect(categorizeError(403, "quota exceeded for this month")).toBe("quota_exceeded");
12
+ expect(categorizeError(403, "subscription required")).toBe("quota_exceeded");
13
+ });
14
+ it("classifies 403 without quota body as auth_failure", () => {
15
+ expect(categorizeError(403, "Forbidden")).toBe("auth_failure");
16
+ expect(categorizeError(403, "")).toBe("auth_failure");
17
+ });
18
+ it("classifies 402 as payment_error", () => {
19
+ expect(categorizeError(402, "payment required")).toBe("payment_error");
20
+ expect(categorizeError(402, "")).toBe("payment_error");
21
+ });
22
+ it("classifies 429 as rate_limited", () => {
23
+ expect(categorizeError(429, "rate limit exceeded")).toBe("rate_limited");
24
+ expect(categorizeError(429, "")).toBe("rate_limited");
25
+ });
26
+ it("classifies 529 as overloaded", () => {
27
+ expect(categorizeError(529, "")).toBe("overloaded");
28
+ expect(categorizeError(529, "overloaded")).toBe("overloaded");
29
+ });
30
+ it("classifies 503 with overload body as overloaded", () => {
31
+ expect(categorizeError(503, "service overloaded, try again")).toBe("overloaded");
32
+ expect(categorizeError(503, "over capacity")).toBe("overloaded");
33
+ expect(categorizeError(503, "too many requests")).toBe("overloaded");
34
+ });
35
+ it("classifies 503 without overload body as server_error", () => {
36
+ expect(categorizeError(503, "service unavailable")).toBe("server_error");
37
+ expect(categorizeError(503, "")).toBe("server_error");
38
+ });
39
+ it("classifies 5xx as server_error", () => {
40
+ expect(categorizeError(500, "internal server error")).toBe("server_error");
41
+ expect(categorizeError(502, "bad gateway")).toBe("server_error");
42
+ expect(categorizeError(504, "gateway timeout")).toBe("server_error");
43
+ });
44
+ it("classifies 413 with size body as config_error", () => {
45
+ expect(categorizeError(413, "request too large")).toBe("config_error");
46
+ expect(categorizeError(413, "payload too large")).toBe("config_error");
47
+ });
48
+ it("classifies 200 as null (not a provider error)", () => {
49
+ expect(categorizeError(200, "ok")).toBeNull();
50
+ });
51
+ it("classifies bare 400 with no pattern match as null", () => {
52
+ expect(categorizeError(400, "bad request")).toBeNull();
53
+ });
54
+ it("classifies 400 with billing body as config_error", () => {
55
+ expect(categorizeError(400, "billing issue with account")).toBe("config_error");
56
+ expect(categorizeError(400, "insufficient balance")).toBe("config_error");
57
+ });
58
+ });
59
+ //# sourceMappingURL=error-classification.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-classification.test.js","sourceRoot":"","sources":["../src/error-classification.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Typed Error Classes for ClawRouter
3
+ *
4
+ * Provides structured errors for balance-related failures with
5
+ * all necessary information for user-friendly error messages.
6
+ */
7
+ /**
8
+ * Thrown when wallet has insufficient USDC balance for a request.
9
+ */
10
+ export declare class InsufficientFundsError extends Error {
11
+ readonly code: "INSUFFICIENT_FUNDS";
12
+ readonly currentBalanceUSD: string;
13
+ readonly requiredUSD: string;
14
+ readonly walletAddress: string;
15
+ constructor(opts: {
16
+ currentBalanceUSD: string;
17
+ requiredUSD: string;
18
+ walletAddress: string;
19
+ });
20
+ }
21
+ /**
22
+ * Thrown when wallet has no USDC balance (or effectively zero).
23
+ */
24
+ export declare class EmptyWalletError extends Error {
25
+ readonly code: "EMPTY_WALLET";
26
+ readonly walletAddress: string;
27
+ constructor(walletAddress: string);
28
+ }
29
+ /**
30
+ * Type guard to check if an error is InsufficientFundsError.
31
+ */
32
+ export declare function isInsufficientFundsError(error: unknown): error is InsufficientFundsError;
33
+ /**
34
+ * Type guard to check if an error is EmptyWalletError.
35
+ */
36
+ export declare function isEmptyWalletError(error: unknown): error is EmptyWalletError;
37
+ /**
38
+ * Type guard to check if an error is a balance-related error.
39
+ */
40
+ export declare function isBalanceError(error: unknown): error is InsufficientFundsError | EmptyWalletError;
41
+ /**
42
+ * Thrown when RPC call fails (network error, node down, etc).
43
+ * Distinguishes infrastructure failures from actual empty wallets.
44
+ */
45
+ export declare class RpcError extends Error {
46
+ readonly code: "RPC_ERROR";
47
+ readonly originalError: unknown;
48
+ constructor(message: string, originalError?: unknown);
49
+ }
50
+ /**
51
+ * Type guard to check if an error is RpcError.
52
+ */
53
+ export declare function isRpcError(error: unknown): error is RpcError;
54
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAU;IAC9C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,IAAI,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE;CAa5F;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,aAAa,EAAE,MAAM;CAYlC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAExF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,GAAG,gBAAgB,CAEjG;AAED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAG,WAAW,CAAU;IACrC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;gBAEpB,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO;CAKrD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D"}
package/dist/errors.js ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Typed Error Classes for ClawRouter
3
+ *
4
+ * Provides structured errors for balance-related failures with
5
+ * all necessary information for user-friendly error messages.
6
+ */
7
+ /**
8
+ * Thrown when wallet has insufficient USDC balance for a request.
9
+ */
10
+ export class InsufficientFundsError extends Error {
11
+ code = "INSUFFICIENT_FUNDS";
12
+ currentBalanceUSD;
13
+ requiredUSD;
14
+ walletAddress;
15
+ constructor(opts) {
16
+ const msg = [
17
+ `Insufficient balance. Current: ${opts.currentBalanceUSD}, Required: ${opts.requiredUSD}`,
18
+ `Options:`,
19
+ ` 1. Fund wallet: ${opts.walletAddress}`,
20
+ ` 2. Use free model: /model free`,
21
+ ].join("\n");
22
+ super(msg);
23
+ this.name = "InsufficientFundsError";
24
+ this.currentBalanceUSD = opts.currentBalanceUSD;
25
+ this.requiredUSD = opts.requiredUSD;
26
+ this.walletAddress = opts.walletAddress;
27
+ }
28
+ }
29
+ /**
30
+ * Thrown when wallet has no USDC balance (or effectively zero).
31
+ */
32
+ export class EmptyWalletError extends Error {
33
+ code = "EMPTY_WALLET";
34
+ walletAddress;
35
+ constructor(walletAddress) {
36
+ const msg = [
37
+ `No USDC balance.`,
38
+ `Options:`,
39
+ ` 1. Fund wallet: ${walletAddress}`,
40
+ ` 2. Use free model: /model free`,
41
+ ` 3. Uninstall: bash ~/.openclaw/extensions/clawrouter/scripts/uninstall.sh`,
42
+ ].join("\n");
43
+ super(msg);
44
+ this.name = "EmptyWalletError";
45
+ this.walletAddress = walletAddress;
46
+ }
47
+ }
48
+ /**
49
+ * Type guard to check if an error is InsufficientFundsError.
50
+ */
51
+ export function isInsufficientFundsError(error) {
52
+ return error instanceof Error && error.code === "INSUFFICIENT_FUNDS";
53
+ }
54
+ /**
55
+ * Type guard to check if an error is EmptyWalletError.
56
+ */
57
+ export function isEmptyWalletError(error) {
58
+ return error instanceof Error && error.code === "EMPTY_WALLET";
59
+ }
60
+ /**
61
+ * Type guard to check if an error is a balance-related error.
62
+ */
63
+ export function isBalanceError(error) {
64
+ return isInsufficientFundsError(error) || isEmptyWalletError(error);
65
+ }
66
+ /**
67
+ * Thrown when RPC call fails (network error, node down, etc).
68
+ * Distinguishes infrastructure failures from actual empty wallets.
69
+ */
70
+ export class RpcError extends Error {
71
+ code = "RPC_ERROR";
72
+ originalError;
73
+ constructor(message, originalError) {
74
+ super(`RPC error: ${message}. Check network connectivity.`);
75
+ this.name = "RpcError";
76
+ this.originalError = originalError;
77
+ }
78
+ }
79
+ /**
80
+ * Type guard to check if an error is RpcError.
81
+ */
82
+ export function isRpcError(error) {
83
+ return error instanceof Error && error.code === "RPC_ERROR";
84
+ }
85
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACtC,IAAI,GAAG,oBAA6B,CAAC;IACrC,iBAAiB,CAAS;IAC1B,WAAW,CAAS;IACpB,aAAa,CAAS;IAE/B,YAAY,IAA+E;QACzF,MAAM,GAAG,GAAG;YACV,kCAAkC,IAAI,CAAC,iBAAiB,eAAe,IAAI,CAAC,WAAW,EAAE;YACzF,UAAU;YACV,qBAAqB,IAAI,CAAC,aAAa,EAAE;YACzC,kCAAkC;SACnC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAChD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;IAC1C,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,GAAG,cAAuB,CAAC;IAC/B,aAAa,CAAS;IAE/B,YAAY,aAAqB;QAC/B,MAAM,GAAG,GAAG;YACV,kBAAkB;YAClB,UAAU;YACV,qBAAqB,aAAa,EAAE;YACpC,kCAAkC;YAClC,6EAA6E;SAC9E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAc;IACrD,OAAO,KAAK,YAAY,KAAK,IAAK,KAAgC,CAAC,IAAI,KAAK,oBAAoB,CAAC;AACnG,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,KAAK,YAAY,KAAK,IAAK,KAA0B,CAAC,IAAI,KAAK,cAAc,CAAC;AACvF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,wBAAwB,CAAC,KAAK,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,GAAG,WAAoB,CAAC;IAC5B,aAAa,CAAU;IAEhC,YAAY,OAAe,EAAE,aAAuB;QAClD,KAAK,CAAC,cAAc,OAAO,+BAA+B,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,KAAK,YAAY,KAAK,IAAK,KAAkB,CAAC,IAAI,KAAK,WAAW,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Exclude-models persistence module.
3
+ *
4
+ * Manages a user-configurable list of model IDs that the smart router
5
+ * should never select. Stored as a sorted JSON array on disk.
6
+ */
7
+ /**
8
+ * Load the exclude list from disk.
9
+ * Returns an empty set if the file does not exist.
10
+ */
11
+ export declare function loadExcludeList(filePath?: string): Set<string>;
12
+ /**
13
+ * Add a model to the exclude list.
14
+ * Resolves aliases before persisting.
15
+ * @returns The resolved model ID.
16
+ */
17
+ export declare function addExclusion(model: string, filePath?: string): string;
18
+ /**
19
+ * Remove a model from the exclude list.
20
+ * Resolves aliases before removing.
21
+ * @returns true if the model was present and removed, false otherwise.
22
+ */
23
+ export declare function removeExclusion(model: string, filePath?: string): boolean;
24
+ /**
25
+ * Clear the entire exclude list.
26
+ */
27
+ export declare function clearExclusions(filePath?: string): void;
28
+ //# sourceMappingURL=exclude-models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exclude-models.d.ts","sourceRoot":"","sources":["../src/exclude-models.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAA0B,GAAG,GAAG,CAAC,MAAM,CAAC,CAWjF;AAYD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAA0B,GAAG,MAAM,CAMxF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAA0B,GAAG,OAAO,CAQ5F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAA0B,GAAG,IAAI,CAE1E"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=exclude-models.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exclude-models.integration.test.d.ts","sourceRoot":"","sources":["../src/exclude-models.integration.test.ts"],"names":[],"mappings":""}