@f2a/openclaw-f2a 0.2.20

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 (71) hide show
  1. package/README.md +510 -0
  2. package/dist/agent-manager.d.ts +78 -0
  3. package/dist/agent-manager.d.ts.map +1 -0
  4. package/dist/agent-manager.js +206 -0
  5. package/dist/agent-manager.js.map +1 -0
  6. package/dist/announcement-queue.d.ts +152 -0
  7. package/dist/announcement-queue.d.ts.map +1 -0
  8. package/dist/announcement-queue.js +307 -0
  9. package/dist/announcement-queue.js.map +1 -0
  10. package/dist/capability-detector.d.ts +21 -0
  11. package/dist/capability-detector.d.ts.map +1 -0
  12. package/dist/capability-detector.js +178 -0
  13. package/dist/capability-detector.js.map +1 -0
  14. package/dist/claim-handlers.d.ts +75 -0
  15. package/dist/claim-handlers.d.ts.map +1 -0
  16. package/dist/claim-handlers.js +368 -0
  17. package/dist/claim-handlers.js.map +1 -0
  18. package/dist/connector.d.ts +174 -0
  19. package/dist/connector.d.ts.map +1 -0
  20. package/dist/connector.js +1284 -0
  21. package/dist/connector.js.map +1 -0
  22. package/dist/index.d.ts +16 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +45 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/logger.d.ts +28 -0
  27. package/dist/logger.d.ts.map +1 -0
  28. package/dist/logger.js +44 -0
  29. package/dist/logger.js.map +1 -0
  30. package/dist/network-client.d.ts +73 -0
  31. package/dist/network-client.d.ts.map +1 -0
  32. package/dist/network-client.js +202 -0
  33. package/dist/network-client.js.map +1 -0
  34. package/dist/node-manager.d.ts +79 -0
  35. package/dist/node-manager.d.ts.map +1 -0
  36. package/dist/node-manager.js +374 -0
  37. package/dist/node-manager.js.map +1 -0
  38. package/dist/plugin.d.ts +22 -0
  39. package/dist/plugin.d.ts.map +1 -0
  40. package/dist/plugin.js +148 -0
  41. package/dist/plugin.js.map +1 -0
  42. package/dist/reputation.d.ts +156 -0
  43. package/dist/reputation.d.ts.map +1 -0
  44. package/dist/reputation.js +432 -0
  45. package/dist/reputation.js.map +1 -0
  46. package/dist/task-guard.d.ts +159 -0
  47. package/dist/task-guard.d.ts.map +1 -0
  48. package/dist/task-guard.js +763 -0
  49. package/dist/task-guard.js.map +1 -0
  50. package/dist/task-queue.d.ts +130 -0
  51. package/dist/task-queue.d.ts.map +1 -0
  52. package/dist/task-queue.js +592 -0
  53. package/dist/task-queue.js.map +1 -0
  54. package/dist/tool-handlers.d.ts +158 -0
  55. package/dist/tool-handlers.d.ts.map +1 -0
  56. package/dist/tool-handlers.js +727 -0
  57. package/dist/tool-handlers.js.map +1 -0
  58. package/dist/types.d.ts +417 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +29 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/webhook-pusher.d.ts +71 -0
  63. package/dist/webhook-pusher.d.ts.map +1 -0
  64. package/dist/webhook-pusher.js +175 -0
  65. package/dist/webhook-pusher.js.map +1 -0
  66. package/dist/webhook-server.d.ts +70 -0
  67. package/dist/webhook-server.d.ts.map +1 -0
  68. package/dist/webhook-server.js +191 -0
  69. package/dist/webhook-server.js.map +1 -0
  70. package/openclaw.plugin.json +107 -0
  71. package/package.json +53 -0
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ /**
3
+ * F2A Webhook Pusher
4
+ * 优先使用 webhook 推送任务到 OpenClaw,失败时退化为轮询
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.WebhookPusher = void 0;
8
+ class WebhookPusher {
9
+ config;
10
+ consecutiveFailures = 0;
11
+ lastFailureTime = 0;
12
+ degradedMode = false;
13
+ logger;
14
+ // 连续失败后暂停推送一段时间
15
+ FAILURE_THRESHOLD = 3;
16
+ BASE_COOLDOWN_MS = 10000; // 基础冷却期 10 秒
17
+ MAX_COOLDOWN_MS = 300000; // 最大冷却期 5 分钟
18
+ constructor(config, logger) {
19
+ this.config = {
20
+ timeout: 5000,
21
+ enabled: true,
22
+ ...config
23
+ };
24
+ this.logger = logger || console;
25
+ }
26
+ /**
27
+ * 计算当前冷却期(指数退避)
28
+ */
29
+ getCooldownMs() {
30
+ if (this.consecutiveFailures <= this.FAILURE_THRESHOLD) {
31
+ return this.BASE_COOLDOWN_MS;
32
+ }
33
+ // 指数退避:冷却期随失败次数增加,但有上限
34
+ const multiplier = Math.pow(2, this.consecutiveFailures - this.FAILURE_THRESHOLD);
35
+ const cooldown = Math.min(this.BASE_COOLDOWN_MS * multiplier, this.MAX_COOLDOWN_MS);
36
+ this.logger.debug?.(`[F2A:Pusher] 冷却期计算: 失败次数=${this.consecutiveFailures}, 冷却期=${Math.round(cooldown / 1000)}秒`);
37
+ return cooldown;
38
+ }
39
+ /**
40
+ * 推送任务到 OpenClaw webhook
41
+ */
42
+ async pushTask(task) {
43
+ if (!this.config.enabled) {
44
+ return { success: false, error: 'Webhook push disabled' };
45
+ }
46
+ // 检查是否在冷却期
47
+ if (this.isInCooldown()) {
48
+ const remainingMs = this.getCooldownMs() - (Date.now() - this.lastFailureTime);
49
+ // 降级机制:冷却期内仍返回特殊结果,让调用方知道可以通过轮询处理
50
+ // 返回 degraded: true 表示处于降级模式,任务需要通过轮询机制处理
51
+ return {
52
+ success: false,
53
+ error: `In cooldown (${Math.round(remainingMs / 1000)}s remaining)`,
54
+ degraded: true
55
+ };
56
+ }
57
+ const start = Date.now();
58
+ try {
59
+ const response = await fetch(`${this.config.url}/hooks/agent`, {
60
+ method: 'POST',
61
+ headers: {
62
+ 'Authorization': `Bearer ${this.config.token}`,
63
+ 'Content-Type': 'application/json'
64
+ },
65
+ body: JSON.stringify({
66
+ message: `F2A 远程任务: ${task.taskType || 'unknown'}`,
67
+ name: 'F2A',
68
+ sessionKey: `f2a:${task.taskId}`,
69
+ wakeMode: 'now',
70
+ deliver: false,
71
+ timeoutSeconds: 120
72
+ }),
73
+ signal: AbortSignal.timeout(this.config.timeout)
74
+ });
75
+ const latency = Date.now() - start;
76
+ if (response.ok || response.status === 202) {
77
+ // 成功,重置失败计数和降级模式
78
+ this.consecutiveFailures = 0;
79
+ this.degradedMode = false;
80
+ return { success: true, latency };
81
+ }
82
+ // 失败
83
+ this.recordFailure();
84
+ return {
85
+ success: false,
86
+ error: `HTTP ${response.status}: ${response.statusText}`,
87
+ latency
88
+ };
89
+ }
90
+ catch (error) {
91
+ this.recordFailure();
92
+ return {
93
+ success: false,
94
+ error: error instanceof Error ? error.message : 'Unknown error',
95
+ latency: Date.now() - start
96
+ };
97
+ }
98
+ }
99
+ /**
100
+ * 批量推送任务
101
+ */
102
+ async pushTasks(tasks) {
103
+ const results = new Map();
104
+ for (const task of tasks) {
105
+ const result = await this.pushTask(task);
106
+ results.set(task.taskId, result);
107
+ // 如果进入冷却期,停止推送但标记剩余任务为可轮询
108
+ if (result.degraded) {
109
+ // 剩余任务标记为需要轮询
110
+ const remainingTasks = tasks.filter(t => !results.has(t.taskId));
111
+ for (const remaining of remainingTasks) {
112
+ results.set(remaining.taskId, {
113
+ success: false,
114
+ error: 'Skipped due to cooldown',
115
+ degraded: true
116
+ });
117
+ }
118
+ break;
119
+ }
120
+ }
121
+ return results;
122
+ }
123
+ /**
124
+ * 检查是否在冷却期
125
+ */
126
+ isInCooldown() {
127
+ if (this.consecutiveFailures < this.FAILURE_THRESHOLD) {
128
+ return false;
129
+ }
130
+ const elapsed = Date.now() - this.lastFailureTime;
131
+ const cooldownMs = this.getCooldownMs();
132
+ return elapsed < cooldownMs;
133
+ }
134
+ /**
135
+ * 记录失败
136
+ */
137
+ recordFailure() {
138
+ this.consecutiveFailures++;
139
+ this.lastFailureTime = Date.now();
140
+ this.degradedMode = true;
141
+ if (this.consecutiveFailures >= this.FAILURE_THRESHOLD) {
142
+ const cooldownSec = Math.round(this.getCooldownMs() / 1000);
143
+ this.logger.warn(`[F2A:Pusher] 连续失败 ${this.consecutiveFailures} 次,进入 ${cooldownSec} 秒冷却期(降级模式启用)`);
144
+ }
145
+ }
146
+ /**
147
+ * 手动重置冷却期(用于外部干预)
148
+ */
149
+ resetCooldown() {
150
+ this.consecutiveFailures = 0;
151
+ this.lastFailureTime = 0;
152
+ this.degradedMode = false;
153
+ this.logger.info('[F2A:Pusher] 冷却期已手动重置');
154
+ }
155
+ /**
156
+ * 获取状态
157
+ */
158
+ getStatus() {
159
+ return {
160
+ enabled: this.config.enabled ?? true,
161
+ consecutiveFailures: this.consecutiveFailures,
162
+ inCooldown: this.isInCooldown(),
163
+ currentCooldownMs: this.isInCooldown() ? this.getCooldownMs() : 0,
164
+ degradedMode: this.degradedMode
165
+ };
166
+ }
167
+ /**
168
+ * 更新配置
169
+ */
170
+ updateConfig(config) {
171
+ this.config = { ...this.config, ...config };
172
+ }
173
+ }
174
+ exports.WebhookPusher = WebhookPusher;
175
+ //# sourceMappingURL=webhook-pusher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-pusher.js","sourceRoot":"","sources":["../src/webhook-pusher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Webhook Server
3
+ * 接收 F2A Node 的事件通知
4
+ */
5
+ import type { DiscoverWebhookPayload, DelegateWebhookPayload, AgentCapability } from './types.js';
6
+ /** Logger 接口 */
7
+ interface Logger {
8
+ info(message: string, ...args: unknown[]): void;
9
+ warn(message: string, ...args: unknown[]): void;
10
+ error(message: string, ...args: unknown[]): void;
11
+ debug?(message: string, ...args: unknown[]): void;
12
+ }
13
+ export interface WebhookHandler {
14
+ onDiscover(payload: DiscoverWebhookPayload): Promise<{
15
+ capabilities: AgentCapability[];
16
+ reputation?: number;
17
+ }>;
18
+ onDelegate(payload: DelegateWebhookPayload): Promise<{
19
+ accepted: boolean;
20
+ taskId: string;
21
+ reason?: string;
22
+ }>;
23
+ onStatus(): Promise<{
24
+ status: 'available' | 'busy' | 'offline';
25
+ load?: number;
26
+ }>;
27
+ onMessage?(payload: {
28
+ from: string;
29
+ content: string;
30
+ metadata?: Record<string, unknown>;
31
+ messageId: string;
32
+ }): Promise<{
33
+ response?: string;
34
+ }>;
35
+ }
36
+ export declare class WebhookServer {
37
+ private port;
38
+ private handler;
39
+ private server?;
40
+ private maxBodySize;
41
+ /** 允许的 CORS 来源列表 */
42
+ private allowedOrigins;
43
+ /** 日志记录器 */
44
+ private logger;
45
+ constructor(port: number, handler: WebhookHandler, options?: {
46
+ maxBodySize?: number;
47
+ allowedOrigins?: string[];
48
+ logger?: Logger;
49
+ });
50
+ /**
51
+ * 启动 Webhook 服务器
52
+ */
53
+ start(): Promise<void>;
54
+ /**
55
+ * 停止 Webhook 服务器
56
+ */
57
+ stop(): Promise<void>;
58
+ /**
59
+ * 处理 HTTP 请求
60
+ */
61
+ private handleRequest;
62
+ /**
63
+ * 解析请求体
64
+ * 带大小限制,防止 DoS 攻击
65
+ */
66
+ private parseBody;
67
+ getUrl(): string;
68
+ }
69
+ export {};
70
+ //# sourceMappingURL=webhook-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-server.d.ts","sourceRoot":"","sources":["../src/webhook-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAEV,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB,gBAAgB;AAChB,UAAU,MAAM;IACd,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACnD;AA6BD,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC;QACnD,YAAY,EAAE,eAAe,EAAE,CAAC;QAChC,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IAEH,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC;QACnD,QAAQ,EAAE,OAAO,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IAEH,QAAQ,IAAI,OAAO,CAAC;QAClB,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;QACzC,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IAEH,SAAS,CAAC,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QACrH,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;CACJ;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAC,CAAkC;IACjD,OAAO,CAAC,WAAW,CAAS;IAC5B,oBAAoB;IACpB,OAAO,CAAC,cAAc,CAAW;IACjC,YAAY;IACZ,OAAO,CAAC,MAAM,CAAS;gBAEX,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE;QAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAcD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B;;OAEG;YACW,aAAa;IAwF3B;;;OAGG;IACH,OAAO,CAAC,SAAS;IA8BjB,MAAM,IAAI,MAAM;CAGjB"}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ /**
3
+ * Webhook Server
4
+ * 接收 F2A Node 的事件通知
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.WebhookServer = void 0;
8
+ const http_1 = require("http");
9
+ /** 默认请求体大小限制 (64KB) - 元数据交换足够,防止 DoS */
10
+ const DEFAULT_MAX_BODY_SIZE = 64 * 1024;
11
+ /** 默认允许的 CORS 来源 */
12
+ const DEFAULT_ALLOWED_ORIGINS = ['http://localhost'];
13
+ /**
14
+ * P2 修复:生产环境 CORS 配置验证
15
+ */
16
+ function validateCorsConfig(allowedOrigins, logger) {
17
+ const isProduction = process.env.NODE_ENV === 'production';
18
+ if (isProduction) {
19
+ // 检查是否使用默认配置
20
+ if (allowedOrigins.length === 1 && allowedOrigins[0] === 'http://localhost') {
21
+ logger.error('[F2A:Webhook] CORS configuration warning: Using default localhost origin in production!');
22
+ logger.error('[F2A:Webhook] Set F2A_WEBHOOK_ALLOWED_ORIGINS environment variable or pass allowedOrigins option.');
23
+ }
24
+ // 检查是否包含通配符
25
+ if (allowedOrigins.includes('*')) {
26
+ logger.error('[F2A:Webhook] CORS configuration error: Wildcard origin (*) is not allowed in production!');
27
+ throw new Error('Wildcard CORS origin is not allowed in production. Configure specific allowed origins.');
28
+ }
29
+ }
30
+ }
31
+ class WebhookServer {
32
+ port;
33
+ handler;
34
+ server;
35
+ maxBodySize;
36
+ /** 允许的 CORS 来源列表 */
37
+ allowedOrigins;
38
+ /** 日志记录器 */
39
+ logger;
40
+ constructor(port, handler, options) {
41
+ this.port = port;
42
+ this.handler = handler;
43
+ this.maxBodySize = options?.maxBodySize || DEFAULT_MAX_BODY_SIZE;
44
+ // P2 修复:支持从环境变量读取 CORS 配置
45
+ const envOrigins = process.env.F2A_WEBHOOK_ALLOWED_ORIGINS?.split(',').map(o => o.trim()).filter(Boolean);
46
+ this.allowedOrigins = options?.allowedOrigins ?? envOrigins ?? DEFAULT_ALLOWED_ORIGINS;
47
+ // 使用传入的 logger 或默认的 console
48
+ this.logger = options?.logger || console;
49
+ // P2 修复:生产环境强制验证 CORS 配置
50
+ validateCorsConfig(this.allowedOrigins, this.logger);
51
+ }
52
+ /**
53
+ * 启动 Webhook 服务器
54
+ */
55
+ async start() {
56
+ return new Promise((resolve, reject) => {
57
+ this.server = (0, http_1.createServer)(this.handleRequest.bind(this));
58
+ this.server.listen(this.port, () => {
59
+ this.logger.info('[F2A:Webhook] 服务器启动在端口 %d', this.port);
60
+ // 允许进程在只有这个服务器时退出(用于 CLI 命令如 gateway status)
61
+ this.server?.unref();
62
+ resolve();
63
+ });
64
+ this.server.on('error', (err) => {
65
+ reject(err);
66
+ });
67
+ });
68
+ }
69
+ /**
70
+ * 停止 Webhook 服务器
71
+ */
72
+ async stop() {
73
+ if (this.server) {
74
+ return new Promise((resolve) => {
75
+ this.server?.close(() => {
76
+ this.logger.info('[F2A:Webhook] 服务器已停止');
77
+ resolve();
78
+ });
79
+ });
80
+ }
81
+ }
82
+ /**
83
+ * 处理 HTTP 请求
84
+ */
85
+ async handleRequest(req, res) {
86
+ // 设置 CORS - 使用配置的允许来源
87
+ const origin = req.headers.origin;
88
+ // 当 allowedOrigins 为空数组时,使用默认值 'http://localhost'
89
+ // 当 origin 不在允许列表中时,使用第一个允许的来源或默认值
90
+ const defaultOrigin = 'http://localhost';
91
+ let allowOrigin;
92
+ if (this.allowedOrigins.length === 0) {
93
+ // 没有配置允许来源,使用默认值
94
+ allowOrigin = defaultOrigin;
95
+ }
96
+ else if (origin && this.allowedOrigins.includes(origin)) {
97
+ // origin 在允许列表中
98
+ allowOrigin = origin;
99
+ }
100
+ else {
101
+ // origin 不在允许列表中,使用第一个允许的来源
102
+ allowOrigin = this.allowedOrigins[0];
103
+ }
104
+ res.setHeader('Access-Control-Allow-Origin', allowOrigin);
105
+ res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
106
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
107
+ if (req.method === 'OPTIONS') {
108
+ res.writeHead(200);
109
+ res.end();
110
+ return;
111
+ }
112
+ if (req.method !== 'POST') {
113
+ res.writeHead(405, { 'Content-Type': 'application/json' });
114
+ res.end(JSON.stringify({ error: 'Method not allowed' }));
115
+ return;
116
+ }
117
+ try {
118
+ const body = await this.parseBody(req);
119
+ const event = body;
120
+ this.logger.info('[F2A:Webhook] 收到事件: %s', event.type);
121
+ let result;
122
+ switch (event.type) {
123
+ case 'discover':
124
+ result = await this.handler.onDiscover(event.payload);
125
+ break;
126
+ case 'delegate':
127
+ result = await this.handler.onDelegate(event.payload);
128
+ break;
129
+ case 'status':
130
+ result = await this.handler.onStatus();
131
+ break;
132
+ case 'message':
133
+ // 处理 P2P 消息(Agent 对话)
134
+ if (this.handler.onMessage) {
135
+ result = await this.handler.onMessage(event.payload);
136
+ }
137
+ else {
138
+ result = { response: 'Message handler not configured' };
139
+ }
140
+ break;
141
+ default:
142
+ res.writeHead(400, { 'Content-Type': 'application/json' });
143
+ res.end(JSON.stringify({ error: `Unknown event type: ${event.type}` }));
144
+ return;
145
+ }
146
+ res.writeHead(200, { 'Content-Type': 'application/json' });
147
+ res.end(JSON.stringify(result));
148
+ }
149
+ catch (error) {
150
+ this.logger.error('[F2A:Webhook] 处理错误: %s', error);
151
+ res.writeHead(500, { 'Content-Type': 'application/json' });
152
+ res.end(JSON.stringify({
153
+ error: error instanceof Error ? error.message : 'Internal error'
154
+ }));
155
+ }
156
+ }
157
+ /**
158
+ * 解析请求体
159
+ * 带大小限制,防止 DoS 攻击
160
+ */
161
+ parseBody(req) {
162
+ return new Promise((resolve, reject) => {
163
+ let body = '';
164
+ let size = 0;
165
+ req.on('data', (chunk) => {
166
+ size += chunk.length;
167
+ // 检查请求体大小
168
+ if (size > this.maxBodySize) {
169
+ req.destroy();
170
+ reject(new Error(`Request body too large: ${size} bytes (max: ${this.maxBodySize})`));
171
+ return;
172
+ }
173
+ body += chunk.toString();
174
+ });
175
+ req.on('end', () => {
176
+ try {
177
+ resolve(JSON.parse(body));
178
+ }
179
+ catch (e) {
180
+ reject(new Error('Invalid JSON'));
181
+ }
182
+ });
183
+ req.on('error', reject);
184
+ });
185
+ }
186
+ getUrl() {
187
+ return `http://localhost:${this.port}/webhook`;
188
+ }
189
+ }
190
+ exports.WebhookServer = WebhookServer;
191
+ //# sourceMappingURL=webhook-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-server.js","sourceRoot":"","sources":["../src/webhook-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ {
2
+ "id": "openclaw-f2a",
3
+ "extension": "./dist/plugin.js",
4
+ "name": "F2A P2P Agent Network",
5
+ "description": "OpenClaw plugin for F2A P2P Agent network",
6
+ "version": "0.2.20",
7
+ "configSchema": {
8
+ "type": "object",
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "f2aPath": {
12
+ "type": "string",
13
+ "description": "Path to F2A installation",
14
+ "default": "~/projects/F2A"
15
+ },
16
+ "autoStart": {
17
+ "type": "boolean",
18
+ "description": "Automatically start F2A node",
19
+ "default": true
20
+ },
21
+ "webhookPort": {
22
+ "type": "number",
23
+ "description": "Port for webhook server",
24
+ "default": 9002
25
+ },
26
+ "controlPort": {
27
+ "type": "number",
28
+ "description": "Port for F2A control API",
29
+ "default": 9001
30
+ },
31
+ "controlToken": {
32
+ "type": "string",
33
+ "description": "Auth token for F2A control API (auto-generated if not provided)",
34
+ "sensitive": true
35
+ },
36
+ "p2pPort": {
37
+ "type": "number",
38
+ "description": "Port for P2P network",
39
+ "default": 9000
40
+ },
41
+ "enableMDNS": {
42
+ "type": "boolean",
43
+ "description": "Enable mDNS discovery",
44
+ "default": true
45
+ },
46
+ "bootstrapPeers": {
47
+ "type": "array",
48
+ "items": { "type": "string" },
49
+ "description": "Bootstrap peer addresses",
50
+ "default": []
51
+ },
52
+ "agentName": {
53
+ "type": "string",
54
+ "description": "Display name for this agent",
55
+ "default": "OpenClaw Agent"
56
+ },
57
+ "capabilities": {
58
+ "type": "array",
59
+ "items": { "type": "string" },
60
+ "description": "Custom capabilities to advertise",
61
+ "default": []
62
+ },
63
+ "dataDir": {
64
+ "type": "string",
65
+ "description": "Directory for plugin data",
66
+ "default": "./f2a-data"
67
+ },
68
+ "maxQueuedTasks": {
69
+ "type": "number",
70
+ "description": "Maximum number of tasks to queue",
71
+ "default": 100
72
+ },
73
+ "reputation": {
74
+ "type": "object",
75
+ "properties": {
76
+ "enabled": { "type": "boolean", "default": true },
77
+ "initialScore": { "type": "number", "default": 50 },
78
+ "minScoreForService": { "type": "number", "default": 20 },
79
+ "decayRate": { "type": "number", "default": 0.01 }
80
+ }
81
+ },
82
+ "security": {
83
+ "type": "object",
84
+ "properties": {
85
+ "requireConfirmation": { "type": "boolean", "default": false },
86
+ "whitelist": { "type": "array", "items": { "type": "string" }, "default": [] },
87
+ "blacklist": { "type": "array", "items": { "type": "string" }, "default": [] },
88
+ "maxTasksPerMinute": { "type": "number", "default": 10 }
89
+ }
90
+ }
91
+ }
92
+ },
93
+ "uiHints": {
94
+ "f2aPath": { "label": "F2A Path", "placeholder": "~/projects/F2A" },
95
+ "autoStart": { "label": "Auto Start F2A Node" },
96
+ "webhookPort": { "label": "Webhook Port" },
97
+ "controlPort": { "label": "Control Port" },
98
+ "controlToken": { "label": "Control Token", "sensitive": true },
99
+ "p2pPort": { "label": "P2P Port" },
100
+ "enableMDNS": { "label": "Enable mDNS Discovery" },
101
+ "bootstrapPeers": { "label": "Bootstrap Peers", "placeholder": ["/ip4/..."] },
102
+ "agentName": { "label": "Agent Display Name" },
103
+ "capabilities": { "label": "Custom Capabilities" },
104
+ "dataDir": { "label": "Data Directory" },
105
+ "maxQueuedTasks": { "label": "Max Queued Tasks" }
106
+ }
107
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@f2a/openclaw-f2a",
3
+ "version": "0.2.20",
4
+ "description": "OpenClaw plugin for F2A P2P Agent network",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "openclaw.plugin.json",
10
+ "README.md"
11
+ ],
12
+ "openclaw": {
13
+ "extensions": [
14
+ "./dist/plugin.js"
15
+ ]
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsc --watch",
20
+ "test": "vitest",
21
+ "lint": "eslint src/**/*.ts"
22
+ },
23
+ "keywords": [
24
+ "openclaw",
25
+ "f2a",
26
+ "p2p",
27
+ "agent",
28
+ "plugin"
29
+ ],
30
+ "author": "F2A Team",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/LuciusCao/F2A.git"
35
+ },
36
+ "dependencies": {
37
+ "@f2a/network": "*",
38
+ "better-sqlite3": "^11.0.0",
39
+ "node-fetch": "^3.3.2",
40
+ "ws": "^8.16.0",
41
+ "zod": "^3.22.4"
42
+ },
43
+ "devDependencies": {
44
+ "@types/better-sqlite3": "^7.6.13",
45
+ "@types/node": "^20.10.0",
46
+ "@types/ws": "^8.5.10",
47
+ "typescript": "^5.3.0",
48
+ "vitest": "^1.6.1"
49
+ },
50
+ "peerDependencies": {
51
+ "openclaw": ">=1.0.0"
52
+ }
53
+ }