multiclaws 0.4.20 → 0.4.21
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/dist/gateway/handlers.d.ts +2 -1
- package/dist/gateway/handlers.js +63 -13
- package/dist/index.js +227 -83
- package/dist/infra/logger.d.ts +1 -0
- package/dist/infra/logger.js +7 -0
- package/dist/service/a2a-adapter.js +2 -0
- package/dist/service/agent-profile.d.ts +4 -1
- package/dist/service/agent-profile.js +30 -9
- package/dist/service/agent-registry.d.ts +4 -1
- package/dist/service/agent-registry.js +76 -45
- package/dist/service/multiclaws-service.d.ts +20 -0
- package/dist/service/multiclaws-service.js +487 -260
- package/dist/service/session-store.d.ts +3 -0
- package/dist/service/session-store.js +4 -1
- package/dist/task/tracker.d.ts +3 -0
- package/dist/task/tracker.js +6 -1
- package/dist/team/team-store.d.ts +4 -1
- package/dist/team/team-store.js +116 -67
- package/package.json +8 -8
- package/skills/multiclaws/SKILL.md +16 -80
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { GatewayRequestHandler } from "../types/openclaw";
|
|
2
2
|
import type { MulticlawsService } from "../service/multiclaws-service";
|
|
3
|
-
|
|
3
|
+
import type { BasicLogger } from "../infra/logger";
|
|
4
|
+
export declare function createGatewayHandlers(getService: () => MulticlawsService, logger?: BasicLogger): Record<string, GatewayRequestHandler>;
|
package/dist/gateway/handlers.js
CHANGED
|
@@ -27,15 +27,27 @@ function safeHandle(respond, code, error) {
|
|
|
27
27
|
message: error instanceof Error ? error.message : String(error),
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
-
function createGatewayHandlers(getService) {
|
|
30
|
+
function createGatewayHandlers(getService, logger) {
|
|
31
|
+
const log = (level, msg) => {
|
|
32
|
+
const fn = level === "debug" ? logger?.debug : logger?.[level];
|
|
33
|
+
fn?.(`[multiclaws:gw] ${msg}`);
|
|
34
|
+
};
|
|
31
35
|
const handlers = {
|
|
32
36
|
/* ── Agent handlers ─────────────────────────────────────────── */
|
|
33
37
|
"multiclaws.agent.list": async ({ respond }) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
log("debug", "agent.list");
|
|
39
|
+
try {
|
|
40
|
+
const service = getService();
|
|
41
|
+
const agents = await service.listAgents();
|
|
42
|
+
respond(true, { agents });
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
log("error", `agent.list failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
|
+
safeHandle(respond, "agent_list_failed", error);
|
|
47
|
+
}
|
|
37
48
|
},
|
|
38
49
|
"multiclaws.agent.add": async ({ params, respond }) => {
|
|
50
|
+
log("debug", `agent.add(url=${params?.url})`);
|
|
39
51
|
try {
|
|
40
52
|
const parsed = agentAddSchema.parse(params);
|
|
41
53
|
const service = getService();
|
|
@@ -43,10 +55,12 @@ function createGatewayHandlers(getService) {
|
|
|
43
55
|
respond(true, agent);
|
|
44
56
|
}
|
|
45
57
|
catch (error) {
|
|
58
|
+
log("error", `agent.add failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
59
|
safeHandle(respond, "invalid_params", error);
|
|
47
60
|
}
|
|
48
61
|
},
|
|
49
62
|
"multiclaws.agent.remove": async ({ params, respond }) => {
|
|
63
|
+
log("debug", `agent.remove(url=${params?.url})`);
|
|
50
64
|
try {
|
|
51
65
|
const parsed = agentRemoveSchema.parse(params);
|
|
52
66
|
const service = getService();
|
|
@@ -54,11 +68,13 @@ function createGatewayHandlers(getService) {
|
|
|
54
68
|
respond(true, { removed });
|
|
55
69
|
}
|
|
56
70
|
catch (error) {
|
|
71
|
+
log("error", `agent.remove failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
57
72
|
safeHandle(respond, "invalid_params", error);
|
|
58
73
|
}
|
|
59
74
|
},
|
|
60
75
|
/* ── Task handlers ──────────────────────────────────────────── */
|
|
61
76
|
"multiclaws.task.delegate": async ({ params, respond }) => {
|
|
77
|
+
log("debug", `task.delegate(agentUrl=${params?.agentUrl})`);
|
|
62
78
|
try {
|
|
63
79
|
const parsed = taskDelegateSchema.parse(params);
|
|
64
80
|
const service = getService();
|
|
@@ -66,10 +82,12 @@ function createGatewayHandlers(getService) {
|
|
|
66
82
|
respond(true, result);
|
|
67
83
|
}
|
|
68
84
|
catch (error) {
|
|
85
|
+
log("error", `task.delegate failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
69
86
|
safeHandle(respond, "task_delegate_failed", error);
|
|
70
87
|
}
|
|
71
88
|
},
|
|
72
89
|
"multiclaws.task.status": async ({ params, respond }) => {
|
|
90
|
+
log("debug", `task.status(taskId=${params?.taskId})`);
|
|
73
91
|
try {
|
|
74
92
|
const parsed = taskStatusSchema.parse(params);
|
|
75
93
|
const service = getService();
|
|
@@ -84,11 +102,13 @@ function createGatewayHandlers(getService) {
|
|
|
84
102
|
respond(true, { task });
|
|
85
103
|
}
|
|
86
104
|
catch (error) {
|
|
105
|
+
log("error", `task.status failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
87
106
|
safeHandle(respond, "task_status_failed", error);
|
|
88
107
|
}
|
|
89
108
|
},
|
|
90
109
|
/* ── Team handlers ──────────────────────────────────────────── */
|
|
91
110
|
"multiclaws.team.create": async ({ params, respond }) => {
|
|
111
|
+
log("debug", `team.create(name=${params?.name})`);
|
|
92
112
|
try {
|
|
93
113
|
const parsed = teamCreateSchema.parse(params);
|
|
94
114
|
const service = getService();
|
|
@@ -97,10 +117,12 @@ function createGatewayHandlers(getService) {
|
|
|
97
117
|
respond(true, { team, inviteCode: invite });
|
|
98
118
|
}
|
|
99
119
|
catch (error) {
|
|
120
|
+
log("error", `team.create failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
100
121
|
safeHandle(respond, "team_create_failed", error);
|
|
101
122
|
}
|
|
102
123
|
},
|
|
103
124
|
"multiclaws.team.join": async ({ params, respond }) => {
|
|
125
|
+
log("debug", "team.join");
|
|
104
126
|
try {
|
|
105
127
|
const parsed = teamJoinSchema.parse(params);
|
|
106
128
|
const service = getService();
|
|
@@ -108,10 +130,12 @@ function createGatewayHandlers(getService) {
|
|
|
108
130
|
respond(true, { team });
|
|
109
131
|
}
|
|
110
132
|
catch (error) {
|
|
133
|
+
log("error", `team.join failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
111
134
|
safeHandle(respond, "team_join_failed", error);
|
|
112
135
|
}
|
|
113
136
|
},
|
|
114
137
|
"multiclaws.team.leave": async ({ params, respond }) => {
|
|
138
|
+
log("debug", "team.leave");
|
|
115
139
|
try {
|
|
116
140
|
const parsed = teamLeaveSchema.parse(params);
|
|
117
141
|
const service = getService();
|
|
@@ -119,10 +143,12 @@ function createGatewayHandlers(getService) {
|
|
|
119
143
|
respond(true, { left: true });
|
|
120
144
|
}
|
|
121
145
|
catch (error) {
|
|
146
|
+
log("error", `team.leave failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
122
147
|
safeHandle(respond, "team_leave_failed", error);
|
|
123
148
|
}
|
|
124
149
|
},
|
|
125
150
|
"multiclaws.team.members": async ({ params, respond }) => {
|
|
151
|
+
log("debug", `team.members(teamId=${params?.teamId})`);
|
|
126
152
|
try {
|
|
127
153
|
const parsed = teamMembersSchema.parse(params);
|
|
128
154
|
const service = getService();
|
|
@@ -137,26 +163,49 @@ function createGatewayHandlers(getService) {
|
|
|
137
163
|
respond(true, result);
|
|
138
164
|
}
|
|
139
165
|
catch (error) {
|
|
166
|
+
log("error", `team.members failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
140
167
|
safeHandle(respond, "team_members_failed", error);
|
|
141
168
|
}
|
|
142
169
|
},
|
|
143
170
|
/* ── Profile handlers ───────────────────────────────────────── */
|
|
144
171
|
"multiclaws.profile.show": async ({ respond }) => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
172
|
+
log("debug", "profile.show");
|
|
173
|
+
try {
|
|
174
|
+
const service = getService();
|
|
175
|
+
const profile = await service.getProfile();
|
|
176
|
+
respond(true, profile);
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
log("error", `profile.show failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
180
|
+
safeHandle(respond, "profile_show_failed", error);
|
|
181
|
+
}
|
|
148
182
|
},
|
|
149
183
|
"multiclaws.profile.pending_review": async ({ respond }) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
184
|
+
log("debug", "profile.pending_review");
|
|
185
|
+
try {
|
|
186
|
+
const service = getService();
|
|
187
|
+
const result = await service.getPendingProfileReview();
|
|
188
|
+
respond(true, result);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
log("error", `profile.pending_review failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
192
|
+
safeHandle(respond, "profile_pending_review_failed", error);
|
|
193
|
+
}
|
|
153
194
|
},
|
|
154
195
|
"multiclaws.profile.clear_pending_review": async ({ respond }) => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
196
|
+
log("debug", "profile.clear_pending_review");
|
|
197
|
+
try {
|
|
198
|
+
const service = getService();
|
|
199
|
+
await service.clearPendingProfileReview();
|
|
200
|
+
respond(true, { cleared: true });
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
log("error", `profile.clear_pending_review failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
204
|
+
safeHandle(respond, "profile_clear_pending_review_failed", error);
|
|
205
|
+
}
|
|
158
206
|
},
|
|
159
207
|
"multiclaws.profile.set": async ({ params, respond }) => {
|
|
208
|
+
log("debug", "profile.set");
|
|
160
209
|
try {
|
|
161
210
|
const parsed = profileSetSchema.parse(params);
|
|
162
211
|
const service = getService();
|
|
@@ -164,6 +213,7 @@ function createGatewayHandlers(getService) {
|
|
|
164
213
|
respond(true, profile);
|
|
165
214
|
}
|
|
166
215
|
catch (error) {
|
|
216
|
+
log("error", `profile.set failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
167
217
|
safeHandle(respond, "profile_set_failed", error);
|
|
168
218
|
}
|
|
169
219
|
},
|
package/dist/index.js
CHANGED
|
@@ -55,7 +55,11 @@ function requireService(service) {
|
|
|
55
55
|
}
|
|
56
56
|
return service;
|
|
57
57
|
}
|
|
58
|
-
function createTools(getService) {
|
|
58
|
+
function createTools(getService, logger) {
|
|
59
|
+
const log = (level, msg) => {
|
|
60
|
+
const fn = level === "debug" ? logger.debug : logger[level];
|
|
61
|
+
fn?.(`[multiclaws] ${msg}`);
|
|
62
|
+
};
|
|
59
63
|
/* ── Agent tools ──────────────────────────────────────────────── */
|
|
60
64
|
const multiclawsAgents = {
|
|
61
65
|
name: "multiclaws_agents",
|
|
@@ -66,9 +70,16 @@ function createTools(getService) {
|
|
|
66
70
|
properties: {},
|
|
67
71
|
},
|
|
68
72
|
execute: async () => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
log("debug", "tool:multiclaws_agents");
|
|
74
|
+
try {
|
|
75
|
+
const service = requireService(getService());
|
|
76
|
+
const agents = await service.listAgents();
|
|
77
|
+
return textResult(JSON.stringify({ agents }, null, 2), { agents });
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
log("error", `tool:multiclaws_agents failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
72
83
|
},
|
|
73
84
|
};
|
|
74
85
|
const multiclawsAddAgent = {
|
|
@@ -84,13 +95,20 @@ function createTools(getService) {
|
|
|
84
95
|
required: ["url"],
|
|
85
96
|
},
|
|
86
97
|
execute: async (_toolCallId, args) => {
|
|
87
|
-
const service = requireService(getService());
|
|
88
98
|
const url = typeof args.url === "string" ? args.url.trim() : "";
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
log("debug", `tool:multiclaws_add_agent(url=${url})`);
|
|
100
|
+
try {
|
|
101
|
+
const service = requireService(getService());
|
|
102
|
+
if (!url)
|
|
103
|
+
throw new Error("url is required");
|
|
104
|
+
const apiKey = typeof args.apiKey === "string" ? args.apiKey.trim() : undefined;
|
|
105
|
+
const agent = await service.addAgent({ url, apiKey });
|
|
106
|
+
return textResult(`Agent added: ${agent.name} (${agent.url})`, agent);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
log("error", `tool:multiclaws_add_agent failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
94
112
|
},
|
|
95
113
|
};
|
|
96
114
|
const multiclawsRemoveAgent = {
|
|
@@ -105,17 +123,26 @@ function createTools(getService) {
|
|
|
105
123
|
required: ["url"],
|
|
106
124
|
},
|
|
107
125
|
execute: async (_toolCallId, args) => {
|
|
108
|
-
const service = requireService(getService());
|
|
109
126
|
const url = typeof args.url === "string" ? args.url.trim() : "";
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
127
|
+
log("debug", `tool:multiclaws_remove_agent(url=${url})`);
|
|
128
|
+
try {
|
|
129
|
+
const service = requireService(getService());
|
|
130
|
+
if (!url)
|
|
131
|
+
throw new Error("url is required");
|
|
132
|
+
const removed = await service.removeAgent(url);
|
|
133
|
+
return textResult(removed ? `Agent ${url} removed.` : `Agent ${url} not found.`);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
log("error", `tool:multiclaws_remove_agent failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
114
139
|
},
|
|
115
140
|
};
|
|
116
141
|
const multiclawsDelegate = {
|
|
117
142
|
name: "multiclaws_delegate",
|
|
118
|
-
description: "Delegate a task to a remote A2A agent."
|
|
143
|
+
description: "Delegate a task to a remote A2A agent. " +
|
|
144
|
+
"Automatically spawns a sub-agent that sends the task, waits for the result, " +
|
|
145
|
+
"and reports back via the message tool. Returns immediately.",
|
|
119
146
|
parameters: {
|
|
120
147
|
type: "object",
|
|
121
148
|
additionalProperties: false,
|
|
@@ -126,13 +153,51 @@ function createTools(getService) {
|
|
|
126
153
|
required: ["agentUrl", "task"],
|
|
127
154
|
},
|
|
128
155
|
execute: async (_toolCallId, args) => {
|
|
129
|
-
const service = requireService(getService());
|
|
130
156
|
const agentUrl = typeof args.agentUrl === "string" ? args.agentUrl.trim() : "";
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
157
|
+
log("info", `tool:multiclaws_delegate(agentUrl=${agentUrl})`);
|
|
158
|
+
try {
|
|
159
|
+
const service = requireService(getService());
|
|
160
|
+
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
161
|
+
if (!agentUrl || !task)
|
|
162
|
+
throw new Error("agentUrl and task are required");
|
|
163
|
+
const result = await service.spawnDelegation({ agentUrl, task });
|
|
164
|
+
return textResult(result.message, result);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
log("error", `tool:multiclaws_delegate failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
const multiclawsDelegateSend = {
|
|
173
|
+
name: "multiclaws_delegate_send",
|
|
174
|
+
description: "Send a task to a remote A2A agent and wait for the result synchronously. " +
|
|
175
|
+
"Used internally by sub-agents spawned from multiclaws_delegate. " +
|
|
176
|
+
"Do NOT call this directly — use multiclaws_delegate instead.",
|
|
177
|
+
parameters: {
|
|
178
|
+
type: "object",
|
|
179
|
+
additionalProperties: false,
|
|
180
|
+
properties: {
|
|
181
|
+
agentUrl: { type: "string" },
|
|
182
|
+
task: { type: "string" },
|
|
183
|
+
},
|
|
184
|
+
required: ["agentUrl", "task"],
|
|
185
|
+
},
|
|
186
|
+
execute: async (_toolCallId, args) => {
|
|
187
|
+
const agentUrl = typeof args.agentUrl === "string" ? args.agentUrl.trim() : "";
|
|
188
|
+
log("info", `tool:multiclaws_delegate_send(agentUrl=${agentUrl})`);
|
|
189
|
+
try {
|
|
190
|
+
const service = requireService(getService());
|
|
191
|
+
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
192
|
+
if (!agentUrl || !task)
|
|
193
|
+
throw new Error("agentUrl and task are required");
|
|
194
|
+
const result = await service.delegateTaskSync({ agentUrl, task });
|
|
195
|
+
return textResult(JSON.stringify(result, null, 2), result);
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
log("error", `tool:multiclaws_delegate_send failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
199
|
+
throw err;
|
|
200
|
+
}
|
|
136
201
|
},
|
|
137
202
|
};
|
|
138
203
|
const multiclawsTaskStatus = {
|
|
@@ -147,14 +212,21 @@ function createTools(getService) {
|
|
|
147
212
|
required: ["taskId"],
|
|
148
213
|
},
|
|
149
214
|
execute: async (_toolCallId, args) => {
|
|
150
|
-
const service = requireService(getService());
|
|
151
215
|
const taskId = typeof args.taskId === "string" ? args.taskId.trim() : "";
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
216
|
+
log("debug", `tool:multiclaws_task_status(taskId=${taskId})`);
|
|
217
|
+
try {
|
|
218
|
+
const service = requireService(getService());
|
|
219
|
+
if (!taskId)
|
|
220
|
+
throw new Error("taskId is required");
|
|
221
|
+
const task = service.getTaskStatus(taskId);
|
|
222
|
+
if (!task)
|
|
223
|
+
throw new Error(`task not found: ${taskId}`);
|
|
224
|
+
return textResult(JSON.stringify(task, null, 2), task);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
log("error", `tool:multiclaws_task_status failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
228
|
+
throw err;
|
|
229
|
+
}
|
|
158
230
|
},
|
|
159
231
|
};
|
|
160
232
|
/* ── Team tools ───────────────────────────────────────────────── */
|
|
@@ -170,13 +242,20 @@ function createTools(getService) {
|
|
|
170
242
|
required: ["name"],
|
|
171
243
|
},
|
|
172
244
|
execute: async (_toolCallId, args) => {
|
|
173
|
-
const service = requireService(getService());
|
|
174
245
|
const name = typeof args.name === "string" ? args.name.trim() : "";
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
246
|
+
log("info", `tool:multiclaws_team_create(name=${name})`);
|
|
247
|
+
try {
|
|
248
|
+
const service = requireService(getService());
|
|
249
|
+
if (!name)
|
|
250
|
+
throw new Error("name is required");
|
|
251
|
+
const team = await service.createTeam(name);
|
|
252
|
+
const invite = await service.createInvite(team.teamId);
|
|
253
|
+
return textResult(`Team "${team.teamName}" created (${team.teamId}).\nInvite code: ${invite}\n\n⚠️ 请只将邀请码分享给完全信任的用户。持有邀请码的人可以加入团队并向你的 AI 委派任务。权限管理模块正在开发中。`, { team, inviteCode: invite });
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
log("error", `tool:multiclaws_team_create failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
180
259
|
},
|
|
181
260
|
};
|
|
182
261
|
const multiclawsTeamJoin = {
|
|
@@ -191,13 +270,20 @@ function createTools(getService) {
|
|
|
191
270
|
required: ["inviteCode"],
|
|
192
271
|
},
|
|
193
272
|
execute: async (_toolCallId, args) => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
273
|
+
log("info", "tool:multiclaws_team_join");
|
|
274
|
+
try {
|
|
275
|
+
const service = requireService(getService());
|
|
276
|
+
const inviteCode = typeof args.inviteCode === "string" ? args.inviteCode.trim() : "";
|
|
277
|
+
if (!inviteCode)
|
|
278
|
+
throw new Error("inviteCode is required");
|
|
279
|
+
const team = await service.joinTeam(inviteCode);
|
|
280
|
+
const memberNames = team.members.map((m) => m.name).join(", ");
|
|
281
|
+
return textResult(`Joined team "${team.teamName}" with ${team.members.length} members: ${memberNames}`, { team });
|
|
282
|
+
}
|
|
283
|
+
catch (err) {
|
|
284
|
+
log("error", `tool:multiclaws_team_join failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
285
|
+
throw err;
|
|
286
|
+
}
|
|
201
287
|
},
|
|
202
288
|
};
|
|
203
289
|
const multiclawsTeamLeave = {
|
|
@@ -211,10 +297,17 @@ function createTools(getService) {
|
|
|
211
297
|
},
|
|
212
298
|
},
|
|
213
299
|
execute: async (_toolCallId, args) => {
|
|
214
|
-
const service = requireService(getService());
|
|
215
300
|
const teamId = typeof args.teamId === "string" ? args.teamId.trim() : undefined;
|
|
216
|
-
|
|
217
|
-
|
|
301
|
+
log("info", `tool:multiclaws_team_leave(teamId=${teamId ?? "first"})`);
|
|
302
|
+
try {
|
|
303
|
+
const service = requireService(getService());
|
|
304
|
+
await service.leaveTeam(teamId || undefined);
|
|
305
|
+
return textResult("Left team successfully.");
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
log("error", `tool:multiclaws_team_leave failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
309
|
+
throw err;
|
|
310
|
+
}
|
|
218
311
|
},
|
|
219
312
|
};
|
|
220
313
|
const multiclawsTeamMembers = {
|
|
@@ -228,13 +321,20 @@ function createTools(getService) {
|
|
|
228
321
|
},
|
|
229
322
|
},
|
|
230
323
|
execute: async (_toolCallId, args) => {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
324
|
+
log("debug", "tool:multiclaws_team_members");
|
|
325
|
+
try {
|
|
326
|
+
const service = requireService(getService());
|
|
327
|
+
const teamId = typeof args.teamId === "string" ? args.teamId.trim() : undefined;
|
|
328
|
+
const result = await service.listTeamMembers(teamId || undefined);
|
|
329
|
+
if (!result) {
|
|
330
|
+
return textResult("No team found.");
|
|
331
|
+
}
|
|
332
|
+
return textResult(JSON.stringify(result, null, 2), result);
|
|
333
|
+
}
|
|
334
|
+
catch (err) {
|
|
335
|
+
log("error", `tool:multiclaws_team_members failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
336
|
+
throw err;
|
|
236
337
|
}
|
|
237
|
-
return textResult(JSON.stringify(result, null, 2), result);
|
|
238
338
|
},
|
|
239
339
|
};
|
|
240
340
|
/* ── Profile tools ──────────────────────────────────────────── */
|
|
@@ -250,14 +350,21 @@ function createTools(getService) {
|
|
|
250
350
|
},
|
|
251
351
|
},
|
|
252
352
|
execute: async (_toolCallId, args) => {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
patch
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
353
|
+
log("debug", "tool:multiclaws_profile_set");
|
|
354
|
+
try {
|
|
355
|
+
const service = requireService(getService());
|
|
356
|
+
const patch = {};
|
|
357
|
+
if (typeof args.ownerName === "string")
|
|
358
|
+
patch.ownerName = args.ownerName.trim();
|
|
359
|
+
if (typeof args.bio === "string")
|
|
360
|
+
patch.bio = args.bio;
|
|
361
|
+
const profile = await service.setProfile(patch);
|
|
362
|
+
return textResult(JSON.stringify(profile, null, 2), profile);
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
log("error", `tool:multiclaws_profile_set failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
366
|
+
throw err;
|
|
367
|
+
}
|
|
261
368
|
},
|
|
262
369
|
};
|
|
263
370
|
const multiclawsProfileShow = {
|
|
@@ -269,9 +376,16 @@ function createTools(getService) {
|
|
|
269
376
|
properties: {},
|
|
270
377
|
},
|
|
271
378
|
execute: async () => {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
379
|
+
log("debug", "tool:multiclaws_profile_show");
|
|
380
|
+
try {
|
|
381
|
+
const service = requireService(getService());
|
|
382
|
+
const profile = await service.getProfile();
|
|
383
|
+
return textResult(JSON.stringify(profile, null, 2), profile);
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
log("error", `tool:multiclaws_profile_show failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
387
|
+
throw err;
|
|
388
|
+
}
|
|
275
389
|
},
|
|
276
390
|
};
|
|
277
391
|
const multiclawsProfilePendingReview = {
|
|
@@ -283,9 +397,16 @@ function createTools(getService) {
|
|
|
283
397
|
properties: {},
|
|
284
398
|
},
|
|
285
399
|
execute: async () => {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
400
|
+
log("debug", "tool:multiclaws_profile_pending_review");
|
|
401
|
+
try {
|
|
402
|
+
const service = requireService(getService());
|
|
403
|
+
const result = await service.getPendingProfileReview();
|
|
404
|
+
return textResult(JSON.stringify(result, null, 2), result);
|
|
405
|
+
}
|
|
406
|
+
catch (err) {
|
|
407
|
+
log("error", `tool:multiclaws_profile_pending_review failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
408
|
+
throw err;
|
|
409
|
+
}
|
|
289
410
|
},
|
|
290
411
|
};
|
|
291
412
|
const multiclawsProfileClearPendingReview = {
|
|
@@ -297,9 +418,16 @@ function createTools(getService) {
|
|
|
297
418
|
properties: {},
|
|
298
419
|
},
|
|
299
420
|
execute: async () => {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
421
|
+
log("debug", "tool:multiclaws_profile_clear_pending_review");
|
|
422
|
+
try {
|
|
423
|
+
const service = requireService(getService());
|
|
424
|
+
await service.clearPendingProfileReview();
|
|
425
|
+
return textResult("Pending profile review cleared.");
|
|
426
|
+
}
|
|
427
|
+
catch (err) {
|
|
428
|
+
log("error", `tool:multiclaws_profile_clear_pending_review failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
429
|
+
throw err;
|
|
430
|
+
}
|
|
303
431
|
},
|
|
304
432
|
};
|
|
305
433
|
return [
|
|
@@ -307,6 +435,7 @@ function createTools(getService) {
|
|
|
307
435
|
multiclawsAddAgent,
|
|
308
436
|
multiclawsRemoveAgent,
|
|
309
437
|
multiclawsDelegate,
|
|
438
|
+
multiclawsDelegateSend,
|
|
310
439
|
multiclawsTaskStatus,
|
|
311
440
|
multiclawsTeamCreate,
|
|
312
441
|
multiclawsTeamJoin,
|
|
@@ -353,30 +482,45 @@ const plugin = {
|
|
|
353
482
|
const pluginService = {
|
|
354
483
|
id: "multiclaws-service",
|
|
355
484
|
start: async (ctx) => {
|
|
356
|
-
service
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
485
|
+
structured.logger.info("[multiclaws] service starting");
|
|
486
|
+
try {
|
|
487
|
+
service = new multiclaws_service_1.MulticlawsService({
|
|
488
|
+
stateDir: ctx.stateDir,
|
|
489
|
+
port: config.port,
|
|
490
|
+
displayName: config.displayName,
|
|
491
|
+
selfUrl: config.selfUrl,
|
|
492
|
+
tunnel: config.tunnel,
|
|
493
|
+
gatewayConfig: gatewayConfig ?? undefined,
|
|
494
|
+
logger: structured.logger,
|
|
495
|
+
});
|
|
496
|
+
await service.start();
|
|
497
|
+
}
|
|
498
|
+
catch (err) {
|
|
499
|
+
structured.logger.error(`[multiclaws] service start failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
500
|
+
throw err;
|
|
501
|
+
}
|
|
366
502
|
},
|
|
367
503
|
stop: async () => {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
service
|
|
504
|
+
structured.logger.info("[multiclaws] service stopping");
|
|
505
|
+
try {
|
|
506
|
+
if (service) {
|
|
507
|
+
await service.stop();
|
|
508
|
+
service = null;
|
|
509
|
+
}
|
|
510
|
+
structured.logger.info("[multiclaws] service stopped");
|
|
511
|
+
}
|
|
512
|
+
catch (err) {
|
|
513
|
+
structured.logger.error(`[multiclaws] service stop failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
514
|
+
throw err;
|
|
371
515
|
}
|
|
372
516
|
},
|
|
373
517
|
};
|
|
374
518
|
api.registerService(pluginService);
|
|
375
|
-
const gatewayHandlers = (0, handlers_1.createGatewayHandlers)(() => requireService(service));
|
|
519
|
+
const gatewayHandlers = (0, handlers_1.createGatewayHandlers)(() => requireService(service), structured.logger);
|
|
376
520
|
for (const [method, handler] of Object.entries(gatewayHandlers)) {
|
|
377
521
|
api.registerGatewayMethod(method, handler);
|
|
378
522
|
}
|
|
379
|
-
for (const tool of createTools(() => service)) {
|
|
523
|
+
for (const tool of createTools(() => service, structured.logger)) {
|
|
380
524
|
api.registerTool(tool);
|
|
381
525
|
}
|
|
382
526
|
api.registerHttpRoute({
|
package/dist/infra/logger.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type BasicLogger = {
|
|
|
4
4
|
error: (message: string) => void;
|
|
5
5
|
debug?: (message: string) => void;
|
|
6
6
|
};
|
|
7
|
+
export declare const noopLogger: BasicLogger;
|
|
7
8
|
/**
|
|
8
9
|
* Creates a structured logger that delegates to OpenClaw's base logger.
|
|
9
10
|
* Only outputs via baseLogger to avoid duplicate stdout writes.
|
package/dist/infra/logger.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noopLogger = void 0;
|
|
3
4
|
exports.createStructuredLogger = createStructuredLogger;
|
|
5
|
+
exports.noopLogger = {
|
|
6
|
+
info: () => { },
|
|
7
|
+
warn: () => { },
|
|
8
|
+
error: () => { },
|
|
9
|
+
debug: () => { },
|
|
10
|
+
};
|
|
4
11
|
/**
|
|
5
12
|
* Creates a structured logger that delegates to OpenClaw's base logger.
|
|
6
13
|
* Only outputs via baseLogger to avoid duplicate stdout writes.
|