@antseed/cli 0.1.157 → 0.1.159

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 (285) hide show
  1. package/README.md +158 -6
  2. package/dist/cli/commands/ants/addresses.d.ts +3 -0
  3. package/dist/cli/commands/ants/addresses.d.ts.map +1 -0
  4. package/dist/cli/commands/ants/addresses.js +20 -0
  5. package/dist/cli/commands/ants/addresses.js.map +1 -0
  6. package/dist/cli/commands/ants/addresses.test.d.ts +2 -0
  7. package/dist/cli/commands/ants/addresses.test.d.ts.map +1 -0
  8. package/dist/cli/commands/ants/addresses.test.js +12 -0
  9. package/dist/cli/commands/ants/addresses.test.js.map +1 -0
  10. package/dist/cli/commands/ants/arguments.test.d.ts +2 -0
  11. package/dist/cli/commands/ants/arguments.test.d.ts.map +1 -0
  12. package/dist/cli/commands/ants/arguments.test.js +51 -0
  13. package/dist/cli/commands/ants/arguments.test.js.map +1 -0
  14. package/dist/cli/commands/ants/dashboard.d.ts +4 -0
  15. package/dist/cli/commands/ants/dashboard.d.ts.map +1 -0
  16. package/dist/cli/commands/ants/dashboard.js +45 -0
  17. package/dist/cli/commands/ants/dashboard.js.map +1 -0
  18. package/dist/cli/commands/ants/dashboard.test.d.ts +2 -0
  19. package/dist/cli/commands/ants/dashboard.test.d.ts.map +1 -0
  20. package/dist/cli/commands/ants/dashboard.test.js +14 -0
  21. package/dist/cli/commands/ants/dashboard.test.js.map +1 -0
  22. package/dist/cli/commands/ants/emissions.d.ts +5 -0
  23. package/dist/cli/commands/ants/emissions.d.ts.map +1 -0
  24. package/dist/cli/commands/ants/emissions.js +44 -0
  25. package/dist/cli/commands/ants/emissions.js.map +1 -0
  26. package/dist/cli/commands/ants/emissions.test.d.ts +2 -0
  27. package/dist/cli/commands/ants/emissions.test.d.ts.map +1 -0
  28. package/dist/cli/commands/ants/emissions.test.js +17 -0
  29. package/dist/cli/commands/ants/emissions.test.js.map +1 -0
  30. package/dist/cli/commands/ants/extend.d.ts +3 -0
  31. package/dist/cli/commands/ants/extend.d.ts.map +1 -0
  32. package/dist/cli/commands/ants/extend.js +14 -0
  33. package/dist/cli/commands/ants/extend.js.map +1 -0
  34. package/dist/cli/commands/ants/extend.test.d.ts +2 -0
  35. package/dist/cli/commands/ants/extend.test.d.ts.map +1 -0
  36. package/dist/cli/commands/ants/extend.test.js +13 -0
  37. package/dist/cli/commands/ants/extend.test.js.map +1 -0
  38. package/dist/cli/commands/ants/index.d.ts +7 -0
  39. package/dist/cli/commands/ants/index.d.ts.map +1 -0
  40. package/dist/cli/commands/ants/index.js +46 -0
  41. package/dist/cli/commands/ants/index.js.map +1 -0
  42. package/dist/cli/commands/ants/index.test.d.ts +2 -0
  43. package/dist/cli/commands/ants/index.test.d.ts.map +1 -0
  44. package/dist/cli/commands/ants/index.test.js +24 -0
  45. package/dist/cli/commands/ants/index.test.js.map +1 -0
  46. package/dist/cli/commands/ants/max-lock.d.ts +3 -0
  47. package/dist/cli/commands/ants/max-lock.d.ts.map +1 -0
  48. package/dist/cli/commands/ants/max-lock.js +13 -0
  49. package/dist/cli/commands/ants/max-lock.js.map +1 -0
  50. package/dist/cli/commands/ants/max-lock.test.d.ts +2 -0
  51. package/dist/cli/commands/ants/max-lock.test.d.ts.map +1 -0
  52. package/dist/cli/commands/ants/max-lock.test.js +15 -0
  53. package/dist/cli/commands/ants/max-lock.test.js.map +1 -0
  54. package/dist/cli/commands/ants/merge.d.ts +3 -0
  55. package/dist/cli/commands/ants/merge.d.ts.map +1 -0
  56. package/dist/cli/commands/ants/merge.js +12 -0
  57. package/dist/cli/commands/ants/merge.js.map +1 -0
  58. package/dist/cli/commands/ants/merge.test.d.ts +2 -0
  59. package/dist/cli/commands/ants/merge.test.d.ts.map +1 -0
  60. package/dist/cli/commands/ants/merge.test.js +16 -0
  61. package/dist/cli/commands/ants/merge.test.js.map +1 -0
  62. package/dist/cli/commands/ants/move.d.ts +3 -0
  63. package/dist/cli/commands/ants/move.d.ts.map +1 -0
  64. package/dist/cli/commands/ants/move.js +14 -0
  65. package/dist/cli/commands/ants/move.js.map +1 -0
  66. package/dist/cli/commands/ants/move.test.d.ts +2 -0
  67. package/dist/cli/commands/ants/move.test.d.ts.map +1 -0
  68. package/dist/cli/commands/ants/move.test.js +16 -0
  69. package/dist/cli/commands/ants/move.test.js.map +1 -0
  70. package/dist/cli/commands/ants/pool.d.ts +3 -0
  71. package/dist/cli/commands/ants/pool.d.ts.map +1 -0
  72. package/dist/cli/commands/ants/pool.js +21 -0
  73. package/dist/cli/commands/ants/pool.js.map +1 -0
  74. package/dist/cli/commands/ants/pool.test.d.ts +2 -0
  75. package/dist/cli/commands/ants/pool.test.d.ts.map +1 -0
  76. package/dist/cli/commands/ants/pool.test.js +13 -0
  77. package/dist/cli/commands/ants/pool.test.js.map +1 -0
  78. package/dist/cli/commands/ants/pools.d.ts +6 -0
  79. package/dist/cli/commands/ants/pools.d.ts.map +1 -0
  80. package/dist/cli/commands/ants/pools.js +50 -0
  81. package/dist/cli/commands/ants/pools.js.map +1 -0
  82. package/dist/cli/commands/ants/pools.test.d.ts +2 -0
  83. package/dist/cli/commands/ants/pools.test.d.ts.map +1 -0
  84. package/dist/cli/commands/ants/pools.test.js +18 -0
  85. package/dist/cli/commands/ants/pools.test.js.map +1 -0
  86. package/dist/cli/commands/ants/positions.d.ts +6 -0
  87. package/dist/cli/commands/ants/positions.d.ts.map +1 -0
  88. package/dist/cli/commands/ants/positions.js +46 -0
  89. package/dist/cli/commands/ants/positions.js.map +1 -0
  90. package/dist/cli/commands/ants/positions.test.d.ts +2 -0
  91. package/dist/cli/commands/ants/positions.test.d.ts.map +1 -0
  92. package/dist/cli/commands/ants/positions.test.js +19 -0
  93. package/dist/cli/commands/ants/positions.test.js.map +1 -0
  94. package/dist/cli/commands/ants/rewards.d.ts +9 -0
  95. package/dist/cli/commands/ants/rewards.d.ts.map +1 -0
  96. package/dist/cli/commands/ants/rewards.js +93 -0
  97. package/dist/cli/commands/ants/rewards.js.map +1 -0
  98. package/dist/cli/commands/ants/rewards.test.d.ts +2 -0
  99. package/dist/cli/commands/ants/rewards.test.d.ts.map +1 -0
  100. package/dist/cli/commands/ants/rewards.test.js +46 -0
  101. package/dist/cli/commands/ants/rewards.test.js.map +1 -0
  102. package/dist/cli/commands/ants/seller.d.ts +3 -0
  103. package/dist/cli/commands/ants/seller.d.ts.map +1 -0
  104. package/dist/cli/commands/ants/seller.js +32 -0
  105. package/dist/cli/commands/ants/seller.js.map +1 -0
  106. package/dist/cli/commands/ants/seller.test.d.ts +2 -0
  107. package/dist/cli/commands/ants/seller.test.d.ts.map +1 -0
  108. package/dist/cli/commands/ants/seller.test.js +16 -0
  109. package/dist/cli/commands/ants/seller.test.js.map +1 -0
  110. package/dist/cli/commands/ants/shared.d.ts +26 -0
  111. package/dist/cli/commands/ants/shared.d.ts.map +1 -0
  112. package/dist/cli/commands/ants/shared.js +94 -0
  113. package/dist/cli/commands/ants/shared.js.map +1 -0
  114. package/dist/cli/commands/ants/shared.test.d.ts +2 -0
  115. package/dist/cli/commands/ants/shared.test.d.ts.map +1 -0
  116. package/dist/cli/commands/ants/shared.test.js +25 -0
  117. package/dist/cli/commands/ants/shared.test.js.map +1 -0
  118. package/dist/cli/commands/ants/split.d.ts +3 -0
  119. package/dist/cli/commands/ants/split.d.ts.map +1 -0
  120. package/dist/cli/commands/ants/split.js +12 -0
  121. package/dist/cli/commands/ants/split.js.map +1 -0
  122. package/dist/cli/commands/ants/split.test.d.ts +2 -0
  123. package/dist/cli/commands/ants/split.test.d.ts.map +1 -0
  124. package/dist/cli/commands/ants/split.test.js +13 -0
  125. package/dist/cli/commands/ants/split.test.js.map +1 -0
  126. package/dist/cli/commands/ants/stake.d.ts +3 -0
  127. package/dist/cli/commands/ants/stake.d.ts.map +1 -0
  128. package/dist/cli/commands/ants/stake.js +15 -0
  129. package/dist/cli/commands/ants/stake.js.map +1 -0
  130. package/dist/cli/commands/ants/stake.test.d.ts +2 -0
  131. package/dist/cli/commands/ants/stake.test.d.ts.map +1 -0
  132. package/dist/cli/commands/ants/stake.test.js +17 -0
  133. package/dist/cli/commands/ants/stake.test.js.map +1 -0
  134. package/dist/cli/commands/ants/status.d.ts +9 -0
  135. package/dist/cli/commands/ants/status.d.ts.map +1 -0
  136. package/dist/cli/commands/ants/status.js +43 -0
  137. package/dist/cli/commands/ants/status.js.map +1 -0
  138. package/dist/cli/commands/ants/status.test.d.ts +2 -0
  139. package/dist/cli/commands/ants/status.test.d.ts.map +1 -0
  140. package/dist/cli/commands/ants/status.test.js +23 -0
  141. package/dist/cli/commands/ants/status.test.js.map +1 -0
  142. package/dist/cli/commands/ants/usage.d.ts +4 -0
  143. package/dist/cli/commands/ants/usage.d.ts.map +1 -0
  144. package/dist/cli/commands/ants/usage.js +31 -0
  145. package/dist/cli/commands/ants/usage.js.map +1 -0
  146. package/dist/cli/commands/ants/usage.test.d.ts +2 -0
  147. package/dist/cli/commands/ants/usage.test.d.ts.map +1 -0
  148. package/dist/cli/commands/ants/usage.test.js +15 -0
  149. package/dist/cli/commands/ants/usage.test.js.map +1 -0
  150. package/dist/cli/commands/ants/verify.d.ts +3 -0
  151. package/dist/cli/commands/ants/verify.d.ts.map +1 -0
  152. package/dist/cli/commands/ants/verify.js +51 -0
  153. package/dist/cli/commands/ants/verify.js.map +1 -0
  154. package/dist/cli/commands/ants/verify.test.d.ts +2 -0
  155. package/dist/cli/commands/ants/verify.test.d.ts.map +1 -0
  156. package/dist/cli/commands/ants/verify.test.js +51 -0
  157. package/dist/cli/commands/ants/verify.test.js.map +1 -0
  158. package/dist/cli/commands/ants/withdraw.d.ts +16 -0
  159. package/dist/cli/commands/ants/withdraw.d.ts.map +1 -0
  160. package/dist/cli/commands/ants/withdraw.js +48 -0
  161. package/dist/cli/commands/ants/withdraw.js.map +1 -0
  162. package/dist/cli/commands/ants/withdraw.test.d.ts +2 -0
  163. package/dist/cli/commands/ants/withdraw.test.d.ts.map +1 -0
  164. package/dist/cli/commands/ants/withdraw.test.js +30 -0
  165. package/dist/cli/commands/ants/withdraw.test.js.map +1 -0
  166. package/dist/cli/commands/buyer/start.d.ts.map +1 -1
  167. package/dist/cli/commands/buyer/start.js +7 -1
  168. package/dist/cli/commands/buyer/start.js.map +1 -1
  169. package/dist/cli/commands/emissions.d.ts +7 -0
  170. package/dist/cli/commands/emissions.d.ts.map +1 -1
  171. package/dist/cli/commands/emissions.js +105 -27
  172. package/dist/cli/commands/emissions.js.map +1 -1
  173. package/dist/cli/commands/emissions.test.js +7 -1
  174. package/dist/cli/commands/emissions.test.js.map +1 -1
  175. package/dist/cli/commands/network/browse.d.ts.map +1 -1
  176. package/dist/cli/commands/network/browse.js +12 -3
  177. package/dist/cli/commands/network/browse.js.map +1 -1
  178. package/dist/cli/commands/network/chain-config-helper.d.ts +21 -1
  179. package/dist/cli/commands/network/chain-config-helper.d.ts.map +1 -1
  180. package/dist/cli/commands/network/chain-config-helper.js +6 -1
  181. package/dist/cli/commands/network/chain-config-helper.js.map +1 -1
  182. package/dist/cli/commands/network/peer.d.ts.map +1 -1
  183. package/dist/cli/commands/network/peer.js +21 -1
  184. package/dist/cli/commands/network/peer.js.map +1 -1
  185. package/dist/cli/commands/parse-positive-integer.d.ts +2 -0
  186. package/dist/cli/commands/parse-positive-integer.d.ts.map +1 -0
  187. package/dist/cli/commands/parse-positive-integer.js +9 -0
  188. package/dist/cli/commands/parse-positive-integer.js.map +1 -0
  189. package/dist/cli/commands/reward-actions.d.ts +11 -0
  190. package/dist/cli/commands/reward-actions.d.ts.map +1 -0
  191. package/dist/cli/commands/reward-actions.js +22 -0
  192. package/dist/cli/commands/reward-actions.js.map +1 -0
  193. package/dist/cli/commands/seller/contract-clients.test.d.ts +2 -0
  194. package/dist/cli/commands/seller/contract-clients.test.d.ts.map +1 -0
  195. package/dist/cli/commands/seller/contract-clients.test.js +46 -0
  196. package/dist/cli/commands/seller/contract-clients.test.js.map +1 -0
  197. package/dist/cli/commands/seller/index.d.ts.map +1 -1
  198. package/dist/cli/commands/seller/index.js +4 -2
  199. package/dist/cli/commands/seller/index.js.map +1 -1
  200. package/dist/cli/commands/seller/pool.d.ts +15 -0
  201. package/dist/cli/commands/seller/pool.d.ts.map +1 -0
  202. package/dist/cli/commands/seller/pool.js +201 -0
  203. package/dist/cli/commands/seller/pool.js.map +1 -0
  204. package/dist/cli/commands/seller/pool.test.d.ts +2 -0
  205. package/dist/cli/commands/seller/pool.test.d.ts.map +1 -0
  206. package/dist/cli/commands/seller/pool.test.js +16 -0
  207. package/dist/cli/commands/seller/pool.test.js.map +1 -0
  208. package/dist/cli/commands/seller/register.d.ts.map +1 -1
  209. package/dist/cli/commands/seller/register.js +38 -8
  210. package/dist/cli/commands/seller/register.js.map +1 -1
  211. package/dist/cli/commands/seller/rewards.d.ts +13 -0
  212. package/dist/cli/commands/seller/rewards.d.ts.map +1 -0
  213. package/dist/cli/commands/seller/rewards.js +115 -0
  214. package/dist/cli/commands/seller/rewards.js.map +1 -0
  215. package/dist/cli/commands/seller/rewards.test.d.ts +2 -0
  216. package/dist/cli/commands/seller/rewards.test.d.ts.map +1 -0
  217. package/dist/cli/commands/seller/rewards.test.js +21 -0
  218. package/dist/cli/commands/seller/rewards.test.js.map +1 -0
  219. package/dist/cli/commands/seller/setup.d.ts.map +1 -1
  220. package/dist/cli/commands/seller/setup.js +2 -1
  221. package/dist/cli/commands/seller/setup.js.map +1 -1
  222. package/dist/cli/commands/seller/stake.d.ts.map +1 -1
  223. package/dist/cli/commands/seller/stake.js +104 -65
  224. package/dist/cli/commands/seller/stake.js.map +1 -1
  225. package/dist/cli/commands/seller/stake.test.d.ts +2 -0
  226. package/dist/cli/commands/seller/stake.test.d.ts.map +1 -0
  227. package/dist/cli/commands/seller/stake.test.js +99 -0
  228. package/dist/cli/commands/seller/stake.test.js.map +1 -0
  229. package/dist/cli/commands/seller/start.d.ts.map +1 -1
  230. package/dist/cli/commands/seller/start.js +6 -0
  231. package/dist/cli/commands/seller/start.js.map +1 -1
  232. package/dist/cli/commands/seller/status.d.ts.map +1 -1
  233. package/dist/cli/commands/seller/status.js +44 -2
  234. package/dist/cli/commands/seller/status.js.map +1 -1
  235. package/dist/cli/index.js +2 -0
  236. package/dist/cli/index.js.map +1 -1
  237. package/dist/cli/payment-utils.d.ts +33 -2
  238. package/dist/cli/payment-utils.d.ts.map +1 -1
  239. package/dist/cli/payment-utils.js +101 -2
  240. package/dist/cli/payment-utils.js.map +1 -1
  241. package/dist/config/types.d.ts +20 -0
  242. package/dist/config/types.d.ts.map +1 -1
  243. package/dist/plugins/verifier-evidence.test.d.ts +2 -0
  244. package/dist/plugins/verifier-evidence.test.d.ts.map +1 -0
  245. package/dist/plugins/verifier-evidence.test.js +41 -0
  246. package/dist/plugins/verifier-evidence.test.js.map +1 -0
  247. package/dist/plugins/verifier.d.ts +8 -10
  248. package/dist/plugins/verifier.d.ts.map +1 -1
  249. package/dist/plugins/verifier.js +23 -51
  250. package/dist/plugins/verifier.js.map +1 -1
  251. package/dist/plugins/verifier.test.js +1 -37
  252. package/dist/plugins/verifier.test.js.map +1 -1
  253. package/dist/proxy/buyer-proxy.d.ts +2 -1
  254. package/dist/proxy/buyer-proxy.d.ts.map +1 -1
  255. package/dist/proxy/buyer-proxy.js +104 -28
  256. package/dist/proxy/buyer-proxy.js.map +1 -1
  257. package/dist/proxy/buyer-proxy.test.js +177 -19
  258. package/dist/proxy/buyer-proxy.test.js.map +1 -1
  259. package/dist/proxy/network-models.d.ts +1 -2
  260. package/dist/proxy/network-models.d.ts.map +1 -1
  261. package/dist/proxy/network-models.js +10 -23
  262. package/dist/proxy/network-models.js.map +1 -1
  263. package/dist/proxy/network-models.test.js +56 -27
  264. package/dist/proxy/network-models.test.js.map +1 -1
  265. package/dist/proxy/tee-control.d.ts +14 -0
  266. package/dist/proxy/tee-control.d.ts.map +1 -0
  267. package/dist/proxy/tee-control.js +100 -0
  268. package/dist/proxy/tee-control.js.map +1 -0
  269. package/dist/proxy/tee-control.test.d.ts +2 -0
  270. package/dist/proxy/tee-control.test.d.ts.map +1 -0
  271. package/dist/proxy/tee-control.test.js +56 -0
  272. package/dist/proxy/tee-control.test.js.map +1 -0
  273. package/dist/proxy/tee-verification.d.ts +24 -0
  274. package/dist/proxy/tee-verification.d.ts.map +1 -0
  275. package/dist/proxy/tee-verification.js +128 -0
  276. package/dist/proxy/tee-verification.js.map +1 -0
  277. package/dist/proxy/tee-verification.test.d.ts +2 -0
  278. package/dist/proxy/tee-verification.test.d.ts.map +1 -0
  279. package/dist/proxy/tee-verification.test.js +241 -0
  280. package/dist/proxy/tee-verification.test.js.map +1 -0
  281. package/package.json +8 -6
  282. package/dist/cli/commands/seller/emissions.d.ts +0 -3
  283. package/dist/cli/commands/seller/emissions.d.ts.map +0 -1
  284. package/dist/cli/commands/seller/emissions.js +0 -5
  285. package/dist/cli/commands/seller/emissions.js.map +0 -1
