@antseed/node 0.1.0 → 0.1.1

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 (130) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/interfaces/seller-provider.d.ts +13 -1
  6. package/dist/interfaces/seller-provider.d.ts.map +1 -1
  7. package/dist/node.d.ts +13 -3
  8. package/dist/node.d.ts.map +1 -1
  9. package/dist/node.js +123 -15
  10. package/dist/node.js.map +1 -1
  11. package/dist/proxy/proxy-mux.d.ts +3 -1
  12. package/dist/proxy/proxy-mux.d.ts.map +1 -1
  13. package/dist/proxy/proxy-mux.js +9 -5
  14. package/dist/proxy/proxy-mux.js.map +1 -1
  15. package/dist/types/http.d.ts +1 -0
  16. package/dist/types/http.d.ts.map +1 -1
  17. package/dist/types/http.js +1 -1
  18. package/dist/types/http.js.map +1 -1
  19. package/package.json +14 -10
  20. package/contracts/AntseedEscrow.sol +0 -310
  21. package/contracts/MockUSDC.sol +0 -64
  22. package/contracts/README.md +0 -102
  23. package/src/config/encryption.test.ts +0 -49
  24. package/src/config/encryption.ts +0 -53
  25. package/src/config/plugin-config-manager.test.ts +0 -92
  26. package/src/config/plugin-config-manager.ts +0 -153
  27. package/src/config/plugin-loader.ts +0 -90
  28. package/src/discovery/announcer.ts +0 -169
  29. package/src/discovery/bootstrap.ts +0 -57
  30. package/src/discovery/default-metadata-resolver.ts +0 -18
  31. package/src/discovery/dht-health.ts +0 -136
  32. package/src/discovery/dht-node.ts +0 -191
  33. package/src/discovery/http-metadata-resolver.ts +0 -47
  34. package/src/discovery/index.ts +0 -15
  35. package/src/discovery/metadata-codec.ts +0 -453
  36. package/src/discovery/metadata-resolver.ts +0 -7
  37. package/src/discovery/metadata-server.ts +0 -73
  38. package/src/discovery/metadata-validator.ts +0 -172
  39. package/src/discovery/peer-lookup.ts +0 -122
  40. package/src/discovery/peer-metadata.ts +0 -34
  41. package/src/discovery/peer-selector.ts +0 -134
  42. package/src/discovery/profile-manager.ts +0 -131
  43. package/src/discovery/profile-search.ts +0 -100
  44. package/src/discovery/reputation-verifier.ts +0 -54
  45. package/src/index.ts +0 -61
  46. package/src/interfaces/buyer-router.ts +0 -21
  47. package/src/interfaces/plugin.ts +0 -36
  48. package/src/interfaces/seller-provider.ts +0 -81
  49. package/src/metering/index.ts +0 -6
  50. package/src/metering/receipt-generator.ts +0 -105
  51. package/src/metering/receipt-verifier.ts +0 -102
  52. package/src/metering/session-tracker.ts +0 -145
  53. package/src/metering/storage.ts +0 -600
  54. package/src/metering/token-counter.ts +0 -127
  55. package/src/metering/usage-aggregator.ts +0 -236
  56. package/src/node.ts +0 -1698
  57. package/src/p2p/connection-auth.ts +0 -152
  58. package/src/p2p/connection-manager.ts +0 -916
  59. package/src/p2p/handshake.ts +0 -162
  60. package/src/p2p/ice-config.ts +0 -59
  61. package/src/p2p/identity.ts +0 -110
  62. package/src/p2p/index.ts +0 -11
  63. package/src/p2p/keepalive.ts +0 -118
  64. package/src/p2p/message-protocol.ts +0 -171
  65. package/src/p2p/nat-traversal.ts +0 -169
  66. package/src/p2p/payment-codec.ts +0 -165
  67. package/src/p2p/payment-mux.ts +0 -153
  68. package/src/p2p/reconnect.ts +0 -117
  69. package/src/payments/balance-manager.ts +0 -77
  70. package/src/payments/buyer-payment-manager.ts +0 -414
  71. package/src/payments/disputes.ts +0 -72
  72. package/src/payments/evm/escrow-client.ts +0 -263
  73. package/src/payments/evm/keypair.ts +0 -31
  74. package/src/payments/evm/signatures.ts +0 -103
  75. package/src/payments/evm/wallet.ts +0 -42
  76. package/src/payments/index.ts +0 -50
  77. package/src/payments/settlement.ts +0 -40
  78. package/src/payments/types.ts +0 -79
  79. package/src/proxy/index.ts +0 -3
  80. package/src/proxy/provider-detection.ts +0 -78
  81. package/src/proxy/proxy-mux.ts +0 -173
  82. package/src/proxy/request-codec.ts +0 -294
  83. package/src/reputation/index.ts +0 -6
  84. package/src/reputation/rating-manager.ts +0 -118
  85. package/src/reputation/report-manager.ts +0 -91
  86. package/src/reputation/trust-engine.ts +0 -120
  87. package/src/reputation/trust-score.ts +0 -74
  88. package/src/reputation/uptime-tracker.ts +0 -155
  89. package/src/routing/default-router.ts +0 -75
  90. package/src/types/bittorrent-dht.d.ts +0 -19
  91. package/src/types/buyer.ts +0 -37
  92. package/src/types/capability.ts +0 -34
  93. package/src/types/connection.ts +0 -29
  94. package/src/types/http.ts +0 -20
  95. package/src/types/index.ts +0 -14
  96. package/src/types/metering.ts +0 -175
  97. package/src/types/nat-api.d.ts +0 -29
  98. package/src/types/peer-profile.ts +0 -25
  99. package/src/types/peer.ts +0 -62
  100. package/src/types/plugin-config.ts +0 -31
  101. package/src/types/protocol.ts +0 -162
  102. package/src/types/provider.ts +0 -40
  103. package/src/types/rating.ts +0 -23
  104. package/src/types/report.ts +0 -30
  105. package/src/types/seller.ts +0 -38
  106. package/src/types/staking.ts +0 -23
  107. package/src/utils/debug.ts +0 -30
  108. package/src/utils/hex.ts +0 -14
  109. package/tests/balance-manager.test.ts +0 -156
  110. package/tests/bootstrap.test.ts +0 -108
  111. package/tests/buyer-payment-manager.test.ts +0 -358
  112. package/tests/connection-auth.test.ts +0 -87
  113. package/tests/default-router.test.ts +0 -148
  114. package/tests/evm-keypair.test.ts +0 -173
  115. package/tests/identity.test.ts +0 -133
  116. package/tests/message-protocol.test.ts +0 -212
  117. package/tests/metadata-codec.test.ts +0 -165
  118. package/tests/metadata-validator.test.ts +0 -261
  119. package/tests/metering-storage.test.ts +0 -244
  120. package/tests/payment-codec.test.ts +0 -95
  121. package/tests/payment-mux.test.ts +0 -191
  122. package/tests/peer-selector.test.ts +0 -184
  123. package/tests/provider-detection.test.ts +0 -107
  124. package/tests/proxy-mux-security.test.ts +0 -38
  125. package/tests/receipt.test.ts +0 -215
  126. package/tests/reputation-integration.test.ts +0 -195
  127. package/tests/request-codec.test.ts +0 -144
  128. package/tests/token-counter.test.ts +0 -122
  129. package/tsconfig.json +0 -9
  130. package/vitest.config.ts +0 -7
