multiclaws 0.3.0
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 +36 -0
- package/README.zh-CN.md +36 -0
- package/dist/gateway/handlers.d.ts +3 -0
- package/dist/gateway/handlers.js +172 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +446 -0
- package/dist/infra/gateway-client.d.ts +27 -0
- package/dist/infra/gateway-client.js +136 -0
- package/dist/infra/json-store.d.ts +4 -0
- package/dist/infra/json-store.js +57 -0
- package/dist/infra/logger.d.ts +13 -0
- package/dist/infra/logger.js +18 -0
- package/dist/infra/rate-limiter.d.ts +19 -0
- package/dist/infra/rate-limiter.js +69 -0
- package/dist/infra/tailscale.d.ts +19 -0
- package/dist/infra/tailscale.js +120 -0
- package/dist/infra/telemetry.d.ts +3 -0
- package/dist/infra/telemetry.js +17 -0
- package/dist/service/a2a-adapter.d.ts +44 -0
- package/dist/service/a2a-adapter.js +208 -0
- package/dist/service/agent-profile.d.ts +13 -0
- package/dist/service/agent-profile.js +38 -0
- package/dist/service/agent-registry.d.ts +26 -0
- package/dist/service/agent-registry.js +100 -0
- package/dist/service/multiclaws-service.d.ts +88 -0
- package/dist/service/multiclaws-service.js +708 -0
- package/dist/task/tracker.d.ts +43 -0
- package/dist/task/tracker.js +186 -0
- package/dist/team/team-store.d.ts +39 -0
- package/dist/team/team-store.js +146 -0
- package/dist/types/openclaw.d.ts +86 -0
- package/dist/types/openclaw.js +2 -0
- package/openclaw.plugin.json +34 -0
- package/package.json +56 -0
- package/skills/multiclaws/SKILL.md +164 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# MultiClaws
|
|
2
|
+
|
|
3
|
+
让多个 OpenClaw 实例通过 [A2A 协议](https://google.github.io/A2A/) 组成团队、互相委派任务。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
对你的 AI 说:
|
|
8
|
+
|
|
9
|
+
> 请运行 `openclaw plugin install multiclaws`,安装完成后告诉我你能做什么
|
|
10
|
+
|
|
11
|
+
AI 会自动完成安装、配置和档案生成,无需手动修改任何文件。
|
|
12
|
+
|
|
13
|
+
## 使用
|
|
14
|
+
|
|
15
|
+
一切通过自然语言完成:
|
|
16
|
+
|
|
17
|
+
- **「创建一个叫 my-team 的团队」** — 创建团队并获取邀请码
|
|
18
|
+
- **「用邀请码 mc:xxxxx 加入团队」** — 加入队友的团队
|
|
19
|
+
- **「让 Bob 总结一下最新报告」** — 把任务委派给队友的 AI
|
|
20
|
+
- **「显示所有智能体」** — 查看团队成员及其能力
|
|
21
|
+
|
|
22
|
+
## 跨网络
|
|
23
|
+
|
|
24
|
+
同局域网开箱即用。不同网络安装 [Tailscale](https://tailscale.com/download),插件自动检测。
|
|
25
|
+
|
|
26
|
+
## 详细文档
|
|
27
|
+
|
|
28
|
+
见 [SKILL.md](skills/multiclaws/SKILL.md)。
|
|
29
|
+
|
|
30
|
+
## 开发
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm install
|
|
34
|
+
pnpm run build
|
|
35
|
+
pnpm test
|
|
36
|
+
```
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# MultiClaws
|
|
2
|
+
|
|
3
|
+
让多个 OpenClaw 实例通过 [A2A 协议](https://google.github.io/A2A/) 组成团队、互相委派任务。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
对你的 AI 说:
|
|
8
|
+
|
|
9
|
+
> 请运行 `openclaw plugin install multiclaws`,安装完成后告诉我你能做什么
|
|
10
|
+
|
|
11
|
+
AI 会自动完成安装、配置和档案生成,无需手动修改任何文件。
|
|
12
|
+
|
|
13
|
+
## 使用
|
|
14
|
+
|
|
15
|
+
一切通过自然语言完成:
|
|
16
|
+
|
|
17
|
+
- **「创建一个叫 my-team 的团队」** — 创建团队并获取邀请码
|
|
18
|
+
- **「用邀请码 mc:xxxxx 加入团队」** — 加入队友的团队
|
|
19
|
+
- **「让 Bob 总结一下最新报告」** — 把任务委派给队友的 AI
|
|
20
|
+
- **「显示所有智能体」** — 查看团队成员及其能力
|
|
21
|
+
|
|
22
|
+
## 跨网络
|
|
23
|
+
|
|
24
|
+
同局域网开箱即用。不同网络安装 [Tailscale](https://tailscale.com/download),插件自动检测。
|
|
25
|
+
|
|
26
|
+
## 详细文档
|
|
27
|
+
|
|
28
|
+
见 [SKILL.md](skills/multiclaws/SKILL.md)。
|
|
29
|
+
|
|
30
|
+
## 开发
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm install
|
|
34
|
+
pnpm run build
|
|
35
|
+
pnpm test
|
|
36
|
+
```
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createGatewayHandlers = createGatewayHandlers;
|
|
4
|
+
const zod_1 = require("zod");
|
|
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
|
+
const agentRemoveSchema = zod_1.z.object({ url: nonEmptyString });
|
|
11
|
+
const taskDelegateSchema = zod_1.z.object({
|
|
12
|
+
agentUrl: nonEmptyString,
|
|
13
|
+
task: nonEmptyString,
|
|
14
|
+
});
|
|
15
|
+
const taskStatusSchema = zod_1.z.object({ taskId: nonEmptyString });
|
|
16
|
+
const profileSetSchema = zod_1.z.object({
|
|
17
|
+
ownerName: zod_1.z.string().trim().optional(),
|
|
18
|
+
bio: zod_1.z.string().optional(),
|
|
19
|
+
});
|
|
20
|
+
const teamCreateSchema = zod_1.z.object({ name: nonEmptyString });
|
|
21
|
+
const teamJoinSchema = zod_1.z.object({ inviteCode: nonEmptyString });
|
|
22
|
+
const teamLeaveSchema = zod_1.z.object({ teamId: zod_1.z.string().trim().min(1).optional() });
|
|
23
|
+
const teamMembersSchema = zod_1.z.object({ teamId: zod_1.z.string().trim().min(1).optional() });
|
|
24
|
+
function safeHandle(respond, code, error) {
|
|
25
|
+
respond(false, undefined, {
|
|
26
|
+
code,
|
|
27
|
+
message: error instanceof Error ? error.message : String(error),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function createGatewayHandlers(getService) {
|
|
31
|
+
const handlers = {
|
|
32
|
+
/* ── Agent handlers ─────────────────────────────────────────── */
|
|
33
|
+
"multiclaws.agent.list": async ({ respond }) => {
|
|
34
|
+
const service = getService();
|
|
35
|
+
const agents = await service.listAgents();
|
|
36
|
+
respond(true, { agents });
|
|
37
|
+
},
|
|
38
|
+
"multiclaws.agent.add": async ({ params, respond }) => {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = agentAddSchema.parse(params);
|
|
41
|
+
const service = getService();
|
|
42
|
+
const agent = await service.addAgent(parsed);
|
|
43
|
+
respond(true, agent);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
safeHandle(respond, "invalid_params", error);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"multiclaws.agent.remove": async ({ params, respond }) => {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = agentRemoveSchema.parse(params);
|
|
52
|
+
const service = getService();
|
|
53
|
+
const removed = await service.removeAgent(parsed.url);
|
|
54
|
+
respond(true, { removed });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
safeHandle(respond, "invalid_params", error);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
/* ── Task handlers ──────────────────────────────────────────── */
|
|
61
|
+
"multiclaws.task.delegate": async ({ params, respond }) => {
|
|
62
|
+
try {
|
|
63
|
+
const parsed = taskDelegateSchema.parse(params);
|
|
64
|
+
const service = getService();
|
|
65
|
+
const result = await service.delegateTask(parsed);
|
|
66
|
+
respond(true, result);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
safeHandle(respond, "task_delegate_failed", error);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"multiclaws.task.status": async ({ params, respond }) => {
|
|
73
|
+
try {
|
|
74
|
+
const parsed = taskStatusSchema.parse(params);
|
|
75
|
+
const service = getService();
|
|
76
|
+
const task = service.getTaskStatus(parsed.taskId);
|
|
77
|
+
if (!task) {
|
|
78
|
+
respond(false, undefined, {
|
|
79
|
+
code: "not_found",
|
|
80
|
+
message: `task not found: ${parsed.taskId}`,
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
respond(true, { task });
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
safeHandle(respond, "task_status_failed", error);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
/* ── Team handlers ──────────────────────────────────────────── */
|
|
91
|
+
"multiclaws.team.create": async ({ params, respond }) => {
|
|
92
|
+
try {
|
|
93
|
+
const parsed = teamCreateSchema.parse(params);
|
|
94
|
+
const service = getService();
|
|
95
|
+
const team = await service.createTeam(parsed.name);
|
|
96
|
+
const invite = await service.createInvite(team.teamId);
|
|
97
|
+
respond(true, { team, inviteCode: invite });
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
safeHandle(respond, "team_create_failed", error);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"multiclaws.team.join": async ({ params, respond }) => {
|
|
104
|
+
try {
|
|
105
|
+
const parsed = teamJoinSchema.parse(params);
|
|
106
|
+
const service = getService();
|
|
107
|
+
const team = await service.joinTeam(parsed.inviteCode);
|
|
108
|
+
respond(true, { team });
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
safeHandle(respond, "team_join_failed", error);
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"multiclaws.team.leave": async ({ params, respond }) => {
|
|
115
|
+
try {
|
|
116
|
+
const parsed = teamLeaveSchema.parse(params);
|
|
117
|
+
const service = getService();
|
|
118
|
+
await service.leaveTeam(parsed.teamId || undefined);
|
|
119
|
+
respond(true, { left: true });
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
safeHandle(respond, "team_leave_failed", error);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"multiclaws.team.members": async ({ params, respond }) => {
|
|
126
|
+
try {
|
|
127
|
+
const parsed = teamMembersSchema.parse(params);
|
|
128
|
+
const service = getService();
|
|
129
|
+
const result = await service.listTeamMembers(parsed.teamId || undefined);
|
|
130
|
+
if (!result) {
|
|
131
|
+
respond(false, undefined, {
|
|
132
|
+
code: "not_found",
|
|
133
|
+
message: "no team found",
|
|
134
|
+
});
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
respond(true, result);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
safeHandle(respond, "team_members_failed", error);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
/* ── Profile handlers ───────────────────────────────────────── */
|
|
144
|
+
"multiclaws.profile.show": async ({ respond }) => {
|
|
145
|
+
const service = getService();
|
|
146
|
+
const profile = await service.getProfile();
|
|
147
|
+
respond(true, profile);
|
|
148
|
+
},
|
|
149
|
+
"multiclaws.profile.pending_review": async ({ respond }) => {
|
|
150
|
+
const service = getService();
|
|
151
|
+
const result = await service.getPendingProfileReview();
|
|
152
|
+
respond(true, result);
|
|
153
|
+
},
|
|
154
|
+
"multiclaws.profile.clear_pending_review": async ({ respond }) => {
|
|
155
|
+
const service = getService();
|
|
156
|
+
await service.clearPendingProfileReview();
|
|
157
|
+
respond(true, { cleared: true });
|
|
158
|
+
},
|
|
159
|
+
"multiclaws.profile.set": async ({ params, respond }) => {
|
|
160
|
+
try {
|
|
161
|
+
const parsed = profileSetSchema.parse(params);
|
|
162
|
+
const service = getService();
|
|
163
|
+
const profile = await service.setProfile(parsed);
|
|
164
|
+
respond(true, profile);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
safeHandle(respond, "profile_set_failed", error);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
return handlers;
|
|
172
|
+
}
|