@f2a/network 0.1.2 → 0.1.3

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 (136) hide show
  1. package/package.json +8 -1
  2. package/.github/workflows/ci.yml +0 -113
  3. package/.github/workflows/publish.yml +0 -60
  4. package/MONOREPO.md +0 -58
  5. package/SKILL.md +0 -137
  6. package/dist/adapters/openclaw.d.ts +0 -103
  7. package/dist/adapters/openclaw.d.ts.map +0 -1
  8. package/dist/adapters/openclaw.js +0 -297
  9. package/dist/adapters/openclaw.js.map +0 -1
  10. package/dist/core/connection-manager.d.ts +0 -80
  11. package/dist/core/connection-manager.d.ts.map +0 -1
  12. package/dist/core/connection-manager.js +0 -235
  13. package/dist/core/connection-manager.js.map +0 -1
  14. package/dist/core/connection-manager.test.d.ts +0 -2
  15. package/dist/core/connection-manager.test.d.ts.map +0 -1
  16. package/dist/core/connection-manager.test.js +0 -52
  17. package/dist/core/connection-manager.test.js.map +0 -1
  18. package/dist/core/identity.d.ts +0 -47
  19. package/dist/core/identity.d.ts.map +0 -1
  20. package/dist/core/identity.js +0 -130
  21. package/dist/core/identity.js.map +0 -1
  22. package/dist/core/identity.test.d.ts +0 -2
  23. package/dist/core/identity.test.d.ts.map +0 -1
  24. package/dist/core/identity.test.js +0 -43
  25. package/dist/core/identity.test.js.map +0 -1
  26. package/dist/core/serverless.d.ts +0 -155
  27. package/dist/core/serverless.d.ts.map +0 -1
  28. package/dist/core/serverless.js +0 -615
  29. package/dist/core/serverless.js.map +0 -1
  30. package/dist/daemon/webhook.test.d.ts +0 -2
  31. package/dist/daemon/webhook.test.d.ts.map +0 -1
  32. package/dist/daemon/webhook.test.js +0 -24
  33. package/dist/daemon/webhook.test.js.map +0 -1
  34. package/dist/protocol/messages.d.ts +0 -739
  35. package/dist/protocol/messages.d.ts.map +0 -1
  36. package/dist/protocol/messages.js +0 -188
  37. package/dist/protocol/messages.js.map +0 -1
  38. package/dist/protocol/messages.test.d.ts +0 -2
  39. package/dist/protocol/messages.test.d.ts.map +0 -1
  40. package/dist/protocol/messages.test.js +0 -55
  41. package/dist/protocol/messages.test.js.map +0 -1
  42. package/docs/F2A-PROTOCOL.md +0 -61
  43. package/docs/MOBILE_BOOTSTRAP_DESIGN.md +0 -126
  44. package/docs/a2a-lessons.md +0 -316
  45. package/docs/middleware-guide.md +0 -448
  46. package/docs/readme-update-checklist.md +0 -90
  47. package/docs/reputation-guide.md +0 -396
  48. package/docs/rfcs/001-reputation-system.md +0 -712
  49. package/docs/security-design.md +0 -247
  50. package/install.sh +0 -231
  51. package/packages/openclaw-adapter/README.md +0 -510
  52. package/packages/openclaw-adapter/openclaw.plugin.json +0 -106
  53. package/packages/openclaw-adapter/package.json +0 -40
  54. package/packages/openclaw-adapter/src/announcement-queue.test.ts +0 -449
  55. package/packages/openclaw-adapter/src/announcement-queue.ts +0 -403
  56. package/packages/openclaw-adapter/src/capability-detector.test.ts +0 -99
  57. package/packages/openclaw-adapter/src/capability-detector.ts +0 -183
  58. package/packages/openclaw-adapter/src/claim-handlers.test.ts +0 -974
  59. package/packages/openclaw-adapter/src/claim-handlers.ts +0 -482
  60. package/packages/openclaw-adapter/src/connector.business.test.ts +0 -583
  61. package/packages/openclaw-adapter/src/connector.ts +0 -795
  62. package/packages/openclaw-adapter/src/index.test.ts +0 -82
  63. package/packages/openclaw-adapter/src/index.ts +0 -18
  64. package/packages/openclaw-adapter/src/integration.e2e.test.ts +0 -829
  65. package/packages/openclaw-adapter/src/logger.ts +0 -51
  66. package/packages/openclaw-adapter/src/network-client.test.ts +0 -266
  67. package/packages/openclaw-adapter/src/network-client.ts +0 -251
  68. package/packages/openclaw-adapter/src/network-recovery.test.ts +0 -465
  69. package/packages/openclaw-adapter/src/node-manager.test.ts +0 -136
  70. package/packages/openclaw-adapter/src/node-manager.ts +0 -429
  71. package/packages/openclaw-adapter/src/plugin.test.ts +0 -439
  72. package/packages/openclaw-adapter/src/plugin.ts +0 -104
  73. package/packages/openclaw-adapter/src/reputation.test.ts +0 -221
  74. package/packages/openclaw-adapter/src/reputation.ts +0 -368
  75. package/packages/openclaw-adapter/src/task-guard.test.ts +0 -502
  76. package/packages/openclaw-adapter/src/task-guard.ts +0 -860
  77. package/packages/openclaw-adapter/src/task-queue.concurrency.test.ts +0 -462
  78. package/packages/openclaw-adapter/src/task-queue.edge-cases.test.ts +0 -284
  79. package/packages/openclaw-adapter/src/task-queue.persistence.test.ts +0 -408
  80. package/packages/openclaw-adapter/src/task-queue.ts +0 -668
  81. package/packages/openclaw-adapter/src/tool-handlers.test.ts +0 -906
  82. package/packages/openclaw-adapter/src/tool-handlers.ts +0 -574
  83. package/packages/openclaw-adapter/src/types.ts +0 -361
  84. package/packages/openclaw-adapter/src/webhook-pusher.test.ts +0 -188
  85. package/packages/openclaw-adapter/src/webhook-pusher.ts +0 -220
  86. package/packages/openclaw-adapter/src/webhook-server.test.ts +0 -580
  87. package/packages/openclaw-adapter/src/webhook-server.ts +0 -202
  88. package/packages/openclaw-adapter/tsconfig.json +0 -20
  89. package/src/cli/commands.test.ts +0 -157
  90. package/src/cli/commands.ts +0 -129
  91. package/src/cli/index.test.ts +0 -77
  92. package/src/cli/index.ts +0 -234
  93. package/src/core/autonomous-economy.test.ts +0 -291
  94. package/src/core/autonomous-economy.ts +0 -428
  95. package/src/core/e2ee-crypto.test.ts +0 -125
  96. package/src/core/e2ee-crypto.ts +0 -246
  97. package/src/core/f2a.test.ts +0 -269
  98. package/src/core/f2a.ts +0 -618
  99. package/src/core/p2p-network.test.ts +0 -199
  100. package/src/core/p2p-network.ts +0 -1432
  101. package/src/core/reputation-security.test.ts +0 -403
  102. package/src/core/reputation-security.ts +0 -562
  103. package/src/core/reputation.test.ts +0 -260
  104. package/src/core/reputation.ts +0 -576
  105. package/src/core/review-committee.test.ts +0 -380
  106. package/src/core/review-committee.ts +0 -401
  107. package/src/core/token-manager.test.ts +0 -133
  108. package/src/core/token-manager.ts +0 -140
  109. package/src/daemon/control-server.test.ts +0 -216
  110. package/src/daemon/control-server.ts +0 -292
  111. package/src/daemon/index.test.ts +0 -85
  112. package/src/daemon/index.ts +0 -89
  113. package/src/daemon/main.ts +0 -44
  114. package/src/daemon/start.ts +0 -29
  115. package/src/daemon/webhook.test.ts +0 -68
  116. package/src/daemon/webhook.ts +0 -105
  117. package/src/index.test.ts +0 -436
  118. package/src/index.ts +0 -72
  119. package/src/types/index.test.ts +0 -87
  120. package/src/types/index.ts +0 -341
  121. package/src/types/result.ts +0 -68
  122. package/src/utils/benchmark.ts +0 -237
  123. package/src/utils/logger.ts +0 -331
  124. package/src/utils/middleware.ts +0 -229
  125. package/src/utils/rate-limiter.ts +0 -207
  126. package/src/utils/signature.ts +0 -136
  127. package/src/utils/validation.ts +0 -186
  128. package/tests/docker/Dockerfile.node +0 -23
  129. package/tests/docker/Dockerfile.runner +0 -18
  130. package/tests/docker/docker-compose.test.yml +0 -73
  131. package/tests/integration/message-passing.test.ts +0 -109
  132. package/tests/integration/multi-node.test.ts +0 -92
  133. package/tests/integration/p2p-connection.test.ts +0 -83
  134. package/tests/integration/test-config.ts +0 -32
  135. package/tsconfig.json +0 -21
  136. package/vitest.config.ts +0 -26
