multiclaws 0.4.3 → 0.4.5

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.
@@ -3,10 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createGatewayHandlers = createGatewayHandlers;
4
4
  const zod_1 = require("zod");
5
5
  const nonEmptyString = zod_1.z.string().trim().min(1);
6
- const agentAddSchema = zod_1.z.object({
7
- url: nonEmptyString,
8
- apiKey: zod_1.z.string().trim().min(1).optional(),
9
- });
10
6
  const agentRemoveSchema = zod_1.z.object({ url: nonEmptyString });
11
7
  const sessionStartSchema = zod_1.z.object({
12
8
  agentUrl: nonEmptyString,
@@ -49,17 +45,6 @@ function createGatewayHandlers(getService) {
49
45
  safeHandle(respond, "agent_list_failed", error);
50
46
  }
51
47
  },
52
- "multiclaws.agent.add": async ({ params, respond }) => {
53
- try {
54
- const parsed = agentAddSchema.parse(params);
55
- const service = getService();
56
- const agent = await service.addAgent(parsed);
57
- respond(true, agent);
58
- }
59
- catch (error) {
60
- safeHandle(respond, "invalid_params", error);
61
- }
62
- },
63
48
  "multiclaws.agent.remove": async ({ params, respond }) => {
64
49
  try {
65
50
  const parsed = agentRemoveSchema.parse(params);
package/dist/index.js CHANGED
@@ -45,31 +45,6 @@ function createTools(getService) {
45
45
  return textResult(JSON.stringify({ agents }, null, 2), { agents });
46
46
  },
47
47
  };
48
- const multiclawsAddAgent = {
49
- name: "multiclaws_add_agent",
50
- description: "Add a remote A2A agent by URL. Automatically fetches its Agent Card.",
51
- parameters: {
52
- type: "object",
53
- additionalProperties: false,
54
- properties: {
55
- url: { type: "string" },
56
- apiKey: { type: "string" },
57
- },
58
- required: ["url"],
59
- },
60
- execute: async (_toolCallId, args) => {
61
- const service = requireService(getService());
62
- const url = typeof args.url === "string" ? args.url.trim() : "";
63
- if (!url)
64
- throw new Error("url is required");
65
- const apiKey = typeof args.apiKey === "string" ? args.apiKey.trim() : undefined;
66
- const agent = await service.addAgent({ url, apiKey });
67
- const status = agent.reachable
68
- ? `Agent added: ${agent.name} (${agent.url})`
69
- : `⚠️ Agent added but NOT reachable: ${agent.url} — agent card could not be fetched. Verify the URL and ensure the agent is running.`;
70
- return textResult(status, agent);
71
- },
72
- };
73
48
  const multiclawsRemoveAgent = {
74
49
  name: "multiclaws_remove_agent",
75
50
  description: "Remove a known A2A agent by URL.",
@@ -349,7 +324,6 @@ function createTools(getService) {
349
324
  };
350
325
  return [
351
326
  multiclawsAgents,
352
- multiclawsAddAgent,
353
327
  multiclawsRemoveAgent,
354
328
  multiclawsSessionStart,
355
329
  multiclawsSessionReply,
@@ -375,19 +349,34 @@ const plugin = {
375
349
  (0, telemetry_1.initializeTelemetry)({ enableConsoleExporter: config.telemetry?.consoleExporter });
376
350
  const structured = (0, logger_1.createStructuredLogger)(api.logger, "multiclaws");
377
351
  let service = null;
378
- // Ensure required tools are in gateway.tools.allow at registration time
379
- // so the gateway starts with them already present (no restart needed).
352
+ // Ensure plugin tools and gateway dependencies are whitelisted at registration time.
353
+ // tools.alsoAllow is additive and won't override the user's tools.profile setting.
380
354
  if (api.config) {
381
355
  const gw = api.config.gateway;
382
356
  if (gw) {
383
357
  const tools = (gw.tools ?? {});
358
+ // 1. Gateway tools the plugin depends on → tools.allow
384
359
  const allow = Array.isArray(tools.allow) ? tools.allow : [];
385
- const required = ["sessions_spawn", "sessions_history", "message"];
386
- const missing = required.filter((t) => !allow.includes(t));
387
- if (missing.length > 0) {
388
- tools.allow = [...allow, ...missing];
389
- gw.tools = tools;
360
+ const requiredGatewayTools = ["sessions_spawn", "sessions_history", "message"];
361
+ const missingGateway = requiredGatewayTools.filter((t) => !allow.includes(t));
362
+ if (missingGateway.length > 0) {
363
+ tools.allow = [...allow, ...missingGateway];
390
364
  }
365
+ // 2. Plugin's own tools → tools.alsoAllow (additive, works with any profile)
366
+ const alsoAllow = Array.isArray(tools.alsoAllow) ? tools.alsoAllow : [];
367
+ const pluginToolNames = [
368
+ "multiclaws_agents", "multiclaws_remove_agent",
369
+ "multiclaws_session_start", "multiclaws_session_reply", "multiclaws_session_status",
370
+ "multiclaws_session_wait_all", "multiclaws_session_end",
371
+ "multiclaws_team_create", "multiclaws_team_join", "multiclaws_team_leave", "multiclaws_team_members",
372
+ "multiclaws_profile_set", "multiclaws_profile_show",
373
+ "multiclaws_profile_pending_review", "multiclaws_profile_clear_pending_review",
374
+ ];
375
+ const missingPlugin = pluginToolNames.filter((t) => !alsoAllow.includes(t));
376
+ if (missingPlugin.length > 0) {
377
+ tools.alsoAllow = [...alsoAllow, ...missingPlugin];
378
+ }
379
+ gw.tools = tools;
391
380
  }
392
381
  }
393
382
  const gatewayConfig = (() => {
@@ -466,7 +455,8 @@ const plugin = {
466
455
  return {
467
456
  appendSystemContext: `## MultiClaws 首次安装 — 需要完成档案设置
468
457
 
469
- multiclaws 插件刚安装,需要在本次对话中完成以下初始化流程(优先处理,不管用户说了什么):
458
+ multiclaws 插件刚安装,需要在本次对话中完成以下初始化流程(优先处理,不管用户说了什么)。
459
+ **务必使用插件工具调用,不要通过命令行或 gateway 方法操作。**
470
460
 
471
461
  1. **扫描当前环境**,自动生成 bio(markdown 格式),内容包括:
472
462
  - 用户角色和职责
@@ -479,9 +469,7 @@ multiclaws 插件刚安装,需要在本次对话中完成以下初始化流程
479
469
  - **Bio**:展示生成的 bio,询问是否需要修改
480
470
  - **网络情况**:告知用户「同局域网开箱即用;跨网络需安装 Tailscale(https://tailscale.com/download)并重启 OpenClaw」,无需用户回答
481
471
 
482
- 3. 根据用户对名字和 bio 的回答更新档案内容(如需修改),然后调用 \`multiclaws_profile_set(ownerName="...", bio="...")\` 保存。
483
-
484
- 4. 调用 \`multiclaws_profile_clear_pending_review()\` 完成初始化。
472
+ 3. 根据用户确认的内容,调用 \`multiclaws_profile_set(ownerName="...", bio="...")\` 保存。保存后初始化自动完成,无需额外操作。
485
473
 
486
474
  **注意**:名字和 bio 需要用户明确确认;网络情况仅告知无需回答。`,
487
475
  };
@@ -50,12 +50,6 @@ export declare class MulticlawsService extends EventEmitter {
50
50
  stop(): Promise<void>;
51
51
  updateGatewayConfig(config: GatewayConfig): void;
52
52
  listAgents(): Promise<AgentRecord[]>;
53
- addAgent(params: {
54
- url: string;
55
- apiKey?: string;
56
- }): Promise<AgentRecord & {
57
- reachable: boolean;
58
- }>;
59
53
  removeAgent(url: string): Promise<boolean>;
60
54
  startSession(params: {
61
55
  agentUrl: string;
@@ -91,6 +85,7 @@ export declare class MulticlawsService extends EventEmitter {
91
85
  ownerName?: string;
92
86
  bio?: string;
93
87
  }): Promise<AgentProfile>;
88
+ private autoClearPendingReviewIfReady;
94
89
  private updateProfileDescription;
95
90
  private getPendingReviewPath;
96
91
  getPendingProfileReview(): Promise<{
@@ -196,30 +196,6 @@ class MulticlawsService extends node_events_1.EventEmitter {
196
196
  async listAgents() {
197
197
  return await this.agentRegistry.list();
198
198
  }
199
- async addAgent(params) {
200
- const normalizedUrl = params.url.replace(/\/+$/, "");
201
- try {
202
- const client = await this.clientFactory.createFromUrl(normalizedUrl);
203
- const card = await client.getAgentCard();
204
- const record = await this.agentRegistry.add({
205
- url: normalizedUrl,
206
- name: card.name ?? normalizedUrl,
207
- description: card.description ?? "",
208
- skills: card.skills?.map((s) => s.name ?? s.id) ?? [],
209
- apiKey: params.apiKey,
210
- });
211
- return { ...record, reachable: true };
212
- }
213
- catch {
214
- this.log("warn", `agent at ${normalizedUrl} is not reachable, adding with limited info`);
215
- const record = await this.agentRegistry.add({
216
- url: normalizedUrl,
217
- name: normalizedUrl,
218
- apiKey: params.apiKey,
219
- });
220
- return { ...record, reachable: false };
221
- }
222
- }
223
199
  async removeAgent(url) {
224
200
  return await this.agentRegistry.remove(url);
225
201
  }
@@ -558,9 +534,20 @@ class MulticlawsService extends node_events_1.EventEmitter {
558
534
  async setProfile(patch) {
559
535
  const profile = await this.profileStore.update(patch);
560
536
  this.updateProfileDescription(profile);
537
+ // Auto-clear pending review once both ownerName and bio are filled
538
+ await this.autoClearPendingReviewIfReady(profile);
561
539
  await this.broadcastProfileToTeams();
562
540
  return profile;
563
541
  }
542
+ async autoClearPendingReviewIfReady(profile) {
543
+ if (profile.ownerName?.trim() && profile.bio?.trim()) {
544
+ const review = await this.getPendingProfileReview();
545
+ if (review.pending) {
546
+ await this.clearPendingProfileReview();
547
+ this.log("info", "pending profile review auto-cleared after profile update");
548
+ }
549
+ }
550
+ }
564
551
  updateProfileDescription(profile) {
565
552
  this.profileDescription = (0, agent_profile_1.renderProfileDescription)(profile);
566
553
  if (this.agentCard) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multiclaws",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "MultiClaws plugin for OpenClaw collaboration via A2A protocol",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -53,4 +53,4 @@
53
53
  "typescript": "^5.9.2",
54
54
  "vitest": "^3.2.4"
55
55
  }
56
- }
56
+ }
@@ -15,8 +15,9 @@ MultiClaws 让多个 OpenClaw 实例通过 [A2A(Agent-to-Agent)](https://goo
15
15
  - **名字**:询问是否需要修改(需用户明确回答)
16
16
  - **Bio**:询问是否需要修改(需用户明确回答)
17
17
  - **网络情况**:告知「同局域网开箱即用;跨网络需安装 Tailscale」,无需用户回答
18
- 3. 调用 `multiclaws_profile_set(ownerName="...", bio="...")` 保存
19
- 4. 调用 `multiclaws_profile_clear_pending_review()` 完成初始化
18
+ 3. 调用 `multiclaws_profile_set(ownerName="...", bio="...")` 保存(pending review 标记会自动清除,无需额外操作)
19
+
20
+ > **重要**:始终使用插件工具调用,不要通过命令行或 gateway 方法操作 MultiClaws。
20
21
 
21
22
  ---
22
23
 
@@ -131,13 +132,13 @@ multiclaws_profile_show()
131
132
  | 工具 | 说明 | 参数 |
132
133
  |------|------|------|
133
134
  | `multiclaws_agents` | 列出已知 agent 及 bio | — |
134
- | `multiclaws_add_agent` | 手动添加 agent | `url`, `apiKey`(可选) |
135
135
  | `multiclaws_remove_agent` | 移除 agent | `url` |
136
136
 
137
137
  ---
138
138
 
139
139
  ## 重要规则
140
140
 
141
+ - **始终使用插件工具调用**,不要通过命令行、shell 或 gateway 方法操作 MultiClaws
141
142
  - **不要问用户 IP 或 selfUrl**,插件自动处理
142
143
  - **Bio 是 markdown**,写得让另一个 AI 能读懂这个 agent 能做什么
143
144
  - **名字和 bio 必须用户明确确认**;网络情况仅告知