@openclaw/signal 2026.11.3 → 2026.11.5-beta.2

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 (179) hide show
  1. package/dist/.setup/{accounts-B0Pba1-q.mjs → accounts-enJKL3ci.mjs} +4 -8
  2. package/dist/.setup/api-CrasQEKI.mjs +14 -0
  3. package/dist/.setup/{api-CbN3mye4.mjs → api-DljZsfUn.mjs} +9 -11
  4. package/dist/.setup/{approval-auth-DhUKkSkA.mjs → approval-auth-B_5Ytx8K.mjs} +7 -11
  5. package/dist/.setup/{approval-handler.runtime-CsEcBZoc.mjs → approval-handler.runtime-0RbVmTxx.mjs} +7 -8
  6. package/dist/.setup/{approval-reactions-JsqCEOHK.mjs → approval-reactions-CvqVSSx8.mjs} +16 -24
  7. package/dist/.setup/{channel-CM-rLLPN.mjs → channel-ByJj8fSh.mjs} +417 -372
  8. package/dist/.setup/{client-Duwqbgqi.mjs → client-CesmEjRc.mjs} +170 -186
  9. package/dist/.setup/{config-schema-DvxZ18SD.mjs → config-schema-BCmW0BLB.mjs} +2 -5
  10. package/dist/.setup/{doctor-contract-api-BIdVW0PF.mjs → doctor-contract-api-CcLwIhsD.mjs} +88 -95
  11. package/dist/.setup/{identity-B3JyPqGO.mjs → identity-vKtR3DrM.mjs} +39 -2
  12. package/dist/.setup/{install-signal-cli-hYVLYGXe.mjs → install-signal-cli-DvLDZfpP.mjs} +95 -109
  13. package/dist/.setup/{transport-url-CAC0JcuI.mjs → legacy-transport-D_cZC3bS.mjs} +18 -1
  14. package/dist/.setup/{monitor-C6u1JV2C.mjs → monitor-Cf5sihwl.mjs} +166 -239
  15. package/dist/.setup/{probe-D_93QCe0.mjs → probe-Caq5Y4kA.mjs} +3 -3
  16. package/dist/.setup/{send-CM7-016e.mjs → send-BJuOWLky.mjs} +34 -66
  17. package/dist/.setup/{setup-surface-DvKLwYrl.mjs → setup-surface-DQ1yFZmY.mjs} +3 -3
  18. package/dist/.setup/{transport-detection-CmlgOybe.mjs → transport-detection-DvR6X_UQ.mjs} +3 -3
  19. package/dist/.setup/{transport-policy-B6C_LogW.mjs → transport-policy-zIR3lRUj.mjs} +1 -1
  20. package/dist/.setup/transport-probes.runtime-CoH6UFtc.mjs +1 -0
  21. package/dist/.source-module-urls/b02c526df8b90083105b63e5b51d5c8bbfe02676df72f6be8dd8f825817b32b9.json +1 -0
  22. package/dist/api.js +9 -11
  23. package/dist/channel-config-api.js +1 -2
  24. package/dist/channel-plugin-api.js +1 -2
  25. package/dist/contract-api.js +3 -4
  26. package/dist/doctor-contract-api.js +1 -2
  27. package/dist/runtime-api.js +1 -2
  28. package/dist/setup-entry.js +1 -1
  29. package/node_modules/@openclaw/fs-safe/CHANGELOG.md +94 -0
  30. package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
  31. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +1 -1
  32. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +3 -1
  33. package/node_modules/@openclaw/fs-safe/dist/copy-path-admission.js +2 -2
  34. package/node_modules/@openclaw/fs-safe/dist/copy-root-file-sync.js +8 -1
  35. package/node_modules/@openclaw/fs-safe/dist/file-open-error.d.ts +2 -0
  36. package/node_modules/@openclaw/fs-safe/dist/file-open-error.js +14 -0
  37. package/node_modules/@openclaw/fs-safe/dist/file-sync.d.ts +2 -1
  38. package/node_modules/@openclaw/fs-safe/dist/file-sync.js +6 -1
  39. package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +3 -0
  40. package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +1 -0
  41. package/node_modules/@openclaw/fs-safe/dist/native-config.js +14 -3
  42. package/node_modules/@openclaw/fs-safe/dist/native-operations.js +2 -0
  43. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.js +9 -2
  44. package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +40 -32
  45. package/node_modules/@openclaw/fs-safe/dist/output.js +6 -0
  46. package/node_modules/@openclaw/fs-safe/dist/owner-dacl.d.ts +2 -0
  47. package/node_modules/@openclaw/fs-safe/dist/owner-dacl.js +1 -0
  48. package/node_modules/@openclaw/fs-safe/dist/path.js +5 -1
  49. package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +25 -2
  50. package/node_modules/@openclaw/fs-safe/dist/publication-handle.d.ts +4 -0
  51. package/node_modules/@openclaw/fs-safe/dist/publication-handle.js +32 -0
  52. package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.d.ts +2 -1
  53. package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +19 -9
  54. package/node_modules/@openclaw/fs-safe/dist/publish-file.js +23 -24
  55. package/node_modules/@openclaw/fs-safe/dist/publish-rename-fallback.d.ts +21 -0
  56. package/node_modules/@openclaw/fs-safe/dist/publish-rename-fallback.js +102 -0
  57. package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +2 -0
  58. package/node_modules/@openclaw/fs-safe/dist/root-directory-entry.d.ts +3 -1
  59. package/node_modules/@openclaw/fs-safe/dist/root-directory-entry.js +8 -5
  60. package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +3 -0
  61. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +2 -1
  62. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +19 -9
  63. package/node_modules/@openclaw/fs-safe/dist/root-file-final-admission.js +3 -3
  64. package/node_modules/@openclaw/fs-safe/dist/root-path-existing.d.ts +2 -2
  65. package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +27 -13
  66. package/node_modules/@openclaw/fs-safe/dist/root-path.js +2 -2
  67. package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.d.ts +3 -0
  68. package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +18 -3
  69. package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +1 -1
  70. package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +68 -21
  71. package/node_modules/@openclaw/fs-safe/dist/watch-io-error.d.ts +2 -0
  72. package/node_modules/@openclaw/fs-safe/dist/watch-io-error.js +27 -0
  73. package/node_modules/@openclaw/fs-safe/dist/watch-io-worker.d.ts +1 -0
  74. package/node_modules/@openclaw/fs-safe/dist/watch-io-worker.js +93 -0
  75. package/node_modules/@openclaw/fs-safe/dist/watch-io.d.ts +47 -0
  76. package/node_modules/@openclaw/fs-safe/dist/watch-io.js +236 -0
  77. package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +1 -1
  78. package/node_modules/@openclaw/fs-safe/dist/watch-native.js +3 -3
  79. package/node_modules/@openclaw/fs-safe/dist/watch-probe.d.ts +16 -0
  80. package/node_modules/@openclaw/fs-safe/dist/watch-probe.js +135 -0
  81. package/node_modules/@openclaw/fs-safe/dist/watch-rescan.d.ts +1 -1
  82. package/node_modules/@openclaw/fs-safe/dist/watch-rescan.js +86 -24
  83. package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +4 -0
  84. package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +78 -16
  85. package/node_modules/@openclaw/fs-safe/dist/watch-stream.d.ts +2 -0
  86. package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +23 -0
  87. package/node_modules/@openclaw/fs-safe/dist/watch-types.d.ts +3 -1
  88. package/node_modules/@openclaw/fs-safe/dist/watch.js +60 -13
  89. package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.d.ts +1 -1
  90. package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.js +1 -0
  91. package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.exe +0 -0
  92. package/node_modules/@openclaw/fs-safe/docs/advanced.md +5 -2
  93. package/node_modules/@openclaw/fs-safe/docs/compiler-qualification.md +392 -0
  94. package/node_modules/@openclaw/fs-safe/docs/config.md +7 -1
  95. package/node_modules/@openclaw/fs-safe/docs/contributing.md +25 -5
  96. package/node_modules/@openclaw/fs-safe/docs/copy.md +10 -0
  97. package/node_modules/@openclaw/fs-safe/docs/durability.md +9 -3
  98. package/node_modules/@openclaw/fs-safe/docs/errors.md +13 -0
  99. package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +6 -4
  100. package/node_modules/@openclaw/fs-safe/docs/native-helper.md +6 -4
  101. package/node_modules/@openclaw/fs-safe/docs/output.md +4 -2
  102. package/node_modules/@openclaw/fs-safe/docs/path.md +5 -2
  103. package/node_modules/@openclaw/fs-safe/docs/permissions.md +15 -0
  104. package/node_modules/@openclaw/fs-safe/docs/security-model.md +9 -0
  105. package/node_modules/@openclaw/fs-safe/docs/staged-file.md +2 -0
  106. package/node_modules/@openclaw/fs-safe/docs/testing.md +1 -1
  107. package/node_modules/@openclaw/fs-safe/docs/watch.md +62 -5
  108. package/node_modules/@openclaw/fs-safe/docs/writing.md +6 -1
  109. package/node_modules/@openclaw/fs-safe/package.json +18 -16
  110. package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
  111. package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
  112. package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
  113. package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
  114. package/node_modules/@openclaw/fs-safe-freebsd-arm64/fs-safe-native.node +0 -0
  115. package/node_modules/@openclaw/fs-safe-freebsd-arm64/package.json +1 -1
  116. package/node_modules/@openclaw/fs-safe-freebsd-x64/fs-safe-native.node +0 -0
  117. package/node_modules/@openclaw/fs-safe-freebsd-x64/package.json +1 -1
  118. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
  119. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
  120. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
  121. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
  122. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
  123. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
  124. package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
  125. package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
  126. package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/fs-safe-native.node +0 -0
  127. package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/package.json +1 -1
  128. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
  129. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
  130. package/node_modules/zod/package.json +1 -1
  131. package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
  132. package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
  133. package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
  134. package/node_modules/zod/src/v4/core/compile.ts +9 -0
  135. package/node_modules/zod/src/v4/core/schemas.ts +35 -1
  136. package/node_modules/zod/src/v4/core/util.ts +13 -0
  137. package/node_modules/zod/src/v4/core/versions.ts +1 -1
  138. package/node_modules/zod/v4/core/compile.cjs +8 -0
  139. package/node_modules/zod/v4/core/compile.js +8 -0
  140. package/node_modules/zod/v4/core/schemas.cjs +30 -0
  141. package/node_modules/zod/v4/core/schemas.d.cts +3 -1
  142. package/node_modules/zod/v4/core/schemas.d.ts +3 -1
  143. package/node_modules/zod/v4/core/schemas.js +30 -0
  144. package/node_modules/zod/v4/core/util.cjs +15 -0
  145. package/node_modules/zod/v4/core/util.d.cts +2 -0
  146. package/node_modules/zod/v4/core/util.d.ts +2 -0
  147. package/node_modules/zod/v4/core/util.js +14 -0
  148. package/node_modules/zod/v4/core/versions.cjs +1 -1
  149. package/node_modules/zod/v4/core/versions.js +1 -1
  150. package/openclaw.plugin.json +0 -30
  151. package/package.json +6 -8
  152. package/dist/.setup/api-CJBtD3lT.mjs +0 -16
  153. package/dist/.setup/client-adapter-Chnbch_z.mjs +0 -30
  154. package/dist/.setup/legacy-transport-QIpaMNST.mjs +0 -18
  155. package/dist/.setup/normalize-D7kSomXt.mjs +0 -39
  156. package/dist/.setup/reaction-runtime-api-mdO4k0yv.mjs +0 -65
  157. package/dist/.setup/reaction-targets-BgPLDHBf.mjs +0 -72
  158. package/dist/.setup/rpc-context-BAXcX7dI.mjs +0 -13
  159. package/dist/.setup/transport-probes.runtime-D-xIMRcn.mjs +0 -2
  160. package/dist/reaction-runtime-api.js +0 -2
  161. package/node_modules/ws/LICENSE +0 -20
  162. package/node_modules/ws/README.md +0 -548
  163. package/node_modules/ws/browser.js +0 -8
  164. package/node_modules/ws/index.js +0 -22
  165. package/node_modules/ws/lib/buffer-util.js +0 -131
  166. package/node_modules/ws/lib/constants.js +0 -19
  167. package/node_modules/ws/lib/event-target.js +0 -292
  168. package/node_modules/ws/lib/extension.js +0 -203
  169. package/node_modules/ws/lib/limiter.js +0 -55
  170. package/node_modules/ws/lib/permessage-deflate.js +0 -530
  171. package/node_modules/ws/lib/receiver.js +0 -743
  172. package/node_modules/ws/lib/sender.js +0 -607
  173. package/node_modules/ws/lib/stream.js +0 -161
  174. package/node_modules/ws/lib/subprotocol.js +0 -62
  175. package/node_modules/ws/lib/validation.js +0 -152
  176. package/node_modules/ws/lib/websocket-server.js +0 -562
  177. package/node_modules/ws/lib/websocket.js +0 -1421
  178. package/node_modules/ws/package.json +0 -74
  179. package/node_modules/ws/wrapper.mjs +0 -21
