multiclaws 0.4.31 → 0.4.32

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/index.js CHANGED
@@ -509,7 +509,7 @@ const plugin = {
509
509
  if (gw) {
510
510
  const tools = (gw.tools ?? {});
511
511
  const allow = Array.isArray(tools.allow) ? tools.allow : [];
512
- const adapterRequired = ["sessions_spawn", "sessions_history", "message"];
512
+ const adapterRequired = ["sessions_spawn", "sessions_history", "message", "chat.send"];
513
513
  const defaultA2AExecutionTools = ["exec", "read", "write", "edit", "process"];
514
514
  const pluginConf = api.pluginConfig ?? {};
515
515
  const a2aExecTools = Array.isArray(pluginConf.a2aAllowedTools)
@@ -595,14 +595,18 @@ const plugin = {
595
595
  api.on("gateway_stop", () => {
596
596
  structured.logger.info("[multiclaws] gateway_stop observed");
597
597
  });
598
- // Collect all channel IDs for broadcasting notifications
598
+ // Collect notification targets from incoming messages (external channels)
599
599
  api.on("message_received", (_event, ctx) => {
600
- if (service && ctx.channelId) {
601
- service.addChannelId(ctx.channelId);
600
+ if (service && ctx.channelId && ctx.channelId !== "webchat" && ctx.conversationId) {
601
+ service.addNotificationTarget(`${ctx.channelId}:${ctx.conversationId}`, { type: "channel", conversationId: ctx.conversationId });
602
602
  }
603
603
  });
604
604
  // Inject onboarding prompt when profile is pending first-run setup
605
- api.on("before_prompt_build", async (_event, _ctx) => {
605
+ // Also capture web session targets for notifications
606
+ api.on("before_prompt_build", async (_event, ctx) => {
607
+ if (service && ctx.sessionKey) {
608
+ service.addNotificationTarget(`web:${ctx.sessionKey}`, { type: "web", sessionKey: ctx.sessionKey });
609
+ }
606
610
  if (!service)
607
611
  return;
608
612
  try {
@@ -1,11 +1,12 @@
1
1
  import type { AgentExecutor, ExecutionEventBus, RequestContext } from "@a2a-js/sdk/server";
2
2
  import { type GatewayConfig } from "../infra/gateway-client";
3
3
  import type { TaskTracker } from "../task/tracker";
4
+ import type { NotificationTarget } from "./multiclaws-service";
4
5
  export type A2AAdapterOptions = {
5
6
  gatewayConfig: GatewayConfig | null;
6
7
  taskTracker: TaskTracker;
7
8
  cwd?: string;
8
- getChannelIds?: () => ReadonlySet<string>;
9
+ getNotificationTargets?: () => ReadonlyMap<string, NotificationTarget>;
9
10
  logger: {
10
11
  info: (msg: string) => void;
11
12
  warn: (msg: string) => void;
@@ -25,7 +26,7 @@ export type A2AAdapterOptions = {
25
26
  export declare class OpenClawAgentExecutor implements AgentExecutor {
26
27
  private gatewayConfig;
27
28
  private readonly taskTracker;
28
- private readonly getChannelIds;
29
+ private readonly getNotificationTargets;
29
30
  private readonly logger;
30
31
  private readonly cwd;
31
32
  private readonly pendingCallbacks;
@@ -43,7 +44,7 @@ export declare class OpenClawAgentExecutor implements AgentExecutor {
43
44
  * or rejects on timeout.
44
45
  */
45
46
  private createCallback;
46
- /** Send a notification to all known channels. Individual failures are silently ignored. */
47
+ /** Send a notification to all known targets. Individual failures are silently ignored. */
47
48
  private notifyUser;
48
49
  private publishMessage;
49
50
  }
@@ -23,14 +23,14 @@ function extractTextFromMessage(message) {
23
23
  class OpenClawAgentExecutor {
24
24
  gatewayConfig;
25
25
  taskTracker;
26
- getChannelIds;
26
+ getNotificationTargets;
27
27
  logger;
28
28
  cwd;
29
29
  pendingCallbacks = new Map();
30
30
  constructor(options) {
31
31
  this.gatewayConfig = options.gatewayConfig;
32
32
  this.taskTracker = options.taskTracker;
33
- this.getChannelIds = options.getChannelIds ?? (() => new Set());
33
+ this.getNotificationTargets = options.getNotificationTargets ?? (() => new Map());
34
34
  this.logger = options.logger;
35
35
  this.cwd = options.cwd || process.cwd();
36
36
  }
@@ -132,17 +132,24 @@ class OpenClawAgentExecutor {
132
132
  this.pendingCallbacks.set(taskId, { resolve, reject, timer });
133
133
  });
134
134
  }
135
- /** Send a notification to all known channels. Individual failures are silently ignored. */
135
+ /** Send a notification to all known targets. Individual failures are silently ignored. */
136
136
  async notifyUser(message) {
137
- const channels = this.getChannelIds();
138
- if (!this.gatewayConfig || channels.size === 0)
137
+ const targets = this.getNotificationTargets();
138
+ if (!this.gatewayConfig || targets.size === 0)
139
139
  return;
140
- await Promise.allSettled([...channels].map((target) => (0, gateway_client_1.invokeGatewayTool)({
141
- gateway: this.gatewayConfig,
142
- tool: "message",
143
- args: { action: "send", target, message },
144
- timeoutMs: 5_000,
145
- })));
140
+ await Promise.allSettled([...targets.values()].map((target) => target.type === "channel"
141
+ ? (0, gateway_client_1.invokeGatewayTool)({
142
+ gateway: this.gatewayConfig,
143
+ tool: "message",
144
+ args: { action: "send", target: target.conversationId, message },
145
+ timeoutMs: 5_000,
146
+ })
147
+ : (0, gateway_client_1.invokeGatewayTool)({
148
+ gateway: this.gatewayConfig,
149
+ tool: "chat.send",
150
+ args: { sessionKey: target.sessionKey, message },
151
+ timeoutMs: 5_000,
152
+ })));
146
153
  }
147
154
  publishMessage(eventBus, text) {
148
155
  const message = {
@@ -27,6 +27,13 @@ export type DelegateTaskResult = {
27
27
  status: string;
28
28
  error?: string;
29
29
  };
30
+ export type NotificationTarget = {
31
+ type: "channel";
32
+ conversationId: string;
33
+ } | {
34
+ type: "web";
35
+ sessionKey: string;
36
+ };
30
37
  export declare class MulticlawsService extends EventEmitter {
31
38
  private readonly options;
32
39
  private started;
@@ -45,7 +52,7 @@ export declare class MulticlawsService extends EventEmitter {
45
52
  private profileDescription;
46
53
  private readonly gatewayConfig;
47
54
  private readonly resolvedCwd;
48
- private readonly knownChannelIds;
55
+ private readonly notificationTargets;
49
56
  constructor(options: MulticlawsServiceOptions);
50
57
  start(): Promise<void>;
51
58
  stop(): Promise<void>;
@@ -128,8 +135,8 @@ export declare class MulticlawsService extends EventEmitter {
128
135
  private fetchWithRetry;
129
136
  /** Register a channel ID for notifications. */
130
137
  resolveA2ACallback(taskId: string, result: string): boolean;
131
- addChannelId(channelId: string): void;
132
- /** Send a notification to all known channels. Individual failures are silently ignored. */
138
+ addNotificationTarget(key: string, target: NotificationTarget): void;
139
+ /** Send a notification to all known targets. Individual failures are silently ignored. */
133
140
  private notifyUser;
134
141
  private log;
135
142
  }
@@ -68,7 +68,7 @@ class MulticlawsService extends node_events_1.EventEmitter {
68
68
  profileDescription = "OpenClaw agent";
69
69
  gatewayConfig;
70
70
  resolvedCwd;
71
- knownChannelIds = new Set();
71
+ notificationTargets = new Map();
72
72
  constructor(options) {
73
73
  super();
74
74
  this.options = options;
@@ -123,7 +123,7 @@ class MulticlawsService extends node_events_1.EventEmitter {
123
123
  gatewayConfig: this.options.gatewayConfig ?? null,
124
124
  taskTracker: this.taskTracker,
125
125
  cwd: this.resolvedCwd,
126
- getChannelIds: () => this.knownChannelIds,
126
+ getNotificationTargets: () => this.notificationTargets,
127
127
  logger,
128
128
  });
129
129
  this.agentCard = {
@@ -925,22 +925,29 @@ class MulticlawsService extends node_events_1.EventEmitter {
925
925
  return false;
926
926
  return this.agentExecutor.resolveCallback(taskId, result);
927
927
  }
928
- addChannelId(channelId) {
929
- if (!this.knownChannelIds.has(channelId)) {
930
- this.knownChannelIds.add(channelId);
931
- this.log("debug", `channel registered: ${channelId} (total: ${this.knownChannelIds.size})`);
928
+ addNotificationTarget(key, target) {
929
+ if (!this.notificationTargets.has(key)) {
930
+ this.notificationTargets.set(key, target);
931
+ this.log("debug", `notification target registered: ${key} (total: ${this.notificationTargets.size})`);
932
932
  }
933
933
  }
934
- /** Send a notification to all known channels. Individual failures are silently ignored. */
934
+ /** Send a notification to all known targets. Individual failures are silently ignored. */
935
935
  async notifyUser(message) {
936
- if (!this.gatewayConfig || this.knownChannelIds.size === 0)
936
+ if (!this.gatewayConfig || this.notificationTargets.size === 0)
937
937
  return;
938
- await Promise.allSettled([...this.knownChannelIds].map((target) => (0, gateway_client_1.invokeGatewayTool)({
939
- gateway: this.gatewayConfig,
940
- tool: "message",
941
- args: { action: "send", target, message },
942
- timeoutMs: 5_000,
943
- })));
938
+ await Promise.allSettled([...this.notificationTargets.values()].map((target) => target.type === "channel"
939
+ ? (0, gateway_client_1.invokeGatewayTool)({
940
+ gateway: this.gatewayConfig,
941
+ tool: "message",
942
+ args: { action: "send", target: target.conversationId, message },
943
+ timeoutMs: 5_000,
944
+ })
945
+ : (0, gateway_client_1.invokeGatewayTool)({
946
+ gateway: this.gatewayConfig,
947
+ tool: "chat.send",
948
+ args: { sessionKey: target.sessionKey, message },
949
+ timeoutMs: 5_000,
950
+ })));
944
951
  }
945
952
  log(level, message) {
946
953
  this.options.logger?.[level]?.(`[multiclaws] ${message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multiclaws",
3
- "version": "0.4.31",
3
+ "version": "0.4.32",
4
4
  "description": "MultiClaws plugin for OpenClaw collaboration via A2A protocol",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",