@openclaw/signal 2026.7.2-beta.5 → 2026.7.2-beta.7
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/api.js +2 -2
- package/dist/{channel-CBIljGCH.js → channel-CmbWaYlm.js} +4 -4
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-B8GXmuol.js → channel.runtime-BRDaqr5-.js} +1 -1
- package/dist/{config-schema-DLvpQPN5.js → config-schema-Y3dFGwdL.js} +1 -3
- package/dist/{doctor-contract-api-DbUCknbC.js → doctor-contract-api-Dcte-QYB.js} +29 -34
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{monitor-CHBkf7lk.js → monitor-BvIzkrYW.js} +53 -63
- package/dist/runtime-api.js +2 -2
- package/package.json +4 -4
package/dist/api.js
CHANGED
|
@@ -2,9 +2,9 @@ import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefau
|
|
|
2
2
|
import { a as normalizeSignalAllowRecipient, c as resolveSignalSender, d as normalizeSignalMessagingTarget, i as isSignalSenderAllowed, l as looksLikeUuid, n as formatSignalSenderDisplay, o as resolveSignalPeerId, r as formatSignalSenderId, s as resolveSignalRecipient, t as formatSignalPairingIdLine, u as looksLikeSignalTargetId } from "./identity-BQ4OzXXk.js";
|
|
3
3
|
import { a as signalMessageActions, c as markdownToSignalText, l as markdownToSignalTextChunks, o as resolveSignalReactionLevel, t as detectSignalTransport } from "./transport-detection-Da06-LOL.js";
|
|
4
4
|
import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-BjeDyKcz.js";
|
|
5
|
-
import { a as normalizeSignalAccountInput, d as probeSignalTransport, f as writeSignalAccountTransport, l as signalSetupContract, n as createSignalPluginBase, p as resolveSignalOutboundTarget, r as signalSetupWizard, t as signalPlugin, u as prepareSignalManagedNativeTransport } from "./channel-
|
|
5
|
+
import { a as normalizeSignalAccountInput, d as probeSignalTransport, f as writeSignalAccountTransport, l as signalSetupContract, n as createSignalPluginBase, p as resolveSignalOutboundTarget, r as signalSetupWizard, t as signalPlugin, u as prepareSignalManagedNativeTransport } from "./channel-CmbWaYlm.js";
|
|
6
6
|
import { i as installSignalCli, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset } from "./install-signal-cli-qJF7iC4h.js";
|
|
7
|
-
import { t as monitorSignalProvider } from "./monitor-
|
|
7
|
+
import { t as monitorSignalProvider } from "./monitor-BvIzkrYW.js";
|
|
8
8
|
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-B_Ks4MZr.js";
|
|
9
9
|
import { t as probeSignal } from "./probe-Br9abaGp.js";
|
|
10
10
|
//#region extensions/signal/src/channel.setup.ts
|
|
@@ -3,8 +3,8 @@ import { a as resolveSignalAccountConfig, i as resolveSignalAccount, n as listSi
|
|
|
3
3
|
import { c as resolveSignalSender, d as normalizeSignalMessagingTarget, l as looksLikeUuid, o as resolveSignalPeerId, s as resolveSignalRecipient, u as looksLikeSignalTargetId } from "./identity-BQ4OzXXk.js";
|
|
4
4
|
import { a as listSignalAliasDirectoryEntries, o as resolveSignalTarget } from "./runtime-JPrGlV7h.js";
|
|
5
5
|
import { a as signalMessageActions, d as shouldSuppressLocalSignalExecApprovalPrompt, f as signalApprovalCapability, i as materializeSignalPresentationFallback, l as markdownToSignalTextChunks, o as resolveSignalReactionLevel, r as resolveSignalReplyContextWithPersistence, s as formatSignalMediaText, t as detectSignalTransport } from "./transport-detection-Da06-LOL.js";
|
|
6
|
-
import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-
|
|
7
|
-
import { t as SignalChannelConfigSchema } from "./config-schema-
|
|
6
|
+
import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-Dcte-QYB.js";
|
|
7
|
+
import { t as SignalChannelConfigSchema } from "./config-schema-Y3dFGwdL.js";
|
|
8
8
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
9
9
|
import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
|
|
10
10
|
import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
@@ -579,7 +579,7 @@ const signalDoctor = {
|
|
|
579
579
|
//#region extensions/signal/src/shared.ts
|
|
580
580
|
const SIGNAL_CHANNEL = "signal";
|
|
581
581
|
async function loadSignalChannelRuntime() {
|
|
582
|
-
return await import("./channel.runtime-
|
|
582
|
+
return await import("./channel.runtime-BRDaqr5-.js");
|
|
583
583
|
}
|
|
584
584
|
const signalSetupWizard = createSignalSetupWizardProxy(async () => (await loadSignalChannelRuntime()).signalSetupWizard);
|
|
585
585
|
const signalConfigAdapter = {
|
|
@@ -663,7 +663,7 @@ function createSignalPluginBase(params) {
|
|
|
663
663
|
}
|
|
664
664
|
//#endregion
|
|
665
665
|
//#region extensions/signal/src/channel.ts
|
|
666
|
-
const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-
|
|
666
|
+
const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-BvIzkrYW.js").then((n) => n.n));
|
|
667
667
|
const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-Br9abaGp.js").then((n) => n.n));
|
|
668
668
|
const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-CbuXycZT.js"));
|
|
669
669
|
const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-DtL47gSK.js").then((n) => n.r));
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as SignalChannelConfigSchema } from "./config-schema-
|
|
1
|
+
import { t as SignalChannelConfigSchema } from "./config-schema-Y3dFGwdL.js";
|
|
2
2
|
export { SignalChannelConfigSchema };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as signalPlugin } from "./channel-
|
|
1
|
+
import { t as signalPlugin } from "./channel-CmbWaYlm.js";
|
|
2
2
|
export { signalPlugin };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-DrStJjiK.js";
|
|
2
|
-
import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-
|
|
2
|
+
import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-CmbWaYlm.js";
|
|
3
3
|
import { i as installSignalCli } from "./install-signal-cli-qJF7iC4h.js";
|
|
4
4
|
import { detectBinary } from "openclaw/plugin-sdk/setup-tools";
|
|
5
5
|
import { createDetectedBinaryStatus, createSetupTranslator, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
|
|
2
2
|
import { 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";
|
|
4
5
|
import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, ReplyToModeSchema, buildChannelConfigSchema, buildChannelReactionShape, buildCommonChannelAccountShape, buildGroupEntrySchema, requireAllowlistAllowFrom, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
//#region extensions/signal/src/config-ui-hints.ts
|
|
@@ -60,9 +61,6 @@ const SIGNAL_RETIRED_TRANSPORT_KEYS = [
|
|
|
60
61
|
"ignoreStories"
|
|
61
62
|
];
|
|
62
63
|
const SignalTransportUrlSchema = z.string().url().regex(/^[Hh][Tt][Tt][Pp][Ss]?:\/\/(?![^/?#]*@)/, "Expected http:// or https:// URL without embedded credentials");
|
|
63
|
-
function isRecord$1(value) {
|
|
64
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
65
|
-
}
|
|
66
64
|
function projectSignalConfigForUpdateValidation(value) {
|
|
67
65
|
if (process.env.OPENCLAW_UPDATE_IN_PROGRESS !== "1" || !isRecord$1(value)) return value;
|
|
68
66
|
const next = { ...value };
|
|
@@ -1,5 +1,6 @@
|
|
|
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
2
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
3
|
+
import { isRecord } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
3
4
|
import { defineChannelAliasMigration } from "openclaw/plugin-sdk/runtime-doctor";
|
|
4
5
|
//#region extensions/signal/src/config-compat.ts
|
|
5
6
|
const LEGACY_TRANSPORT_FIELDS = [
|
|
@@ -18,11 +19,8 @@ const PENDING_LEGACY_INVALID_URL_WARNING = "- channels.signal: legacy httpUrl is
|
|
|
18
19
|
const PENDING_LEGACY_INVALID_HOST_WARNING = "- channels.signal: legacy httpHost is invalid; keep the current config, correct httpHost, then run openclaw doctor --fix.";
|
|
19
20
|
const PENDING_LEGACY_INVALID_PORT_WARNING = "- channels.signal: legacy httpPort must be an integer between 1 and 65535; correct httpPort, then run openclaw doctor --fix.";
|
|
20
21
|
const PENDING_LEGACY_CONTAINER_ACCOUNT_WARNING = "- channels.signal: legacy container transport requires an account number; add channels.signal.account (or the relevant channels.signal.accounts.*.account) and rerun openclaw doctor --fix.";
|
|
21
|
-
function isRecord$1(value) {
|
|
22
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
-
}
|
|
24
22
|
function isSignalTransportConfig(value) {
|
|
25
|
-
if (!isRecord
|
|
23
|
+
if (!isRecord(value)) return false;
|
|
26
24
|
if (value.kind === "managed-native") {
|
|
27
25
|
if (value.httpPort !== void 0 && !isValidSignalManagedNativePort(value.httpPort)) return false;
|
|
28
26
|
if (value.url === void 0) return true;
|
|
@@ -175,8 +173,8 @@ function hasRootSignalAccount(entries) {
|
|
|
175
173
|
return entries.length === 1 || Boolean(optionalString(root?.account)) || isSignalTransportConfig(root?.transport);
|
|
176
174
|
}
|
|
177
175
|
function signalAccountIds(entries) {
|
|
178
|
-
const accounts = isRecord
|
|
179
|
-
return Object.entries(accounts).filter(([, entry]) => isRecord
|
|
176
|
+
const accounts = isRecord(entries[0]?.accounts) ? entries[0].accounts : {};
|
|
177
|
+
return Object.entries(accounts).filter(([, entry]) => isRecord(entry)).map(([accountId]) => accountId);
|
|
180
178
|
}
|
|
181
179
|
function isDefaultSignalAccountId(accountId) {
|
|
182
180
|
return Boolean(accountId?.trim()) && normalizeAccountId(accountId) === DEFAULT_ACCOUNT_ID;
|
|
@@ -186,10 +184,10 @@ function resolveSignalAccountKey(accounts, accountId) {
|
|
|
186
184
|
return Object.keys(accounts).find((key) => Boolean(key.trim()) && normalizeAccountId(key) === normalizedAccountId);
|
|
187
185
|
}
|
|
188
186
|
function nestedDefaultOwnsEffectiveTransport(entries) {
|
|
189
|
-
const accounts = isRecord
|
|
187
|
+
const accounts = isRecord(entries[0]?.accounts) ? entries[0].accounts : {};
|
|
190
188
|
const nestedDefaultKey = resolveSignalAccountKey(accounts, DEFAULT_ACCOUNT_ID);
|
|
191
189
|
const nestedDefault = nestedDefaultKey ? accounts[nestedDefaultKey] : void 0;
|
|
192
|
-
return isRecord
|
|
190
|
+
return isRecord(nestedDefault) && (isSignalTransportConfig(nestedDefault.transport) || hasLegacyFields(nestedDefault));
|
|
193
191
|
}
|
|
194
192
|
function isDiscardedTransportEntry(entries, index) {
|
|
195
193
|
if (index === 0) return !hasRootSignalAccount(entries) || nestedDefaultOwnsEffectiveTransport(entries);
|
|
@@ -204,23 +202,23 @@ function shouldMaterializeTransport(entries, index) {
|
|
|
204
202
|
function clearLegacySignalTransportFieldsForAccount(params) {
|
|
205
203
|
const next = structuredClone(params.cfg);
|
|
206
204
|
const signal = next.channels?.signal;
|
|
207
|
-
if (!isRecord
|
|
205
|
+
if (!isRecord(signal)) return next;
|
|
208
206
|
if (isDefaultSignalAccountId(params.accountId)) {
|
|
209
207
|
clearLegacyTransportFields(signal);
|
|
210
208
|
delete signal.apiMode;
|
|
211
|
-
const accounts = isRecord
|
|
209
|
+
const accounts = isRecord(signal.accounts) ? signal.accounts : void 0;
|
|
212
210
|
const nestedDefaultKey = accounts ? resolveSignalAccountKey(accounts, DEFAULT_ACCOUNT_ID) : void 0;
|
|
213
211
|
const nestedDefault = nestedDefaultKey ? accounts?.[nestedDefaultKey] : void 0;
|
|
214
|
-
if (isRecord
|
|
212
|
+
if (isRecord(nestedDefault)) {
|
|
215
213
|
clearLegacyTransportFields(nestedDefault);
|
|
216
214
|
delete nestedDefault.transport;
|
|
217
215
|
}
|
|
218
216
|
return next;
|
|
219
217
|
}
|
|
220
|
-
const accounts = isRecord
|
|
218
|
+
const accounts = isRecord(signal.accounts) ? signal.accounts : void 0;
|
|
221
219
|
const accountKey = accounts ? resolveSignalAccountKey(accounts, params.accountId) : void 0;
|
|
222
220
|
const account = accountKey ? accounts?.[accountKey] : void 0;
|
|
223
|
-
if (isRecord
|
|
221
|
+
if (isRecord(account)) clearLegacyTransportFields(account);
|
|
224
222
|
return next;
|
|
225
223
|
}
|
|
226
224
|
function allocateMigratedManagedPorts(params) {
|
|
@@ -239,12 +237,12 @@ function allocateMigratedManagedPorts(params) {
|
|
|
239
237
|
const localConnectionPort = resolveLocalSignalTransportPort(transport.url);
|
|
240
238
|
if (localConnectionPort !== void 0) reservedPorts.add(localConnectionPort);
|
|
241
239
|
}
|
|
242
|
-
if (index === canonicalDefaultIndex || isRecord
|
|
240
|
+
if (index === canonicalDefaultIndex || isRecord(params.entries[index]?.transport)) reservedPorts.add(transport.httpPort ?? 8080);
|
|
243
241
|
}
|
|
244
242
|
return params.transports.map((transport, index) => {
|
|
245
243
|
if (!transport || index === 0 && canonicalDefaultIndex !== 0) return transport;
|
|
246
244
|
if (transport.kind !== "managed-native") return transport;
|
|
247
|
-
if (isRecord
|
|
245
|
+
if (isRecord(params.entries[index]?.transport) || index === canonicalDefaultIndex) return transport;
|
|
248
246
|
const rawPreferredPort = params.entries[index]?.httpPort;
|
|
249
247
|
const preferredPort = typeof rawPreferredPort === "number" ? rawPreferredPort : transport.httpPort;
|
|
250
248
|
const httpPort = allocateSignalManagedNativePort({
|
|
@@ -258,10 +256,10 @@ function allocateMigratedManagedPorts(params) {
|
|
|
258
256
|
function applyMigratedSignalTransports(params) {
|
|
259
257
|
const next = structuredClone(params.cfg);
|
|
260
258
|
const nextSignal = next.channels?.signal;
|
|
261
|
-
if (!isRecord
|
|
259
|
+
if (!isRecord(nextSignal)) return;
|
|
262
260
|
const accountIds = signalAccountIds(params.entries);
|
|
263
|
-
const nextAccounts = isRecord
|
|
264
|
-
const nextEntries = [nextSignal, ...Object.values(nextAccounts).filter(isRecord
|
|
261
|
+
const nextAccounts = isRecord(nextSignal.accounts) ? nextSignal.accounts : {};
|
|
262
|
+
const nextEntries = [nextSignal, ...Object.values(nextAccounts).filter(isRecord)];
|
|
265
263
|
const rootIsAccount = hasRootSignalAccount(params.entries);
|
|
266
264
|
const canonicalRootTransport = isSignalTransportConfig(params.entries[0]?.transport) ? params.entries[0].transport : void 0;
|
|
267
265
|
for (const [index, entry] of nextEntries.entries()) {
|
|
@@ -280,17 +278,17 @@ function applyMigratedSignalTransports(params) {
|
|
|
280
278
|
}
|
|
281
279
|
function hasContainerTransportWithoutEffectiveAccount(cfg) {
|
|
282
280
|
const signal = cfg.channels?.signal;
|
|
283
|
-
if (!isRecord
|
|
284
|
-
const accounts = isRecord
|
|
281
|
+
if (!isRecord(signal)) return false;
|
|
282
|
+
const accounts = isRecord(signal.accounts) ? signal.accounts : {};
|
|
285
283
|
const rootTransport = isSignalTransportConfig(signal.transport) ? signal.transport : void 0;
|
|
286
284
|
const defaultKey = resolveSignalAccountKey(accounts, DEFAULT_ACCOUNT_ID);
|
|
287
285
|
const defaultEntry = defaultKey ? accounts[defaultKey] : void 0;
|
|
288
|
-
const defaultAccount = isRecord
|
|
286
|
+
const defaultAccount = isRecord(defaultEntry) && defaultEntry.account !== void 0 ? optionalString(defaultEntry.account) : optionalString(signal.account);
|
|
289
287
|
const channelEnabled = signal.enabled !== false;
|
|
290
|
-
const defaultEnabled = !isRecord
|
|
288
|
+
const defaultEnabled = !isRecord(defaultEntry) || defaultEntry.enabled !== false;
|
|
291
289
|
if (rootTransport?.kind === "container" && channelEnabled && defaultEnabled && !defaultAccount) return true;
|
|
292
290
|
for (const [accountId, entry] of Object.entries(accounts)) {
|
|
293
|
-
if (!isRecord
|
|
291
|
+
if (!isRecord(entry)) continue;
|
|
294
292
|
if (!channelEnabled || entry.enabled === false) continue;
|
|
295
293
|
const isDefaultAccount = isDefaultSignalAccountId(accountId);
|
|
296
294
|
if ((isDefaultAccount && rootTransport ? rootTransport : isSignalTransportConfig(entry.transport) ? entry.transport : void 0)?.kind !== "container" || isDefaultAccount && rootTransport) continue;
|
|
@@ -300,17 +298,17 @@ function hasContainerTransportWithoutEffectiveAccount(cfg) {
|
|
|
300
298
|
}
|
|
301
299
|
async function migrateLegacySignalTransportConfig(params) {
|
|
302
300
|
const signal = params.cfg.channels?.signal;
|
|
303
|
-
if (!isRecord
|
|
301
|
+
if (!isRecord(signal)) return {
|
|
304
302
|
config: params.cfg,
|
|
305
303
|
changes: []
|
|
306
304
|
};
|
|
307
|
-
const accounts = isRecord
|
|
308
|
-
if (!(Object.hasOwn(signal, "apiMode") || hasLegacyFields(signal) || Object.values(accounts).some((entry) => isRecord
|
|
305
|
+
const accounts = isRecord(signal.accounts) ? signal.accounts : {};
|
|
306
|
+
if (!(Object.hasOwn(signal, "apiMode") || hasLegacyFields(signal) || Object.values(accounts).some((entry) => isRecord(entry) && hasLegacyFields(entry)))) return {
|
|
309
307
|
config: params.cfg,
|
|
310
308
|
changes: []
|
|
311
309
|
};
|
|
312
310
|
const apiMode = signal.apiMode;
|
|
313
|
-
const entries = [signal, ...Object.values(accounts).filter(isRecord
|
|
311
|
+
const entries = [signal, ...Object.values(accounts).filter(isRecord)];
|
|
314
312
|
const legacyResolutionEntries = entries.filter((_, index) => shouldMaterializeTransport(entries, index)).filter((entry) => !isSignalTransportConfig(entry.transport));
|
|
315
313
|
const invalidDerivedEndpoint = findInvalidLegacyDerivedEndpoint(legacyResolutionEntries, signal);
|
|
316
314
|
if (invalidDerivedEndpoint) return {
|
|
@@ -369,16 +367,16 @@ async function migrateLegacySignalTransportConfig(params) {
|
|
|
369
367
|
}
|
|
370
368
|
function migrateLegacySignalTransportConfigSync(cfg) {
|
|
371
369
|
const signal = cfg.channels?.signal;
|
|
372
|
-
if (!isRecord
|
|
370
|
+
if (!isRecord(signal)) return {
|
|
373
371
|
config: cfg,
|
|
374
372
|
changes: []
|
|
375
373
|
};
|
|
376
|
-
const accounts = isRecord
|
|
377
|
-
if (!(Object.hasOwn(signal, "apiMode") || hasLegacyFields(signal) || Object.values(accounts).some((entry) => isRecord
|
|
374
|
+
const accounts = isRecord(signal.accounts) ? signal.accounts : {};
|
|
375
|
+
if (!(Object.hasOwn(signal, "apiMode") || hasLegacyFields(signal) || Object.values(accounts).some((entry) => isRecord(entry) && hasLegacyFields(entry)))) return {
|
|
378
376
|
config: cfg,
|
|
379
377
|
changes: []
|
|
380
378
|
};
|
|
381
|
-
const entries = [signal, ...Object.values(accounts).filter(isRecord
|
|
379
|
+
const entries = [signal, ...Object.values(accounts).filter(isRecord)];
|
|
382
380
|
const legacyResolutionEntries = entries.filter((_, index) => shouldMaterializeTransport(entries, index)).filter((entry) => !isSignalTransportConfig(entry.transport));
|
|
383
381
|
const invalidDerivedEndpoint = findInvalidLegacyDerivedEndpoint(legacyResolutionEntries, signal);
|
|
384
382
|
if (invalidDerivedEndpoint) return {
|
|
@@ -445,9 +443,6 @@ const RETIRED_SIGNAL_ACCOUNT_TRANSPORT_FIELDS = [
|
|
|
445
443
|
"receiveMode",
|
|
446
444
|
"ignoreStories"
|
|
447
445
|
];
|
|
448
|
-
function isRecord(value) {
|
|
449
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
450
|
-
}
|
|
451
446
|
function hasRetiredSignalAccountTransportFields(value) {
|
|
452
447
|
return isRecord(value) && RETIRED_SIGNAL_ACCOUNT_TRANSPORT_FIELDS.some((field) => Object.hasOwn(value, field));
|
|
453
448
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-api-
|
|
1
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-api-Dcte-QYB.js";
|
|
2
2
|
export { legacyConfigRules, normalizeCompatibilityConfig };
|
|
@@ -8,17 +8,18 @@ import { n as sendReactionSignal } from "./reaction-runtime-api-BjeDyKcz.js";
|
|
|
8
8
|
import { a as maybeResolveSignalApprovalReaction, l as resolveSignalApprovalConversationKey, s as registerSignalApprovalReactionTargetForDeliveredPayload, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-DtL47gSK.js";
|
|
9
9
|
import { r as registerSignalQuestionReactionTargetForDeliveredPayload, t as maybeResolveSignalQuestionReaction } from "./question-reactions-Ds48FtEu.js";
|
|
10
10
|
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-B_Ks4MZr.js";
|
|
11
|
-
import { bindIngressLifecycleToReplyOptions, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
11
|
+
import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
12
12
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
13
|
-
import { detectMime, estimateBase64DecodedBytes, kindFromMime, saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
|
|
13
|
+
import { canonicalizeBase64, detectMime, estimateBase64DecodedBytes, kindFromMime, saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
|
|
14
14
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
|
15
|
-
import { normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
15
|
+
import { normalizeNullableString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
16
16
|
import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
|
|
17
17
|
import { normalizeE164, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
18
|
-
import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toHistoryMediaEntries,
|
|
18
|
+
import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toHistoryMediaEntries, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
19
19
|
import nodePath from "node:path";
|
|
20
20
|
import { collectErrorGraphCandidates, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
21
21
|
import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
|
|
22
|
+
import { isRecord as isRecord$1 } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
22
23
|
import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
23
24
|
import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
|
|
24
25
|
import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
@@ -387,17 +388,9 @@ function createSignalPendingInboundRegistry(accountId) {
|
|
|
387
388
|
if (!conversationKey) return;
|
|
388
389
|
for (const inboundKey of countsByConversation.get(conversationKey)?.keys() ?? []) cancelKey(inboundKey);
|
|
389
390
|
};
|
|
390
|
-
const completeAfter = (flush) => async (entries) => {
|
|
391
|
-
try {
|
|
392
|
-
await flush(entries);
|
|
393
|
-
} finally {
|
|
394
|
-
complete(entries);
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
391
|
return {
|
|
398
392
|
track,
|
|
399
393
|
complete,
|
|
400
|
-
completeAfter,
|
|
401
394
|
cancelPendingOnAbort
|
|
402
395
|
};
|
|
403
396
|
}
|
|
@@ -612,7 +605,7 @@ function createSignalEventHandler(deps) {
|
|
|
612
605
|
chatType: entry.isGroup ? "group" : "direct"
|
|
613
606
|
});
|
|
614
607
|
const replyThreading = resolveBatchedReplyThreadingPolicy(replyToMode, entry.isBatched === true);
|
|
615
|
-
const media =
|
|
608
|
+
const media = await toInboundMediaFactsWithMetadata(entry.media);
|
|
616
609
|
const ctxPayload = buildChannelInboundEventContext({
|
|
617
610
|
channel: "signal",
|
|
618
611
|
supplemental: { quote: entry.replyToBody ? {
|
|
@@ -664,7 +657,7 @@ function createSignalEventHandler(deps) {
|
|
|
664
657
|
}
|
|
665
658
|
});
|
|
666
659
|
if (shouldLogVerbose()) {
|
|
667
|
-
const preview = truncateUtf16Safe(body, 200).replace(
|
|
660
|
+
const preview = truncateUtf16Safe(body, 200).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
668
661
|
logVerbose(`signal inbound: from=${ctxPayload.From} len=${body.length} preview="${preview}"`);
|
|
669
662
|
}
|
|
670
663
|
const statusReactionTimestamp = resolveSignalStatusReactionTimestamp(entry);
|
|
@@ -682,7 +675,6 @@ function createSignalEventHandler(deps) {
|
|
|
682
675
|
isDirect: !entry.isGroup,
|
|
683
676
|
isGroup: entry.isGroup,
|
|
684
677
|
isMentionableGroup: entry.isGroup,
|
|
685
|
-
requireMention: entry.requireMention === true,
|
|
686
678
|
canDetectMention: entry.canDetectMention === true,
|
|
687
679
|
effectiveWasMentioned: entry.wasMentioned === true
|
|
688
680
|
}));
|
|
@@ -872,15 +864,14 @@ function createSignalEventHandler(deps) {
|
|
|
872
864
|
}
|
|
873
865
|
});
|
|
874
866
|
}
|
|
875
|
-
async function flushSignalInboundEntries(entries) {
|
|
867
|
+
async function flushSignalInboundEntries(entries, lifecycle, settle) {
|
|
876
868
|
const last = entries.at(-1);
|
|
877
869
|
if (!last) return;
|
|
878
|
-
const { lifecycle, settle } = fanInChannelIngressLifecycles(entries.map((entry) => entry.turnAdoptionLifecycle));
|
|
879
870
|
if (entries.length === 1) {
|
|
880
|
-
await handleSignalInboundMessage(
|
|
871
|
+
await handleSignalInboundMessage({
|
|
881
872
|
...last,
|
|
882
873
|
turnAdoptionLifecycle: lifecycle
|
|
883
|
-
}
|
|
874
|
+
});
|
|
884
875
|
await settle();
|
|
885
876
|
return;
|
|
886
877
|
}
|
|
@@ -894,14 +885,14 @@ function createSignalEventHandler(deps) {
|
|
|
894
885
|
...last,
|
|
895
886
|
bodyText: combinedText,
|
|
896
887
|
commandBody: combinedCommandBody,
|
|
897
|
-
|
|
888
|
+
turnAdoptionLifecycle: lifecycle,
|
|
898
889
|
isBatched: true,
|
|
899
890
|
nativeReplyBody: last.nativeReplyBody ?? last.bodyText,
|
|
900
891
|
media: entries.flatMap((entry) => entry.media ?? [])
|
|
901
892
|
});
|
|
902
893
|
await settle();
|
|
903
894
|
}
|
|
904
|
-
async function retrySignalInboundFlush(entries, initialError) {
|
|
895
|
+
async function retrySignalInboundFlush(entries, lifecycle, settle, initialError) {
|
|
905
896
|
let lastError = initialError;
|
|
906
897
|
for (const [attemptIndex, delayMs] of RETRYABLE_FLUSH_RETRY_DELAYS_MS.entries()) {
|
|
907
898
|
const attempt = attemptIndex + 1;
|
|
@@ -917,7 +908,7 @@ function createSignalEventHandler(deps) {
|
|
|
917
908
|
}
|
|
918
909
|
if (deps.abortSignal?.aborted) return;
|
|
919
910
|
try {
|
|
920
|
-
await flushSignalInboundEntries(entries);
|
|
911
|
+
await flushSignalInboundEntries(entries, lifecycle, settle);
|
|
921
912
|
return;
|
|
922
913
|
} catch (err) {
|
|
923
914
|
if (deps.abortSignal?.aborted) return;
|
|
@@ -927,26 +918,41 @@ function createSignalEventHandler(deps) {
|
|
|
927
918
|
}
|
|
928
919
|
throw lastError;
|
|
929
920
|
}
|
|
930
|
-
const flushDebouncedSignalInboundEntries =
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
921
|
+
const flushDebouncedSignalInboundEntries = (entries, createFlush) => {
|
|
922
|
+
const { lifecycle, settle } = fanInChannelIngressLifecycles(entries.map((entry) => entry.turnAdoptionLifecycle));
|
|
923
|
+
return createFlush({
|
|
924
|
+
lifecycle,
|
|
925
|
+
dispatch: async (admissionLifecycle) => {
|
|
926
|
+
if (!entries.some((entry) => activeEnqueueEntries.has(entry)) && deps.abortSignal?.aborted) return;
|
|
927
|
+
try {
|
|
928
|
+
await flushSignalInboundEntries(entries, admissionLifecycle, settle);
|
|
929
|
+
} catch (err) {
|
|
930
|
+
if (!isSignalReplySessionInitConflictError(err)) throw err;
|
|
931
|
+
if (deps.abortSignal?.aborted) return;
|
|
932
|
+
await retrySignalInboundFlush(entries, admissionLifecycle, settle, err).catch(async (terminalError) => {
|
|
933
|
+
await Promise.all(entries.map((entry) => Promise.resolve(entry.turnAdoptionLifecycle?.onAbandoned())));
|
|
934
|
+
throw terminalError;
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
});
|
|
944
939
|
};
|
|
945
940
|
const reportSignalInboundFlushError = (err) => {
|
|
946
941
|
deps.runtime.error?.(`signal debounce flush failed: ${String(err)}`);
|
|
947
942
|
};
|
|
948
943
|
const pendingInboundRegistry = createSignalPendingInboundRegistry(deps.accountId);
|
|
949
|
-
const
|
|
944
|
+
const trackSignalInboundFlush = (flush) => {
|
|
945
|
+
deps.runTrackedTask?.(() => flush.completion.catch(() => void 0));
|
|
946
|
+
return flush;
|
|
947
|
+
};
|
|
948
|
+
const flushNormalSignalInboundEntries = (entries, createFlush) => {
|
|
949
|
+
const flush = flushDebouncedSignalInboundEntries(entries, createFlush);
|
|
950
|
+
const completion = flush.completion.finally(() => pendingInboundRegistry.complete(entries));
|
|
951
|
+
return trackSignalInboundFlush({
|
|
952
|
+
admission: flush.admission,
|
|
953
|
+
completion
|
|
954
|
+
});
|
|
955
|
+
};
|
|
950
956
|
const { debouncer } = createChannelInboundDebouncer({
|
|
951
957
|
cfg: deps.cfg,
|
|
952
958
|
channel: "signal",
|
|
@@ -966,7 +972,7 @@ function createSignalEventHandler(deps) {
|
|
|
966
972
|
serializeImmediate: true,
|
|
967
973
|
buildKey: (entry) => resolveSignalControlLaneKey(deps.accountId, entry),
|
|
968
974
|
shouldDebounce: () => false,
|
|
969
|
-
onFlush: flushDebouncedSignalInboundEntries,
|
|
975
|
+
onFlush: (entries, createFlush) => trackSignalInboundFlush(flushDebouncedSignalInboundEntries(entries, createFlush)),
|
|
970
976
|
onError: reportSignalInboundFlushError
|
|
971
977
|
});
|
|
972
978
|
async function handleReactionOnlyInbound(params) {
|
|
@@ -1365,24 +1371,8 @@ function registerSignalReactionTargetsForDeliveredPayload(params) {
|
|
|
1365
1371
|
}
|
|
1366
1372
|
//#endregion
|
|
1367
1373
|
//#region extensions/signal/src/signal-ingress.ts
|
|
1368
|
-
const SIGNAL_INGRESS_COMPLETED_TTL_MS = 720 * 60 * 60 * 1e3;
|
|
1369
|
-
const SIGNAL_INGRESS_COMPLETED_MAX_ENTRIES = 1e3;
|
|
1370
|
-
const SIGNAL_INGRESS_FAILED_TTL_MS = 720 * 60 * 60 * 1e3;
|
|
1371
|
-
const SIGNAL_INGRESS_FAILED_MAX_ENTRIES = 1e3;
|
|
1372
1374
|
const SIGNAL_INGRESS_DRAIN_INTERVAL_MS = 1e3;
|
|
1373
|
-
|
|
1374
|
-
constructor(reason, message, options) {
|
|
1375
|
-
super(message, options);
|
|
1376
|
-
this.reason = reason;
|
|
1377
|
-
this.name = "SignalIngressPermanentError";
|
|
1378
|
-
}
|
|
1379
|
-
};
|
|
1380
|
-
function isRecord$1(value) {
|
|
1381
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1382
|
-
}
|
|
1383
|
-
function normalizeRawString(value) {
|
|
1384
|
-
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
1385
|
-
}
|
|
1375
|
+
const SignalIngressPermanentError = createChannelIngressError("SignalIngressPermanentError", { withReason: true });
|
|
1386
1376
|
function normalizeTimestamp(value) {
|
|
1387
1377
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
1388
1378
|
}
|
|
@@ -1407,15 +1397,15 @@ function inspectSignalIngressEvent(event) {
|
|
|
1407
1397
|
const dataMessage = resolveDataMessage(envelope);
|
|
1408
1398
|
const reactionMessage = isRecord$1(envelope.reactionMessage) ? envelope.reactionMessage : null;
|
|
1409
1399
|
if (!dataMessage && !reactionMessage) return null;
|
|
1410
|
-
const senderUuid =
|
|
1411
|
-
const senderNumber =
|
|
1400
|
+
const senderUuid = normalizeNullableString(envelope.sourceUuid);
|
|
1401
|
+
const senderNumber = normalizeNullableString(envelope.sourceNumber);
|
|
1412
1402
|
const senderKey = senderUuid ? `uuid:${senderUuid}` : senderNumber ? `number:${senderNumber}` : null;
|
|
1413
1403
|
if (!senderKey) throw new SignalIngressPermanentError("missing-sender", "Signal dispatchable envelope is missing sourceUuid/sourceNumber");
|
|
1414
1404
|
const timestamp = normalizeTimestamp(envelope.timestamp) ?? normalizeTimestamp(dataMessage?.timestamp);
|
|
1415
1405
|
if (timestamp === null) throw new SignalIngressPermanentError("missing-timestamp", "Signal dispatchable envelope is missing a stable timestamp");
|
|
1416
1406
|
const dataGroup = isRecord$1(dataMessage?.groupInfo) ? dataMessage.groupInfo : null;
|
|
1417
1407
|
const reactionGroup = isRecord$1(reactionMessage?.groupInfo) ? reactionMessage.groupInfo : null;
|
|
1418
|
-
const groupId =
|
|
1408
|
+
const groupId = normalizeNullableString(dataGroup?.groupId) ?? normalizeNullableString(reactionGroup?.groupId);
|
|
1419
1409
|
return {
|
|
1420
1410
|
eventId: JSON.stringify([senderKey, timestamp]),
|
|
1421
1411
|
laneKey: groupId ? `group:${groupId}` : `direct:${senderKey}`
|
|
@@ -1459,10 +1449,8 @@ async function startSignalIngressMonitor(params) {
|
|
|
1459
1449
|
pollIntervalMs: SIGNAL_INGRESS_DRAIN_INTERVAL_MS,
|
|
1460
1450
|
retention: {
|
|
1461
1451
|
pruneIntervalMs: 0,
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
failedTtlMs: SIGNAL_INGRESS_FAILED_TTL_MS,
|
|
1465
|
-
failedMaxEntries: SIGNAL_INGRESS_FAILED_MAX_ENTRIES
|
|
1452
|
+
completedMaxEntries: 1e3,
|
|
1453
|
+
failedMaxEntries: 1e3
|
|
1466
1454
|
},
|
|
1467
1455
|
appendRetryDelaysMs: [0],
|
|
1468
1456
|
drain: {
|
|
@@ -1680,7 +1668,9 @@ async function fetchAttachment(params) {
|
|
|
1680
1668
|
});
|
|
1681
1669
|
if (!result?.data) return null;
|
|
1682
1670
|
if (estimateBase64DecodedBytes(result.data) > params.maxBytes) throw new Error(`Signal attachment ${attachment.id} exceeds ${(params.maxBytes / (1024 * 1024)).toFixed(0)}MB limit`);
|
|
1683
|
-
const
|
|
1671
|
+
const canonicalData = canonicalizeBase64(result.data);
|
|
1672
|
+
if (!canonicalData) throw new Error(`Signal attachment ${attachment.id} returned malformed base64 data`);
|
|
1673
|
+
const buffer = Buffer.from(canonicalData, "base64");
|
|
1684
1674
|
const originalFilename = normalizeOptionalString(attachment.filename ?? void 0);
|
|
1685
1675
|
const saved = await saveMediaBuffer(buffer, normalizeOptionalString(attachment.contentType ?? void 0) ?? await detectMime({
|
|
1686
1676
|
buffer,
|
package/dist/runtime-api.js
CHANGED
|
@@ -3,9 +3,9 @@ import { d as normalizeSignalMessagingTarget, u as looksLikeSignalTargetId } fro
|
|
|
3
3
|
import { n as setSignalRuntime } from "./runtime-JPrGlV7h.js";
|
|
4
4
|
import { a as signalMessageActions, o as resolveSignalReactionLevel } from "./transport-detection-Da06-LOL.js";
|
|
5
5
|
import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-BjeDyKcz.js";
|
|
6
|
-
import { n as SignalConfigSchema } from "./config-schema-
|
|
6
|
+
import { n as SignalConfigSchema } from "./config-schema-Y3dFGwdL.js";
|
|
7
7
|
import { i as installSignalCli } from "./install-signal-cli-qJF7iC4h.js";
|
|
8
|
-
import { t as monitorSignalProvider } from "./monitor-
|
|
8
|
+
import { t as monitorSignalProvider } from "./monitor-BvIzkrYW.js";
|
|
9
9
|
import { t as sendMessageSignal } from "./send-B_Ks4MZr.js";
|
|
10
10
|
import { t as probeSignal } from "./probe-Br9abaGp.js";
|
|
11
11
|
import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/signal",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.7",
|
|
4
4
|
"description": "OpenClaw Signal channel plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
@@ -93,10 +93,10 @@
|
|
|
93
93
|
"allowInvalidConfigRecovery": true
|
|
94
94
|
},
|
|
95
95
|
"compat": {
|
|
96
|
-
"pluginApi": ">=2026.7.2-beta.
|
|
96
|
+
"pluginApi": ">=2026.7.2-beta.7"
|
|
97
97
|
},
|
|
98
98
|
"build": {
|
|
99
|
-
"openclawVersion": "2026.7.2-beta.
|
|
99
|
+
"openclawVersion": "2026.7.2-beta.7",
|
|
100
100
|
"bundledDist": false
|
|
101
101
|
},
|
|
102
102
|
"release": {
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"README.md"
|
|
119
119
|
],
|
|
120
120
|
"peerDependencies": {
|
|
121
|
-
"openclaw": ">=2026.7.2-beta.
|
|
121
|
+
"openclaw": ">=2026.7.2-beta.7"
|
|
122
122
|
},
|
|
123
123
|
"peerDependenciesMeta": {
|
|
124
124
|
"openclaw": {
|