@@ -1,29 +1,25 @@
1
- import { createRequire } from "node:module";
2
1
  import { fileURLToPath } from "node:url";
3
2
  import { isRecord, normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
3
  import net, { createConnection } from "node:net";
5
4
  import path from "node:path";
6
5
  import { detectMime, extractOriginalFilename, parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
7
- import { asNonNegativeFiniteNumber, asPositiveFiniteNumber, parseStrictNonNegativeInteger, resolvePositiveTimerTimeoutMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
6
+ import { asNonNegativeFiniteNumber, asPositiveFiniteNumber, floorPositiveFiniteNumber, parseStrictNonNegativeInteger, resolvePositiveTimerTimeoutMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
8
7
  import { coerceErrorMessage, formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
9
8
  import { captureEffectAuthority, resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
10
9
  import { readResponseTextPrefix, readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
11
10
  import { readRegularFile } from "openclaw/plugin-sdk/security-runtime";
11
+ import { WebSocket, startWebSocketKeepalive } from "openclaw/plugin-sdk/websocket-runtime";
12
12
  import { Buffer as Buffer$1 } from "node:buffer";
13
+ import { randomUUID } from "node:crypto";
13
14
  import http from "node:http";
14
15
  import https from "node:https";
15
16
  import { generateSecureUuid } from "openclaw/plugin-sdk/core";
16
- import { randomUUID } from "node:crypto";
17
17
  import { execFile } from "node:child_process";
18
18
  import { lstat, mkdir, rmdir, unlink } from "node:fs/promises";
19
19
  import os from "node:os";
20
20
  import { promisify } from "node:util";
21
- //#region extensions/signal/src/ws-runtime.ts
22
- const require = createRequire(import.meta.url);
23
- const WebSocket = require(path.join(path.dirname(require.resolve("ws/package.json")), "index.js"));
24
- //#endregion
25
21
  //#region extensions/signal/src/client-container.ts
26
- const DEFAULT_TIMEOUT_MS$2 = 1e4;
22
+ const DEFAULT_TIMEOUT_MS$1 = 1e4;
27
23
  const DEFAULT_ATTACHMENT_RESPONSE_MAX_BYTES = 1048576;
28
24
  const SIGNAL_REST_ERROR_RESPONSE_MAX_BYTES = 16384;
29
25
  const SIGNAL_REST_SUCCESS_RESPONSE_MAX_BYTES = 16777216;
@@ -59,7 +55,7 @@ function signalRestRequestTimeoutError() {
59
55
  }
60
56
  /** Keep one absolute deadline across headers and every bounded body reader. */
61
57
  async function withSignalRestDeadline(timeoutMs, run) {
62
- const safeTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$2);
58
+ const safeTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$1);
63
59
  const deadlineAtMs = Date.now() + safeTimeoutMs;
64
60
  const controller = new AbortController();
65
61
  const timer = setTimeout(() => controller.abort(signalRestRequestTimeoutError()), safeTimeoutMs);
@@ -83,7 +79,7 @@ function signalRestIdleTimeoutError({ chunkTimeoutMs }) {
83
79
  function releaseUnreadResponseBody(res) {
84
80
  if (res?.bodyUsed !== true) res?.body?.cancel().catch(() => void 0);
85
81
  }
86
- async function containerCheck(baseUrl, timeoutMs = DEFAULT_TIMEOUT_MS$2, account) {
82
+ async function containerCheck(baseUrl, timeoutMs = DEFAULT_TIMEOUT_MS$1, account) {
87
83
  const normalized = normalizeBaseUrl$1(baseUrl);
88
84
  let res;
89
85
  try {
@@ -118,7 +114,7 @@ async function containerCheck(baseUrl, timeoutMs = DEFAULT_TIMEOUT_MS$2, account
118
114
  function containerReceiveCheck(normalizedBaseUrl, account, timeoutMs) {
119
115
  const wsUrl = `${normalizedBaseUrl.replace(/^http/, "ws")}/v1/receive/${encodeURIComponent(account)}`;
120
116
  return new Promise((resolve) => {
121
- const safeTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$2);
117
+ const safeTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$1);
122
118
  let settled = false;
123
119
  let ws;
124
120
  const timer = setTimeout(() => {
@@ -187,8 +183,8 @@ async function containerRestRequest(endpoint, opts, method = "GET", body) {
187
183
  headers: { "Content-Type": "application/json" }
188
184
  };
189
185
  if (body) init.body = JSON.stringify(body);
190
- const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$2;
191
- const bodyIdleTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$2);
186
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$1;
187
+ const bodyIdleTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$1);
192
188
  const fetchImpl = resolveFetch();
193
189
  if (!fetchImpl) throw new Error("fetch is not available");
194
190
  return await withSignalRestDeadline(timeoutMs, async ({ signal, timeoutMs: bodyTimeoutMs }) => {
@@ -232,8 +228,8 @@ async function containerRestRequest(endpoint, opts, method = "GET", body) {
232
228
  }
233
229
  async function containerFetchAttachment(attachmentId, opts) {
234
230
  const url = `${normalizeBaseUrl$1(opts.baseUrl)}/v1/attachments/${encodeURIComponent(attachmentId)}`;
235
- const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$2;
236
- const bodyIdleTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$2);
231
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$1;
232
+ const bodyIdleTimeoutMs = resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS$1);
237
233
  const fetchImpl = resolveFetch();
238
234
  if (!fetchImpl) throw new Error("fetch is not available");
239
235
  return await withSignalRestDeadline(timeoutMs, async ({ signal, timeoutMs: bodyTimeoutMs }) => {
@@ -312,6 +308,11 @@ async function streamContainerEvents(params) {
312
308
  }
313
309
  ws.on("open", () => {
314
310
  log("[signal-ws] connected");
311
+ startWebSocketKeepalive(ws, () => {
312
+ if (ws.isPaused) return;
313
+ logError("[signal-ws] heartbeat timed out; reconnecting");
314
+ ws.terminate();
315
+ });
315
316
  params.onStreamOpen?.();
316
317
  });
317
318
  ws.on("message", (data) => {
@@ -329,8 +330,8 @@ async function streamContainerEvents(params) {
329
330
  ws.close();
330
331
  });
331
332
  }
332
- } catch (err) {
333
- logError(`[signal-ws] parse error: ${coerceErrorMessage(err)}`);
333
+ } catch {
334
+ logError("[signal-ws] parse error: invalid JSON frame");
334
335
  }
335
336
  });
336
337
  ws.on("error", (err) => {
@@ -344,9 +345,6 @@ async function streamContainerEvents(params) {
344
345
  ws.on("ping", () => {
345
346
  log("[signal-ws] ping received");
346
347
  });
347
- ws.on("pong", () => {
348
- log("[signal-ws] pong received");
349
- });
350
348
  if (params.abortSignal) {
351
349
  abortHandler = () => {
352
350
  log("[signal-ws] aborted, closing connection");
@@ -660,142 +658,6 @@ async function prepareSignalSocketPath(socketPath, abortSignal) {
660
658
  }
661
659
  }
662
660
  //#endregion
663
- //#region extensions/signal/src/client-unix.ts
664
- const MAX_FRAME_BYTES = 1048576;
665
- const DEFAULT_TIMEOUT_MS$1 = 1e4;
666
- function socketPath(baseUrl) {
667
- const url = new URL(baseUrl.trim());
668
- if (url.protocol !== "unix:" || url.host || url.username || url.password || url.search || url.hash) throw new Error("Signal UNIX URL must contain only an absolute socket path");
669
- return fileURLToPath(`file://${url.pathname}`);
670
- }
671
- function abortError() {
672
- return Object.assign(/* @__PURE__ */ new Error("Signal UNIX stream aborted"), { name: "AbortError" });
673
- }
674
- async function openSocket(options, abortSignal) {
675
- if (abortSignal?.aborted) throw abortError();
676
- const path = socketPath(options.baseUrl);
677
- await assertSignalSocketEndpoint(path);
678
- if (abortSignal?.aborted) throw abortError();
679
- const socket = net.createConnection({ path });
680
- socket.on("error", () => {});
681
- const timeoutMs = resolveTimerTimeoutMs(options.timeoutMs ?? DEFAULT_TIMEOUT_MS$1, DEFAULT_TIMEOUT_MS$1);
682
- const deadline = setTimeout(() => {
683
- socket.destroy(/* @__PURE__ */ new Error(`Signal UNIX RPC exceeded deadline after ${timeoutMs}ms`));
684
- }, timeoutMs);
685
- deadline.unref();
686
- const onAbort = () => socket.destroy(abortError());
687
- abortSignal?.addEventListener("abort", onAbort, { once: true });
688
- return {
689
- socket,
690
- ready: () => clearTimeout(deadline),
691
- close: () => {
692
- clearTimeout(deadline);
693
- abortSignal?.removeEventListener("abort", onAbort);
694
- socket.destroy();
695
- }
696
- };
697
- }
698
- async function* messages(socket, maxBytes = MAX_FRAME_BYTES) {
699
- let pending = Buffer$1.alloc(0);
700
- for await (const chunk of socket) {
701
- if (!Buffer$1.isBuffer(chunk)) throw new Error("Signal UNIX RPC expected a byte stream");
702
- let offset = 0;
703
- while (offset < chunk.length) {
704
- const newline = chunk.indexOf(10, offset);
705
- const end = newline < 0 ? chunk.length : newline;
706
- const fragment = chunk.subarray(offset, end);
707
- if (pending.length + fragment.length > maxBytes) throw new Error("Signal UNIX RPC frame exceeded size limit");
708
- pending = Buffer$1.concat([pending, fragment]);
709
- if (newline < 0) break;
710
- const text = new TextDecoder("utf-8", { fatal: true }).decode(pending);
711
- pending = Buffer$1.alloc(0);
712
- offset = newline + 1;
713
- let parsed;
714
- try {
715
- parsed = JSON.parse(text);
716
- } catch {
717
- throw new Error("Signal UNIX RPC returned malformed JSON");
718
- }
719
- if (!isRecord(parsed)) throw new Error("Signal UNIX RPC returned invalid response envelope");
720
- yield parsed;
721
- }
722
- }
723
- if (pending.length) throw new Error("Signal UNIX RPC closed with an incomplete frame");
724
- }
725
- function result(message) {
726
- if (message.jsonrpc !== "2.0" || !Object.hasOwn(message, "result") && !message.error) throw new Error("Signal UNIX RPC returned invalid response envelope");
727
- if (message.error) {
728
- const error = isRecord(message.error) ? message.error : {};
729
- const code = typeof error.code === "number" ? error.code : "unknown";
730
- if (typeof error.message === "string" && isSignalQuoteMetadataRejection(`Signal RPC ${code}: ${error.message}`)) throw new Error(`Signal RPC ${code}: quote metadata rejected (redacted)`);
731
- throw new Error(`Signal RPC ${code}: remote error`);
732
- }
733
- return message.result;
734
- }
735
- async function signalUnixRpcRequest(method, params, options) {
736
- const effect = captureEffectAuthority();
737
- const connection = await openSocket(options);
738
- const id = randomUUID();
739
- const maxBytes = typeof options.maxResponseBytes === "number" && Number.isFinite(options.maxResponseBytes) && options.maxResponseBytes >= 1 ? Math.floor(options.maxResponseBytes) : MAX_FRAME_BYTES;
740
- try {
741
- const frame = `${JSON.stringify({
742
- jsonrpc: "2.0",
743
- id,
744
- method,
745
- params
746
- })}\n`;
747
- await effect.initiate(() => {
748
- options.assertDirectAdapterHandoff?.();
749
- connection.socket.write(frame);
750
- });
751
- for await (const message of messages(connection.socket, maxBytes)) if (message.id === id) return result(message);
752
- throw new Error("Signal UNIX RPC closed before response");
753
- } finally {
754
- connection.close();
755
- }
756
- }
757
- async function streamSignalUnixEvents(params) {
758
- const connection = await openSocket({
759
- ...params,
760
- timeoutMs: params.timeoutMs === 0 ? DEFAULT_TIMEOUT_MS$1 : params.timeoutMs
761
- }, params.abortSignal);
762
- const id = randomUUID();
763
- let subscription;
764
- try {
765
- connection.socket.write(`${JSON.stringify({
766
- jsonrpc: "2.0",
767
- id,
768
- method: "subscribeReceive",
769
- params: params.account ? { account: params.account } : void 0
770
- })}\n`);
771
- for await (const message of messages(connection.socket)) {
772
- if (params.abortSignal?.aborted) throw abortError();
773
- if (message.id === id) {
774
- const value = result(message);
775
- if (typeof value !== "number" || !Number.isInteger(value) || value < 0) throw new Error("Signal UNIX RPC returned invalid receive subscription");
776
- subscription = value;
777
- connection.ready();
778
- params.onStreamOpen?.();
779
- continue;
780
- }
781
- if (message.jsonrpc !== "2.0" || message.method !== "receive" || !isRecord(message.params)) continue;
782
- const notification = message.params;
783
- if (subscription !== void 0 && notification.subscription !== subscription) continue;
784
- const payload = notification.result;
785
- if (!isRecord(payload)) continue;
786
- const account = payload.account;
787
- if (params.account && typeof account === "string" && account !== params.account) continue;
788
- await params.onEvent({
789
- event: "receive",
790
- data: JSON.stringify(payload)
791
- });
792
- }
793
- if (subscription === void 0) throw new Error("Signal UNIX RPC closed before receive subscription");
794
- } finally {
795
- connection.close();
796
- }
797
- }
798
- //#endregion
799
661
  //#region extensions/signal/src/client.ts
800
662
  /** Thrown when the native SSE endpoint rejects the request with a non-2xx HTTP status. */
801
663
  var SignalSseRejectionError = class extends Error {
@@ -844,9 +706,6 @@ function parseSignalRpcResponse(text, status) {
844
706
  if (!rpc.error && !hasResult) throw new Error(`Signal RPC returned invalid response envelope (status ${status})`);
845
707
  return rpc;
846
708
  }
847
- function assertSignalHttpProtocol(url, label) {
848
- if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error(`Signal ${label} unsupported protocol: ${url.protocol}`);
849
- }
850
709
  function normalizeSignalSseTimeoutMs(timeoutMs) {
851
710
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) return null;
852
711
  return resolveTimerTimeoutMs(timeoutMs, DEFAULT_TIMEOUT_MS);
@@ -855,7 +714,6 @@ function requestSignalHttp(url, options) {
855
714
  return captureEffectAuthority().initiate(() => initiateSignalHttp(url, options));
856
715
  }
857
716
  function initiateSignalHttp(url, options) {
858
- assertSignalHttpProtocol(url, "HTTP");
859
717
  const timeoutMs = resolveTimerTimeoutMs(options.timeoutMs, DEFAULT_TIMEOUT_MS);
860
718
  const client = url.protocol === "https:" ? https : http;
861
719
  options.assertDirectAdapterHandoff?.();
@@ -864,13 +722,9 @@ function initiateSignalHttp(url, options) {
864
722
  request?.destroy(/* @__PURE__ */ new Error(`Signal HTTP exceeded deadline after ${timeoutMs}ms`));
865
723
  }, timeoutMs);
866
724
  deadline.unref?.();
867
- const cleanup = () => {
868
- clearTimeout(deadline);
869
- request?.setTimeout(0);
870
- };
871
725
  const rejectResponse = (error) => {
872
- cleanup();
873
- reject(toErrorObject(error, "Non-Error rejection"));
726
+ clearTimeout(deadline);
727
+ reject(error);
874
728
  };
875
729
  const maxResponseBytes = Math.floor(asPositiveFiniteNumber(options.maxResponseBytes) ?? DEFAULT_SIGNAL_HTTP_RESPONSE_MAX_BYTES);
876
730
  const request = client.request(url, {
@@ -893,21 +747,110 @@ function initiateSignalHttp(url, options) {
893
747
  });
894
748
  res.on("error", rejectResponse);
895
749
  res.on("end", () => {
896
- cleanup();
750
+ clearTimeout(deadline);
897
751
  resolve({
898
752
  status: res.statusCode ?? 0,
899
753
  body: Buffer$1.concat(chunks)
900
754
  });
901
755
  });
902
756
  });
903
- request.setTimeout(timeoutMs, () => {
904
- request?.destroy(/* @__PURE__ */ new Error(`Signal HTTP timed out after ${timeoutMs}ms`));
905
- });
906
757
  request.on("error", rejectResponse);
907
758
  if (options.body !== void 0) request.write(options.body);
908
759
  request.end();
909
760
  });
910
761
  }
762
+ const MAX_FRAME_BYTES = 1048576;
763
+ function socketPath(baseUrl) {
764
+ const url = new URL(baseUrl.trim());
765
+ if (url.protocol !== "unix:" || url.host || url.username || url.password || url.search || url.hash) throw new Error("Signal UNIX URL must contain only an absolute socket path");
766
+ return fileURLToPath(`file://${url.pathname}`);
767
+ }
768
+ function abortError() {
769
+ return Object.assign(/* @__PURE__ */ new Error("Signal UNIX stream aborted"), { name: "AbortError" });
770
+ }
771
+ async function openSocket(options, abortSignal) {
772
+ if (abortSignal?.aborted) throw abortError();
773
+ const path = socketPath(options.baseUrl);
774
+ await assertSignalSocketEndpoint(path);
775
+ if (abortSignal?.aborted) throw abortError();
776
+ const socket = net.createConnection({ path });
777
+ socket.on("error", () => {});
778
+ const timeoutMs = resolveTimerTimeoutMs(options.timeoutMs ?? DEFAULT_TIMEOUT_MS, DEFAULT_TIMEOUT_MS);
779
+ const deadline = setTimeout(() => {
780
+ socket.destroy(/* @__PURE__ */ new Error(`Signal UNIX RPC exceeded deadline after ${timeoutMs}ms`));
781
+ }, timeoutMs);
782
+ deadline.unref();
783
+ const onAbort = () => socket.destroy(abortError());
784
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
785
+ return {
786
+ socket,
787
+ ready: () => clearTimeout(deadline),
788
+ close: () => {
789
+ clearTimeout(deadline);
790
+ abortSignal?.removeEventListener("abort", onAbort);
791
+ socket.destroy();
792
+ }
793
+ };
794
+ }
795
+ async function* messages(socket, maxBytes = MAX_FRAME_BYTES) {
796
+ let pending = Buffer$1.alloc(0);
797
+ for await (const chunk of socket) {
798
+ if (!Buffer$1.isBuffer(chunk)) throw new Error("Signal UNIX RPC expected a byte stream");
799
+ let offset = 0;
800
+ while (offset < chunk.length) {
801
+ const newline = chunk.indexOf(10, offset);
802
+ const end = newline < 0 ? chunk.length : newline;
803
+ const fragment = chunk.subarray(offset, end);
804
+ if (pending.length + fragment.length > maxBytes) throw new Error("Signal UNIX RPC frame exceeded size limit");
805
+ pending = Buffer$1.concat([pending, fragment]);
806
+ if (newline < 0) break;
807
+ const text = new TextDecoder("utf-8", { fatal: true }).decode(pending);
808
+ pending = Buffer$1.alloc(0);
809
+ offset = newline + 1;
810
+ let parsed;
811
+ try {
812
+ parsed = JSON.parse(text);
813
+ } catch {
814
+ throw new Error("Signal UNIX RPC returned malformed JSON");
815
+ }
816
+ if (!isRecord(parsed)) throw new Error("Signal UNIX RPC returned invalid response envelope");
817
+ yield parsed;
818
+ }
819
+ }
820
+ if (pending.length) throw new Error("Signal UNIX RPC closed with an incomplete frame");
821
+ }
822
+ function result(message) {
823
+ if (message.jsonrpc !== "2.0" || !Object.hasOwn(message, "result") && !message.error) throw new Error("Signal UNIX RPC returned invalid response envelope");
824
+ if (message.error) {
825
+ const error = isRecord(message.error) ? message.error : {};
826
+ const code = typeof error.code === "number" ? error.code : "unknown";
827
+ if (typeof error.message === "string" && isSignalQuoteMetadataRejection(`Signal RPC ${code}: ${error.message}`)) throw new Error(`Signal RPC ${code}: quote metadata rejected (redacted)`);
828
+ throw new Error(`Signal RPC ${code}: remote error`);
829
+ }
830
+ return message.result;
831
+ }
832
+ async function signalUnixRpcRequest(method, params, options) {
833
+ const effect = captureEffectAuthority();
834
+ const connection = await openSocket(options);
835
+ const id = randomUUID();
836
+ const maxBytes = floorPositiveFiniteNumber(options.maxResponseBytes) || MAX_FRAME_BYTES;
837
+ try {
838
+ const frame = `${JSON.stringify({
839
+ jsonrpc: "2.0",
840
+ id,
841
+ method,
842
+ params
843
+ })}\n`;
844
+ await effect.initiate(() => {
845
+ options.assertDirectAdapterHandoff?.();
846
+ connection.socket.write(frame);
847
+ });
848
+ for await (const message of messages(connection.socket, maxBytes)) if (message.id === id) return result(message);
849
+ throw new Error("Signal UNIX RPC closed before response");
850
+ } finally {
851
+ connection.close();
852
+ }
853
+ }
911
854
  async function signalRpcRequest(method, params, opts) {
912
855
  if (opts.baseUrl.trim().startsWith("unix:")) return signalUnixRpcRequest(method, params, opts);
913
856
  const id = generateSecureUuid();
@@ -974,11 +917,56 @@ async function signalCheck(baseUrl, timeoutMs = DEFAULT_TIMEOUT_MS) {
974
917
  };
975
918
  }
976
919
  }
977
- function openSignalEventStream(url, abortSignal, timeoutMs = DEFAULT_TIMEOUT_MS) {
978
- assertSignalHttpProtocol(url, "SSE");
920
+ async function streamSignalEvents(params) {
921
+ if (params.baseUrl.trim().startsWith("unix:")) {
922
+ const connection = await openSocket({
923
+ ...params,
924
+ timeoutMs: params.timeoutMs === 0 ? DEFAULT_TIMEOUT_MS : params.timeoutMs
925
+ }, params.abortSignal);
926
+ const id = randomUUID();
927
+ let subscription;
928
+ try {
929
+ connection.socket.write(`${JSON.stringify({
930
+ jsonrpc: "2.0",
931
+ id,
932
+ method: "subscribeReceive",
933
+ params: params.account ? { account: params.account } : void 0
934
+ })}\n`);
935
+ for await (const message of messages(connection.socket)) {
936
+ if (params.abortSignal?.aborted) throw abortError();
937
+ if (message.id === id) {
938
+ const value = result(message);
939
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0) throw new Error("Signal UNIX RPC returned invalid receive subscription");
940
+ subscription = value;
941
+ connection.ready();
942
+ params.onStreamOpen?.();
943
+ continue;
944
+ }
945
+ if (message.jsonrpc !== "2.0" || message.method !== "receive" || !isRecord(message.params)) continue;
946
+ const notification = message.params;
947
+ if (subscription !== void 0 && notification.subscription !== subscription) continue;
948
+ const payload = notification.result;
949
+ if (!isRecord(payload)) continue;
950
+ const account = payload.account;
951
+ if (params.account && typeof account === "string" && account !== params.account) continue;
952
+ await params.onEvent({
953
+ event: "receive",
954
+ data: JSON.stringify(payload)
955
+ });
956
+ }
957
+ if (subscription === void 0) throw new Error("Signal UNIX RPC closed before receive subscription");
958
+ } finally {
959
+ connection.close();
960
+ }
961
+ return;
962
+ }
963
+ const url = resolveSignalEndpointUrl(params.baseUrl, "/api/v1/events");
964
+ if (params.account) url.searchParams.set("account", params.account);
965
+ const abortSignal = params.abortSignal;
966
+ const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
979
967
  if (abortSignal?.aborted) throw createSignalSseAbortError();
980
968
  const client = url.protocol === "https:" ? https : http;
981
- return new Promise((resolve, reject) => {
969
+ const { response: streamResponse, cleanup: cleanupStream } = await new Promise((resolve, reject) => {
982
970
  let settled = false;
983
971
  let response;
984
972
  let onAbort = () => {};
@@ -998,11 +986,14 @@ function openSignalEventStream(url, abortSignal, timeoutMs = DEFAULT_TIMEOUT_MS)
998
986
  if (settled) return;
999
987
  settled = true;
1000
988
  cleanup();
1001
- reject(toErrorObject(error, "Non-Error rejection"));
989
+ reject(error);
1002
990
  };
1003
991
  const request = client.request(url, {
1004
992
  method: "GET",
1005
- headers: { Accept: "text/event-stream" }
993
+ headers: {
994
+ Accept: "text/event-stream",
995
+ ...params.lastEventId ? { "Last-Event-ID": params.lastEventId } : {}
996
+ }
1006
997
  }, (res) => {
1007
998
  const status = res.statusCode ?? 0;
1008
999
  if (status < 200 || status >= 300) {
@@ -1032,12 +1023,6 @@ function openSignalEventStream(url, abortSignal, timeoutMs = DEFAULT_TIMEOUT_MS)
1032
1023
  request.on("error", rejectOnce);
1033
1024
  request.end();
1034
1025
  });
1035
- }
1036
- async function streamSignalEvents(params) {
1037
- if (params.baseUrl.trim().startsWith("unix:")) return streamSignalUnixEvents(params);
1038
- const url = resolveSignalEndpointUrl(params.baseUrl, "/api/v1/events");
1039
- if (params.account) url.searchParams.set("account", params.account);
1040
- const { response, cleanup } = await openSignalEventStream(url, params.abortSignal, params.timeoutMs ?? DEFAULT_TIMEOUT_MS);
1041
1026
  params.onStreamOpen?.();
1042
1027
  const decoder = new TextDecoder();
1043
1028
  let buffer = "";
@@ -1045,7 +1030,7 @@ async function streamSignalEvents(params) {
1045
1030
  let currentEvent = {};
1046
1031
  let currentEventDataBytes = 0;
1047
1032
  const flushEvent = async () => {
1048
- if (!currentEvent.data && !currentEvent.event && !currentEvent.id) return;
1033
+ if (!currentEvent.data && !currentEvent.event && currentEvent.id === void 0) return;
1049
1034
  await params.onEvent({
1050
1035
  event: currentEvent.event,
1051
1036
  data: currentEvent.data,
@@ -1071,7 +1056,7 @@ async function streamSignalEvents(params) {
1071
1056
  currentEventDataBytes += Buffer$1.byteLength(segment, "utf8");
1072
1057
  if (currentEventDataBytes > MAX_SIGNAL_SSE_EVENT_DATA_BYTES) throw new Error("Signal SSE event data exceeded size limit");
1073
1058
  currentEvent.data = currentEvent.data ? `${currentEvent.data}${segment}` : segment;
1074
- } else if (field === "id") currentEvent.id = value;
1059
+ } else if (field === "id" && !value.includes("\0")) currentEvent.id = value;
1075
1060
  };
1076
1061
  const drainCompleteLines = async () => {
1077
1062
  let lineEnd = buffer.indexOf("\n");
@@ -1085,7 +1070,7 @@ async function streamSignalEvents(params) {
1085
1070
  bufferedBytes = Buffer$1.byteLength(buffer, "utf8");
1086
1071
  };
1087
1072
  try {
1088
- for await (const chunk of response) {
1073
+ for await (const chunk of streamResponse) {
1089
1074
  const value = typeof chunk === "string" ? Buffer$1.from(chunk) : chunk;
1090
1075
  bufferedBytes += value.byteLength;
1091
1076
  if (bufferedBytes > MAX_SIGNAL_SSE_BUFFER_BYTES) throw new Error("Signal SSE buffer exceeded size limit");
@@ -1100,9 +1085,8 @@ async function streamSignalEvents(params) {
1100
1085
  if (bufferedBytes > MAX_SIGNAL_SSE_BUFFER_BYTES) throw new Error("Signal SSE buffer exceeded size limit");
1101
1086
  await drainCompleteLines();
1102
1087
  } finally {
1103
- cleanup();
1088
+ cleanupStream();
1104
1089
  }
1105
- await flushEvent();
1106
1090
  }
1107
1091
  //#endregion
1108
1092
  export { prepareSignalSocketPath as a, containerRpcRequest as c, streamSignalEvents as i, streamContainerEvents as l, signalCheck as n, isSignalQuoteMetadataRejection as o, signalRpcRequest as r, containerCheck as s, SignalSseRejectionError as t };
@@ -1,11 +1,10 @@
1
- import { o as resolveSignalAccountEntry, t as assertSignalSocketTransport } from "./transport-url-CAC0JcuI.mjs";
2
- import { t as LEGACY_SIGNAL_TRANSPORT_FIELDS } from "./legacy-transport-QIpaMNST.mjs";
1
+ import { c as resolveSignalAccountEntry, r as assertSignalSocketTransport, t as LEGACY_SIGNAL_TRANSPORT_FIELDS } from "./legacy-transport-D_cZC3bS.mjs";
3
2
  import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
4
3
  import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
4
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
6
5
  import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, ReplyToModeSchema, buildChannelAccountSchemaParts, buildChannelConfigSchema, buildChannelReactionShape, buildGroupEntrySchema, refineChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-schema";
7
6
  import { z } from "zod";
8
- //#region extensions/signal/src/config-ui-hints.ts
7
+ //#region extensions/signal/src/config-schema.ts
9
8
  const signalChannelConfigUiHints = {
10
9
  "": {
11
10
  label: "Signal",
@@ -51,8 +50,6 @@ const signalChannelConfigUiHints = {
51
50
  help: "Base URL for an external-native or container transport, or the connection endpoint for a managed-native daemon when it differs from the bind address."
52
51
  }
53
52
  };
54
- //#endregion
55
- //#region extensions/signal/src/config-schema.ts
56
53
  const SIGNAL_RETIRED_TRANSPORT_KEYS = ["apiMode", ...LEGACY_SIGNAL_TRANSPORT_FIELDS];
57
54
  const SignalTransportUrlSchema = z.string().url().regex(/^[Hh][Tt][Tt][Pp][Ss]?:\/\/(?![^/?#]*@)/, "Expected http:// or https:// URL without embedded credentials");
58
55
  function projectSignalConfigForUpdateValidation(value) {