@@ -5,8 +5,9 @@ import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { Readable } from 'node:stream';
7
7
  import test from 'node:test';
8
- import { ANTSEED_BUYER_FAULT_ERROR_CODE, ANTSEED_FAULT_ATTRIBUTION_HEADER, CONNECTION_CAPABILITY_COOPERATIVE_CLOSE_V1, CONNECTION_CAPABILITY_RELAYS_SWEEPS_V1, adaptPeerFaultErrorResponse, buyerFault, computeOnChainReputationScore, } from '@antseed/node';
8
+ import { ANTSEED_BUYER_FAULT_ERROR_CODE, ANTSEED_FAULT_ATTRIBUTION_HEADER, CONNECTION_CAPABILITY_COOPERATIVE_CLOSE_V1, CONNECTION_CAPABILITY_RELAYS_SWEEPS_V1, adaptPeerFaultErrorResponse, buyerFault, computeTrustScore, } from '@antseed/node';
9
9
  import { DEFAULT_BUYER_PEER_REFRESH_INTERVAL_MS } from '../config/defaults.js';
10
+ import { TeeVerification } from './tee-verification.js';
10
11
  import { BuyerProxy, isModelNotFoundResponse, makeVerifierReach, mergeJsonStateFile, parsePeerPinnedService, parsePersistedPeers, rewritePeerPinnedServiceInBody, sanitizePeerBuyerFaultMarker, selectCandidatePeersForRouting, substituteRoutedModelAlias, sweepStaleStateTmpFiles, } from './buyer-proxy.js';
