@openclaw/signal 2026.7.2-beta.7 → 2026.8.1-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 (29) hide show
  1. package/dist/api.js +7 -7
  2. package/dist/{approval-handler.runtime-C-XYgcxE.js → approval-handler.runtime-Bi5yNhnj.js} +2 -2
  3. package/dist/{approval-reactions-DtL47gSK.js → approval-reactions-BulCzhdB.js} +15 -45
  4. package/dist/{channel-CmbWaYlm.js → channel-CzDJMDtX.js} +50 -91
  5. package/dist/channel-config-api.js +1 -1
  6. package/dist/channel-plugin-api.js +1 -1
  7. package/dist/{channel.runtime-BRDaqr5-.js → channel.runtime-D12iYzJB.js} +2 -2
  8. package/dist/{client-BazXTH7O.js → client-CvnR8_XA.js} +31 -34
  9. package/dist/{client-adapter-mXGeEHQJ.js → client-adapter-D9SNPaNx.js} +13 -6
  10. package/dist/{config-schema-Y3dFGwdL.js → config-schema-CkMIK7zp.js} +4 -5
  11. package/dist/contract-api.js +1 -1
  12. package/dist/{doctor-contract-api-Dcte-QYB.js → doctor-contract-api-Dnp5eQQJ.js} +19 -22
  13. package/dist/doctor-contract-api.js +1 -1
  14. package/dist/{install-signal-cli-qJF7iC4h.js → install-signal-cli-Cpiyk0k1.js} +8 -5
  15. package/dist/{monitor-BvIzkrYW.js → monitor-DiN2hKnG.js} +128 -67
  16. package/dist/{probe-Br9abaGp.js → probe-C_THuQzn.js} +23 -7
  17. package/dist/question-reactions-ByjH5qST.js +80 -0
  18. package/dist/{reaction-runtime-api-BjeDyKcz.js → reaction-runtime-api-Cf6QHcE5.js} +8 -19
  19. package/dist/reaction-runtime-api.js +1 -1
  20. package/dist/runtime-api.js +7 -7
  21. package/dist/{send-B_Ks4MZr.js → send-BvGgByMd.js} +12 -3
  22. package/dist/{send.runtime-CbuXycZT.js → send.runtime-CtTBBrjL.js} +1 -1
  23. package/dist/{transport-detection-Da06-LOL.js → transport-detection-BItHawMq.js} +50 -145
  24. package/dist/{transport-detection.runtime-D_190UUL.js → transport-detection.runtime-DoiwPcrG.js} +1 -1
  25. package/dist/{transport-probes.runtime-CV6Qs0Og.js → transport-probes.runtime-BsJdp0oI.js} +1 -1
  26. package/openclaw.plugin.json +4 -1
  27. package/package.json +5 -5
  28. package/dist/approval-resolver-B3m0D2R0.js +0 -16
  29. package/dist/question-reactions-Ds48FtEu.js +0 -109
@@ -1,9 +1,14 @@
1
- import { a as containerRpcRequest, i as containerCheck, n as signalRpcRequest$1, o as streamContainerEvents, r as streamSignalEvents$1, t as signalCheck$1 } from "./client-BazXTH7O.js";
1
+ import { a as containerRpcRequest, i as containerCheck, n as signalRpcRequest$1, o as streamContainerEvents, r as streamSignalEvents$1, t as signalCheck$1 } from "./client-CvnR8_XA.js";
2
+ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
2
3
  //#region extensions/signal/src/client-adapter.ts
4
+ /**
5
+ * Signal client adapter - unified interface for both native signal-cli and bbernhard container.
6
+ *
7
+ * This adapter provides a single API that routes to the concrete account transport.
8
+ * Exports mirror client.ts names so consumers
9
+ * only need to change their import path.
10
+ */
3
11
  const DEFAULT_TIMEOUT_MS = 1e4;
4
- function formatErrorMessage(error) {
5
- return error instanceof Error ? error.message : String(error);
6
- }
7
12
  function usesContainer(kind) {
8
13
  return kind === "container";
9
14
  }