@@ -1,44 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * F2A Daemon 入口
4
- */
5
-
6
- import { F2ADaemon } from './index.js';
7
-
8
- // 解析引导节点地址
9
- const bootstrapPeers = process.env.BOOTSTRAP_PEERS
10
- ? process.env.BOOTSTRAP_PEERS.split(',')
11
- : undefined;
12
-
13
- // P2P 端口(默认 0 = 随机分配)
14
- const p2pPort = parseInt(process.env.F2A_P2P_PORT || '0');
15
-
16
- const daemon = new F2ADaemon({
17
- controlPort: parseInt(process.env.F2A_CONTROL_PORT || '9001'),
18
- network: {
19
- listenPort: p2pPort,
20
- bootstrapPeers,
21
- },
22
- });
23
-
24
- // 处理信号
25
- process.on('SIGINT', async () => {
26
- console.log('[Daemon] Received SIGINT, shutting down...');
27
- await daemon.stop();
28
- process.exit(0);
29
- });
30
-
31
- process.on('SIGTERM', async () => {
32
- console.log('[Daemon] Received SIGTERM, shutting down...');
33
- await daemon.stop();
34
- process.exit(0);
35
- });
36
-
37
- // 启动
38
- daemon.start().catch((error) => {
39
- console.error('[Daemon] Failed to start:', error instanceof Error ? error.message : String(error));
40
- if (error instanceof Error && error.stack) {
41
- console.error('[Daemon] Stack trace:', error.stack);
42
- }
43
- process.exit(1);
44
- });
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * F2A Daemon 入口
4
- */
5
-
6
- import { F2ADaemon } from './index.js';
7
-
8
- const daemon = new F2ADaemon({
9
- controlPort: parseInt(process.env.F2A_CONTROL_PORT || '9001'),
10
- });
11
-
12
- // 处理信号
13
- process.on('SIGINT', async () => {
14
- console.log('[Daemon] Received SIGINT, shutting down...');
15
- await daemon.stop();
16
- process.exit(0);
17
- });
18
-
19
- process.on('SIGTERM', async () => {
20
- console.log('[Daemon] Received SIGTERM, shutting down...');
21
- await daemon.stop();
22
- process.exit(0);
23
- });
24
-
25
- // 启动
26
- daemon.start().catch((error) => {
27
- console.error('[Daemon] Failed to start:', error);
28
- process.exit(1);
29
- });
@@ -1,68 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { WebhookService } from './webhook.js';
3
-
4
- describe('WebhookService', () => {
5
- let service: WebhookService;
6
-
7
- beforeEach(() => {
8
- service = new WebhookService({
9
- url: 'http://localhost:8080/hooks',
10
- token: 'test-token'
11
- });
12
- });
13
-
14
- describe('constructor', () => {
15
- it('should create service with default options', () => {
16
- const defaultService = new WebhookService({
17
- url: 'http://localhost:8080/hooks',
18
- token: 'test-token'
19
- });
20
- expect(defaultService).toBeDefined();
21
- });
22
-
23
- it('should create service with custom options', () => {
24
- const customService = new WebhookService({
25
- url: 'http://localhost:8080/hooks',
26
- token: 'test-token',
27
- timeout: 10000,
28
- retries: 5,
29
- retryDelay: 2000
30
- });
31
- expect(customService).toBeDefined();
32
- });
33
- });
34
-
35
- describe('send', () => {
36
- it('should skip notification when token not set', async () => {
37
- const noTokenService = new WebhookService({
38
- url: 'http://localhost:8080/hooks',
39
- token: ''
40
- });
41
-
42
- const result = await noTokenService.send({ message: 'test' });
43
- expect(result.success).toBe(false);
44
- expect(result.error).toBe('Token not set');
45
- });
46
-
47
- it('should send notification with default options', async () => {
48
- // This would make actual HTTP request in real scenario
49
- // For unit test, we just verify it doesn't throw
50
- const result = await service.send({ message: 'test' });
51
- // Result depends on network
52
- });
53
-
54
- it('should send notification with custom options', async () => {
55
- const result = await service.send({
56
- message: 'test message',
57
- name: 'Test Agent',
58
- wakeMode: 'now',
59
- deliver: true
60
- });
61
- });
62
-
63
- it('should handle network errors with retries', async () => {
64
- // Mock would be needed to test retry logic
65
- const result = await service.send({ message: 'test' });
66
- });
67
- });
68
- });
@@ -1,105 +0,0 @@
1
- /**
2
- * Webhook 通知服务
3
- */
4
-
5
- import { request, RequestOptions } from 'https';
6
- import { request as httpRequest } from 'http';
7
- import { WebhookConfig } from '../types/index.js';
8
-
9
- export interface WebhookNotification {
10
- message: string;
11
- name?: string;
12
- wakeMode?: 'now' | 'next-heartbeat';
13
- deliver?: boolean;
14
- }
15
-
16
- export class WebhookService {
17
- private config: WebhookConfig;
18
-
19
- constructor(config: WebhookConfig) {
20
- this.config = {
21
- timeout: 5000,
22
- retries: 3,
23
- retryDelay: 1000,
24
- ...config
25
- };
26
- }
27
-
28
- /**
29
- * 发送通知
30
- */
31
- async send(notification: WebhookNotification): Promise<{ success: boolean; error?: string }> {
32
- if (!this.config.token) {
33
- console.log('[Webhook] Token not set, skipping notification');
34
- return { success: false, error: 'Token not set' };
35
- }
36
-
37
- const payload = JSON.stringify({
38
- message: notification.message,
39
- name: notification.name || 'F2A',
40
- wakeMode: notification.wakeMode || 'now',
41
- deliver: notification.deliver !== false
42
- });
43
-
44
- for (let attempt = 1; attempt <= this.config.retries!; attempt++) {
45
- try {
46
- await this.sendRequest(payload);
47
- console.log(`[Webhook] Notification sent (attempt ${attempt})`);
48
- return { success: true };
49
- } catch (err) {
50
- const message = err instanceof Error ? err.message : String(err);
51
- console.log(`[Webhook] Attempt ${attempt} failed: ${message}`);
52
-
53
- if (attempt < this.config.retries!) {
54
- await this.delay(this.config.retryDelay!);
55
- }
56
- }
57
- }
58
-
59
- return { success: false, error: 'All retries failed' };
60
- }
61
-
62
- /**
63
- * 发送 HTTP 请求
64
- */
65
- private sendRequest(payload: string): Promise<void> {
66
- return new Promise((resolve, reject) => {
67
- const isHttps = this.config.url.startsWith('https');
68
- const client = isHttps ? request : httpRequest;
69
-
70
- const options: RequestOptions = {
71
- method: 'POST',
72
- headers: {
73
- 'Authorization': `Bearer ${this.config.token}`,
74
- 'Content-Type': 'application/json',
75
- 'Content-Length': Buffer.byteLength(payload)
76
- },
77
- timeout: this.config.timeout
78
- };
79
-
80
- const req = client(this.config.url, options, (res) => {
81
- if (res.statusCode === 200 || res.statusCode === 202) {
82
- resolve();
83
- } else {
84
- reject(new Error(`HTTP ${res.statusCode}`));
85
- }
86
- });
87
-
88
- req.on('error', reject);
89
- req.on('timeout', () => {
90
- req.destroy();
91
- reject(new Error('Timeout'));
92
- });
93
-
94
- req.write(payload);
95
- req.end();
96
- });
97
- }
98
-
99
- /**
100
- * 延迟
101
- */
102
- private delay(ms: number): Promise<void> {
103
- return new Promise(resolve => setTimeout(resolve, ms));
104
- }
105
- }
package/src/index.test.ts DELETED
@@ -1,436 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { randomUUID } from 'crypto';
3
- import {
4
- // 核心 P2P 网络
5
- F2A,
6
- P2PNetwork,
7
- TokenManager,
8
- E2EECrypto,
9
- // 信誉系统
10
- ReputationManager,
11
- REPUTATION_TIERS,
12
- ReviewCommittee,
13
- AutonomousEconomy,
14
- // 信誉安全机制
15
- ChainSignatureManager,
16
- InvitationManager,
17
- ChallengeManager,
18
- // 工具模块
19
- Logger,
20
- RateLimiter,
21
- RequestSigner,
22
- createMessageSizeLimitMiddleware,
23
- createMessageTypeFilterMiddleware,
24
- // 类型
25
- type ReputationLevel,
26
- type MiddlewareContext,
27
- // 版本号
28
- VERSION,
29
- } from './index.js';
30
-
31
- // ============================================================================
32
- // 业务场景 1: SDK 导出完整性验证
33
- // 确保用户可以通过 SDK 正确导入所有需要的模块
34
- // ============================================================================
35
- describe('SDK Exports - 用户使用场景', () => {
36
- describe('场景 1.1: 用户创建 F2A 节点', () => {
37
- it('应该能导入 F2A 主类并创建实例', () => {
38
- expect(F2A).toBeDefined();
39
- expect(typeof F2A.create).toBe('function');
40
- });
41
-
42
- it('应该能导入 P2PNetwork 用于底层网络操作', () => {
43
- expect(P2PNetwork).toBeDefined();
44
- expect(typeof P2PNetwork).toBe('function');
45
- });
46
- });
47
-
48
- describe('场景 1.2: 用户配置安全机制', () => {
49
- it('应该能导入 TokenManager 进行认证管理', () => {
50
- expect(TokenManager).toBeDefined();
51
- });
52
-
53
- it('应该能导入 E2EECrypto 进行加密通信', () => {
54
- expect(E2EECrypto).toBeDefined();
55
- });
56
-
57
- it('应该能导入 RequestSigner 进行请求签名', () => {
58
- expect(RequestSigner).toBeDefined();
59
- });
60
- });
61
-
62
- describe('场景 1.3: 用户实现信誉系统', () => {
63
- it('应该能导入 ReputationManager 和等级配置', () => {
64
- expect(ReputationManager).toBeDefined();
65
- expect(REPUTATION_TIERS).toBeDefined();
66
- expect(REPUTATION_TIERS.length).toBe(5); // 5个等级
67
- });
68
-
69
- it('REPUTATION_TIERS 应该包含完整的业务等级定义', () => {
70
- const levels: ReputationLevel[] = ['restricted', 'novice', 'participant', 'contributor', 'core'];
71
- REPUTATION_TIERS.forEach((tier, index) => {
72
- expect(tier.level).toBe(levels[index]);
73
- expect(tier.permissions).toHaveProperty('canPublish');
74
- expect(tier.permissions).toHaveProperty('canExecute');
75
- expect(tier.permissions).toHaveProperty('canReview');
76
- expect(tier.permissions).toHaveProperty('publishPriority');
77
- expect(tier.permissions).toHaveProperty('publishDiscount');
78
- });
79
- });
80
-
81
- it('应该能导入 ReviewCommittee 进行任务评审', () => {
82
- expect(ReviewCommittee).toBeDefined();
83
- });
84
-
85
- it('应该能导入 AutonomousEconomy 进行经济系统管理', () => {
86
- expect(AutonomousEconomy).toBeDefined();
87
- });
88
- });
89
-
90
- describe('场景 1.4: 用户配置网络安全', () => {
91
- it('应该能导入 ChainSignatureManager 进行链式签名', () => {
92
- expect(ChainSignatureManager).toBeDefined();
93
- });
94
-
95
- it('应该能导入 InvitationManager 管理节点邀请', () => {
96
- expect(InvitationManager).toBeDefined();
97
- });
98
-
99
- it('应该能导入 ChallengeManager 进行节点挑战验证', () => {
100
- expect(ChallengeManager).toBeDefined();
101
- });
102
- });
103
-
104
- describe('场景 1.5: 用户配置基础设施', () => {
105
- it('应该能导入 Logger 进行日志记录', () => {
106
- expect(Logger).toBeDefined();
107
- });
108
-
109
- it('应该能导入 RateLimiter 进行速率限制', () => {
110
- expect(RateLimiter).toBeDefined();
111
- });
112
-
113
- it('应该能导入中间件工厂函数', () => {
114
- expect(createMessageSizeLimitMiddleware).toBeDefined();
115
- expect(createMessageTypeFilterMiddleware).toBeDefined();
116
- });
117
- });
118
- });
119
-
120
- // ============================================================================
121
- // 业务场景 2: 真实业务功能验证
122
- // 测试模块在真实业务场景中的工作能力
123
- // ============================================================================
124
- describe('SDK Integration - 真实业务场景', () => {
125
- describe('场景 2.1: 信誉管理业务流程', () => {
126
- it('应该能获取新节点的初始信誉分(默认70分)', () => {
127
- const reputationManager = new ReputationManager();
128
- const peerId = 'peer-' + Date.now() + '-' + Math.random();
129
- const initialRep = reputationManager.getReputation(peerId);
130
- expect(initialRep.score).toBe(70); // 默认初始分是70
131
- expect(initialRep.level).toBe('contributor'); // 70分对应contributor等级
132
- });
133
-
134
- it('应该能记录任务成功并改变信誉分', () => {
135
- // 使用自定义配置创建新的管理器,避免状态污染
136
- const reputationManager = new ReputationManager({
137
- initialScore: 50,
138
- alpha: 0.3,
139
- minScore: 0,
140
- maxScore: 100,
141
- maxHistory: 100,
142
- });
143
- const peerId = 'peer-' + randomUUID();
144
-
145
- // 先获取初始状态(会创建条目,分数为50)
146
- const initialRep = reputationManager.getReputation(peerId);
147
- expect(initialRep.score).toBe(50);
148
- // 记录初始历史长度(getReputation 会创建 'initial' 记录)
149
- const initialHistoryLength = initialRep.history.length;
150
-
151
- // 记录成功,delta=10
152
- reputationManager.recordSuccess(peerId, 'task-1', 10);
153
- const updatedRep = reputationManager.getReputation(peerId);
154
-
155
- // EWMA 算法: newScore = 0.3 * (50 + 10) + 0.7 * 50 = 53
156
- // 验证分数确实增加了
157
- expect(updatedRep.score).toBe(53);
158
- expect(updatedRep.score).toBeGreaterThan(50);
159
-
160
- // 验证历史记录增加了
161
- expect(updatedRep.history.length).toBe(initialHistoryLength + 1);
162
- expect(updatedRep.history[updatedRep.history.length - 1].type).toBe('task_success');
163
- });
164
-
165
- it('应该能根据信誉分判断权限', () => {
166
- const reputationManager = new ReputationManager();
167
- const peerId = 'peer-' + Date.now() + '-' + Math.random();
168
- // 默认70分为 contributor 等级,拥有所有权限
169
- expect(reputationManager.hasPermission(peerId, 'publish')).toBe(true);
170
- expect(reputationManager.hasPermission(peerId, 'execute')).toBe(true);
171
- expect(reputationManager.hasPermission(peerId, 'review')).toBe(true);
172
- });
173
-
174
- it('应该能获取信誉等级', () => {
175
- const reputationManager = new ReputationManager();
176
- const tier = reputationManager.getTier(75);
177
- expect(tier.level).toBe('contributor');
178
- expect(tier.permissions.canPublish).toBe(true);
179
- });
180
-
181
- it('应该能记录任务失败并改变信誉分', () => {
182
- // 使用自定义配置创建新的管理器,避免状态污染
183
- const reputationManager = new ReputationManager({
184
- initialScore: 50,
185
- alpha: 0.3,
186
- minScore: 0,
187
- maxScore: 100,
188
- maxHistory: 100,
189
- });
190
- const peerId = 'peer-' + randomUUID();
191
-
192
- // 使用默认的 delta (-20) 或传入负数
193
- reputationManager.recordFailure(peerId, 'task-fail', 'timeout');
194
- const updatedRep = reputationManager.getReputation(peerId);
195
- // 默认 delta 为 -20,EWMA: newScore = 0.3 * (50 - 20) + 0.7 * 50 = 44
196
- expect(updatedRep.score).toBeLessThan(50);
197
- });
198
-
199
- it('应该能获取发布优先级和折扣(根据实际等级)', () => {
200
- const reputationManager = new ReputationManager();
201
- const peerId = 'peer-' + Date.now() + '-' + Math.random();
202
- // 默认70分为 contributor 等级,优先级为3,折扣90%
203
- expect(reputationManager.getPublishPriority(peerId)).toBe(3);
204
- expect(reputationManager.getPublishDiscount(peerId)).toBe(0.9);
205
- });
206
-
207
- it('应该能获取高信誉节点列表', () => {
208
- const reputationManager = new ReputationManager();
209
- const peerA = 'peer-a-' + Date.now() + '-' + Math.random();
210
- const peerB = 'peer-b-' + Date.now() + '-' + Math.random();
211
-
212
- // 提升 peerA 的信誉
213
- reputationManager.recordSuccess(peerA, 'task-1', 20);
214
- reputationManager.recordSuccess(peerA, 'task-2', 20);
215
-
216
- // peerB 保持默认
217
-
218
- const highRepNodes = reputationManager.getHighReputationNodes(80);
219
- const highRepPeerIds = highRepNodes.map(n => n.peerId);
220
- expect(highRepPeerIds).toContain(peerA);
221
- });
222
- });
223
-
224
- describe('场景 2.2: 速率限制业务流程', () => {
225
- let rateLimiter: RateLimiter;
226
-
227
- beforeEach(() => {
228
- rateLimiter = new RateLimiter({ windowMs: 1000, maxRequests: 3 });
229
- });
230
-
231
- afterEach(() => {
232
- rateLimiter.stop();
233
- });
234
-
235
- it('应该允许在限制内的请求', () => {
236
- const clientId = 'client-' + Date.now() + '-' + Math.random();
237
- expect(rateLimiter.allowRequest(clientId)).toBe(true);
238
- expect(rateLimiter.allowRequest(clientId)).toBe(true);
239
- expect(rateLimiter.allowRequest(clientId)).toBe(true);
240
- });
241
-
242
- it('应该拒绝超出限制的请求', () => {
243
- const clientId = 'client-' + Date.now() + '-' + Math.random();
244
- rateLimiter.allowRequest(clientId);
245
- rateLimiter.allowRequest(clientId);
246
- rateLimiter.allowRequest(clientId);
247
- expect(rateLimiter.allowRequest(clientId)).toBe(false);
248
- });
249
-
250
- it('应该能查询剩余令牌数', () => {
251
- const clientId = 'client-' + Date.now() + '-' + Math.random();
252
- expect(rateLimiter.getRemainingTokens(clientId)).toBe(3);
253
- rateLimiter.allowRequest(clientId);
254
- expect(rateLimiter.getRemainingTokens(clientId)).toBe(2);
255
- });
256
-
257
- it('应该能重置限制', () => {
258
- const clientId = 'client-' + Date.now() + '-' + Math.random();
259
- rateLimiter.allowRequest(clientId);
260
- rateLimiter.allowRequest(clientId);
261
- rateLimiter.allowRequest(clientId);
262
- expect(rateLimiter.allowRequest(clientId)).toBe(false);
263
-
264
- rateLimiter.reset(clientId);
265
- expect(rateLimiter.allowRequest(clientId)).toBe(true);
266
- });
267
- });
268
-
269
- describe('场景 2.3: 请求签名业务流程', () => {
270
- it('应该能签名和验证请求', () => {
271
- const signer = new RequestSigner({ secretKey: 'my-secret-key' });
272
- const payload = JSON.stringify({ action: 'publish', data: 'test' });
273
-
274
- const signedMessage = signer.sign(payload);
275
- expect(signedMessage).toBeDefined();
276
- expect(signedMessage.signature).toBeDefined();
277
- expect(signedMessage.timestamp).toBeDefined();
278
- expect(signedMessage.nonce).toBeDefined();
279
-
280
- const result = signer.verify(signedMessage);
281
- expect(result.valid).toBe(true);
282
- });
283
-
284
- it('应该拒绝篡改后的请求', () => {
285
- const signer = new RequestSigner({ secretKey: 'my-secret-key' });
286
- const payload = JSON.stringify({ action: 'publish', data: 'test' });
287
- const signedMessage = signer.sign(payload);
288
-
289
- // 篡改 payload
290
- signedMessage.payload = JSON.stringify({ action: 'publish', data: 'tampered' });
291
- const result = signer.verify(signedMessage);
292
- expect(result.valid).toBe(false);
293
- });
294
- });
295
-
296
- describe('场景 2.4: 日志记录业务流程', () => {
297
- it('应该能创建带组件标识的日志记录器', () => {
298
- const logger = new Logger({ component: 'TestService' });
299
- expect(logger).toBeInstanceOf(Logger);
300
-
301
- // 验证日志方法存在且可调用
302
- expect(() => logger.info('test message')).not.toThrow();
303
- expect(() => logger.error('error message')).not.toThrow();
304
- expect(() => logger.warn('warning message')).not.toThrow();
305
- expect(() => logger.debug('debug message')).not.toThrow();
306
- });
307
- });
308
-
309
- describe('场景 2.5: 中间件业务流程', () => {
310
- it('消息大小限制中间件应该能拦截大消息', async () => {
311
- const middleware = createMessageSizeLimitMiddleware(100);
312
- const context: MiddlewareContext = {
313
- message: {
314
- id: 'msg-1',
315
- type: 'task',
316
- payload: { data: 'x'.repeat(200) }, // 大消息
317
- timestamp: Date.now(),
318
- },
319
- peerId: 'peer-1',
320
- metadata: new Map(),
321
- };
322
-
323
- const result = await middleware.process(context);
324
- expect(result.action).toBe('drop');
325
- });
326
-
327
- it('消息类型过滤中间件应该能过滤不允许的类型', async () => {
328
- const middleware = createMessageTypeFilterMiddleware(['task', 'response']);
329
- const context: MiddlewareContext = {
330
- message: {
331
- id: 'msg-2',
332
- type: 'unknown-type',
333
- payload: {},
334
- timestamp: Date.now(),
335
- },
336
- peerId: 'peer-1',
337
- metadata: new Map(),
338
- };
339
-
340
- const result = await middleware.process(context);
341
- expect(result.action).toBe('drop');
342
- });
343
-
344
- it('允许的消息应该继续处理', async () => {
345
- const middleware = createMessageTypeFilterMiddleware(['task', 'response']);
346
- const context: MiddlewareContext = {
347
- message: {
348
- id: 'msg-3',
349
- type: 'task',
350
- payload: {},
351
- timestamp: Date.now(),
352
- },
353
- peerId: 'peer-1',
354
- metadata: new Map(),
355
- };
356
-
357
- const result = await middleware.process(context);
358
- expect(result.action).toBe('continue');
359
- });
360
- });
361
-
362
- describe('场景 2.6: 评审委员会业务流程', () => {
363
- it('应该能创建评审委员会', () => {
364
- const reputationManager = new ReputationManager();
365
- const committee = new ReviewCommittee({
366
- reputationManager,
367
- minReviewers: 2,
368
- maxReviewers: 5,
369
- reviewTimeout: 5000,
370
- });
371
-
372
- expect(committee).toBeInstanceOf(ReviewCommittee);
373
- });
374
- });
375
-
376
- describe('场景 2.7: 自治经济系统业务流程', () => {
377
- it('应该能创建经济系统', () => {
378
- const reputationManager = new ReputationManager();
379
- const economy = new AutonomousEconomy({
380
- reputationManager,
381
- baseTaskCost: 10,
382
- complexityMultiplier: 1.5,
383
- });
384
-
385
- expect(economy).toBeInstanceOf(AutonomousEconomy);
386
- });
387
- });
388
-
389
- describe('场景 2.8: 邀请管理业务流程', () => {
390
- it('应该能创建邀请管理器', () => {
391
- const reputationManager = new ReputationManager();
392
- const invitationManager = new InvitationManager({
393
- reputationManager,
394
- minInviterReputation: 60,
395
- });
396
-
397
- expect(invitationManager).toBeInstanceOf(InvitationManager);
398
- });
399
- });
400
-
401
- describe('场景 2.9: 挑战管理业务流程', () => {
402
- it('应该能创建挑战管理器', () => {
403
- const reputationManager = new ReputationManager();
404
- const challengeManager = new ChallengeManager({
405
- reputationManager,
406
- });
407
-
408
- expect(challengeManager).toBeInstanceOf(ChallengeManager);
409
- });
410
- });
411
-
412
- describe('场景 2.10: 链式签名业务流程', () => {
413
- it('应该能创建链式签名管理器', () => {
414
- const signatureManager = new ChainSignatureManager();
415
- expect(signatureManager).toBeInstanceOf(ChainSignatureManager);
416
- });
417
- });
418
- });
419
-
420
- // ============================================================================
421
- // 业务场景 3: 版本和兼容性
422
- // ============================================================================
423
- describe('SDK Version - 版本管理', () => {
424
- it('应该导出有效的语义化版本号', () => {
425
- expect(VERSION).toBeDefined();
426
- expect(typeof VERSION).toBe('string');
427
- expect(VERSION).toMatch(/^\d+\.\d+\.\d+$/);
428
- });
429
-
430
- it('版本号应该符合当前发布版本', () => {
431
- const [major, minor, patch] = VERSION.split('.').map(Number);
432
- expect(major).toBeGreaterThanOrEqual(1);
433
- expect(minor).toBeGreaterThanOrEqual(0);
434
- expect(patch).toBeGreaterThanOrEqual(0);
435
- });
436
- });