11
12
  import { extractRequestedService, overrideRoutedModelInBody, SYSTEM_ROUTED_MODEL_HEADER, } from './request-utils.js';
12
13
  function makePeer(seed, providers) {
@@ -17,6 +18,40 @@ function makePeer(seed, providers) {
17
18
  providers,
18
19
  };
19
20
  }
21
+ test('existing required CLI verification rejects a failed pin without payment/inference and auto falls back to a verified seller', async () => {
22
+ const rejected = makePeer('a', ['openai']);
23
+ const accepted = makePeer('b', ['openai']);
24
+ for (const peer of [rejected, accepted]) {
25
+ peer.capabilities = ['verifier.antseed-verifier'];
26
+ peer.providerServiceApiProtocols = { openai: { services: { 'gpt-4o': ['openai-chat-completions'] } } };
27
+ }
28
+ rejected.reputationScore = 99;
29
+ accepted.reputationScore = 90;
30
+ const peers = [rejected, accepted];
31
+ const proxy = makeBuyerProxyWithPeers(peers, peers, permissiveRouter());
32
+ const policy = { require: true, prefer: ['antseed-verifier'] };
33
+ const verification = new TeeVerification(policy);
34
+ proxy._verifier = policy;
35
+ proxy._teeVerification = verification;
36
+ proxy._cachedPeers = peers;
37
+ await verification.verify(rejected, policy, async () => ({ ok: false, verified: false, reason: 'Seller binding failed' }));
38
+ await verification.verify(accepted, policy, async () => ({ ok: true, verified: true, sellerNodeVerified: true }));
39
+ const dispatches = [];
40
+ proxy._node.sendRequest = async (peer, request) => {
41
+ dispatches.push(peer.peerId);
42
+ return { requestId: request.requestId, statusCode: 200, headers: { 'content-type': 'application/json' }, body: Buffer.from('{}') };
43
+ };
44
+ const pinned = await invokeProxy(proxy, makeProxyRequest({ headers: { 'x-antseed-pin-peer': rejected.peerId } }));
45
+ assert.equal(pinned.statusCode, 502);
46
+ assert.match(pinned.body, /failed required verification/);
47
+ assert.deepEqual(dispatches, []);
48
+ const automatic = await invokeProxy(proxy, makeProxyRequest({}));
49
+ assert.equal(automatic.statusCode, 200);
50
+ assert.deepEqual(dispatches, [accepted.peerId]);
51
+ const explicit = await invokeProxy(proxy, makeProxyRequest({ headers: { 'x-antseed-pin-peer': accepted.peerId } }));
52
+ assert.equal(explicit.statusCode, 200);
53
+ assert.deepEqual(dispatches, [accepted.peerId, accepted.peerId]);
54
+ });
20
55
  function makeProxyRequest(options) {
21
56
  const body = JSON.stringify(options.body ?? { model: 'gpt-4o', messages: [] });
22
57
  const req = Readable.from([Buffer.from(body)]);
@@ -425,12 +460,12 @@ test('selectCandidatePeersForRouting can still include peers without service pro
425
460
  });