@@ -19,7 +24,7 @@ async function signalRpcRequest(method, params, opts) {
19
24
  */
20
25
  async function signalCheck(baseUrl, timeoutMs = DEFAULT_TIMEOUT_MS, options = {}) {
21
26
  try {
22
- return usesContainer(options.transportKind) ? await containerCheck(baseUrl, timeoutMs) : await signalCheck$1(baseUrl, timeoutMs);
27
+ return usesContainer(options.transportKind) ? await containerCheck(baseUrl, timeoutMs, options.account) : await signalCheck$1(baseUrl, timeoutMs);
23
28
  } catch (error) {
24
29
  return {
25
30
  ok: false,
@@ -42,6 +47,7 @@ async function streamSignalEvents(params) {
42
47
  event: "receive",
43
48
  data: JSON.stringify(event)
44
49
  }),
50
+ onStreamOpen: params.onStreamOpen,
45
51
  logger: params.logger
46
52
  });
47
53
  return streamSignalEvents$1({
@@ -49,7 +55,8 @@ async function streamSignalEvents(params) {
49
55
  account: params.account,
50
56
  abortSignal: params.abortSignal,
51
57
  timeoutMs: params.timeoutMs,
52
- onEvent: (event) => params.onEvent(event)
58
+ onEvent: (event) => params.onEvent(event),
59
+ onStreamOpen: params.onStreamOpen
53
60
  });
54
61
  }
55
62
  //#endregion
@@ -1,7 +1,6 @@
1
1
  import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
2
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId, resolveAccountEntry } from "openclaw/plugin-sdk/account-resolution";
4
- import { isRecord as isRecord$1 } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
5
4
  import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, ReplyToModeSchema, buildChannelConfigSchema, buildChannelReactionShape, buildCommonChannelAccountShape, buildGroupEntrySchema, requireAllowlistAllowFrom, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
6
5
  import { z } from "zod";
7
6
  //#region extensions/signal/src/config-ui-hints.ts
@@ -62,11 +61,11 @@ const SIGNAL_RETIRED_TRANSPORT_KEYS = [
62
61
  ];
