multiclaws 0.4.35 → 0.4.37
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/README.md +39 -39
- package/README.zh-CN.md +39 -39
- package/dist/gateway/handlers.js +17 -0
- package/dist/index.js +88 -44
- package/dist/service/a2a-adapter.d.ts +18 -4
- package/dist/service/a2a-adapter.js +177 -28
- package/dist/service/multiclaws-service.d.ts +5 -0
- package/dist/service/multiclaws-service.js +33 -17
- package/openclaw.plugin.json +47 -47
- package/package.json +56 -56
- package/skills/meeting-scheduler/SKILL.md +175 -0
- package/skills/multiclaws/SKILL.md +218 -218
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OpenClawAgentExecutor = void 0;
|
|
4
4
|
const gateway_client_1 = require("../infra/gateway-client");
|
|
5
|
+
/* ------------------------------------------------------------------ */
|
|
6
|
+
/* Risk classification */
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/**
|
|
9
|
+
* Heuristic risk classifier. Returns "safe" only when the task is
|
|
10
|
+
* clearly a read-only query; defaults to "risky" for anything ambiguous.
|
|
11
|
+
*
|
|
12
|
+
* This drives the permission gate: risky tasks require explicit human
|
|
13
|
+
* approval before a sub-agent is spawned to execute them.
|
|
14
|
+
*/
|
|
15
|
+
function classifyTaskRisk(taskText) {
|
|
16
|
+
const text = taskText.toLowerCase();
|
|
17
|
+
// Explicit risky patterns (write / modify / execute / send)
|
|
18
|
+
const riskyPatterns = [
|
|
19
|
+
// English
|
|
20
|
+
/\b(write|creat|delet|remov|modif|edit|updat|install|execut|deploy|push|commit|send|post|drop|format|rename|overwrite|reset|wipe|destroy|kill|terminat|rm\b|mkdir|touch\b|mv\b)\b/i,
|
|
21
|
+
// Chinese write-oriented verbs
|
|
22
|
+
/[写创建删除修改编辑更新安装执行运行发送提交部署重命名覆盖重置清空销毁终止]/,
|
|
23
|
+
];
|
|
24
|
+
if (riskyPatterns.some((p) => p.test(text))) {
|
|
25
|
+
return "risky";
|
|
26
|
+
}
|
|
27
|
+
// Explicitly safe read-only patterns
|
|
28
|
+
const safePatterns = [
|
|
29
|
+
/\b(list|show|get|check|view|read|query|find|search|display|fetch|retriev|look|what|which|count|how many|summariz|describ|explain|analyz|report)\b/i,
|
|
30
|
+
/[查看获取搜索显示检查列出查询统计描述分析报告]/,
|
|
31
|
+
// Calendar / schedule queries
|
|
32
|
+
/\b(calendar|schedule|event|meeting|free|busy|availab)\b/i,
|
|
33
|
+
/[日历日程会议空闲忙碌可用时间]/,
|
|
34
|
+
// Process / system info
|
|
35
|
+
/\b(process|pid|cpu|memory|disk|uptime|version|status|running|service)\b/i,
|
|
36
|
+
/[进程内存磁盘状态运行版本服务]/,
|
|
37
|
+
];
|
|
38
|
+
if (safePatterns.some((p) => p.test(text))) {
|
|
39
|
+
return "safe";
|
|
40
|
+
}
|
|
41
|
+
// Default: treat as risky if uncertain
|
|
42
|
+
return "risky";
|
|
43
|
+
}
|
|
44
|
+
/* ------------------------------------------------------------------ */
|
|
45
|
+
/* Helpers */
|
|
46
|
+
/* ------------------------------------------------------------------ */
|
|
5
47
|
function extractTextFromMessage(message) {
|
|
6
48
|
if (!message.parts)
|
|
7
49
|
return "";
|
|
@@ -15,10 +57,13 @@ function extractTextFromMessage(message) {
|
|
|
15
57
|
*
|
|
16
58
|
* When a remote agent sends a task via A2A `message/send`,
|
|
17
59
|
* this executor:
|
|
18
|
-
* 1.
|
|
19
|
-
* 2.
|
|
20
|
-
* 3.
|
|
21
|
-
*
|
|
60
|
+
* 1. Classifies the task risk (safe vs risky)
|
|
61
|
+
* 2. Notifies the local human owner
|
|
62
|
+
* 3. For risky tasks: waits for explicit human approval
|
|
63
|
+
* For safe tasks: executes immediately
|
|
64
|
+
* 4. Calls OpenClaw's `sessions_spawn` (run mode) to start execution
|
|
65
|
+
* 5. Waits for the sub-agent to call back via `multiclaws_a2a_callback`
|
|
66
|
+
* 6. Returns the final result as a Message
|
|
22
67
|
*/
|
|
23
68
|
class OpenClawAgentExecutor {
|
|
24
69
|
gatewayConfig;
|
|
@@ -27,6 +72,7 @@ class OpenClawAgentExecutor {
|
|
|
27
72
|
logger;
|
|
28
73
|
cwd;
|
|
29
74
|
pendingCallbacks = new Map();
|
|
75
|
+
pendingApprovals = new Map();
|
|
30
76
|
constructor(options) {
|
|
31
77
|
this.gatewayConfig = options.gatewayConfig;
|
|
32
78
|
this.taskTracker = options.taskTracker;
|
|
@@ -61,10 +107,49 @@ class OpenClawAgentExecutor {
|
|
|
61
107
|
eventBus.finished();
|
|
62
108
|
return;
|
|
63
109
|
}
|
|
64
|
-
//
|
|
65
|
-
const
|
|
66
|
-
this.logger.info(`[a2a-adapter] task ${taskId}
|
|
67
|
-
|
|
110
|
+
// Classify risk and gate accordingly
|
|
111
|
+
const risk = classifyTaskRisk(taskText);
|
|
112
|
+
this.logger.info(`[a2a-adapter] task ${taskId} risk=${risk}`);
|
|
113
|
+
if (risk === "risky") {
|
|
114
|
+
// Notify with approval request and wait
|
|
115
|
+
const approvalTimeoutMs = 5 * 60 * 1000; // 5 minutes
|
|
116
|
+
const approvalPromise = this.createApprovalCallback(taskId, approvalTimeoutMs);
|
|
117
|
+
this.logger.info(`[a2a-adapter] task ${taskId} requesting human approval (timeout=${approvalTimeoutMs / 1000}s)`);
|
|
118
|
+
void this.notifyUser(buildApprovalRequest(taskId, fromAgentName, taskText));
|
|
119
|
+
let approved;
|
|
120
|
+
try {
|
|
121
|
+
approved = await approvalPromise;
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
const isCanceled = err instanceof Error && err.message === "canceled";
|
|
125
|
+
if (isCanceled) {
|
|
126
|
+
// Task was explicitly canceled — use the canonical "canceled" message
|
|
127
|
+
this.logger.info(`[a2a-adapter] task ${taskId} canceled during approval wait`);
|
|
128
|
+
this.taskTracker.update(taskId, { status: "failed", error: "canceled" });
|
|
129
|
+
this.publishMessage(eventBus, "Task was canceled.");
|
|
130
|
+
eventBus.finished();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// Approval timed out → auto-reject
|
|
134
|
+
approved = false;
|
|
135
|
+
this.logger.warn(`[a2a-adapter] task ${taskId} approval timed out — auto-rejected`);
|
|
136
|
+
}
|
|
137
|
+
if (!approved) {
|
|
138
|
+
const reason = "用户拒绝或未在超时时间内授权。";
|
|
139
|
+
this.logger.info(`[a2a-adapter] task ${taskId} rejected`);
|
|
140
|
+
this.taskTracker.update(taskId, { status: "failed", error: reason });
|
|
141
|
+
this.publishMessage(eventBus, `任务已被拒绝:${reason}`);
|
|
142
|
+
eventBus.finished();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
this.logger.info(`[a2a-adapter] task ${taskId} approved by user`);
|
|
146
|
+
void this.notifyUser(`✅ 已授权,开始执行来自 **${fromAgentName}** 的任务…`);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// Safe task: notify but auto-execute
|
|
150
|
+
this.logger.info(`[a2a-adapter] task ${taskId} safe query — auto-executing`);
|
|
151
|
+
void this.notifyUser(`📨 收到来自 **${fromAgentName}** 的查询任务(安全,自动执行):\n\n${taskText.slice(0, 300)}`);
|
|
152
|
+
}
|
|
68
153
|
try {
|
|
69
154
|
// Create a promise that resolves when sub-agent calls multiclaws_a2a_callback
|
|
70
155
|
const timeoutMs = 180_000;
|
|
@@ -88,15 +173,17 @@ class OpenClawAgentExecutor {
|
|
|
88
173
|
this.logger.info(`[a2a-adapter] task ${taskId} waiting for callback from sub-agent...`);
|
|
89
174
|
// Wait for the sub-agent to call back
|
|
90
175
|
const output = await resultPromise;
|
|
91
|
-
// Return result
|
|
176
|
+
// Return result and notify user
|
|
92
177
|
this.taskTracker.update(taskId, { status: "completed", result: output });
|
|
93
178
|
this.logger.info(`[a2a-adapter] ✓ task ${taskId} completed — resultLen=${output.length}, preview=${output.slice(0, 120)}`);
|
|
179
|
+
void this.notifyUser(`✅ **来自 ${fromAgentName} 的任务已完成**\n\n${output.slice(0, 800)}`);
|
|
94
180
|
this.publishMessage(eventBus, output || "Task completed with no output.");
|
|
95
181
|
}
|
|
96
182
|
catch (err) {
|
|
97
183
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
98
184
|
this.logger.error(`[a2a-adapter] ✗ task ${taskId} failed: ${errorMsg}`);
|
|
99
185
|
this.taskTracker.update(taskId, { status: "failed", error: errorMsg });
|
|
186
|
+
void this.notifyUser(`❌ 来自 **${fromAgentName}** 的任务执行失败:${errorMsg}`);
|
|
100
187
|
this.publishMessage(eventBus, `Error: ${errorMsg}`);
|
|
101
188
|
}
|
|
102
189
|
this.logger.info(`[a2a-adapter] task ${taskId} eventBus.finished()`);
|
|
@@ -118,8 +205,32 @@ class OpenClawAgentExecutor {
|
|
|
118
205
|
pending.resolve(result);
|
|
119
206
|
return true;
|
|
120
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Called when the local human owner approves or rejects a pending risky task.
|
|
210
|
+
* Returns true if a pending approval was found.
|
|
211
|
+
*/
|
|
212
|
+
resolveApproval(taskId, approved) {
|
|
213
|
+
const pending = this.pendingApprovals.get(taskId);
|
|
214
|
+
if (!pending) {
|
|
215
|
+
this.logger.warn(`[a2a-adapter] resolveApproval: no pending approval for taskId=${taskId}`);
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
clearTimeout(pending.timer);
|
|
219
|
+
this.pendingApprovals.delete(taskId);
|
|
220
|
+
this.logger.info(`[a2a-adapter] resolveApproval: taskId=${taskId} approved=${approved}`);
|
|
221
|
+
pending.resolve(approved);
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
121
224
|
async cancelTask(taskId, eventBus) {
|
|
122
225
|
this.logger.info(`[a2a-adapter] cancelTask(taskId=${taskId})`);
|
|
226
|
+
// Reject pending approval if any — distinct from user-rejection, uses Error("canceled")
|
|
227
|
+
const approval = this.pendingApprovals.get(taskId);
|
|
228
|
+
if (approval) {
|
|
229
|
+
clearTimeout(approval.timer);
|
|
230
|
+
this.pendingApprovals.delete(taskId);
|
|
231
|
+
approval.reject(new Error("canceled"));
|
|
232
|
+
this.logger.info(`[a2a-adapter] cancelTask: pending approval canceled for taskId=${taskId}`);
|
|
233
|
+
}
|
|
123
234
|
// Reject pending callback if any
|
|
124
235
|
const pending = this.pendingCallbacks.get(taskId);
|
|
125
236
|
if (pending) {
|
|
@@ -149,6 +260,20 @@ class OpenClawAgentExecutor {
|
|
|
149
260
|
this.pendingCallbacks.set(taskId, { resolve, reject, timer });
|
|
150
261
|
});
|
|
151
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Create a pending approval that resolves when the human owner responds,
|
|
265
|
+
* or rejects on timeout or cancellation.
|
|
266
|
+
*/
|
|
267
|
+
createApprovalCallback(taskId, timeoutMs) {
|
|
268
|
+
return new Promise((resolve, reject) => {
|
|
269
|
+
const timer = setTimeout(() => {
|
|
270
|
+
this.pendingApprovals.delete(taskId);
|
|
271
|
+
this.logger.warn(`[a2a-adapter] task ${taskId} approval timed out after ${timeoutMs / 1000}s`);
|
|
272
|
+
reject(new Error(`approval timed out after ${timeoutMs / 1000}s`));
|
|
273
|
+
}, timeoutMs);
|
|
274
|
+
this.pendingApprovals.set(taskId, { resolve, reject, timer });
|
|
275
|
+
});
|
|
276
|
+
}
|
|
152
277
|
/** Send a notification to all known targets. Individual failures are silently ignored. */
|
|
153
278
|
async notifyUser(message) {
|
|
154
279
|
const targets = this.getNotificationTargets();
|
|
@@ -167,8 +292,10 @@ class OpenClawAgentExecutor {
|
|
|
167
292
|
timeoutMs: 5_000,
|
|
168
293
|
})
|
|
169
294
|
: (0, gateway_client_1.invokeGatewayTool)({
|
|
295
|
+
// sessions_send injects a message into the session so the AI
|
|
296
|
+
// can relay it to the human (correct tool; was "chat.send" before)
|
|
170
297
|
gateway: this.gatewayConfig,
|
|
171
|
-
tool: "
|
|
298
|
+
tool: "sessions_send",
|
|
172
299
|
args: { sessionKey: target.sessionKey, message },
|
|
173
300
|
timeoutMs: 5_000,
|
|
174
301
|
}));
|
|
@@ -194,28 +321,50 @@ class OpenClawAgentExecutor {
|
|
|
194
321
|
}
|
|
195
322
|
}
|
|
196
323
|
exports.OpenClawAgentExecutor = OpenClawAgentExecutor;
|
|
324
|
+
/* ------------------------------------------------------------------ */
|
|
325
|
+
/* Prompt builders */
|
|
326
|
+
/* ------------------------------------------------------------------ */
|
|
327
|
+
/**
|
|
328
|
+
* Build the approval request message injected into the human's active session.
|
|
329
|
+
* The AI in that session will relay it and handle the human's approve/reject response.
|
|
330
|
+
*/
|
|
331
|
+
function buildApprovalRequest(taskId, fromAgentName, taskText) {
|
|
332
|
+
const preview = taskText.length > 600 ? taskText.slice(0, 600) + "…" : taskText;
|
|
333
|
+
return `[MultiClaws] 收到来自 **${fromAgentName}** 的委派任务,需要授权
|
|
334
|
+
|
|
335
|
+
**任务内容:**
|
|
336
|
+
${preview}
|
|
337
|
+
|
|
338
|
+
⚠️ 该任务涉及写操作或高风险操作,需要您授权才能执行。
|
|
339
|
+
|
|
340
|
+
请询问用户是否同意执行,并根据回复调用对应工具:
|
|
341
|
+
- 同意:\`multiclaws_task_respond(taskId="${taskId}", approved=true)\`
|
|
342
|
+
- 拒绝:\`multiclaws_task_respond(taskId="${taskId}", approved=false)\`
|
|
343
|
+
|
|
344
|
+
授权等待时间:5 分钟,超时自动拒绝。`;
|
|
345
|
+
}
|
|
197
346
|
/**
|
|
198
347
|
* Build the prompt for the sub-agent that handles an incoming A2A task.
|
|
199
348
|
* The sub-agent must call `multiclaws_a2a_callback` to report its result.
|
|
200
349
|
*/
|
|
201
350
|
function buildA2ASubagentPrompt(taskId, taskText) {
|
|
202
|
-
return `你收到了一个来自远端智能体的委派任务。请完成任务并汇报结果。
|
|
203
|
-
|
|
204
|
-
## 任务内容
|
|
205
|
-
|
|
206
|
-
${taskText}
|
|
207
|
-
|
|
208
|
-
## 完成后必做
|
|
209
|
-
|
|
210
|
-
完成任务后,你**必须**调用 \`multiclaws_a2a_callback\` 工具汇报结果:
|
|
211
|
-
|
|
212
|
-
\`\`\`
|
|
213
|
-
multiclaws_a2a_callback(taskId="${taskId}", result="你的完整回复内容")
|
|
214
|
-
\`\`\`
|
|
215
|
-
|
|
216
|
-
**重要**:
|
|
217
|
-
- 无论任务成功还是失败,都必须调用 \`multiclaws_a2a_callback\`
|
|
218
|
-
- result 参数填写你的完整回复文本
|
|
219
|
-
- 如果任务失败,在 result 中说明失败原因
|
|
351
|
+
return `你收到了一个来自远端智能体的委派任务。请完成任务并汇报结果。
|
|
352
|
+
|
|
353
|
+
## 任务内容
|
|
354
|
+
|
|
355
|
+
${taskText}
|
|
356
|
+
|
|
357
|
+
## 完成后必做
|
|
358
|
+
|
|
359
|
+
完成任务后,你**必须**调用 \`multiclaws_a2a_callback\` 工具汇报结果:
|
|
360
|
+
|
|
361
|
+
\`\`\`
|
|
362
|
+
multiclaws_a2a_callback(taskId="${taskId}", result="你的完整回复内容")
|
|
363
|
+
\`\`\`
|
|
364
|
+
|
|
365
|
+
**重要**:
|
|
366
|
+
- 无论任务成功还是失败,都必须调用 \`multiclaws_a2a_callback\`
|
|
367
|
+
- result 参数填写你的完整回复文本
|
|
368
|
+
- 如果任务失败,在 result 中说明失败原因
|
|
220
369
|
- 这是唯一的结果回传方式,不调用则结果会丢失`;
|
|
221
370
|
}
|
|
@@ -133,6 +133,11 @@ export declare class MulticlawsService extends EventEmitter {
|
|
|
133
133
|
private extractArtifactText;
|
|
134
134
|
/** Fetch with up to 2 retries and exponential backoff. */
|
|
135
135
|
private fetchWithRetry;
|
|
136
|
+
/**
|
|
137
|
+
* Called by the `multiclaws_task_respond` tool when the local human
|
|
138
|
+
* approves or rejects a pending risky incoming task.
|
|
139
|
+
*/
|
|
140
|
+
respondToTask(taskId: string, approved: boolean): boolean;
|
|
136
141
|
/** Resolve a pending A2A callback from sub-agent. */
|
|
137
142
|
resolveA2ACallback(taskId: string, result: string): boolean;
|
|
138
143
|
addNotificationTarget(key: string, target: NotificationTarget): void;
|
|
@@ -30,22 +30,22 @@ function buildDelegationPrompt(agent, task) {
|
|
|
30
30
|
const bioSnippet = agent.description
|
|
31
31
|
? `\n**智能体能力**: ${agent.description.slice(0, 500)}`
|
|
32
32
|
: "";
|
|
33
|
-
return `## 委派任务
|
|
34
|
-
向远端智能体发送任务并汇报结果。
|
|
35
|
-
|
|
36
|
-
**目标智能体**: ${agent.name} (${agent.url})${bioSnippet}
|
|
37
|
-
**任务内容**: ${task}
|
|
38
|
-
|
|
39
|
-
## 执行步骤
|
|
40
|
-
1. 调用 multiclaws_delegate_send(agentUrl="${agent.url}", task="${task.replace(/"/g, '\\"')}") 发送任务
|
|
41
|
-
2. 收到回复后,调用 multiclaws_notify(message="结果内容") 将结果推送给用户
|
|
42
|
-
3. 如果需要进一步沟通,可再次调用 multiclaws_delegate_send(最多 5 轮)
|
|
43
|
-
4. 每次收到回复后立即调用 multiclaws_notify 推送进展
|
|
44
|
-
|
|
45
|
-
## 规则
|
|
46
|
-
- 使用 multiclaws_delegate_send(不是 multiclaws_delegate)发送任务
|
|
47
|
-
- 使用 multiclaws_notify(不是 message)将结果推送给用户
|
|
48
|
-
- 最多 5 轮沟通
|
|
33
|
+
return `## 委派任务
|
|
34
|
+
向远端智能体发送任务并汇报结果。
|
|
35
|
+
|
|
36
|
+
**目标智能体**: ${agent.name} (${agent.url})${bioSnippet}
|
|
37
|
+
**任务内容**: ${task}
|
|
38
|
+
|
|
39
|
+
## 执行步骤
|
|
40
|
+
1. 调用 multiclaws_delegate_send(agentUrl="${agent.url}", task="${task.replace(/"/g, '\\"')}") 发送任务
|
|
41
|
+
2. 收到回复后,调用 multiclaws_notify(message="结果内容") 将结果推送给用户
|
|
42
|
+
3. 如果需要进一步沟通,可再次调用 multiclaws_delegate_send(最多 5 轮)
|
|
43
|
+
4. 每次收到回复后立即调用 multiclaws_notify 推送进展
|
|
44
|
+
|
|
45
|
+
## 规则
|
|
46
|
+
- 使用 multiclaws_delegate_send(不是 multiclaws_delegate)发送任务
|
|
47
|
+
- 使用 multiclaws_notify(不是 message)将结果推送给用户
|
|
48
|
+
- 最多 5 轮沟通
|
|
49
49
|
- 遇到错误时在 multiclaws_notify 中说明失败原因`;
|
|
50
50
|
}
|
|
51
51
|
/* ------------------------------------------------------------------ */
|
|
@@ -940,6 +940,20 @@ class MulticlawsService extends node_events_1.EventEmitter {
|
|
|
940
940
|
}
|
|
941
941
|
throw lastError;
|
|
942
942
|
}
|
|
943
|
+
/**
|
|
944
|
+
* Called by the `multiclaws_task_respond` tool when the local human
|
|
945
|
+
* approves or rejects a pending risky incoming task.
|
|
946
|
+
*/
|
|
947
|
+
respondToTask(taskId, approved) {
|
|
948
|
+
this.log("info", `respondToTask(taskId=${taskId}, approved=${approved})`);
|
|
949
|
+
if (!this.agentExecutor) {
|
|
950
|
+
this.log("warn", `respondToTask: no agentExecutor available for taskId=${taskId}`);
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
const resolved = this.agentExecutor.resolveApproval(taskId, approved);
|
|
954
|
+
this.log("info", `respondToTask: ${resolved ? "✓" : "✗"} taskId=${taskId} ${resolved ? "resolved" : "no pending approval found"}`);
|
|
955
|
+
return resolved;
|
|
956
|
+
}
|
|
943
957
|
/** Resolve a pending A2A callback from sub-agent. */
|
|
944
958
|
resolveA2ACallback(taskId, result) {
|
|
945
959
|
this.log("info", `[a2a-callback] resolveA2ACallback(taskId=${taskId}, resultLen=${result.length})`);
|
|
@@ -980,8 +994,10 @@ class MulticlawsService extends node_events_1.EventEmitter {
|
|
|
980
994
|
timeoutMs: 5_000,
|
|
981
995
|
})
|
|
982
996
|
: (0, gateway_client_1.invokeGatewayTool)({
|
|
997
|
+
// sessions_send injects a message into the session so the AI
|
|
998
|
+
// can relay it to the human (correct tool; was "chat.send" before)
|
|
983
999
|
gateway: this.gatewayConfig,
|
|
984
|
-
tool: "
|
|
1000
|
+
tool: "sessions_send",
|
|
985
1001
|
args: { sessionKey: target.sessionKey, message },
|
|
986
1002
|
timeoutMs: 5_000,
|
|
987
1003
|
}));
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "multiclaws",
|
|
3
|
-
"name": "MultiClaws",
|
|
4
|
-
"description": "MultiClaws plugin for multi-instance collaboration using A2A protocol",
|
|
5
|
-
"version": "0.3.0",
|
|
6
|
-
"skills": ["./skills/multiclaws"],
|
|
7
|
-
"configSchema": {
|
|
8
|
-
"type": "object",
|
|
9
|
-
"additionalProperties": false,
|
|
10
|
-
"properties": {
|
|
11
|
-
"port": {
|
|
12
|
-
"type": "integer",
|
|
13
|
-
"minimum": 1,
|
|
14
|
-
"maximum": 65535,
|
|
15
|
-
"default": 3100
|
|
16
|
-
},
|
|
17
|
-
"displayName": {
|
|
18
|
-
"type": "string",
|
|
19
|
-
"minLength": 1
|
|
20
|
-
},
|
|
21
|
-
"selfUrl": {
|
|
22
|
-
"type": "string",
|
|
23
|
-
"description": "Publicly reachable URL for this agent. If not set, tunnel configuration is required."
|
|
24
|
-
},
|
|
25
|
-
"tunnel": {
|
|
26
|
-
"type": "object",
|
|
27
|
-
"description": "FRP tunnel configuration for cross-network connectivity. Required if selfUrl is not set.",
|
|
28
|
-
"properties": {
|
|
29
|
-
"type": { "type": "string", "enum": ["frp"] },
|
|
30
|
-
"serverAddr": { "type": "string", "description": "FRP server address (IP or domain)" },
|
|
31
|
-
"serverPort": { "type": "integer", "default": 7000, "description": "FRP server bind port" },
|
|
32
|
-
"token": { "type": "string", "description": "FRP authentication token" },
|
|
33
|
-
"portRangeStart": { "type": "integer", "description": "Start of available remote port range" },
|
|
34
|
-
"portRangeEnd": { "type": "integer", "description": "End of available remote port range (inclusive)" }
|
|
35
|
-
},
|
|
36
|
-
"required": ["type", "serverAddr", "serverPort", "token", "portRangeStart", "portRangeEnd"]
|
|
37
|
-
},
|
|
38
|
-
"telemetry": {
|
|
39
|
-
"type": "object",
|
|
40
|
-
"additionalProperties": false,
|
|
41
|
-
"properties": {
|
|
42
|
-
"consoleExporter": { "type": "boolean", "default": false }
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "multiclaws",
|
|
3
|
+
"name": "MultiClaws",
|
|
4
|
+
"description": "MultiClaws plugin for multi-instance collaboration using A2A protocol",
|
|
5
|
+
"version": "0.3.0",
|
|
6
|
+
"skills": ["./skills/multiclaws", "./skills/meeting-scheduler"],
|
|
7
|
+
"configSchema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"additionalProperties": false,
|
|
10
|
+
"properties": {
|
|
11
|
+
"port": {
|
|
12
|
+
"type": "integer",
|
|
13
|
+
"minimum": 1,
|
|
14
|
+
"maximum": 65535,
|
|
15
|
+
"default": 3100
|
|
16
|
+
},
|
|
17
|
+
"displayName": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1
|
|
20
|
+
},
|
|
21
|
+
"selfUrl": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Publicly reachable URL for this agent. If not set, tunnel configuration is required."
|
|
24
|
+
},
|
|
25
|
+
"tunnel": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"description": "FRP tunnel configuration for cross-network connectivity. Required if selfUrl is not set.",
|
|
28
|
+
"properties": {
|
|
29
|
+
"type": { "type": "string", "enum": ["frp"] },
|
|
30
|
+
"serverAddr": { "type": "string", "description": "FRP server address (IP or domain)" },
|
|
31
|
+
"serverPort": { "type": "integer", "default": 7000, "description": "FRP server bind port" },
|
|
32
|
+
"token": { "type": "string", "description": "FRP authentication token" },
|
|
33
|
+
"portRangeStart": { "type": "integer", "description": "Start of available remote port range" },
|
|
34
|
+
"portRangeEnd": { "type": "integer", "description": "End of available remote port range (inclusive)" }
|
|
35
|
+
},
|
|
36
|
+
"required": ["type", "serverAddr", "serverPort", "token", "portRangeStart", "portRangeEnd"]
|
|
37
|
+
},
|
|
38
|
+
"telemetry": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"properties": {
|
|
42
|
+
"consoleExporter": { "type": "boolean", "default": false }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "multiclaws",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "MultiClaws plugin for OpenClaw collaboration via A2A protocol",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"openclaw": {
|
|
8
|
-
"extensions": [
|
|
9
|
-
"./dist/index.js"
|
|
10
|
-
]
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"dist",
|
|
14
|
-
"skills",
|
|
15
|
-
"openclaw.plugin.json",
|
|
16
|
-
"README.md"
|
|
17
|
-
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsc -p tsconfig.json",
|
|
20
|
-
"test": "vitest run",
|
|
21
|
-
"test:watch": "vitest",
|
|
22
|
-
"clean": "rm -rf dist"
|
|
23
|
-
},
|
|
24
|
-
"keywords": [
|
|
25
|
-
"openclaw",
|
|
26
|
-
"plugin",
|
|
27
|
-
"multiclaws",
|
|
28
|
-
"a2a",
|
|
29
|
-
"collaboration"
|
|
30
|
-
],
|
|
31
|
-
"author": "Eric Sun",
|
|
32
|
-
"license": "MIT",
|
|
33
|
-
"repository": {
|
|
34
|
-
"type": "git",
|
|
35
|
-
"url": "https://github.com/EricSun0218/multiclaws.git"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"@a2a-js/sdk": "^0.3.10",
|
|
39
|
-
"@opentelemetry/api": "^1.9.0",
|
|
40
|
-
"@opentelemetry/sdk-trace-base": "^2.6.0",
|
|
41
|
-
"@opentelemetry/sdk-trace-node": "^2.6.0",
|
|
42
|
-
"express": "^5.2.1",
|
|
43
|
-
"opossum": "^9.0.0",
|
|
44
|
-
"p-retry": "^7.1.1",
|
|
45
|
-
"proper-lockfile": "^4.1.2",
|
|
46
|
-
"zod": "^4.3.6"
|
|
47
|
-
},
|
|
48
|
-
"devDependencies": {
|
|
49
|
-
"@types/express": "^5.0.6",
|
|
50
|
-
"@types/node": "^24.3.0",
|
|
51
|
-
"@types/opossum": "^8.1.9",
|
|
52
|
-
"@types/proper-lockfile": "^4.1.4",
|
|
53
|
-
"typescript": "^5.9.2",
|
|
54
|
-
"vitest": "^3.2.4"
|
|
55
|
-
}
|
|
56
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "multiclaws",
|
|
3
|
+
"version": "0.4.37",
|
|
4
|
+
"description": "MultiClaws plugin for OpenClaw collaboration via A2A protocol",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"openclaw": {
|
|
8
|
+
"extensions": [
|
|
9
|
+
"./dist/index.js"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"skills",
|
|
15
|
+
"openclaw.plugin.json",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.json",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"clean": "rm -rf dist"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"openclaw",
|
|
26
|
+
"plugin",
|
|
27
|
+
"multiclaws",
|
|
28
|
+
"a2a",
|
|
29
|
+
"collaboration"
|
|
30
|
+
],
|
|
31
|
+
"author": "Eric Sun",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/EricSun0218/multiclaws.git"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@a2a-js/sdk": "^0.3.10",
|
|
39
|
+
"@opentelemetry/api": "^1.9.0",
|
|
40
|
+
"@opentelemetry/sdk-trace-base": "^2.6.0",
|
|
41
|
+
"@opentelemetry/sdk-trace-node": "^2.6.0",
|
|
42
|
+
"express": "^5.2.1",
|
|
43
|
+
"opossum": "^9.0.0",
|
|
44
|
+
"p-retry": "^7.1.1",
|
|
45
|
+
"proper-lockfile": "^4.1.2",
|
|
46
|
+
"zod": "^4.3.6"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/express": "^5.0.6",
|
|
50
|
+
"@types/node": "^24.3.0",
|
|
51
|
+
"@types/opossum": "^8.1.9",
|
|
52
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
53
|
+
"typescript": "^5.9.2",
|
|
54
|
+
"vitest": "^3.2.4"
|
|
55
|
+
}
|
|
56
|
+
}
|