multiclaws 0.4.5 → 0.4.7

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,21 +3,16 @@ 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
+ });
6
10
  const agentRemoveSchema = zod_1.z.object({ url: nonEmptyString });
7
- const sessionStartSchema = zod_1.z.object({
11
+ const taskDelegateSchema = zod_1.z.object({
8
12
  agentUrl: nonEmptyString,
9
- message: nonEmptyString,
10
- });
11
- const sessionReplySchema = zod_1.z.object({
12
- sessionId: nonEmptyString,
13
- message: nonEmptyString,
14
- });
15
- const sessionStatusSchema = zod_1.z.object({ sessionId: zod_1.z.string().trim().min(1).optional() });
16
- const sessionEndSchema = zod_1.z.object({ sessionId: nonEmptyString });
17
- const sessionWaitAllSchema = zod_1.z.object({
18
- sessionIds: zod_1.z.array(nonEmptyString).min(1),
19
- timeoutMs: zod_1.z.number().positive().optional(),
13
+ task: nonEmptyString,
20
14
  });
15
+ const taskStatusSchema = zod_1.z.object({ taskId: nonEmptyString });
21
16
  const profileSetSchema = zod_1.z.object({
22
17
  ownerName: zod_1.z.string().trim().optional(),
23
18
  bio: zod_1.z.string().optional(),
@@ -36,13 +31,19 @@ function createGatewayHandlers(getService) {
36
31
  const handlers = {
37
32
  /* ── Agent handlers ─────────────────────────────────────────── */
38
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
39
  try {
40
+ const parsed = agentAddSchema.parse(params);
40
41
  const service = getService();
41
- const agents = await service.listAgents();
42
- respond(true, { agents });
42
+ const agent = await service.addAgent(parsed);
43
+ respond(true, agent);
43
44
  }
44
45
  catch (error) {
45
- safeHandle(respond, "agent_list_failed", error);
46
+ safeHandle(respond, "invalid_params", error);
46
47
  }
47
48
  },
48
49
  "multiclaws.agent.remove": async ({ params, respond }) => {
@@ -56,70 +57,34 @@ function createGatewayHandlers(getService) {
56
57
  safeHandle(respond, "invalid_params", error);
57
58
  }
58
59
  },
59
- /* ── Session handlers ───────────────────────────────────────── */
60
- "multiclaws.session.start": async ({ params, respond }) => {
61
- try {
62
- const parsed = sessionStartSchema.parse(params);
63
- const service = getService();
64
- const result = await service.startSession(parsed);
65
- respond(true, result);
66
- }
67
- catch (error) {
68
- safeHandle(respond, "session_start_failed", error);
69
- }
70
- },
71
- "multiclaws.session.reply": async ({ params, respond }) => {
60
+ /* ── Task handlers ──────────────────────────────────────────── */
61
+ "multiclaws.task.delegate": async ({ params, respond }) => {
72
62
  try {
73
- const parsed = sessionReplySchema.parse(params);
63
+ const parsed = taskDelegateSchema.parse(params);
74
64
  const service = getService();
75
- const result = await service.sendSessionMessage(parsed);
65
+ const result = await service.delegateTask(parsed);
76
66
  respond(true, result);
77
67
  }
78
68
  catch (error) {
79
- safeHandle(respond, "session_reply_failed", error);
69
+ safeHandle(respond, "task_delegate_failed", error);
80
70
  }
81
71
  },
82
- "multiclaws.session.status": async ({ params, respond }) => {
72
+ "multiclaws.task.status": async ({ params, respond }) => {
83
73
  try {
84
- const parsed = sessionStatusSchema.parse(params);
74
+ const parsed = taskStatusSchema.parse(params);
85
75
  const service = getService();
86
- if (parsed.sessionId) {
87
- const session = service.getSession(parsed.sessionId);
88
- if (!session) {
89
- respond(false, undefined, { code: "not_found", message: `session not found: ${parsed.sessionId}` });
90
- return;
91
- }
92
- respond(true, session);
93
- }
94
- else {
95
- const sessions = service.listSessions();
96
- respond(true, { sessions });
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;
97
83
  }
84
+ respond(true, { task });
98
85
  }
99
86
  catch (error) {
100
- safeHandle(respond, "session_status_failed", error);
101
- }
102
- },
103
- "multiclaws.session.wait_all": async ({ params, respond }) => {
104
- try {
105
- const parsed = sessionWaitAllSchema.parse(params);
106
- const service = getService();
107
- const result = await service.waitForSessions(parsed);
108
- respond(true, result);
109
- }
110
- catch (error) {
111
- safeHandle(respond, "session_wait_all_failed", error);
112
- }
113
- },
114
- "multiclaws.session.end": async ({ params, respond }) => {
115
- try {
116
- const parsed = sessionEndSchema.parse(params);
117
- const service = getService();
118
- const ok = service.endSession(parsed.sessionId);
119
- respond(true, { ended: ok });
120
- }
121
- catch (error) {
122
- safeHandle(respond, "session_end_failed", error);
87
+ safeHandle(respond, "task_status_failed", error);
123
88
  }
124
89
  },
125
90
  /* ── Team handlers ──────────────────────────────────────────── */
@@ -177,34 +142,19 @@ function createGatewayHandlers(getService) {
177
142
  },
178
143
  /* ── Profile handlers ───────────────────────────────────────── */
179
144
  "multiclaws.profile.show": async ({ respond }) => {
180
- try {
181
- const service = getService();
182
- const profile = await service.getProfile();
183
- respond(true, profile);
184
- }
185
- catch (error) {
186
- safeHandle(respond, "profile_show_failed", error);
187
- }
145
+ const service = getService();
146
+ const profile = await service.getProfile();
147
+ respond(true, profile);
188
148
  },
189
149
  "multiclaws.profile.pending_review": async ({ respond }) => {
190
- try {
191
- const service = getService();
192
- const result = await service.getPendingProfileReview();
193
- respond(true, result);
194
- }
195
- catch (error) {
196
- safeHandle(respond, "profile_pending_review_failed", error);
197
- }
150
+ const service = getService();
151
+ const result = await service.getPendingProfileReview();
152
+ respond(true, result);
198
153
  },
199
154
  "multiclaws.profile.clear_pending_review": async ({ respond }) => {
200
- try {
201
- const service = getService();
202
- await service.clearPendingProfileReview();
203
- respond(true, { cleared: true });
204
- }
205
- catch (error) {
206
- safeHandle(respond, "profile_clear_pending_review_failed", error);
207
- }
155
+ const service = getService();
156
+ await service.clearPendingProfileReview();
157
+ respond(true, { cleared: true });
208
158
  },
209
159
  "multiclaws.profile.set": async ({ params, respond }) => {
210
160
  try {
package/dist/index.js CHANGED
@@ -45,14 +45,15 @@ function createTools(getService) {
45
45
  return textResult(JSON.stringify({ agents }, null, 2), { agents });
46
46
  },
47
47
  };
48
- const multiclawsRemoveAgent = {
49
- name: "multiclaws_remove_agent",
50
- description: "Remove a known A2A agent by URL.",
48
+ const multiclawsAddAgent = {
49
+ name: "multiclaws_add_agent",
50
+ description: "Add a remote A2A agent by URL. Automatically fetches its Agent Card.",
51
51
  parameters: {
52
52
  type: "object",
53
53
  additionalProperties: false,
54
54
  properties: {
55
55
  url: { type: "string" },
56
+ apiKey: { type: "string" },
56
57
  },
57
58
  required: ["url"],
58
59
  },
@@ -61,120 +62,73 @@ function createTools(getService) {
61
62
  const url = typeof args.url === "string" ? args.url.trim() : "";
62
63
  if (!url)
63
64
  throw new Error("url is required");
64
- const removed = await service.removeAgent(url);
65
- return textResult(removed ? `Agent ${url} removed.` : `Agent ${url} not found.`);
66
- },
67
- };
68
- /* ── Session tools (multi-turn collaboration) ─────────────────── */
69
- const multiclawsSessionStart = {
70
- name: "multiclaws_session_start",
71
- description: "Start a multi-turn collaboration session with a remote agent. Sends the first message and returns immediately with a sessionId (async). The agent's response will be pushed as a message when ready. Covers both single-turn and multi-turn use cases.",
72
- parameters: {
73
- type: "object",
74
- additionalProperties: false,
75
- properties: {
76
- agentUrl: { type: "string" },
77
- message: { type: "string" },
78
- },
79
- required: ["agentUrl", "message"],
80
- },
81
- execute: async (_toolCallId, args) => {
82
- const service = requireService(getService());
83
- const agentUrl = typeof args.agentUrl === "string" ? args.agentUrl.trim() : "";
84
- const message = typeof args.message === "string" ? args.message.trim() : "";
85
- if (!agentUrl || !message)
86
- throw new Error("agentUrl and message are required");
87
- const result = await service.startSession({ agentUrl, message });
88
- return textResult(JSON.stringify(result, null, 2), result);
89
- },
90
- };
91
- const multiclawsSessionReply = {
92
- name: "multiclaws_session_reply",
93
- description: "Send a follow-up message in an existing collaboration session. Use when the remote agent returns 'input-required' or to continue a multi-turn conversation.",
94
- parameters: {
95
- type: "object",
96
- additionalProperties: false,
97
- properties: {
98
- sessionId: { type: "string" },
99
- message: { type: "string" },
100
- },
101
- required: ["sessionId", "message"],
102
- },
103
- execute: async (_toolCallId, args) => {
104
- const service = requireService(getService());
105
- const sessionId = typeof args.sessionId === "string" ? args.sessionId.trim() : "";
106
- const message = typeof args.message === "string" ? args.message.trim() : "";
107
- if (!sessionId || !message)
108
- throw new Error("sessionId and message are required");
109
- const result = await service.sendSessionMessage({ sessionId, message });
110
- return textResult(JSON.stringify(result, null, 2), result);
65
+ const apiKey = typeof args.apiKey === "string" ? args.apiKey.trim() : undefined;
66
+ const agent = await service.addAgent({ url, apiKey });
67
+ return textResult(`Agent added: ${agent.name} (${agent.url})`, agent);
111
68
  },
112
69
  };
113
- const multiclawsSessionStatus = {
114
- name: "multiclaws_session_status",
115
- description: "Get the status and message history of a collaboration session. If sessionId is omitted, lists all sessions.",
70
+ const multiclawsRemoveAgent = {
71
+ name: "multiclaws_remove_agent",
72
+ description: "Remove a known A2A agent by URL.",
116
73
  parameters: {
117
74
  type: "object",
118
75
  additionalProperties: false,
119
76
  properties: {
120
- sessionId: { type: "string" },
77
+ url: { type: "string" },
121
78
  },
79
+ required: ["url"],
122
80
  },
123
81
  execute: async (_toolCallId, args) => {
124
82
  const service = requireService(getService());
125
- const sessionId = typeof args.sessionId === "string" ? args.sessionId.trim() : "";
126
- if (sessionId) {
127
- const session = service.getSession(sessionId);
128
- if (!session)
129
- throw new Error(`session not found: ${sessionId}`);
130
- return textResult(JSON.stringify(session, null, 2), session);
131
- }
132
- const sessions = service.listSessions();
133
- return textResult(JSON.stringify({ sessions }, null, 2), { sessions });
83
+ const url = typeof args.url === "string" ? args.url.trim() : "";
84
+ if (!url)
85
+ throw new Error("url is required");
86
+ const removed = await service.removeAgent(url);
87
+ return textResult(removed ? `Agent ${url} removed.` : `Agent ${url} not found.`);
134
88
  },
135
89
  };
136
- const multiclawsSessionWaitAll = {
137
- name: "multiclaws_session_wait_all",
138
- description: "Wait for multiple sessions to complete, then return all results at once. Use this when you have started multiple sessions concurrently and need all results before synthesizing an answer. Returns early if any session needs input (input-required). Default timeout: 5 minutes.",
90
+ const multiclawsDelegate = {
91
+ name: "multiclaws_delegate",
92
+ description: "Delegate a task to a remote A2A agent.",
139
93
  parameters: {
140
94
  type: "object",
141
95
  additionalProperties: false,
142
96
  properties: {
143
- sessionIds: { type: "array", items: { type: "string" } },
144
- timeoutMs: { type: "number" },
97
+ agentUrl: { type: "string" },
98
+ task: { type: "string" },
145
99
  },
146
- required: ["sessionIds"],
100
+ required: ["agentUrl", "task"],
147
101
  },
148
102
  execute: async (_toolCallId, args) => {
149
103
  const service = requireService(getService());
150
- const sessionIds = Array.isArray(args.sessionIds)
151
- ? args.sessionIds.map((s) => String(s).trim()).filter(Boolean)
152
- : [];
153
- if (!sessionIds.length)
154
- throw new Error("sessionIds must be a non-empty array");
155
- const timeoutMs = typeof args.timeoutMs === "number" ? args.timeoutMs : undefined;
156
- const result = await service.waitForSessions({ sessionIds, timeoutMs });
104
+ const agentUrl = typeof args.agentUrl === "string" ? args.agentUrl.trim() : "";
105
+ const task = typeof args.task === "string" ? args.task.trim() : "";
106
+ if (!agentUrl || !task)
107
+ throw new Error("agentUrl and task are required");
108
+ const result = await service.delegateTask({ agentUrl, task });
157
109
  return textResult(JSON.stringify(result, null, 2), result);
158
110
  },
159
111
  };
160
- const multiclawsSessionEnd = {
161
- name: "multiclaws_session_end",
162
- description: "Cancel and close a collaboration session.",
112
+ const multiclawsTaskStatus = {
113
+ name: "multiclaws_task_status",
114
+ description: "Check the status of a delegated task.",
163
115
  parameters: {
164
116
  type: "object",
165
117
  additionalProperties: false,
166
118
  properties: {
167
- sessionId: { type: "string" },
119
+ taskId: { type: "string" },
168
120
  },
169
- required: ["sessionId"],
121
+ required: ["taskId"],
170
122
  },
171
123
  execute: async (_toolCallId, args) => {
172
124
  const service = requireService(getService());
173
- const sessionId = typeof args.sessionId === "string" ? args.sessionId.trim() : "";
174
- if (!sessionId)
175
- throw new Error("sessionId is required");
176
- const ok = service.endSession(sessionId);
177
- return textResult(ok ? `Session ${sessionId} ended.` : `Session ${sessionId} not found.`);
125
+ const taskId = typeof args.taskId === "string" ? args.taskId.trim() : "";
126
+ if (!taskId)
127
+ throw new Error("taskId is required");
128
+ const task = service.getTaskStatus(taskId);
129
+ if (!task)
130
+ throw new Error(`task not found: ${taskId}`);
131
+ return textResult(JSON.stringify(task, null, 2), task);
178
132
  },
179
133
  };
180
134
  /* ── Team tools ───────────────────────────────────────────────── */
@@ -324,12 +278,10 @@ function createTools(getService) {
324
278
  };
325
279
  return [
326
280
  multiclawsAgents,
281
+ multiclawsAddAgent,
327
282
  multiclawsRemoveAgent,
328
- multiclawsSessionStart,
329
- multiclawsSessionReply,
330
- multiclawsSessionStatus,
331
- multiclawsSessionWaitAll,
332
- multiclawsSessionEnd,
283
+ multiclawsDelegate,
284
+ multiclawsTaskStatus,
333
285
  multiclawsTeamCreate,
334
286
  multiclawsTeamJoin,
335
287
  multiclawsTeamLeave,
@@ -343,40 +295,25 @@ function createTools(getService) {
343
295
  const plugin = {
344
296
  id: "multiclaws",
345
297
  name: "MultiClaws",
346
- version: "0.4.2",
298
+ version: "0.3.1",
347
299
  register(api) {
348
300
  const config = readConfig(api);
349
301
  (0, telemetry_1.initializeTelemetry)({ enableConsoleExporter: config.telemetry?.consoleExporter });
350
302
  const structured = (0, logger_1.createStructuredLogger)(api.logger, "multiclaws");
351
303
  let service = null;
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.
304
+ // Ensure required tools are in gateway.tools.allow at registration time
305
+ // so the gateway starts with them already present (no restart needed).
354
306
  if (api.config) {
355
307
  const gw = api.config.gateway;
356
308
  if (gw) {
357
309
  const tools = (gw.tools ?? {});
358
- // 1. Gateway tools the plugin depends on → tools.allow
359
310
  const allow = Array.isArray(tools.allow) ? tools.allow : [];
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];
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];
311
+ const required = ["sessions_spawn", "sessions_history"];
312
+ const missing = required.filter((t) => !allow.includes(t));
313
+ if (missing.length > 0) {
314
+ tools.allow = [...allow, ...missing];
315
+ gw.tools = tools;
378
316
  }
379
- gw.tools = tools;
380
317
  }
381
318
  }
382
319
  const gatewayConfig = (() => {
@@ -429,17 +366,6 @@ const plugin = {
429
366
  });
430
367
  api.on("gateway_start", () => {
431
368
  structured.logger.info("[multiclaws] gateway_start observed");
432
- // Re-read gateway config in case token became available after initial registration
433
- if (service && !gatewayConfig) {
434
- const gw = api.config?.gateway;
435
- const port = typeof gw?.port === "number" ? gw.port : 18789;
436
- const token = typeof gw?.auth?.token === "string" ? gw.auth.token : null;
437
- if (token) {
438
- const newConfig = { port, token };
439
- service.updateGatewayConfig(newConfig);
440
- structured.logger.info("[multiclaws] gateway config updated from gateway_start event");
441
- }
442
- }
443
369
  });
444
370
  api.on("gateway_stop", () => {
445
371
  structured.logger.info("[multiclaws] gateway_stop observed");
@@ -455,8 +381,7 @@ const plugin = {
455
381
  return {
456
382
  appendSystemContext: `## MultiClaws 首次安装 — 需要完成档案设置
457
383
 
458
- multiclaws 插件刚安装,需要在本次对话中完成以下初始化流程(优先处理,不管用户说了什么)。
459
- **务必使用插件工具调用,不要通过命令行或 gateway 方法操作。**
384
+ multiclaws 插件刚安装,需要在本次对话中完成以下初始化流程(优先处理,不管用户说了什么):
460
385
 
461
386
  1. **扫描当前环境**,自动生成 bio(markdown 格式),内容包括:
462
387
  - 用户角色和职责
@@ -469,7 +394,9 @@ multiclaws 插件刚安装,需要在本次对话中完成以下初始化流程
469
394
  - **Bio**:展示生成的 bio,询问是否需要修改
470
395
  - **网络情况**:告知用户「同局域网开箱即用;跨网络需安装 Tailscale(https://tailscale.com/download)并重启 OpenClaw」,无需用户回答
471
396
 
472
- 3. 根据用户确认的内容,调用 \`multiclaws_profile_set(ownerName="...", bio="...")\` 保存。保存后初始化自动完成,无需额外操作。
397
+ 3. 根据用户对名字和 bio 的回答更新档案内容(如需修改),然后调用 \`multiclaws_profile_set(ownerName="...", bio="...")\` 保存。
398
+
399
+ 4. 调用 \`multiclaws_profile_clear_pending_review()\` 完成初始化。
473
400
 
474
401
  **注意**:名字和 bio 需要用户明确确认;网络情况仅告知无需回答。`,
475
402
  };
@@ -40,7 +40,6 @@ exports.invokeGatewayTool = invokeGatewayTool;
40
40
  const opossum_1 = __importDefault(require("opossum"));
41
41
  class NonRetryableError extends Error {
42
42
  }
43
- const MAX_BREAKERS = 50;
44
43
  const breakerCache = new Map();
45
44
  let pRetryModulePromise = null;
46
45
  async function loadPRetry() {
@@ -54,15 +53,6 @@ function getBreaker(key, timeoutMs) {
54
53
  if (existing) {
55
54
  return existing;
56
55
  }
57
- // Evict oldest entries when cache is full
58
- if (breakerCache.size >= MAX_BREAKERS) {
59
- const oldest = breakerCache.keys().next().value;
60
- if (oldest !== undefined) {
61
- const old = breakerCache.get(oldest);
62
- old?.shutdown();
63
- breakerCache.delete(oldest);
64
- }
65
- }
66
56
  const breaker = new opossum_1.default((operation) => operation(), {
67
57
  timeout: false, // timeout handled by AbortController in the operation
68
58
  errorThresholdPercentage: 50,
@@ -10,7 +10,7 @@ export type TailscaleStatus = {
10
10
  status: "unavailable";
11
11
  reason: string;
12
12
  };
13
- /** Check network interfaces for a Tailscale IP (100.64.0.0/10) — exported for fast-path checks */
13
+ /** Check network interfaces for a Tailscale IP (100.x.x.x) — exported for fast-path checks */
14
14
  export declare function getTailscaleIpFromInterfaces(): string | null;
15
15
  /**
16
16
  * Detect Tailscale status — does NOT install or modify system state.
@@ -7,7 +7,6 @@ exports.getTailscaleIpFromInterfaces = getTailscaleIpFromInterfaces;
7
7
  exports.detectTailscale = detectTailscale;
8
8
  const node_child_process_1 = require("node:child_process");
9
9
  const node_os_1 = __importDefault(require("node:os"));
10
- const isWindows = process.platform === "win32";
11
10
  function run(cmd, timeoutMs = 5_000) {
12
11
  return (0, node_child_process_1.execSync)(cmd, { timeout: timeoutMs, stdio: ["ignore", "pipe", "pipe"] })
13
12
  .toString()
@@ -15,30 +14,21 @@ function run(cmd, timeoutMs = 5_000) {
15
14
  }
16
15
  function commandExists(cmd) {
17
16
  try {
18
- run(isWindows ? `where ${cmd}` : `which ${cmd}`);
17
+ run(`which ${cmd}`);
19
18
  return true;
20
19
  }
21
20
  catch {
22
21
  return false;
23
22
  }
24
23
  }
25
- /** Check whether an IPv4 address falls within the Tailscale CGNAT range (100.64.0.0/10). */
26
- function isTailscaleCGNAT(ip) {
27
- const parts = ip.split(".");
28
- if (parts.length !== 4)
29
- return false;
30
- const first = parseInt(parts[0], 10);
31
- const second = parseInt(parts[1], 10);
32
- return first === 100 && second >= 64 && second <= 127;
33
- }
34
- /** Check network interfaces for a Tailscale IP (100.64.0.0/10) — exported for fast-path checks */
24
+ /** Check network interfaces for a Tailscale IP (100.x.x.x) — exported for fast-path checks */
35
25
  function getTailscaleIpFromInterfaces() {
36
26
  const interfaces = node_os_1.default.networkInterfaces();
37
27
  for (const addrs of Object.values(interfaces)) {
38
28
  if (!addrs)
39
29
  continue;
40
30
  for (const addr of addrs) {
41
- if (addr.family === "IPv4" && isTailscaleCGNAT(addr.address)) {
31
+ if (addr.family === "IPv4" && addr.address.startsWith("100.")) {
42
32
  return addr.address;
43
33
  }
44
34
  }
@@ -71,7 +61,8 @@ async function getAuthUrl() {
71
61
  return new Promise((resolve) => {
72
62
  try {
73
63
  // tailscale up prints the auth URL to stderr
74
- const proc = (0, node_child_process_1.spawn)("tailscale", ["up"], { stdio: ["ignore", "pipe", "pipe"] });
64
+ const { spawn } = require("node:child_process");
65
+ const proc = spawn("tailscale", ["up"], { stdio: ["ignore", "pipe", "pipe"] });
75
66
  let output = "";
76
67
  let resolved = false;
77
68
  const tryResolve = (text) => {
@@ -24,7 +24,6 @@ export declare class OpenClawAgentExecutor implements AgentExecutor {
24
24
  private gatewayConfig;
25
25
  private readonly taskTracker;
26
26
  private readonly logger;
27
- private readonly a2aToTracker;
28
27
  constructor(options: A2AAdapterOptions);
29
28
  execute(context: RequestContext, eventBus: ExecutionEventBus): Promise<void>;
30
29
  /**