@matelink/cli 2026.4.18 → 2026.4.19

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.
Files changed (2) hide show
  1. package/bin/matecli.mjs +39 -11
  2. package/package.json +1 -1
package/bin/matecli.mjs CHANGED
@@ -3152,13 +3152,11 @@ function createGatewayWsClient({ gatewayBaseUrl, gatewayAuthToken }) {
3152
3152
  connectTimer = null;
3153
3153
  }
3154
3154
  const role = "operator";
3155
- const scopes = [
3156
- "operator.admin",
3157
- "operator.read",
3158
- "operator.write",
3159
- "operator.approvals",
3160
- "operator.pairing",
3161
- ];
3155
+ // The bridge WS client only performs read-side gateway RPCs such as
3156
+ // config.get, sessions.list, skills.status, and chat.history. Asking
3157
+ // for broader scopes causes local token-mode gateways to reject the
3158
+ // connection with a scope-upgrade/pairing-required error.
3159
+ const scopes = ["operator.read"];
3162
3160
  const clientId = "openclaw-macos";
3163
3161
  const clientMode = "ui";
3164
3162
  const signedAtMs = Date.now();
@@ -3287,6 +3285,11 @@ async function callGatewayRpcLocal({
3287
3285
  return callWorkspaceRpcLocal({ method, params });
3288
3286
  }
3289
3287
 
3288
+ if (method === "config.get" || method === "sessions.list") {
3289
+ const client = getOrCreateGatewayWsClient({ gatewayBaseUrl, gatewayAuthToken });
3290
+ return client.call(method, params ?? {});
3291
+ }
3292
+
3290
3293
  // Prefer CLI first for broad compatibility, but fall back to the persistent
3291
3294
  // WS client when the CLI gateway call hits transient websocket closures.
3292
3295
  try {
@@ -3313,7 +3316,10 @@ function shouldFallbackGatewayRpcViaWs(error) {
3313
3316
  message.includes("(1006") ||
3314
3317
  message.includes("no close reason") ||
3315
3318
  message.includes("gateway ws error") ||
3316
- message.includes("gateway disconnected")
3319
+ message.includes("gateway disconnected") ||
3320
+ message.includes("spawn openclaw enoent") ||
3321
+ message.includes("enoent") ||
3322
+ message.includes("gateway call timed out")
3317
3323
  );
3318
3324
  }
3319
3325
 
@@ -3354,7 +3360,7 @@ async function callGatewayRpcLocalViaCli({
3354
3360
  }
3355
3361
  }, GATEWAY_RPC_CLI_TIMEOUT_MS);
3356
3362
 
3357
- const [stdoutChunks, stderrChunks] = await Promise.all([
3363
+ const [stdoutChunks, stderrChunks, spawnError] = await Promise.all([
3358
3364
  new Promise((resolve) => {
3359
3365
  const chunks = [];
3360
3366
  child.stdout?.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
@@ -3367,10 +3373,18 @@ async function callGatewayRpcLocalViaCli({
3367
3373
  child.stderr?.on("end", () => resolve(chunks));
3368
3374
  child.stderr?.on("error", () => resolve(chunks));
3369
3375
  }),
3376
+ new Promise((resolve) => {
3377
+ child.once("error", (error) => resolve(error));
3378
+ child.once("spawn", () => resolve(null));
3379
+ }),
3370
3380
  new Promise((resolve) => child.on("close", resolve)),
3371
3381
  ]);
3372
3382
  clearTimeout(timeout);
3373
3383
 
3384
+ if (spawnError instanceof Error) {
3385
+ throw spawnError;
3386
+ }
3387
+
3374
3388
  const stdoutText = Buffer.concat(stdoutChunks).toString("utf8");
3375
3389
  const stderrText = Buffer.concat(stderrChunks).toString("utf8");
3376
3390
  if (timedOut) {
@@ -3595,6 +3609,11 @@ async function proxyGatewayRequestLocal({
3595
3609
  const reader = response.body.getReader();
3596
3610
  const decoder = new TextDecoder();
3597
3611
 
3612
+ // Fire-and-forget chunk publishing: don't await each POST so the reader
3613
+ // is never blocked by network round-trips. We keep an ordered queue of
3614
+ // in-flight promises and drain it before sending the final "end" event.
3615
+ const inflightChunks = [];
3616
+
3598
3617
  while (true) {
3599
3618
  const { done, value } = await reader.read();
3600
3619
  if (done) {
@@ -3604,7 +3623,7 @@ async function proxyGatewayRequestLocal({
3604
3623
  if (!text) {
3605
3624
  continue;
3606
3625
  }
3607
- await publishRelayGatewayEvent({
3626
+ const p = publishRelayGatewayEvent({
3608
3627
  relayUrl,
3609
3628
  gatewayId,
3610
3629
  gatewayToken,
@@ -3613,12 +3632,15 @@ async function proxyGatewayRequestLocal({
3613
3632
  event: "chunk",
3614
3633
  data: text,
3615
3634
  },
3635
+ }).catch((err) => {
3636
+ console.error(`[relay chunk publish error] ${err?.message || err}`);
3616
3637
  });
3638
+ inflightChunks.push(p);
3617
3639
  }
3618
3640
 
3619
3641
  const tail = decoder.decode();
3620
3642
  if (tail) {
3621
- await publishRelayGatewayEvent({
3643
+ const p = publishRelayGatewayEvent({
3622
3644
  relayUrl,
3623
3645
  gatewayId,
3624
3646
  gatewayToken,
@@ -3627,9 +3649,15 @@ async function proxyGatewayRequestLocal({
3627
3649
  event: "chunk",
3628
3650
  data: tail,
3629
3651
  },
3652
+ }).catch((err) => {
3653
+ console.error(`[relay tail publish error] ${err?.message || err}`);
3630
3654
  });
3655
+ inflightChunks.push(p);
3631
3656
  }
3632
3657
 
3658
+ // Wait for all chunk publishes to complete before sending "end".
3659
+ await Promise.all(inflightChunks);
3660
+
3633
3661
  await publishRelayGatewayEvent({
3634
3662
  relayUrl,
3635
3663
  gatewayId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matelink/cli",
3
- "version": "2026.4.18",
3
+ "version": "2026.4.19",
4
4
  "private": false,
5
5
  "description": "Relay-first CLI for pairing and bridging OpenClaw gateway traffic",
6
6
  "type": "module",