63
62
  const SignalTransportUrlSchema = z.string().url().regex(/^[Hh][Tt][Tt][Pp][Ss]?:\/\/(?![^/?#]*@)/, "Expected http:// or https:// URL without embedded credentials");
64
63
  function projectSignalConfigForUpdateValidation(value) {
65
- if (process.env.OPENCLAW_UPDATE_IN_PROGRESS !== "1" || !isRecord$1(value)) return value;
64
+ if (process.env.OPENCLAW_UPDATE_IN_PROGRESS !== "1" || !isRecord(value)) return value;
66
65
  const next = { ...value };
67
66
  for (const key of SIGNAL_RETIRED_TRANSPORT_KEYS) delete next[key];
68
- if (isRecord$1(value.accounts)) next.accounts = Object.fromEntries(Object.entries(value.accounts).map(([accountId, account]) => {
69
- if (!isRecord$1(account)) return [accountId, account];
67
+ if (isRecord(value.accounts)) next.accounts = Object.fromEntries(Object.entries(value.accounts).map(([accountId, account]) => {
68
+ if (!isRecord(account)) return [accountId, account];
70
69
  const nextAccount = { ...account };
71
70
  for (const key of SIGNAL_RETIRED_TRANSPORT_KEYS) delete nextAccount[key];
72
71
  return [accountId, nextAccount];
@@ -1,3 +1,3 @@
1
1
  import { d as normalizeSignalMessagingTarget, i as isSignalSenderAllowed, u as looksLikeSignalTargetId } from "./identity-BQ4OzXXk.js";
2
- import { a as installSignalCliFromRelease, i as installSignalCli, n as downloadToFile, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset, t as MAX_SIGNAL_CLI_EXTRACTED_BYTES } from "./install-signal-cli-qJF7iC4h.js";
2
+ import { a as installSignalCliFromRelease, i as installSignalCli, n as downloadToFile, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset, t as MAX_SIGNAL_CLI_EXTRACTED_BYTES } from "./install-signal-cli-Cpiyk0k1.js";
3
3
  export { MAX_SIGNAL_CLI_EXTRACTED_BYTES, downloadToFile, extractSignalCliArchive, installSignalCli, installSignalCliFromRelease, isSignalSenderAllowed, looksLikeArchive, looksLikeSignalTargetId, normalizeSignalMessagingTarget, pickAsset };
@@ -1,7 +1,7 @@
1
1
  import { a as isSignalManagedNativeConnectionUrlForBind, c as buildSignalTransportHttpUrl, i as assignSignalManagedNativePort, o as isValidSignalManagedNativePort, r as allocateSignalManagedNativePort, s as resolveLocalSignalTransportPort, u as normalizeSignalTransportUrl } from "./transport-policy-DxvSMHp9.js";
2
+ import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
3
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
3
- import { isRecord } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
4
- import { defineChannelAliasMigration } from "openclaw/plugin-sdk/runtime-doctor";
4
+ import { defineChannelAliasMigration } from "openclaw/plugin-sdk/runtime-doctor-migrations";
5
5
  //#region extensions/signal/src/config-compat.ts
6
6
  const LEGACY_TRANSPORT_FIELDS = [
7
7
  "configPath",
@@ -40,16 +40,13 @@ function isSignalTransportConfig(value) {
40
40
  return false;
41
41
  }
42
42
  }
43
- function optionalString(value) {
44
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
45
- }
46
43
  function inherited(entry, parent, key) {
47
44
  return Object.hasOwn(entry, key) ? entry[key] : parent[key];
48
45
  }
49
46
  function legacyBaseUrl(entry, parent) {
50
- const url = optionalString(inherited(entry, parent, "httpUrl"));
47
+ const url = normalizeOptionalString(inherited(entry, parent, "httpUrl"));
51
48
  if (url) return normalizeSignalTransportUrl(url);
52
- const host = optionalString(inherited(entry, parent, "httpHost")) ?? "127.0.0.1";
49
+ const host = normalizeOptionalString(inherited(entry, parent, "httpHost")) ?? "127.0.0.1";
53
50
  const rawPort = inherited(entry, parent, "httpPort");
54
51
  return buildSignalTransportHttpUrl(host, typeof rawPort === "number" ? rawPort : 8080);
55
52
  }
@@ -57,11 +54,11 @@ function hasLegacyFields(entry) {
57
54
  return LEGACY_TRANSPORT_FIELDS.some((field) => Object.hasOwn(entry, field));
58
55
  }
59
56
  function wasLegacySignalAccountConfigured(entry, parent) {
60
- return Boolean(optionalString(inherited(entry, parent, "account")) || optionalString(inherited(entry, parent, "configPath")) || optionalString(inherited(entry, parent, "httpUrl")) || optionalString(inherited(entry, parent, "httpHost")) || optionalString(inherited(entry, parent, "cliPath")) || typeof inherited(entry, parent, "httpPort") === "number" || typeof inherited(entry, parent, "autoStart") === "boolean");
57
+ return Boolean(normalizeOptionalString(inherited(entry, parent, "account")) || normalizeOptionalString(inherited(entry, parent, "configPath")) || normalizeOptionalString(inherited(entry, parent, "httpUrl")) || normalizeOptionalString(inherited(entry, parent, "httpHost")) || normalizeOptionalString(inherited(entry, parent, "cliPath")) || typeof inherited(entry, parent, "httpPort") === "number" || typeof inherited(entry, parent, "autoStart") === "boolean");
61
58
  }
62
59
  function hasInvalidLegacyHttpUrl(entries, parent) {
63
60
  return entries.some((entry) => {
64
- const httpUrl = optionalString(inherited(entry, parent, "httpUrl"));
61
+ const httpUrl = normalizeOptionalString(inherited(entry, parent, "httpUrl"));
65
62
  if (!httpUrl) return false;
66
63
  try {
67
64
  normalizeSignalTransportUrl(httpUrl);
@@ -73,10 +70,10 @@ function hasInvalidLegacyHttpUrl(entries, parent) {
73
70
  }
74
71
  function findInvalidLegacyDerivedEndpoint(entries, parent) {
75
72
  for (const entry of entries) {
76
- if (optionalString(inherited(entry, parent, "httpUrl"))) continue;
73
+ if (normalizeOptionalString(inherited(entry, parent, "httpUrl"))) continue;
77
74
  const rawPort = inherited(entry, parent, "httpPort");
78
75
  if (rawPort !== void 0 && !isValidSignalManagedNativePort(rawPort)) return "port";
79
- const host = optionalString(inherited(entry, parent, "httpHost")) ?? "127.0.0.1";
76
+ const host = normalizeOptionalString(inherited(entry, parent, "httpHost")) ?? "127.0.0.1";
80
77
  try {
81
78
  buildSignalTransportHttpUrl(host, typeof rawPort === "number" ? rawPort : 8080);
82
79
  } catch {
@@ -89,19 +86,19 @@ function hasInvalidManagedTransportPort(transports) {
89
86
  }
90
87
  function requiresDetection(entry, parent, apiMode) {
91
88
  if (apiMode !== void 0 && apiMode !== "auto") return false;
92
- return Boolean(optionalString(inherited(entry, parent, "httpUrl"))) || !resolveLegacyAutoStart(entry, parent);
89
+ return Boolean(normalizeOptionalString(inherited(entry, parent, "httpUrl"))) || !resolveLegacyAutoStart(entry, parent);
93
90
  }
94
91
  function resolveLegacyAutoStart(entry, parent) {
95
92
  const autoStart = inherited(entry, parent, "autoStart");
96
93
  if (typeof autoStart === "boolean") return autoStart;
97
- return !optionalString(inherited(entry, parent, "httpUrl"));
94
+ return !normalizeOptionalString(inherited(entry, parent, "httpUrl"));
98
95
  }
99
96
  function resolveManagedConnectionUrl(entry, parent) {
100
- const httpUrl = optionalString(inherited(entry, parent, "httpUrl"));
97
+ const httpUrl = normalizeOptionalString(inherited(entry, parent, "httpUrl"));
101
98
  if (!httpUrl) return;
102
99
  const normalizedUrl = normalizeSignalTransportUrl(httpUrl);
103
100
  const endpoint = new URL(normalizedUrl);
104
- const bindHost = (optionalString(inherited(entry, parent, "httpHost")) ?? "127.0.0.1").replace(/^\[|\]$/g, "").toLowerCase();
101
+ const bindHost = (normalizeOptionalString(inherited(entry, parent, "httpHost")) ?? "127.0.0.1").replace(/^\[|\]$/g, "").toLowerCase();
105
102
  const rawBindPort = inherited(entry, parent, "httpPort");
106
103
  const bindPort = typeof rawBindPort === "number" ? rawBindPort : 8080;
107
104
  const endpointHost = endpoint.hostname.replace(/^\[|\]$/g, "").toLowerCase();
@@ -110,10 +107,10 @@ function resolveManagedConnectionUrl(entry, parent) {
110
107
  }
111
108
  function buildManagedNativeTransport(entry, parent) {
112
109
  const value = (key) => inherited(entry, parent, key);
113
- const configPath = optionalString(value("configPath"));
114
- const cliPath = optionalString(value("cliPath"));
110
+ const configPath = normalizeOptionalString(value("configPath"));
111
+ const cliPath = normalizeOptionalString(value("cliPath"));
115
112
  const url = resolveManagedConnectionUrl(entry, parent);
116
- const httpHost = optionalString(value("httpHost"));
113
+ const httpHost = normalizeOptionalString(value("httpHost"));
117
114
  const httpPort = value("httpPort");
118
115
  const startupTimeoutMs = value("startupTimeoutMs");
119
116
  const receiveMode = value("receiveMode");
@@ -152,7 +149,7 @@ function resolveLegacyTransportWithoutDetection(params) {
152
149
  async function resolveLegacyTransport(params) {
153
150
  const resolved = resolveLegacyTransportWithoutDetection(params);
154
151
  if (resolved) return resolved;
155
- const account = optionalString(inherited(params.entry, params.parent, "account"));
152
+ const account = normalizeOptionalString(inherited(params.entry, params.parent, "account"));
156
153
  try {
157
154
  const detected = await params.detect?.({
158
155
  url: legacyBaseUrl(params.entry, params.parent),
@@ -170,7 +167,7 @@ function clearLegacyTransportFields(entry) {
170
167
  }
171
168
  function hasRootSignalAccount(entries) {
172
169
  const root = entries[0];
173
- return entries.length === 1 || Boolean(optionalString(root?.account)) || isSignalTransportConfig(root?.transport);
170
+ return entries.length === 1 || Boolean(normalizeOptionalString(root?.account)) || isSignalTransportConfig(root?.transport);
174
171
  }
175
172
  function signalAccountIds(entries) {
176
173
  const accounts = isRecord(entries[0]?.accounts) ? entries[0].accounts : {};
@@ -283,7 +280,7 @@ function hasContainerTransportWithoutEffectiveAccount(cfg) {
283
280
  const rootTransport = isSignalTransportConfig(signal.transport) ? signal.transport : void 0;
284
281
  const defaultKey = resolveSignalAccountKey(accounts, DEFAULT_ACCOUNT_ID);
285
282
  const defaultEntry = defaultKey ? accounts[defaultKey] : void 0;
286
- const defaultAccount = isRecord(defaultEntry) && defaultEntry.account !== void 0 ? optionalString(defaultEntry.account) : optionalString(signal.account);
283
+ const defaultAccount = isRecord(defaultEntry) && defaultEntry.account !== void 0 ? normalizeOptionalString(defaultEntry.account) : normalizeOptionalString(signal.account);
287
284
  const channelEnabled = signal.enabled !== false;
288
285
  const defaultEnabled = !isRecord(defaultEntry) || defaultEntry.enabled !== false;
289
286
  if (rootTransport?.kind === "container" && channelEnabled && defaultEnabled && !defaultAccount) return true;
@@ -292,7 +289,7 @@ function hasContainerTransportWithoutEffectiveAccount(cfg) {
292
289
  if (!channelEnabled || entry.enabled === false) continue;
293
290
  const isDefaultAccount = isDefaultSignalAccountId(accountId);
294
291
  if ((isDefaultAccount && rootTransport ? rootTransport : isSignalTransportConfig(entry.transport) ? entry.transport : void 0)?.kind !== "container" || isDefaultAccount && rootTransport) continue;
295
- if (!(entry.account === void 0 ? optionalString(signal.account) : optionalString(entry.account))) return true;
292
+ if (!(entry.account === void 0 ? normalizeOptionalString(signal.account) : normalizeOptionalString(entry.account))) return true;
296
293
  }
297
294
  return false;
298
295
  }
@@ -1,2 +1,2 @@
1
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-api-Dcte-QYB.js";
1
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-api-Dnp5eQQJ.js";
2
2
  export { legacyConfigRules, normalizeCompatibilityConfig };
@@ -1,10 +1,10 @@
1
1
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
2
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
3
- import nodePath from "node:path";
4
3
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
4
  import { CONFIG_DIR, extractArchive, resolveBrewExecutable } from "openclaw/plugin-sdk/setup-tools";
6
5
  import { createWriteStream } from "node:fs";
7
6
  import fs from "node:fs/promises";
7
+ import path from "node:path";
8
8
  import { Readable, Transform } from "node:stream";
9
9
  import { pipeline } from "node:stream/promises";
10
10
  import { readProviderJsonObjectResponse } from "openclaw/plugin-sdk/provider-http";
@@ -107,7 +107,10 @@ async function downloadToFile(url, dest, maxRedirects = 5, maxBytes = MAX_SIGNAL
107
107
  if (rawLength !== null) {
108
108
  const trimmedLength = rawLength.trim();
109
109
  const declaredLength = CONTENT_LENGTH_RE.test(trimmedLength) ? Number(trimmedLength) : NaN;
110
- if (Number.isFinite(declaredLength) && declaredLength > maxBytes) throw new Error(`signal-cli archive exceeds the ${maxBytes}-byte download cap (declared ${declaredLength}).`);
110
+ if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
111
+ await cancelUnusedResponseBody(response);
112
+ throw new Error(`signal-cli archive exceeds the ${maxBytes}-byte download cap (declared ${declaredLength}).`);
113
+ }
111
114
  }
112
115
  let totalBytes = 0;
113
116
  const body = response.body;
@@ -131,7 +134,7 @@ async function findSignalCliBinary(root) {
131
134
  if (depth > 3) return;
132
135
  const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
133
136
  for (const entry of entries) {
134
- const full = nodePath.join(dir, entry.name);
137
+ const full = path.join(dir, entry.name);
135
138
  if (entry.isDirectory()) await enqueue(full, depth + 1);
136
139
  else if (entry.isFile() && entry.name === "signal-cli") candidates.push(full);
137
140
  }
@@ -151,7 +154,7 @@ async function resolveBrewSignalCliPath(brewExe) {
151
154
  });
152
155
  if (result.code === 0 && result.stdout.trim()) {
153
156
  const prefix = result.stdout.trim();
154
- const candidate = nodePath.join(prefix, "bin", "signal-cli");
157
+ const candidate = path.join(prefix, "bin", "signal-cli");
155
158
  try {
156
159
  await fs.access(candidate);
157
160
  return candidate;
@@ -246,7 +249,7 @@ async function installSignalCliFromRelease(runtime) {
246
249
  }, async (archivePath) => {
247
250
  runtime.log(`Downloading signal-cli ${releaseInfo.version} (${asset.name})…`);
248
251
  await downloadToFile(asset.browser_download_url, archivePath);
249
- const installRoot = nodePath.join(CONFIG_DIR, "tools", "signal-cli", releaseInfo.version);
252
+ const installRoot = path.join(CONFIG_DIR, "tools", "signal-cli", releaseInfo.version);
250
253
  await fs.mkdir(installRoot, { recursive: true });
251
254
  if (!looksLikeArchive(normalizeLowercaseStringOrEmpty(asset.name))) return {
252
255
  ok: false,