multiclaws 0.4.26 → 0.4.28

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
@@ -489,6 +489,7 @@ const plugin = {
489
489
  port: config.port,
490
490
  displayName: config.displayName,
491
491
  selfUrl: config.selfUrl,
492
+ cwd: process.cwd(),
492
493
  tunnel: config.tunnel,
493
494
  gatewayConfig: gatewayConfig ?? undefined,
494
495
  logger: structured.logger,
@@ -542,9 +543,13 @@ const plugin = {
542
543
  structured.logger.info("[multiclaws] gateway_stop observed");
543
544
  });
544
545
  // Inject onboarding prompt when profile is pending first-run setup
545
- api.on("before_prompt_build", async (_event, _ctx) => {
546
+ api.on("before_prompt_build", async (_event, ctx) => {
546
547
  if (!service)
547
548
  return;
549
+ // Capture the active channel so notifications go to the right place
550
+ if (ctx.channelId) {
551
+ service.setActiveChannelId(ctx.channelId);
552
+ }
548
553
  try {
549
554
  const review = await service.getPendingProfileReview();
550
555
  if (!review.pending)
package/dist/infra/frp.js CHANGED
@@ -362,9 +362,16 @@ class FrpTunnelManager {
362
362
  (0, node_child_process_1.execSync)(`tar -xzf "${archivePath}" -C "${downloadDir}"`, { stdio: "ignore" });
363
363
  }
364
364
  else {
365
- // Windows: suppress progress bar to prevent silent failure in headless environments;
366
- // use stdio:"pipe" so execSync captures errors if PowerShell exits non-zero
367
- (0, node_child_process_1.execSync)(`powershell -NoProfile -Command "$ProgressPreference = 'SilentlyContinue'; Expand-Archive -LiteralPath '${archivePath}' -DestinationPath '${downloadDir}' -Force"`, { stdio: "pipe" });
365
+ // Windows: use spawnSync to bypass cmd.exe quote-mangling that breaks
366
+ // the embedded PowerShell double-quotes when execSync(string) is used.
367
+ const psCmd = `$ProgressPreference = 'SilentlyContinue'; Expand-Archive -LiteralPath '${archivePath.replace(/'/g, "''")}' -DestinationPath '${downloadDir.replace(/'/g, "''")}' -Force`;
368
+ const psResult = (0, node_child_process_1.spawnSync)("powershell", ["-NoProfile", "-Command", psCmd], {
369
+ stdio: "pipe",
370
+ });
371
+ if (psResult.status !== 0) {
372
+ const stderr = psResult.stderr?.toString().trim() ?? "";
373
+ throw new Error(`Expand-Archive failed (exit ${psResult.status}): ${stderr}`);
374
+ }
368
375
  }
369
376
  // Move binary to target
370
377
  const extractedBinary = node_path_1.default.join(downloadDir, archiveName, binaryName);
@@ -4,6 +4,8 @@ import type { TaskTracker } from "../task/tracker";
4
4
  export type A2AAdapterOptions = {
5
5
  gatewayConfig: GatewayConfig | null;
6
6
  taskTracker: TaskTracker;
7
+ cwd?: string;
8
+ getActiveChannelId?: () => string | null;
7
9
  logger: {
8
10
  info: (msg: string) => void;
9
11
  warn: (msg: string) => void;
@@ -23,7 +25,9 @@ export type A2AAdapterOptions = {
23
25
  export declare class OpenClawAgentExecutor implements AgentExecutor {
24
26
  private gatewayConfig;
25
27
  private readonly taskTracker;
28
+ private readonly getActiveChannelId;
26
29
  private readonly logger;
30
+ private readonly cwd;
27
31
  constructor(options: A2AAdapterOptions);
28
32
  execute(context: RequestContext, eventBus: ExecutionEventBus): Promise<void>;
29
33
  /**
@@ -41,11 +41,15 @@ function extractDetails(result) {
41
41
  class OpenClawAgentExecutor {
42
42
  gatewayConfig;
43
43
  taskTracker;
44
+ getActiveChannelId;
44
45
  logger;
46
+ cwd;
45
47
  constructor(options) {
46
48
  this.gatewayConfig = options.gatewayConfig;
47
49
  this.taskTracker = options.taskTracker;
50
+ this.getActiveChannelId = options.getActiveChannelId ?? (() => null);
48
51
  this.logger = options.logger;
52
+ this.cwd = options.cwd || process.cwd();
49
53
  }
50
54
  async execute(context, eventBus) {
51
55
  const taskText = extractTextFromMessage(context.userMessage);
@@ -82,7 +86,7 @@ class OpenClawAgentExecutor {
82
86
  args: {
83
87
  task: taskText,
84
88
  mode: "run",
85
- cwd: process.cwd(),
89
+ cwd: this.cwd,
86
90
  },
87
91
  sessionKey: `a2a-${taskId}`,
88
92
  timeoutMs: 15_000,
@@ -251,13 +255,14 @@ class OpenClawAgentExecutor {
251
255
  }
252
256
  /** Send a notification to the local user via the gateway message tool. */
253
257
  async notifyUser(message) {
254
- if (!this.gatewayConfig)
258
+ const target = this.getActiveChannelId();
259
+ if (!this.gatewayConfig || !target)
255
260
  return;
256
261
  try {
257
262
  await (0, gateway_client_1.invokeGatewayTool)({
258
263
  gateway: this.gatewayConfig,
259
264
  tool: "message",
260
- args: { action: "send", message },
265
+ args: { action: "send", target, message },
261
266
  timeoutMs: 5_000,
262
267
  });
263
268
  }
@@ -9,6 +9,7 @@ export type MulticlawsServiceOptions = {
9
9
  port?: number;
10
10
  displayName?: string;
11
11
  selfUrl?: string;
12
+ cwd?: string;
12
13
  tunnel?: FrpTunnelConfig & {
13
14
  type: "frp";
14
15
  };
@@ -43,6 +44,8 @@ export declare class MulticlawsService extends EventEmitter {
43
44
  private selfUrl;
44
45
  private profileDescription;
45
46
  private readonly gatewayConfig;
47
+ private readonly resolvedCwd;
48
+ private activeChannelId;
46
49
  constructor(options: MulticlawsServiceOptions);
47
50
  start(): Promise<void>;
48
51
  stop(): Promise<void>;
@@ -123,6 +126,8 @@ export declare class MulticlawsService extends EventEmitter {
123
126
  private extractArtifactText;
124
127
  /** Fetch with up to 2 retries and exponential backoff. */
125
128
  private fetchWithRetry;
129
+ /** Update the active channel ID used for notifications. */
130
+ setActiveChannelId(channelId: string): void;
126
131
  /** Send a notification message to the local user via the gateway message tool. */
127
132
  private notifyUser;
128
133
  private log;
@@ -67,6 +67,8 @@ class MulticlawsService extends node_events_1.EventEmitter {
67
67
  selfUrl;
68
68
  profileDescription = "OpenClaw agent";
69
69
  gatewayConfig;
70
+ resolvedCwd;
71
+ activeChannelId = null;
70
72
  constructor(options) {
71
73
  super();
72
74
  this.options = options;
@@ -81,6 +83,7 @@ class MulticlawsService extends node_events_1.EventEmitter {
81
83
  // selfUrl resolved later in start() after FRP tunnel setup
82
84
  this.selfUrl = options.selfUrl ?? "";
83
85
  this.gatewayConfig = options.gatewayConfig ?? null;
86
+ this.resolvedCwd = options.cwd || node_os_1.default.homedir();
84
87
  }
85
88
  async start() {
86
89
  if (this.started)
@@ -119,6 +122,8 @@ class MulticlawsService extends node_events_1.EventEmitter {
119
122
  this.agentExecutor = new a2a_adapter_1.OpenClawAgentExecutor({
120
123
  gatewayConfig: this.options.gatewayConfig ?? null,
121
124
  taskTracker: this.taskTracker,
125
+ cwd: this.resolvedCwd,
126
+ getActiveChannelId: () => this.activeChannelId,
122
127
  logger,
123
128
  });
124
129
  this.agentCard = {
@@ -357,7 +362,7 @@ class MulticlawsService extends node_events_1.EventEmitter {
357
362
  await (0, gateway_client_1.invokeGatewayTool)({
358
363
  gateway: this.gatewayConfig,
359
364
  tool: "sessions_spawn",
360
- args: { task: prompt, mode: "run", cwd: process.cwd() },
365
+ args: { task: prompt, mode: "run", cwd: this.resolvedCwd },
361
366
  sessionKey: `delegate-${Date.now()}`,
362
367
  timeoutMs: 15_000,
363
368
  });
@@ -914,15 +919,20 @@ class MulticlawsService extends node_events_1.EventEmitter {
914
919
  }
915
920
  throw lastError;
916
921
  }
922
+ /** Update the active channel ID used for notifications. */
923
+ setActiveChannelId(channelId) {
924
+ this.activeChannelId = channelId;
925
+ this.log("debug", `activeChannelId set to: ${channelId}`);
926
+ }
917
927
  /** Send a notification message to the local user via the gateway message tool. */
918
928
  async notifyUser(message) {
919
- if (!this.gatewayConfig)
929
+ if (!this.gatewayConfig || !this.activeChannelId)
920
930
  return;
921
931
  try {
922
932
  await (0, gateway_client_1.invokeGatewayTool)({
923
933
  gateway: this.gatewayConfig,
924
934
  tool: "message",
925
- args: { action: "send", message },
935
+ args: { action: "send", target: this.activeChannelId, message },
926
936
  timeoutMs: 5_000,
927
937
  });
928
938
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multiclaws",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
4
4
  "description": "MultiClaws plugin for OpenClaw collaboration via A2A protocol",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",