@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.
- package/package.json +8 -1
- package/.github/workflows/ci.yml +0 -113
- package/.github/workflows/publish.yml +0 -60
- package/MONOREPO.md +0 -58
- package/SKILL.md +0 -137
- package/dist/adapters/openclaw.d.ts +0 -103
- package/dist/adapters/openclaw.d.ts.map +0 -1
- package/dist/adapters/openclaw.js +0 -297
- package/dist/adapters/openclaw.js.map +0 -1
- package/dist/core/connection-manager.d.ts +0 -80
- package/dist/core/connection-manager.d.ts.map +0 -1
- package/dist/core/connection-manager.js +0 -235
- package/dist/core/connection-manager.js.map +0 -1
- package/dist/core/connection-manager.test.d.ts +0 -2
- package/dist/core/connection-manager.test.d.ts.map +0 -1
- package/dist/core/connection-manager.test.js +0 -52
- package/dist/core/connection-manager.test.js.map +0 -1
- package/dist/core/identity.d.ts +0 -47
- package/dist/core/identity.d.ts.map +0 -1
- package/dist/core/identity.js +0 -130
- package/dist/core/identity.js.map +0 -1
- package/dist/core/identity.test.d.ts +0 -2
- package/dist/core/identity.test.d.ts.map +0 -1
- package/dist/core/identity.test.js +0 -43
- package/dist/core/identity.test.js.map +0 -1
- package/dist/core/serverless.d.ts +0 -155
- package/dist/core/serverless.d.ts.map +0 -1
- package/dist/core/serverless.js +0 -615
- package/dist/core/serverless.js.map +0 -1
- package/dist/daemon/webhook.test.d.ts +0 -2
- package/dist/daemon/webhook.test.d.ts.map +0 -1
- package/dist/daemon/webhook.test.js +0 -24
- package/dist/daemon/webhook.test.js.map +0 -1
- package/dist/protocol/messages.d.ts +0 -739
- package/dist/protocol/messages.d.ts.map +0 -1
- package/dist/protocol/messages.js +0 -188
- package/dist/protocol/messages.js.map +0 -1
- package/dist/protocol/messages.test.d.ts +0 -2
- package/dist/protocol/messages.test.d.ts.map +0 -1
- package/dist/protocol/messages.test.js +0 -55
- package/dist/protocol/messages.test.js.map +0 -1
- package/docs/F2A-PROTOCOL.md +0 -61
- package/docs/MOBILE_BOOTSTRAP_DESIGN.md +0 -126
- package/docs/a2a-lessons.md +0 -316
- package/docs/middleware-guide.md +0 -448
- package/docs/readme-update-checklist.md +0 -90
- package/docs/reputation-guide.md +0 -396
- package/docs/rfcs/001-reputation-system.md +0 -712
- package/docs/security-design.md +0 -247
- package/install.sh +0 -231
- package/packages/openclaw-adapter/README.md +0 -510
- package/packages/openclaw-adapter/openclaw.plugin.json +0 -106
- package/packages/openclaw-adapter/package.json +0 -40
- package/packages/openclaw-adapter/src/announcement-queue.test.ts +0 -449
- package/packages/openclaw-adapter/src/announcement-queue.ts +0 -403
- package/packages/openclaw-adapter/src/capability-detector.test.ts +0 -99
- package/packages/openclaw-adapter/src/capability-detector.ts +0 -183
- package/packages/openclaw-adapter/src/claim-handlers.test.ts +0 -974
- package/packages/openclaw-adapter/src/claim-handlers.ts +0 -482
- package/packages/openclaw-adapter/src/connector.business.test.ts +0 -583
- package/packages/openclaw-adapter/src/connector.ts +0 -795
- package/packages/openclaw-adapter/src/index.test.ts +0 -82
- package/packages/openclaw-adapter/src/index.ts +0 -18
- package/packages/openclaw-adapter/src/integration.e2e.test.ts +0 -829
- package/packages/openclaw-adapter/src/logger.ts +0 -51
- package/packages/openclaw-adapter/src/network-client.test.ts +0 -266
- package/packages/openclaw-adapter/src/network-client.ts +0 -251
- package/packages/openclaw-adapter/src/network-recovery.test.ts +0 -465
- package/packages/openclaw-adapter/src/node-manager.test.ts +0 -136
- package/packages/openclaw-adapter/src/node-manager.ts +0 -429
- package/packages/openclaw-adapter/src/plugin.test.ts +0 -439
- package/packages/openclaw-adapter/src/plugin.ts +0 -104
- package/packages/openclaw-adapter/src/reputation.test.ts +0 -221
- package/packages/openclaw-adapter/src/reputation.ts +0 -368
- package/packages/openclaw-adapter/src/task-guard.test.ts +0 -502
- package/packages/openclaw-adapter/src/task-guard.ts +0 -860
- package/packages/openclaw-adapter/src/task-queue.concurrency.test.ts +0 -462
- package/packages/openclaw-adapter/src/task-queue.edge-cases.test.ts +0 -284
- package/packages/openclaw-adapter/src/task-queue.persistence.test.ts +0 -408
- package/packages/openclaw-adapter/src/task-queue.ts +0 -668
- package/packages/openclaw-adapter/src/tool-handlers.test.ts +0 -906
- package/packages/openclaw-adapter/src/tool-handlers.ts +0 -574
- package/packages/openclaw-adapter/src/types.ts +0 -361
- package/packages/openclaw-adapter/src/webhook-pusher.test.ts +0 -188
- package/packages/openclaw-adapter/src/webhook-pusher.ts +0 -220
- package/packages/openclaw-adapter/src/webhook-server.test.ts +0 -580
- package/packages/openclaw-adapter/src/webhook-server.ts +0 -202
- package/packages/openclaw-adapter/tsconfig.json +0 -20
- package/src/cli/commands.test.ts +0 -157
- package/src/cli/commands.ts +0 -129
- package/src/cli/index.test.ts +0 -77
- package/src/cli/index.ts +0 -234
- package/src/core/autonomous-economy.test.ts +0 -291
- package/src/core/autonomous-economy.ts +0 -428
- package/src/core/e2ee-crypto.test.ts +0 -125
- package/src/core/e2ee-crypto.ts +0 -246
- package/src/core/f2a.test.ts +0 -269
- package/src/core/f2a.ts +0 -618
- package/src/core/p2p-network.test.ts +0 -199
- package/src/core/p2p-network.ts +0 -1432
- package/src/core/reputation-security.test.ts +0 -403
- package/src/core/reputation-security.ts +0 -562
- package/src/core/reputation.test.ts +0 -260
- package/src/core/reputation.ts +0 -576
- package/src/core/review-committee.test.ts +0 -380
- package/src/core/review-committee.ts +0 -401
- package/src/core/token-manager.test.ts +0 -133
- package/src/core/token-manager.ts +0 -140
- package/src/daemon/control-server.test.ts +0 -216
- package/src/daemon/control-server.ts +0 -292
- package/src/daemon/index.test.ts +0 -85
- package/src/daemon/index.ts +0 -89
- package/src/daemon/main.ts +0 -44
- package/src/daemon/start.ts +0 -29
- package/src/daemon/webhook.test.ts +0 -68
- package/src/daemon/webhook.ts +0 -105
- package/src/index.test.ts +0 -436
- package/src/index.ts +0 -72
- package/src/types/index.test.ts +0 -87
- package/src/types/index.ts +0 -341
- package/src/types/result.ts +0 -68
- package/src/utils/benchmark.ts +0 -237
- package/src/utils/logger.ts +0 -331
- package/src/utils/middleware.ts +0 -229
- package/src/utils/rate-limiter.ts +0 -207
- package/src/utils/signature.ts +0 -136
- package/src/utils/validation.ts +0 -186
- package/tests/docker/Dockerfile.node +0 -23
- package/tests/docker/Dockerfile.runner +0 -18
- package/tests/docker/docker-compose.test.yml +0 -73
- package/tests/integration/message-passing.test.ts +0 -109
- package/tests/integration/multi-node.test.ts +0 -92
- package/tests/integration/p2p-connection.test.ts +0 -83
- package/tests/integration/test-config.ts +0 -32
- package/tsconfig.json +0 -21
- package/vitest.config.ts +0 -26
|
@@ -1,574 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* F2A OpenClaw Connector - Tool Handlers
|
|
3
|
-
* 工具处理器模块 - 处理 f2a_discover, f2a_delegate 等工具
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
SessionContext,
|
|
8
|
-
ToolResult,
|
|
9
|
-
AgentInfo,
|
|
10
|
-
TaskResponse,
|
|
11
|
-
F2APluginConfig,
|
|
12
|
-
OpenClawPluginApi
|
|
13
|
-
} from './types.js';
|
|
14
|
-
import type { F2AOpenClawAdapter } from './connector.js';
|
|
15
|
-
import type { QueuedTask } from './task-queue.js';
|
|
16
|
-
import type { ReputationSystem } from './reputation.js';
|
|
17
|
-
import type { F2ANetworkClient } from './network-client.js';
|
|
18
|
-
import type { F2ANodeManager } from './node-manager.js';
|
|
19
|
-
import type { TaskQueue } from './task-queue.js';
|
|
20
|
-
import type { AnnouncementQueue } from './announcement-queue.js';
|
|
21
|
-
import { pluginLogger as logger } from './logger.js';
|
|
22
|
-
|
|
23
|
-
/** 广播结果类型 */
|
|
24
|
-
interface BroadcastResult {
|
|
25
|
-
agent: string;
|
|
26
|
-
success: boolean;
|
|
27
|
-
error?: string;
|
|
28
|
-
latency?: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Adapter 内部接口 - 用于类型安全的属性访问
|
|
33
|
-
*/
|
|
34
|
-
interface AdapterInternalAccess {
|
|
35
|
-
networkClient: F2ANetworkClient;
|
|
36
|
-
reputationSystem: ReputationSystem;
|
|
37
|
-
nodeManager: F2ANodeManager;
|
|
38
|
-
taskQueue: TaskQueue;
|
|
39
|
-
announcementQueue: AnnouncementQueue;
|
|
40
|
-
config: F2APluginConfig;
|
|
41
|
-
api?: OpenClawPluginApi;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 工具处理器参数类型
|
|
46
|
-
*/
|
|
47
|
-
export interface ToolHandlerParams {
|
|
48
|
-
discover: { capability?: string; min_reputation?: number };
|
|
49
|
-
delegate: { agent: string; task: string; context?: string; timeout?: number };
|
|
50
|
-
broadcast: { capability: string; task: string; min_responses?: number };
|
|
51
|
-
reputation: { action: string; peer_id?: string };
|
|
52
|
-
pollTasks: { limit?: number; status?: 'pending' | 'processing' | 'completed' | 'failed' };
|
|
53
|
-
submitResult: { task_id: string; result: string; status: 'success' | 'error' };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 工具处理器类
|
|
58
|
-
* 包含所有核心工具的处理逻辑
|
|
59
|
-
*/
|
|
60
|
-
export class ToolHandlers {
|
|
61
|
-
constructor(private adapter: F2AOpenClawAdapter) {}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 处理 f2a_discover 工具
|
|
65
|
-
* 发现 F2A 网络中的 Agents
|
|
66
|
-
*/
|
|
67
|
-
async handleDiscover(
|
|
68
|
-
params: ToolHandlerParams['discover'],
|
|
69
|
-
context: SessionContext
|
|
70
|
-
): Promise<ToolResult> {
|
|
71
|
-
const networkClient = (this.adapter as unknown as AdapterInternalAccess).networkClient;
|
|
72
|
-
const reputationSystem = (this.adapter as unknown as AdapterInternalAccess).reputationSystem;
|
|
73
|
-
|
|
74
|
-
const result = await networkClient.discoverAgents(params.capability);
|
|
75
|
-
|
|
76
|
-
if (!result.success) {
|
|
77
|
-
return { content: `发现失败: ${result.error}` };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let agents = result.data || [];
|
|
81
|
-
|
|
82
|
-
// 过滤信誉
|
|
83
|
-
if (params.min_reputation !== undefined) {
|
|
84
|
-
agents = agents.filter((a: AgentInfo) => {
|
|
85
|
-
const rep = reputationSystem.getReputation(a.peerId);
|
|
86
|
-
return rep.score >= params.min_reputation!;
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (agents.length === 0) {
|
|
91
|
-
return { content: '🔍 未发现符合条件的 Agents' };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const content = `
|
|
95
|
-
🔍 发现 ${agents.length} 个 Agents:
|
|
96
|
-
|
|
97
|
-
${agents.map((a: AgentInfo, i: number) => {
|
|
98
|
-
const rep = reputationSystem.getReputation(a.peerId);
|
|
99
|
-
return `${i + 1}. ${a.displayName} (信誉: ${rep.score})
|
|
100
|
-
ID: ${a.peerId.slice(0, 20)}...
|
|
101
|
-
能力: ${a.capabilities?.map(c => c.name).join(', ') || '无'}`;
|
|
102
|
-
}).join('\n\n')}
|
|
103
|
-
|
|
104
|
-
💡 使用方式:
|
|
105
|
-
- 委托任务: 让 ${agents[0]?.displayName} 帮我写代码
|
|
106
|
-
- 指定ID: 委托给 #1 分析数据
|
|
107
|
-
`.trim();
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
content,
|
|
111
|
-
data: { agents, count: agents.length }
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* 处理 f2a_delegate 工具
|
|
117
|
-
* 委托任务给特定 Agent
|
|
118
|
-
*/
|
|
119
|
-
async handleDelegate(
|
|
120
|
-
params: ToolHandlerParams['delegate'],
|
|
121
|
-
context: SessionContext
|
|
122
|
-
): Promise<ToolResult> {
|
|
123
|
-
// 输入验证
|
|
124
|
-
if (!params.agent || typeof params.agent !== 'string' || params.agent.trim() === '') {
|
|
125
|
-
return { content: '❌ 请提供有效的 agent 参数(Agent ID、名称或 #索引)' };
|
|
126
|
-
}
|
|
127
|
-
if (!params.task || typeof params.task !== 'string' || params.task.trim() === '') {
|
|
128
|
-
return { content: '❌ 请提供有效的 task 参数(任务描述)' };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const networkClient = (this.adapter as unknown as AdapterInternalAccess).networkClient;
|
|
132
|
-
const reputationSystem = (this.adapter as unknown as AdapterInternalAccess).reputationSystem;
|
|
133
|
-
|
|
134
|
-
// 解析 Agent 引用
|
|
135
|
-
const targetAgent = await this.resolveAgent(params.agent);
|
|
136
|
-
|
|
137
|
-
if (!targetAgent) {
|
|
138
|
-
return { content: `❌ 找不到 Agent: ${params.agent}` };
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// 检查信誉
|
|
142
|
-
if (!reputationSystem.isAllowed(targetAgent.peerId)) {
|
|
143
|
-
return {
|
|
144
|
-
content: `⚠️ ${targetAgent.displayName} 信誉过低 (${reputationSystem.getReputation(targetAgent.peerId).score}),建议谨慎委托`
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
logger.info(`委托任务给 ${targetAgent.displayName}...`);
|
|
149
|
-
|
|
150
|
-
const result = await networkClient.delegateTask({
|
|
151
|
-
peerId: targetAgent.peerId,
|
|
152
|
-
taskType: 'openclaw-task',
|
|
153
|
-
description: params.task,
|
|
154
|
-
parameters: {
|
|
155
|
-
context: params.context,
|
|
156
|
-
sessionContext: context.toJSON()
|
|
157
|
-
},
|
|
158
|
-
timeout: params.timeout || 60000
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
if (!result.success) {
|
|
162
|
-
// 记录失败
|
|
163
|
-
reputationSystem.recordFailure(targetAgent.peerId, 'unknown', result.error);
|
|
164
|
-
return { content: `❌ 委托失败: ${result.error}` };
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return {
|
|
168
|
-
content: `✅ ${targetAgent.displayName} 已完成任务:\n\n${JSON.stringify(result.data, null, 2)}`,
|
|
169
|
-
data: result.data
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* 处理 f2a_broadcast 工具
|
|
175
|
-
* 广播任务给所有具备某能力的 Agents
|
|
176
|
-
*/
|
|
177
|
-
async handleBroadcast(
|
|
178
|
-
params: ToolHandlerParams['broadcast'],
|
|
179
|
-
context: SessionContext
|
|
180
|
-
): Promise<ToolResult> {
|
|
181
|
-
// 输入验证
|
|
182
|
-
if (!params.capability || typeof params.capability !== 'string' || params.capability.trim() === '') {
|
|
183
|
-
return { content: '❌ 请提供有效的 capability 参数(所需能力)' };
|
|
184
|
-
}
|
|
185
|
-
if (!params.task || typeof params.task !== 'string' || params.task.trim() === '') {
|
|
186
|
-
return { content: '❌ 请提供有效的 task 参数(任务描述)' };
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const networkClient = (this.adapter as unknown as AdapterInternalAccess).networkClient;
|
|
190
|
-
|
|
191
|
-
const discoverResult = await networkClient.discoverAgents(params.capability);
|
|
192
|
-
|
|
193
|
-
if (!discoverResult.success || !discoverResult.data?.length) {
|
|
194
|
-
return { content: `❌ 未发现具备 "${params.capability}" 能力的 Agents` };
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const agents = discoverResult.data;
|
|
198
|
-
logger.info(`广播任务给 ${agents.length} 个 Agents...`);
|
|
199
|
-
|
|
200
|
-
// 并行委托
|
|
201
|
-
const promises = agents.map(async (agent: AgentInfo) => {
|
|
202
|
-
const start = Date.now();
|
|
203
|
-
const result = await networkClient.delegateTask({
|
|
204
|
-
peerId: agent.peerId,
|
|
205
|
-
taskType: 'openclaw-task',
|
|
206
|
-
description: params.task,
|
|
207
|
-
parameters: { sessionContext: context.toJSON() },
|
|
208
|
-
timeout: 60000
|
|
209
|
-
});
|
|
210
|
-
const latency = Date.now() - start;
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
agent: agent.displayName,
|
|
214
|
-
peerId: agent.peerId,
|
|
215
|
-
success: result.success,
|
|
216
|
-
result: result.data,
|
|
217
|
-
error: result.error,
|
|
218
|
-
latency
|
|
219
|
-
};
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
const results = await Promise.allSettled(promises);
|
|
223
|
-
const settled = results.map((r, i) =>
|
|
224
|
-
r.status === 'fulfilled' ? r.value : {
|
|
225
|
-
agent: agents[i].displayName,
|
|
226
|
-
success: false,
|
|
227
|
-
error: String(r.reason)
|
|
228
|
-
}
|
|
229
|
-
);
|
|
230
|
-
|
|
231
|
-
const successful = settled.filter(r => r.success);
|
|
232
|
-
const minResponses = params.min_responses || 1;
|
|
233
|
-
|
|
234
|
-
if (successful.length < minResponses) {
|
|
235
|
-
return {
|
|
236
|
-
content: `⚠️ 仅 ${successful.length} 个成功响应(需要 ${minResponses})\n\n${this.formatBroadcastResults(settled)}`
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return {
|
|
241
|
-
content: `✅ 收到 ${successful.length}/${settled.length} 个成功响应:\n\n${this.formatBroadcastResults(settled)}`,
|
|
242
|
-
data: { results: settled }
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* 处理 f2a_status 工具
|
|
248
|
-
* 查看网络状态
|
|
249
|
-
*/
|
|
250
|
-
async handleStatus(
|
|
251
|
-
params: {},
|
|
252
|
-
context: SessionContext
|
|
253
|
-
): Promise<ToolResult> {
|
|
254
|
-
const nodeManager = (this.adapter as unknown as AdapterInternalAccess).nodeManager;
|
|
255
|
-
const networkClient = (this.adapter as unknown as AdapterInternalAccess).networkClient;
|
|
256
|
-
const taskQueue = (this.adapter as unknown as AdapterInternalAccess).taskQueue;
|
|
257
|
-
const reputationSystem = (this.adapter as unknown as AdapterInternalAccess).reputationSystem;
|
|
258
|
-
|
|
259
|
-
const [nodeStatus, peersResult] = await Promise.all([
|
|
260
|
-
nodeManager.getStatus(),
|
|
261
|
-
networkClient.getConnectedPeers()
|
|
262
|
-
]);
|
|
263
|
-
|
|
264
|
-
if (!nodeStatus.success) {
|
|
265
|
-
return { content: `❌ 获取状态失败: ${nodeStatus.error}` };
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const peers = peersResult.success ? (peersResult.data || []) : [];
|
|
269
|
-
const taskStats = taskQueue.getStats();
|
|
270
|
-
|
|
271
|
-
const content = `
|
|
272
|
-
🟢 F2A 状态: ${nodeStatus.data?.running ? '运行中' : '已停止'}
|
|
273
|
-
📡 本机 PeerID: ${nodeStatus.data?.peerId || 'N/A'}
|
|
274
|
-
⏱️ 运行时间: ${nodeStatus.data?.uptime ? Math.floor(nodeStatus.data.uptime / 60) + ' 分钟' : 'N/A'}
|
|
275
|
-
🔗 已连接 Peers: ${peers.length}
|
|
276
|
-
📋 任务队列: ${taskStats.pending} 待处理, ${taskStats.processing} 处理中, ${taskStats.completed} 已完成
|
|
277
|
-
|
|
278
|
-
${peers.map((p: any) => {
|
|
279
|
-
const rep = reputationSystem.getReputation(p.peerId);
|
|
280
|
-
return ` • ${p.agentInfo?.displayName || 'Unknown'} (信誉: ${rep.score})\n ID: ${p.peerId.slice(0, 20)}...`;
|
|
281
|
-
}).join('\n')}
|
|
282
|
-
`.trim();
|
|
283
|
-
|
|
284
|
-
return { content, data: { status: nodeStatus.data, peers, taskStats } };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* 处理 f2a_reputation 工具
|
|
289
|
-
* 查看或管理 Peer 信誉
|
|
290
|
-
*/
|
|
291
|
-
async handleReputation(
|
|
292
|
-
params: ToolHandlerParams['reputation'],
|
|
293
|
-
context: SessionContext
|
|
294
|
-
): Promise<ToolResult> {
|
|
295
|
-
// 输入验证
|
|
296
|
-
if (!params.action || !['list', 'view', 'block', 'unblock'].includes(params.action)) {
|
|
297
|
-
return { content: '❌ action 参数必须是 list, view, block 或 unblock' };
|
|
298
|
-
}
|
|
299
|
-
if ((params.action === 'view' || params.action === 'block' || params.action === 'unblock') &&
|
|
300
|
-
(!params.peer_id || typeof params.peer_id !== 'string' || params.peer_id.trim() === '')) {
|
|
301
|
-
return { content: '❌ view/block/unblock 操作需要提供 peer_id 参数' };
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const reputationSystem = (this.adapter as unknown as AdapterInternalAccess).reputationSystem;
|
|
305
|
-
const config = (this.adapter as unknown as AdapterInternalAccess).config;
|
|
306
|
-
|
|
307
|
-
switch (params.action) {
|
|
308
|
-
case 'list': {
|
|
309
|
-
const reps = reputationSystem.getAllReputations();
|
|
310
|
-
return {
|
|
311
|
-
content: `📊 信誉记录 (${reps.length} 条):\n\n${reps.map((r: any) =>
|
|
312
|
-
` ${r.peerId.slice(0, 20)}...: ${r.score} (成功: ${r.successfulTasks}, 失败: ${r.failedTasks})`
|
|
313
|
-
).join('\n')}`
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
case 'view': {
|
|
318
|
-
if (!params.peer_id) {
|
|
319
|
-
return { content: '❌ 请提供 peer_id' };
|
|
320
|
-
}
|
|
321
|
-
const rep = reputationSystem.getReputation(params.peer_id);
|
|
322
|
-
return {
|
|
323
|
-
content: `📊 Peer ${params.peer_id.slice(0, 20)}...:\n` +
|
|
324
|
-
` 信誉分: ${rep.score}\n` +
|
|
325
|
-
` 成功任务: ${rep.successfulTasks}\n` +
|
|
326
|
-
` 失败任务: ${rep.failedTasks}\n` +
|
|
327
|
-
` 平均响应: ${rep.avgResponseTime.toFixed(0)}ms\n` +
|
|
328
|
-
` 最后交互: ${new Date(rep.lastInteraction).toLocaleString()}`
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
case 'block': {
|
|
333
|
-
if (!params.peer_id) {
|
|
334
|
-
return { content: '❌ 请提供 peer_id' };
|
|
335
|
-
}
|
|
336
|
-
if (!config.security) {
|
|
337
|
-
config.security = { requireConfirmation: false, whitelist: [], blacklist: [], maxTasksPerMinute: 10 };
|
|
338
|
-
}
|
|
339
|
-
config.security.blacklist.push(params.peer_id);
|
|
340
|
-
return { content: `🚫 已屏蔽 ${params.peer_id.slice(0, 20)}...` };
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
case 'unblock': {
|
|
344
|
-
if (!params.peer_id) {
|
|
345
|
-
return { content: '❌ 请提供 peer_id' };
|
|
346
|
-
}
|
|
347
|
-
if (!config.security) {
|
|
348
|
-
config.security = { requireConfirmation: false, whitelist: [], blacklist: [], maxTasksPerMinute: 10 };
|
|
349
|
-
}
|
|
350
|
-
config.security.blacklist = config.security.blacklist.filter(
|
|
351
|
-
(id: string) => id !== params.peer_id
|
|
352
|
-
);
|
|
353
|
-
return { content: `✅ 已解除屏蔽 ${params.peer_id.slice(0, 20)}...` };
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
default:
|
|
357
|
-
return { content: `❌ 未知操作: ${params.action}` };
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* 处理 f2a_poll_tasks 工具
|
|
363
|
-
* 查询任务队列
|
|
364
|
-
*/
|
|
365
|
-
async handlePollTasks(
|
|
366
|
-
params: ToolHandlerParams['pollTasks'],
|
|
367
|
-
context: SessionContext
|
|
368
|
-
): Promise<ToolResult> {
|
|
369
|
-
// 输入验证
|
|
370
|
-
if (params.limit !== undefined && (typeof params.limit !== 'number' || params.limit < 1 || params.limit > 100)) {
|
|
371
|
-
return { content: '❌ limit 参数必须是 1-100 之间的数字' };
|
|
372
|
-
}
|
|
373
|
-
if (params.status !== undefined && !['pending', 'processing', 'completed', 'failed'].includes(params.status)) {
|
|
374
|
-
return { content: '❌ status 参数必须是 pending, processing, completed 或 failed' };
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
const taskQueue = (this.adapter as unknown as AdapterInternalAccess).taskQueue;
|
|
378
|
-
|
|
379
|
-
let tasks: QueuedTask[];
|
|
380
|
-
|
|
381
|
-
if (params.status) {
|
|
382
|
-
// 按状态过滤时不改变任务状态(只是查看)
|
|
383
|
-
tasks = taskQueue.getAll().filter((t: QueuedTask) => t.status === params.status);
|
|
384
|
-
} else {
|
|
385
|
-
// 默认返回待处理任务,并标记为 processing(防止重复执行)
|
|
386
|
-
tasks = taskQueue.getPending(params.limit || 10);
|
|
387
|
-
|
|
388
|
-
// 将返回的任务标记为 processing,防止重复获取
|
|
389
|
-
for (const task of tasks) {
|
|
390
|
-
taskQueue.markProcessing(task.taskId);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (tasks.length > 0) {
|
|
394
|
-
logger.info(`已将 ${tasks.length} 个任务标记为 processing`);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (tasks.length === 0) {
|
|
399
|
-
return { content: '📭 没有符合条件的任务' };
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
const content = `
|
|
403
|
-
📋 任务列表 (${tasks.length} 个):
|
|
404
|
-
|
|
405
|
-
${tasks.map(t => {
|
|
406
|
-
const statusIcon = {
|
|
407
|
-
pending: '⏳',
|
|
408
|
-
processing: '🔄',
|
|
409
|
-
completed: '✅',
|
|
410
|
-
failed: '❌'
|
|
411
|
-
}[t.status];
|
|
412
|
-
|
|
413
|
-
return `${statusIcon} [${t.taskId.slice(0, 8)}...] ${t.description.slice(0, 50)}${t.description.length > 50 ? '...' : ''}
|
|
414
|
-
来自: ${t.from.slice(0, 16)}...
|
|
415
|
-
类型: ${t.taskType} | 状态: ${t.status} | 创建: ${new Date(t.createdAt).toLocaleTimeString()}`;
|
|
416
|
-
}).join('\n\n')}
|
|
417
|
-
|
|
418
|
-
💡 使用方式:
|
|
419
|
-
- 查看详情: 使用 task_id 查询
|
|
420
|
-
- 提交结果: f2a_submit_result 工具
|
|
421
|
-
`.trim();
|
|
422
|
-
|
|
423
|
-
return {
|
|
424
|
-
content,
|
|
425
|
-
data: {
|
|
426
|
-
count: tasks.length,
|
|
427
|
-
tasks: tasks.map(t => ({
|
|
428
|
-
taskId: t.taskId,
|
|
429
|
-
from: t.from,
|
|
430
|
-
description: t.description,
|
|
431
|
-
taskType: t.taskType,
|
|
432
|
-
parameters: t.parameters,
|
|
433
|
-
status: t.status,
|
|
434
|
-
createdAt: t.createdAt,
|
|
435
|
-
timeout: t.timeout
|
|
436
|
-
}))
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* 处理 f2a_submit_result 工具
|
|
443
|
-
* 提交任务结果
|
|
444
|
-
*/
|
|
445
|
-
async handleSubmitResult(
|
|
446
|
-
params: ToolHandlerParams['submitResult'],
|
|
447
|
-
context: SessionContext
|
|
448
|
-
): Promise<ToolResult> {
|
|
449
|
-
// 输入验证
|
|
450
|
-
if (!params.task_id || typeof params.task_id !== 'string' || params.task_id.trim() === '') {
|
|
451
|
-
return { content: '❌ 请提供有效的 task_id 参数' };
|
|
452
|
-
}
|
|
453
|
-
if (!params.result || typeof params.result !== 'string') {
|
|
454
|
-
return { content: '❌ 请提供有效的 result 参数' };
|
|
455
|
-
}
|
|
456
|
-
if (params.status !== 'success' && params.status !== 'error') {
|
|
457
|
-
return { content: '❌ status 参数必须是 success 或 error' };
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
const taskQueue = (this.adapter as unknown as AdapterInternalAccess).taskQueue;
|
|
461
|
-
const networkClient = (this.adapter as unknown as AdapterInternalAccess).networkClient;
|
|
462
|
-
const reputationSystem = (this.adapter as unknown as AdapterInternalAccess).reputationSystem;
|
|
463
|
-
|
|
464
|
-
// 查找任务
|
|
465
|
-
const task = taskQueue.get(params.task_id);
|
|
466
|
-
if (!task) {
|
|
467
|
-
return { content: `❌ 找不到任务: ${params.task_id}` };
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// 更新任务状态
|
|
471
|
-
const response: TaskResponse = {
|
|
472
|
-
taskId: params.task_id,
|
|
473
|
-
status: params.status,
|
|
474
|
-
result: params.status === 'success' ? params.result : undefined,
|
|
475
|
-
error: params.status === 'error' ? params.result : undefined,
|
|
476
|
-
latency: Date.now() - task.createdAt
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
taskQueue.complete(params.task_id, response);
|
|
480
|
-
|
|
481
|
-
// 发送响应给原节点
|
|
482
|
-
const sendResult = await networkClient.sendTaskResponse(task.from, response);
|
|
483
|
-
|
|
484
|
-
if (!sendResult.success) {
|
|
485
|
-
return {
|
|
486
|
-
content: `⚠️ 结果已记录,但发送给原节点失败: ${sendResult.error}`,
|
|
487
|
-
data: { taskId: params.task_id, sent: false }
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// 更新信誉
|
|
492
|
-
if (params.status === 'success') {
|
|
493
|
-
reputationSystem.recordSuccess(task.from, params.task_id, response.latency!);
|
|
494
|
-
} else {
|
|
495
|
-
reputationSystem.recordFailure(task.from, params.task_id, params.result);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
return {
|
|
499
|
-
content: `✅ 任务结果已提交并发送给原节点\n 任务ID: ${params.task_id.slice(0, 16)}...\n 状态: ${params.status}\n 响应时间: ${response.latency}ms`,
|
|
500
|
-
data: { taskId: params.task_id, sent: true, latency: response.latency }
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* 处理 f2a_task_stats 工具
|
|
506
|
-
* 查看任务队列统计
|
|
507
|
-
*/
|
|
508
|
-
async handleTaskStats(
|
|
509
|
-
params: {},
|
|
510
|
-
context: SessionContext
|
|
511
|
-
): Promise<ToolResult> {
|
|
512
|
-
const taskQueue = (this.adapter as unknown as AdapterInternalAccess).taskQueue;
|
|
513
|
-
const stats = taskQueue.getStats();
|
|
514
|
-
|
|
515
|
-
const content = `
|
|
516
|
-
📊 任务队列统计:
|
|
517
|
-
|
|
518
|
-
⏳ 待处理: ${stats.pending}
|
|
519
|
-
🔄 处理中: ${stats.processing}
|
|
520
|
-
✅ 已完成: ${stats.completed}
|
|
521
|
-
❌ 失败: ${stats.failed}
|
|
522
|
-
📦 总计: ${stats.total}
|
|
523
|
-
|
|
524
|
-
💡 使用 f2a_poll_tasks 查看详细任务列表
|
|
525
|
-
`.trim();
|
|
526
|
-
|
|
527
|
-
return { content, data: stats };
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// ========== Helper Methods ==========
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* 解析 Agent 引用
|
|
534
|
-
*/
|
|
535
|
-
private async resolveAgent(agentRef: string): Promise<AgentInfo | null> {
|
|
536
|
-
const networkClient = (this.adapter as unknown as AdapterInternalAccess).networkClient;
|
|
537
|
-
const result = await networkClient.discoverAgents();
|
|
538
|
-
if (!result.success) return null;
|
|
539
|
-
|
|
540
|
-
const agents = result.data || [];
|
|
541
|
-
|
|
542
|
-
// #索引格式
|
|
543
|
-
if (agentRef.startsWith('#')) {
|
|
544
|
-
const index = parseInt(agentRef.slice(1)) - 1;
|
|
545
|
-
return agents[index] || null;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
// 精确匹配
|
|
549
|
-
const exact = agents.find((a: AgentInfo) =>
|
|
550
|
-
a.peerId === agentRef ||
|
|
551
|
-
a.displayName === agentRef
|
|
552
|
-
);
|
|
553
|
-
if (exact) return exact;
|
|
554
|
-
|
|
555
|
-
// 模糊匹配
|
|
556
|
-
const fuzzy = agents.find((a: AgentInfo) =>
|
|
557
|
-
a.peerId.startsWith(agentRef) ||
|
|
558
|
-
a.displayName.toLowerCase().includes(agentRef.toLowerCase())
|
|
559
|
-
);
|
|
560
|
-
|
|
561
|
-
return fuzzy || null;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
/**
|
|
565
|
-
* 格式化广播结果
|
|
566
|
-
*/
|
|
567
|
-
private formatBroadcastResults(results: BroadcastResult[]): string {
|
|
568
|
-
return results.map(r => {
|
|
569
|
-
const icon = r.success ? '✅' : '❌';
|
|
570
|
-
const latency = r.latency ? ` (${r.latency}ms)` : '';
|
|
571
|
-
return `${icon} ${r.agent}${latency}\n ${r.success ? '完成' : `失败: ${r.error}`}`;
|
|
572
|
-
}).join('\n\n');
|
|
573
|
-
}
|
|
574
|
-
}
|