@@ -1,95 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- encodeSessionLockAuth, decodeSessionLockAuth,
4
- encodeSessionLockConfirm, decodeSessionLockConfirm,
5
- encodeSessionLockReject, decodeSessionLockReject,
6
- encodeSellerReceipt, decodeSellerReceipt,
7
- encodeBuyerAck, decodeBuyerAck,
8
- encodeSessionEnd, decodeSessionEnd,
9
- encodeTopUpRequest, decodeTopUpRequest,
10
- encodeTopUpAuth, decodeTopUpAuth,
11
- encodeDisputeNotify, decodeDisputeNotify,
12
- } from '../src/p2p/payment-codec.js';
13
-
14
- describe('payment codec round-trips', () => {
15
- it('SessionLockAuth', () => {
16
- const payload = {
17
- sessionId: 'a'.repeat(64),
18
- lockedAmount: '1000000',
19
- buyerSig: 'b'.repeat(128),
20
- };
21
- const encoded = encodeSessionLockAuth(payload);
22
- const decoded = decodeSessionLockAuth(encoded);
23
- expect(decoded).toEqual(payload);
24
- });
25
-
26
- it('SessionLockConfirm', () => {
27
- const payload = { sessionId: 'a'.repeat(64), txSignature: 'tx123' };
28
- expect(decodeSessionLockConfirm(encodeSessionLockConfirm(payload))).toEqual(payload);
29
- });
30
-
31
- it('SessionLockReject', () => {
32
- const payload = { sessionId: 'a'.repeat(64), reason: 'Insufficient funds' };
33
- expect(decodeSessionLockReject(encodeSessionLockReject(payload))).toEqual(payload);
34
- });
35
-
36
- it('SellerReceipt', () => {
37
- const payload = {
38
- sessionId: 'a'.repeat(64),
39
- runningTotal: '500000',
40
- requestCount: 5,
41
- responseHash: 'c'.repeat(64),
42
- sellerSig: 'd'.repeat(128),
43
- };
44
- expect(decodeSellerReceipt(encodeSellerReceipt(payload))).toEqual(payload);
45
- });
46
-
47
- it('BuyerAck', () => {
48
- const payload = {
49
- sessionId: 'a'.repeat(64),
50
- runningTotal: '500000',
51
- requestCount: 5,
52
- buyerSig: 'e'.repeat(128),
53
- };
54
- expect(decodeBuyerAck(encodeBuyerAck(payload))).toEqual(payload);
55
- });
56
-
57
- it('SessionEnd', () => {
58
- const payload = {
59
- sessionId: 'a'.repeat(64),
60
- runningTotal: '500000',
61
- requestCount: 5,
62
- score: 85,
63
- buyerSig: 'f'.repeat(128),
64
- };
65
- expect(decodeSessionEnd(encodeSessionEnd(payload))).toEqual(payload);
66
- });
67
-
68
- it('TopUpRequest', () => {
69
- const payload = {
70
- sessionId: 'a'.repeat(64),
71
- additionalAmount: '500000',
72
- currentRunningTotal: '400000',
73
- currentLockedAmount: '500000',
74
- };
75
- expect(decodeTopUpRequest(encodeTopUpRequest(payload))).toEqual(payload);
76
- });
77
-
78
- it('TopUpAuth', () => {
79
- const payload = {
80
- sessionId: 'a'.repeat(64),
81
- additionalAmount: '500000',
82
- buyerSig: 'g'.repeat(128),
83
- };
84
- expect(decodeTopUpAuth(encodeTopUpAuth(payload))).toEqual(payload);
85
- });
86
-
87
- it('DisputeNotify', () => {
88
- const payload = {
89
- sessionId: 'a'.repeat(64),
90
- reason: 'Unacknowledged service',
91
- txSignature: 'tx456',
92
- };
93
- expect(decodeDisputeNotify(encodeDisputeNotify(payload))).toEqual(payload);
94
- });
95
- });
@@ -1,191 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
- import { PaymentMux } from '../src/p2p/payment-mux.js';
3
- import { MessageType, type FramedMessage } from '../src/types/protocol.js';
4
- import * as codec from '../src/p2p/payment-codec.js';
5
- import type { PeerConnection } from '../src/p2p/connection-manager.js';
6
-
7
- function mockConnection(): PeerConnection {
8
- return { send: vi.fn() } as unknown as PeerConnection;
9
- }
10
-
11
- describe('PaymentMux', () => {
12
- describe('isPaymentMessage correctly identifies range', () => {
13
- it('returns true for 0x50-0x58', () => {
14
- for (let type = 0x50; type <= 0x58; type++) {
15
- expect(PaymentMux.isPaymentMessage(type)).toBe(true);
16
- }
17
- });
18
-
19
- it('returns true for 0x59-0x5F (rest of payment range)', () => {
20
- for (let type = 0x59; type <= 0x5f; type++) {
21
- expect(PaymentMux.isPaymentMessage(type)).toBe(true);
22
- }
23
- });
24
-
25
- it('returns false for non-payment types', () => {
26
- expect(PaymentMux.isPaymentMessage(0x01)).toBe(false);
27
- expect(PaymentMux.isPaymentMessage(0x20)).toBe(false);
28
- expect(PaymentMux.isPaymentMessage(0x4f)).toBe(false);
29
- expect(PaymentMux.isPaymentMessage(0x60)).toBe(false);
30
- expect(PaymentMux.isPaymentMessage(0xff)).toBe(false);
31
- });
32
- });
33
-
34
- describe('handleFrame returns false for non-payment messages', () => {
35
- it('returns false for HttpRequest', async () => {
36
- const mux = new PaymentMux(mockConnection());
37
- const frame: FramedMessage = {
38
- type: MessageType.HttpRequest,
39
- messageId: 1,
40
- payload: new Uint8Array(0),
41
- };
42
- expect(await mux.handleFrame(frame)).toBe(false);
43
- });
44
-
45
- it('returns false for Ping', async () => {
46
- const mux = new PaymentMux(mockConnection());
47
- const frame: FramedMessage = {
48
- type: MessageType.Ping,
49
- messageId: 1,
50
- payload: new Uint8Array(0),
51
- };
52
- expect(await mux.handleFrame(frame)).toBe(false);
53
- });
54
- });
55
-
56
- describe('handleFrame dispatches to correct handler', () => {
57
- it('dispatches SessionLockAuth', async () => {
58
- const conn = mockConnection();
59
- const mux = new PaymentMux(conn);
60
- const handler = vi.fn();
61
- mux.onSessionLockAuth(handler);
62
-
63
- const payload = {
64
- sessionId: 'a'.repeat(64),
65
- lockedAmount: '1000000',
66
- buyerSig: 'b'.repeat(128),
67
- };
68
- const frame: FramedMessage = {
69
- type: MessageType.SessionLockAuth,
70
- messageId: 1,
71
- payload: codec.encodeSessionLockAuth(payload),
72
- };
73
-
74
- const result = await mux.handleFrame(frame);
75
- expect(result).toBe(true);
76
- expect(handler).toHaveBeenCalledWith(payload);
77
- });
78
-
79
- it('dispatches SellerReceipt', async () => {
80
- const conn = mockConnection();
81
- const mux = new PaymentMux(conn);
82
- const handler = vi.fn();
83
- mux.onSellerReceipt(handler);
84
-
85
- const payload = {
86
- sessionId: 'a'.repeat(64),
87
- runningTotal: '500000',
88
- requestCount: 5,
89
- responseHash: 'c'.repeat(64),
90
- sellerSig: 'd'.repeat(128),
91
- };
92
- const frame: FramedMessage = {
93
- type: MessageType.SellerReceipt,
94
- messageId: 2,
95
- payload: codec.encodeSellerReceipt(payload),
96
- };
97
-
98
- const result = await mux.handleFrame(frame);
99
- expect(result).toBe(true);
100
- expect(handler).toHaveBeenCalledWith(payload);
101
- });
102
-
103
- it('dispatches BuyerAck', async () => {
104
- const conn = mockConnection();
105
- const mux = new PaymentMux(conn);
106
- const handler = vi.fn();
107
- mux.onBuyerAck(handler);
108
-
109
- const payload = {
110
- sessionId: 'a'.repeat(64),
111
- runningTotal: '500000',
112
- requestCount: 5,
113
- buyerSig: 'e'.repeat(128),
114
- };
115
- const frame: FramedMessage = {
116
- type: MessageType.BuyerAck,
117
- messageId: 3,
118
- payload: codec.encodeBuyerAck(payload),
119
- };
120
-
121
- const result = await mux.handleFrame(frame);
122
- expect(result).toBe(true);
123
- expect(handler).toHaveBeenCalledWith(payload);
124
- });
125
-
126
- it('dispatches SessionEnd', async () => {
127
- const conn = mockConnection();
128
- const mux = new PaymentMux(conn);
129
- const handler = vi.fn();
130
- mux.onSessionEnd(handler);
131
-
132
- const payload = {
133
- sessionId: 'a'.repeat(64),
134
- runningTotal: '500000',
135
- requestCount: 5,
136
- score: 85,
137
- buyerSig: 'f'.repeat(128),
138
- };
139
- const frame: FramedMessage = {
140
- type: MessageType.SessionEnd,
141
- messageId: 4,
142
- payload: codec.encodeSessionEnd(payload),
143
- };
144
-
145
- const result = await mux.handleFrame(frame);
146
- expect(result).toBe(true);
147
- expect(handler).toHaveBeenCalledWith(payload);
148
- });
149
-
150
- it('dispatches DisputeNotify', async () => {
151
- const conn = mockConnection();
152
- const mux = new PaymentMux(conn);
153
- const handler = vi.fn();
154
- mux.onDisputeNotify(handler);
155
-
156
- const payload = {
157
- sessionId: 'a'.repeat(64),
158
- reason: 'Unacknowledged service',
159
- txSignature: 'tx456',
160
- };
161
- const frame: FramedMessage = {
162
- type: MessageType.DisputeNotify,
163
- messageId: 5,
164
- payload: codec.encodeDisputeNotify(payload),
165
- };
166
-
167
- const result = await mux.handleFrame(frame);
168
- expect(result).toBe(true);
169
- expect(handler).toHaveBeenCalledWith(payload);
170
- });
171
-
172
- it('returns true even with no handler registered', async () => {
173
- const conn = mockConnection();
174
- const mux = new PaymentMux(conn);
175
-
176
- const payload = {
177
- sessionId: 'a'.repeat(64),
178
- lockedAmount: '1000000',
179
- buyerSig: 'b'.repeat(128),
180
- };
181
- const frame: FramedMessage = {
182
- type: MessageType.SessionLockAuth,
183
- messageId: 1,
184
- payload: codec.encodeSessionLockAuth(payload),
185
- };
186
-
187
- const result = await mux.handleFrame(frame);
188
- expect(result).toBe(true);
189
- });
190
- });
191
- });
@@ -1,184 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- scorePeer,
4
- rankPeers,
5
- selectBestPeer,
6
- selectDiversePeers,
7
- DEFAULT_SCORING_WEIGHTS,
8
- type PeerCandidate,
9
- } from '../src/discovery/peer-selector.js';
10
-
11
- function makeCandidate(overrides?: Partial<PeerCandidate>): PeerCandidate {
12
- return {
13
- peerId: 'peer-1',
14
- region: 'us-east-1',
15
- inputUsdPerMillion: 0.01,
16
- maxConcurrency: 10,
17
- currentLoad: 0,
18
- latencyMs: 100,
19
- reputation: 0.9,
20
- ...overrides,
21
- };
22
- }
23
-
24
- describe('scorePeer', () => {
25
- it('should return a score between 0 and 1', () => {
26
- const score = scorePeer(makeCandidate(), 0.01);
27
- expect(score).toBeGreaterThanOrEqual(0);
28
- expect(score).toBeLessThanOrEqual(1);
29
- });
30
-
31
- it('should give perfect score to ideal candidate', () => {
32
- const candidate = makeCandidate({
33
- inputUsdPerMillion: 0.01,
34
- maxConcurrency: 10,
35
- currentLoad: 0,
36
- latencyMs: 0,
37
- reputation: 1,
38
- });
39
- const score = scorePeer(candidate, 0.01);
40
- expect(score).toBeCloseTo(1.0, 2);
41
- });
42
-
43
- it('should give lower score to more expensive peers', () => {
44
- const cheap = makeCandidate({ inputUsdPerMillion: 0.01 });
45
- const expensive = makeCandidate({ inputUsdPerMillion: 0.10 });
46
- const cheapScore = scorePeer(cheap, 0.01);
47
- const expensiveScore = scorePeer(expensive, 0.01);
48
- expect(cheapScore).toBeGreaterThan(expensiveScore);
49
- });
50
-
51
- it('should give lower score to heavily loaded peers', () => {
52
- const idle = makeCandidate({ currentLoad: 0, maxConcurrency: 10 });
53
- const loaded = makeCandidate({ currentLoad: 9, maxConcurrency: 10 });
54
- expect(scorePeer(idle, 0.01)).toBeGreaterThan(scorePeer(loaded, 0.01));
55
- });
56
-
57
- it('should give lower score to high-latency peers', () => {
58
- const fast = makeCandidate({ latencyMs: 50 });
59
- const slow = makeCandidate({ latencyMs: 10000 });
60
- expect(scorePeer(fast, 0.01)).toBeGreaterThan(scorePeer(slow, 0.01));
61
- });
62
-
63
- it('should handle zero price (free) as perfect price score', () => {
64
- const free = makeCandidate({ inputUsdPerMillion: 0 });
65
- const score = scorePeer(free, 0.01);
66
- // price score = 1.0 for free peers
67
- expect(score).toBeGreaterThanOrEqual(0);
68
- });
69
-
70
- it('should handle maxConcurrency = 0 as zero capacity', () => {
71
- const candidate = makeCandidate({ maxConcurrency: 0, currentLoad: 0 });
72
- // capacity score = 0 when maxConcurrency is 0
73
- const score = scorePeer(candidate, 0.01);
74
- expect(score).toBeLessThan(1);
75
- });
76
-
77
- it('should clamp latency score at 0 for >= 15000ms', () => {
78
- const verySlowA = makeCandidate({ latencyMs: 15000 });
79
- const verySlowB = makeCandidate({ latencyMs: 20000 });
80
- expect(scorePeer(verySlowA, 0.01)).toEqual(scorePeer(verySlowB, 0.01));
81
- });
82
-
83
- it('should accept custom weights', () => {
84
- // Use a candidate where price score and capacity score differ
85
- const candidate = makeCandidate({
86
- inputUsdPerMillion: 0.05, // price score = 0.01/0.05 = 0.2
87
- maxConcurrency: 10,
88
- currentLoad: 5, // capacity score = 5/10 = 0.5
89
- latencyMs: 0,
90
- reputation: 0,
91
- });
92
- const priceOnly = { price: 1, capacity: 0, latency: 0, reputation: 0 };
93
- const capOnly = { price: 0, capacity: 1, latency: 0, reputation: 0 };
94
- const s1 = scorePeer(candidate, 0.01, priceOnly);
95
- const s2 = scorePeer(candidate, 0.01, capOnly);
96
- expect(s1).not.toBe(s2);
97
- expect(s1).toBeCloseTo(0.2, 2);
98
- expect(s2).toBeCloseTo(0.5, 2);
99
- });
100
- });
101
-
102
- describe('rankPeers', () => {
103
- it('should return empty array for empty input', () => {
104
- expect(rankPeers([])).toEqual([]);
105
- });
106
-
107
- it('should sort peers by score descending', () => {
108
- const candidates = [
109
- makeCandidate({ peerId: 'expensive', inputUsdPerMillion: 1.0, latencyMs: 5000 }),
110
- makeCandidate({ peerId: 'cheap', inputUsdPerMillion: 0.001, latencyMs: 50 }),
111
- ];
112
- const ranked = rankPeers(candidates);
113
- expect(ranked[0]!.candidate.peerId).toBe('cheap');
114
- expect(ranked[0]!.score).toBeGreaterThan(ranked[1]!.score);
115
- });
116
-
117
- it('should derive cheapest price automatically', () => {
118
- const candidates = [
119
- makeCandidate({ peerId: 'a', inputUsdPerMillion: 0.1 }),
120
- makeCandidate({ peerId: 'b', inputUsdPerMillion: 0.01 }),
121
- ];
122
- const ranked = rankPeers(candidates);
123
- // 'b' is cheapest so it should have perfect price score
124
- expect(ranked[0]!.candidate.peerId).toBe('b');
125
- });
126
- });
127
-
128
- describe('selectBestPeer', () => {
129
- it('should return null for empty candidates', () => {
130
- expect(selectBestPeer([])).toBeNull();
131
- });
132
-
133
- it('should return the highest-scoring peer', () => {
134
- const candidates = [
135
- makeCandidate({ peerId: 'slow', latencyMs: 10000, inputUsdPerMillion: 1 }),
136
- makeCandidate({ peerId: 'fast', latencyMs: 10, inputUsdPerMillion: 0.001 }),
137
- ];
138
- const best = selectBestPeer(candidates);
139
- expect(best).not.toBeNull();
140
- expect(best!.candidate.peerId).toBe('fast');
141
- });
142
- });
143
-
144
- describe('selectDiversePeers', () => {
145
- it('should return all peers when count >= candidates', () => {
146
- const candidates = [makeCandidate({ peerId: 'a' }), makeCandidate({ peerId: 'b' })];
147
- const result = selectDiversePeers(candidates, 5);
148
- expect(result).toHaveLength(2);
149
- });
150
-
151
- it('should prefer peers from different regions', () => {
152
- const candidates = [
153
- makeCandidate({ peerId: 'us1', region: 'us-east-1', inputUsdPerMillion: 0.01 }),
154
- makeCandidate({ peerId: 'us2', region: 'us-east-1', inputUsdPerMillion: 0.02 }),
155
- makeCandidate({ peerId: 'eu1', region: 'eu-west-1', inputUsdPerMillion: 0.03 }),
156
- ];
157
- const result = selectDiversePeers(candidates, 2);
158
- expect(result).toHaveLength(2);
159
- const regions = result.map((r) => r.candidate.region);
160
- expect(regions).toContain('us-east-1');
161
- expect(regions).toContain('eu-west-1');
162
- });
163
-
164
- it('should fill remaining slots by score after region diversity', () => {
165
- const candidates = [
166
- makeCandidate({ peerId: 'a', region: 'us', inputUsdPerMillion: 0.001 }),
167
- makeCandidate({ peerId: 'b', region: 'us', inputUsdPerMillion: 0.01 }),
168
- makeCandidate({ peerId: 'c', region: 'eu', inputUsdPerMillion: 0.1 }),
169
- ];
170
- const result = selectDiversePeers(candidates, 3);
171
- expect(result).toHaveLength(3);
172
- });
173
- });
174
-
175
- describe('DEFAULT_SCORING_WEIGHTS', () => {
176
- it('should sum to approximately 1.0', () => {
177
- const sum =
178
- DEFAULT_SCORING_WEIGHTS.price +
179
- DEFAULT_SCORING_WEIGHTS.capacity +
180
- DEFAULT_SCORING_WEIGHTS.latency +
181
- DEFAULT_SCORING_WEIGHTS.reputation;
182
- expect(sum).toBeCloseTo(1.0, 5);
183
- });
184
- });
@@ -1,107 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- detectProviderFromHeaders,
4
- detectProviderFromPath,
5
- resolveProvider,
6
- ANTSEED_PROVIDER_HEADER,
7
- } from '../src/proxy/provider-detection.js';
8
-
9
- describe('detectProviderFromHeaders', () => {
10
- it('should detect anthropic from header', () => {
11
- expect(detectProviderFromHeaders({ [ANTSEED_PROVIDER_HEADER]: 'anthropic' })).toBe('anthropic');
12
- });
13
-
14
- it('should detect openai from header', () => {
15
- expect(detectProviderFromHeaders({ [ANTSEED_PROVIDER_HEADER]: 'openai' })).toBe('openai');
16
- });
17
-
18
- it('should detect google from header', () => {
19
- expect(detectProviderFromHeaders({ [ANTSEED_PROVIDER_HEADER]: 'google' })).toBe('google');
20
- });
21
-
22
- it('should detect moonshot from header', () => {
23
- expect(detectProviderFromHeaders({ [ANTSEED_PROVIDER_HEADER]: 'moonshot' })).toBe('moonshot');
24
- });
25
-
26
- it('should be case-insensitive for header name', () => {
27
- expect(detectProviderFromHeaders({ 'X-ANTSEED-PROVIDER': 'anthropic' })).toBe('anthropic');
28
- });
29
-
30
- it('should trim and lowercase the header value', () => {
31
- expect(detectProviderFromHeaders({ [ANTSEED_PROVIDER_HEADER]: ' OPENAI ' })).toBe('openai');
32
- });
33
-
34
- it('should return null for unknown provider', () => {
35
- expect(detectProviderFromHeaders({ [ANTSEED_PROVIDER_HEADER]: 'unknown' })).toBeNull();
36
- });
37
-
38
- it('should return null when header is missing', () => {
39
- expect(detectProviderFromHeaders({ 'content-type': 'application/json' })).toBeNull();
40
- });
41
- });
42
-
43
- describe('detectProviderFromPath', () => {
44
- it('should detect anthropic from /v1/messages', () => {
45
- expect(detectProviderFromPath('/v1/messages')).toBe('anthropic');
46
- });
47
-
48
- it('should detect anthropic from /v1/complete', () => {
49
- expect(detectProviderFromPath('/v1/complete')).toBe('anthropic');
50
- });
51
-
52
- it('should detect openai from /v1/chat/completions', () => {
53
- expect(detectProviderFromPath('/v1/chat/completions')).toBe('openai');
54
- });
55
-
56
- it('should detect openai from /v1/completions', () => {
57
- expect(detectProviderFromPath('/v1/completions')).toBe('openai');
58
- });
59
-
60
- it('should detect openai from /v1/embeddings', () => {
61
- expect(detectProviderFromPath('/v1/embeddings')).toBe('openai');
62
- });
63
-
64
- it('should detect google from /v1beta/ paths', () => {
65
- expect(detectProviderFromPath('/v1beta/models/gemini-pro:generateContent')).toBe('google');
66
- });
67
-
68
- it('should detect google from /v1/models/gemini paths', () => {
69
- expect(detectProviderFromPath('/v1/models/gemini-pro:generateContent')).toBe('google');
70
- });
71
-
72
- it('should detect moonshot from paths containing moonshot', () => {
73
- expect(detectProviderFromPath('/v1/moonshot/chat/completions')).toBe('moonshot');
74
- });
75
-
76
- it('should prioritize moonshot over openai for ambiguous paths', () => {
77
- // moonshot check happens before openai
78
- expect(detectProviderFromPath('/v1/chat/moonshot/completions')).toBe('moonshot');
79
- });
80
-
81
- it('should return null for unrecognized paths', () => {
82
- expect(detectProviderFromPath('/api/v2/infer')).toBeNull();
83
- });
84
-
85
- it('should be case-insensitive', () => {
86
- expect(detectProviderFromPath('/V1/Messages')).toBe('anthropic');
87
- });
88
- });
89
-
90
- describe('resolveProvider', () => {
91
- it('should prefer header over path', () => {
92
- const result = resolveProvider('/v1/chat/completions', {
93
- [ANTSEED_PROVIDER_HEADER]: 'anthropic',
94
- }, 'openai');
95
- expect(result).toBe('anthropic');
96
- });
97
-
98
- it('should fall back to path when header is absent', () => {
99
- const result = resolveProvider('/v1/messages', {}, 'openai');
100
- expect(result).toBe('anthropic');
101
- });
102
-
103
- it('should fall back to default when neither header nor path matches', () => {
104
- const result = resolveProvider('/unknown', {}, 'openai');
105
- expect(result).toBe('openai');
106
- });
107
- });
@@ -1,38 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { ProxyMux } from '../src/proxy/proxy-mux.js';
3
- import { MessageType } from '../src/types/protocol.js';
4
- import type { PeerConnection } from '../src/p2p/connection-manager.js';
5
-
6
- function createMux(): ProxyMux {
7
- const conn = {
8
- send: () => {},
9
- } as unknown as PeerConnection;
10
-
11
- return new ProxyMux(conn);
12
- }
13
-
14
- describe('ProxyMux security handling', () => {
15
- it('rejects malformed payloads instead of silently proceeding', async () => {
16
- const mux = createMux();
17
-
18
- await expect(
19
- mux.handleFrame({
20
- type: MessageType.HttpResponse,
21
- messageId: 1,
22
- payload: new Uint8Array([0x01]),
23
- }),
24
- ).rejects.toThrow('Failed to handle proxy frame type');
25
- });
26
-
27
- it('ignores unknown frame types', async () => {
28
- const mux = createMux();
29
-
30
- await expect(
31
- mux.handleFrame({
32
- type: 0x99 as MessageType,
33
- messageId: 2,
34
- payload: new Uint8Array(),
35
- }),
36
- ).resolves.toBeUndefined();
37
- });
38
- });