426
461
  test('model-only request routes to the highest-ranked canonical service match', async () => {
427
462
  const lower = makePeer('a', ['anthropic']);
428
- lower.reputationScore = 40;
463
+ lower.onChainReputationScore = 40;
429
464
  lower.providerServiceApiProtocols = {
430
465
  anthropic: { services: { 'Claude Opus 5': ['anthropic-messages'] } },
431
466
  };
432
467
  const higher = makePeer('b', ['anthropic']);
433
- higher.reputationScore = 90;
468
+ higher.onChainReputationScore = 90;
434
469
  higher.providerServiceApiProtocols = {
435
470
  anthropic: { services: { 'opus-5': ['anthropic-messages'] } },
436
471
  };
@@ -647,7 +682,7 @@ test('model-only request applies a cached-input pricing reputation penalty', asy
647
682
  });
648
683
  test('model-only cached-input pricing penalty does not bury a substantially stronger peer', async () => {
649
684
  const priced = makePeer('a', ['openai']);
650
- priced.reputationScore = 20;
685
+ priced.onChainReputationScore = 20;
651
686
  priced.providerPricing = {
652
687
  openai: {
653
688
  defaults: { inputUsdPerMillion: 2, outputUsdPerMillion: 4 },
@@ -660,7 +695,7 @@ test('model-only cached-input pricing penalty does not bury a substantially stro
660
695
  openai: { services: { 'cache-model': ['openai-chat-completions'] } },
661
696
  };
662
697
  const unpriced = makePeer('b', ['openai']);
663
- unpriced.reputationScore = 100;
698
+ unpriced.onChainReputationScore = 100;
664
699
  unpriced.providerServiceApiProtocols = {
665
700
  openai: { services: { 'cache-model': ['openai-chat-completions'] } },
666
701
  };
@@ -681,12 +716,12 @@ test('model-only cached-input pricing penalty does not bury a substantially stro
681
716
  });
682
717
  test('model-only request keeps reputation ordering when cached-input pricing is absent for all peers', async () => {
683
718
  const lower = makePeer('a', ['openai']);
684
- lower.reputationScore = 20;
719
+ lower.onChainReputationScore = 20;
685
720
  lower.providerServiceApiProtocols = {
686
721
  openai: { services: { 'no-cache-model': ['openai-chat-completions'] } },
687
722
  };
688
723
  const higher = makePeer('b', ['openai']);
689
- higher.reputationScore = 100;
724
+ higher.onChainReputationScore = 100;
690
725
  higher.providerServiceApiProtocols = {
691
726
  openai: { services: { 'no-cache-model': ['openai-chat-completions'] } },
692
727
  };
@@ -789,12 +824,12 @@ test('model-only request uses the cheapest duplicate service advertised by one p
789
824
  });
790
825
  test('antseed alias with a model-only default route uses automatic peer selection', async () => {
791
826
  const lower = makePeer('a', ['openai']);
792
- lower.reputationScore = 40;
827
+ lower.onChainReputationScore = 40;
793
828
  lower.providerServiceApiProtocols = {
794
829
  openai: { services: { 'gpt-56-sol': ['openai-chat-completions'] } },
795
830
  };
796
831
  const higher = makePeer('b', ['openai']);
797
- higher.reputationScore = 90;
832
+ higher.onChainReputationScore = 90;
798
833
  higher.providerServiceApiProtocols = {
799
834
  openai: { services: { 'openai-gpt-56-sol': ['openai-chat-completions'] } },
800
835
  };
@@ -849,7 +884,7 @@ test('model-only routing skips higher-reputation peers rejected by buyer policy'
849
884
  });
850
885
  test('/models order and model-only dispatch use the same Price + Trust ranking', async () => {
851
886
  const cobaltRelay = makePeer('a', ['openai']);
852
- cobaltRelay.reputationScore = 99;
887
+ cobaltRelay.onChainReputationScore = 99;
853
888
  cobaltRelay.providerPricing = {
854
889
  openai: { defaults: { inputUsdPerMillion: 1.88, outputUsdPerMillion: 9.38 } },
855
890
  };
@@ -857,7 +892,7 @@ test('/models order and model-only dispatch use the same Price + Trust ranking',
857
892
  openai: { services: { 'kimi-k3': ['openai-chat-completions'] } },
858
893
  };
859
894
  const emberRoute = makePeer('b', ['openai']);
860
- emberRoute.reputationScore = 96;
895
+ emberRoute.onChainReputationScore = 96;
861
896
  emberRoute.providerPricing = {
862
897
  openai: { defaults: { inputUsdPerMillion: 0.9, outputUsdPerMillion: 2.7 } },
863
898
  };
@@ -886,7 +921,7 @@ test('/models order and model-only dispatch use the same Price + Trust ranking',
886
921
  });
887
922
  test('Price + Trust routing falls back after the preferred cheaper peer fails', async () => {
888
923
  const cobaltRelay = makePeer('a', ['openai']);
889
- cobaltRelay.reputationScore = 99;
924
+ cobaltRelay.onChainReputationScore = 99;
890
925
  cobaltRelay.providerPricing = {
891
926
  openai: { defaults: { inputUsdPerMillion: 1.88, outputUsdPerMillion: 9.38 } },
892
927
  };
@@ -894,7 +929,7 @@ test('Price + Trust routing falls back after the preferred cheaper peer fails',
894
929
  openai: { services: { 'kimi-k3': ['openai-chat-completions'] } },
895
930
  };
896
931
  const emberRoute = makePeer('b', ['openai']);
897
- emberRoute.reputationScore = 96;
932
+ emberRoute.onChainReputationScore = 96;
898
933
  emberRoute.providerPricing = {
899
934
  openai: { defaults: { inputUsdPerMillion: 0.9, outputUsdPerMillion: 2.7 } },
900
935
  };
@@ -1321,7 +1356,7 @@ test('a pinned seller failure explains the peer boundary and preserves the selle
1321
1356
  assert.equal(parsed.error.peer_status, 503);
1322
1357
  assert.equal(parsed.error.message, [
1323
1358
  'Oops, pinned peer could not complete the request.',
1324
- 'AntSeed is a peer-to-peer network. Try another peer or use Auto routing.',
1359
+ 'Antseed is a peer-to-peer network. Try another peer or use Auto routing.',
1325
1360
  'Original Response: {"message":"No billing tier matches this request.","status":503}',
1326
1361
  ].join('\n'));
1327
1362
  });
@@ -1955,6 +1990,19 @@ test('parsePersistedPeers drops entries with non-array providers', () => {
1955
1990
  }, NOW);
1956
1991
  assert.equal(result.length, 0);
1957
1992
  });
1993
+ test('parsePersistedPeers removes decorative icons from legacy display names', () => {
1994
+ const result = parsePersistedPeers({
1995
+ discoveredPeers: [
1996
+ {
1997
+ peerId: validPeerId,
1998
+ displayName: '▲ Example Seller ✅ 🌐',
1999
+ providers: ['openai'],
2000
+ lastSeen: NOW,
2001
+ },
2002
+ ],
2003
+ }, NOW);
2004
+ assert.equal(result[0]?.displayName, 'Example Seller');
2005
+ });
1958
2006
  test('parsePersistedPeers drops entries with stale or missing freshness anchors', () => {
1959
2007
  const result = parsePersistedPeers({
1960
2008
  discoveredPeers: [
@@ -2072,26 +2120,90 @@ test('parsePersistedPeers preserves provider metadata so routing filters still w
2072
2120
  assert.equal(result.candidatePeers[0]?.peerId, validPeerId);
2073
2121
  assert.equal(result.routePlanByPeerId.get(validPeerId)?.provider, 'claude-oauth');
2074
2122
  });
2075
- test('parsePersistedPeers re-derives on-chain reputation from persisted stats', () => {
2123
+ test('parsePersistedPeers re-derives the trust score from persisted on-chain signals', () => {
2076
2124
  const persisted = {
2077
2125
  discoveredPeers: [
2078
2126
  {
2079
2127
  peerId: validPeerId,
2080
2128
  providers: ['claude-oauth'],
2081
2129
  lastSeen: NOW - 5_000,
2082
- onChainStakeUsdcMicros: 2_000_000,
2130
+ // A stale cached score and breakdown must never win over the signals.
2131
+ onChainReputationScore: 3,
2132
+ trust: { score: 3, history: null, usage: null, power: null, identity: null, washFlagged: null },
2083
2133
  onChainChannelCount: 20,
2084
2134
  onChainGhostCount: 0,
2085
2135
  onChainTotalVolumeUsdcMicros: 100_000_000,
2086
2136
  onChainLastSettledAtSec: Math.floor((NOW - 60_000) / 1000),
2087
2137
  onChainStakedAtSec: Math.floor((NOW - 40 * 86_400_000) / 1000),
2138
+ onChainUsageEpoch: 22,
2139
+ onChainUsageShareBps: 1_000,
2140
+ onChainUsageLastEpochUsdcMicros: 500_000_000,
2141
+ onChainPoolStakeAnts: 1_250.5,
2142
+ onChainPoolPowerShareBps: 1_000,
2143
+ onChainWashFlagged: false,
2144
+ onChainWashShareBps: 0,
2088
2145
  },
2089
2146
  ],
2090
2147
  };
2091
2148
  const [peer] = parsePersistedPeers(persisted, NOW);
2092
2149
  assert.ok(peer);
2093
- assert.equal(peer.onChainReputationScore, computeOnChainReputationScore(peer, NOW));
2094
- assert.ok((peer.onChainReputationScore ?? 0) > 0);
2150
+ assert.equal(peer.onChainUsageEpoch, 22);
2151
+ assert.equal(peer.onChainUsageShareBps, 1_000);
2152
+ assert.equal(peer.onChainUsageLastEpochUsdcMicros, 500_000_000);
2153
+ assert.equal(peer.onChainPoolStakeAnts, 1_250.5);
2154
+ assert.equal(peer.onChainPoolPowerShareBps, 1_000);
2155
+ assert.equal(peer.onChainWashFlagged, false);
2156
+ assert.equal(peer.onChainWashShareBps, 0);
2157
+ assert.equal(peer.onChainStakedAtSec, Math.floor((NOW - 40 * 86_400_000) / 1000));
2158
+ assert.ok(!('onChainStakeUsdcMicros' in peer));
2159
+ assert.ok(!('onChainTrustScore' in peer));
2160
+ assert.deepEqual(peer.trust, computeTrustScore(peer, NOW));
2161
+ assert.equal(peer.onChainReputationScore, peer.trust?.score);
2162
+ // Twenty settled sessions and 100 USDC of volume contribute about 49 history
2163
+ // points; a 10% usage share adds about 10 and a 10% power share about 3 more.
2164
+ assert.equal(Math.round(peer.onChainReputationScore ?? 0), 63);
2165
+ assert.equal(peer.trust?.history?.channelCount, 20);
2166
+ assert.equal(peer.trust?.history?.totalVolumeUsdcMicros, 100_000_000);
2167
+ assert.equal(peer.trust?.usage?.epoch, 21);
2168
+ assert.equal(peer.trust?.usage?.shareBps, 1_000);
2169
+ assert.equal(peer.trust?.power?.shareBps, 1_000);
2170
+ assert.equal(peer.trust?.washFlagged, false);
2171
+ });
2172
+ test('parsePersistedPeers scores a proven wash trader at zero regardless of usage', () => {
2173
+ const [peer] = parsePersistedPeers({
2174
+ discoveredPeers: [{
2175
+ peerId: validPeerId,
2176
+ providers: ['openai'],
2177
+ lastSeen: NOW - 5_000,
2178
+ onChainReputationScore: 95,
2179
+ onChainUsageEpoch: 22,
2180
+ onChainUsageShareBps: 10_000,
2181
+ onChainPoolPowerShareBps: 10_000,
2182
+ onChainWashFlagged: true,
2183
+ onChainWashShareBps: 9_800,
2184
+ }],
2185
+ }, NOW);
2186
+ assert.ok(peer);
2187
+ assert.equal(peer.onChainWashFlagged, true);
2188
+ assert.equal(peer.onChainWashShareBps, 9_800);
2189
+ assert.equal(peer.onChainReputationScore, 0);
2190
+ assert.equal(peer.trust?.washFlagged, true);
2191
+ assert.equal(peer.trust?.score, 0);
2192
+ });
2193
+ test('parsePersistedPeers keeps the persisted score when nothing scoreable was stored', () => {
2194
+ const [peer] = parsePersistedPeers({
2195
+ discoveredPeers: [{
2196
+ peerId: validPeerId,
2197
+ providers: ['openai'],
2198
+ lastSeen: NOW - 5_000,
2199
+ onChainReputationScore: 42,
2200
+ onChainChannelCount: 3,
2201
+ }],
2202
+ }, NOW);
2203
+ assert.ok(peer);
2204
+ assert.equal(computeTrustScore(peer, NOW), null);
2205
+ assert.equal(peer.onChainReputationScore, 42);
2206
+ assert.equal(peer.trust, undefined);
2095
2207
  });
2096
2208
  test('parsePersistedPeers restores sellerContract into peer.metadata', () => {
2097
2209
  // Regression: dropping sellerContract through the persistence layer caused
@@ -2115,6 +2227,8 @@ test('parsePersistedPeers restores sellerContract into peer.metadata', () => {
2115
2227
  });
2116
2228
  test('parsePersistedPeers restores external verification claims and results', () => {
2117
2229
  const verificationResults = {
2230
+ identityHistory: { version: 1, identities: [{ kind: 'domain', claim: 'example.com', identityId: 'domain:example.com',
2231
+ status: 'available', fetchedAtMs: NOW - 500, createdAtMs: NOW - 10 * 365.25 * 86_400_000 }] },
2118
2232
  verified: true,
2119
2233
  checkedAtMs: NOW - 500,
2120
2234
  domains: [
@@ -2147,6 +2261,50 @@ test('parsePersistedPeers restores external verification claims and results', ()
2147
2261
  domains: [{ domain: 'example.com', methods: ['dns-txt'] }],
2148
2262
  });
2149
2263
  assert.deepEqual(peer.verificationResults, verificationResults);
2264
+ // A ten-year-old verified domain earns the full 12 identity points, worth 20 * 12 / 70 trust.
2265
+ assert.equal(peer.onChainReputationScore, 20 * 12 / 70);
2266
+ assert.deepEqual(peer.trust?.identity, { score: 20 * 12 / 70, kind: 'domain', claim: 'example.com' });
2267
+ assert.equal(peer.trust?.history, null);
2268
+ assert.equal(peer.trust?.usage, null);
2269
+ assert.equal(peer.trust?.washFlagged, null);
2270
+ // Ownership proofs and identity evidence expire after seven days: once
2271
+ // stale the peer is unscored again rather than keeping the cached score.
2272
+ const [stale] = parsePersistedPeers({ discoveredPeers: [{ peerId: validPeerId, providers: ['openai'], lastSeen: NOW + 8 * 86_400_000 - 1_000,
2273
+ verifications: { domains: [{ domain: 'example.com', methods: ['dns-txt'] }] }, verificationResults }] }, NOW + 8 * 86_400_000);
2274
+ assert.ok(stale);
2275
+ assert.equal(computeTrustScore(stale, NOW + 8 * 86_400_000), null);
2276
+ assert.equal(stale.onChainReputationScore, undefined);
2277
+ assert.equal(stale.trust, undefined);
2278
+ });
2279
+ test('parsePersistedPeers restores GitHub identity history but never trusts persisted score breakdowns', () => {
2280
+ const stored = { discoveredPeers: [{ peerId: validPeerId, providers: ['openai'], lastSeen: NOW - 1_000,
2281
+ verifications: { github: [{ username: 'portfolio', repository: 'proof' }] },
2282
+ onChainReputationScore: 100,
2283
+ trust: { score: 100, history: { score: 60, channelCount: 100, totalVolumeUsdcMicros: 100_000_000 }, usage: { score: 15, shareBps: 10_000, epoch: 1 }, power: { score: 5, shareBps: 10_000, epoch: 1 }, identity: { score: 20, kind: 'github', claim: 'portfolio' }, washFlagged: false },
2284
+ verificationResults: { verified: true, checkedAtMs: NOW - 500, domains: [],
2285
+ github: [{ username: 'portfolio', repository: 'proof', peerId: validPeerId, verified: true, checkedAtMs: NOW - 500 }],
2286
+ identityHistory: { version: 1, identities: [{ kind: 'github', claim: 'portfolio', identityId: 'github:42', status: 'available',
2287
+ fetchedAtMs: NOW - 500, createdAtMs: NOW - 2 * 365.25 * 86_400_000,
2288
+ projects: [
2289
+ { id: 1, name: 'alpha', createdAtMs: NOW - 365.25 * 86_400_000, stars: 31, archived: false },
2290
+ // The ownership-proof repository never counts, however popular.
2291
+ { id: 2, name: 'proof', createdAtMs: NOW - 365.25 * 86_400_000, stars: 5_000, archived: false },
2292
+ ] }] } },
2293
+ }] };
2294
+ const [peer] = parsePersistedPeers(JSON.parse(JSON.stringify(stored)), NOW);
2295
+ assert.ok(peer);
2296
+ assert.equal(peer.verificationResults?.identityHistory?.version, 1);
2297
+ assert.equal(peer.verificationResults?.identityHistory?.identities[0]?.projects?.length, 2);
2298
+ const trust = computeTrustScore(peer, NOW);
2299
+ assert.ok(trust);
2300
+ assert.deepEqual(peer.trust, trust);
2301
+ assert.equal(peer.onChainReputationScore, trust.score);
2302
+ assert.equal(trust.identity?.kind, 'github');
2303
+ assert.equal(trust.identity?.claim, 'portfolio');
2304
+ assert.equal(trust.usage, null);
2305
+ assert.ok(trust.score > 0 && trust.score < 20, `expected a modest identity-only score, got ${trust.score}`);
2306
+ const [stale] = parsePersistedPeers(JSON.parse(JSON.stringify(stored)), NOW + 8 * 86_400_000);
2307
+ assert.equal(stale, undefined);
2150
2308
  });
2151
2309
  test('parsePersistedPeers leaves metadata undefined when sellerContract is absent', () => {
2152
2310
  const [peer] = parsePersistedPeers({
@@ -2888,7 +3046,7 @@ test('adaptPeerFaultErrorResponse upgrades a generic wrapper for a pinned route'
2888
3046
  assert.equal(parsed.error.peer_status, 429);
2889
3047
  assert.equal(parsed.error.message, [
2890
3048
  'Oops, pinned peer could not complete the request.',
2891
- 'AntSeed is a peer-to-peer network. Try another peer or use Auto routing.',
3049
+ 'Antseed is a peer-to-peer network. Try another peer or use Auto routing.',
2892
3050
  'Original Response: {"message":"Insufficient balance or no resource package. Please recharge.","status":429}',
2893
3051
  ].join('\n'));
2894
3052
  });