@openclaw/signal 2026.7.2-beta.7 → 2026.8.1-beta.3
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/{accounts-DrStJjiK.js → accounts-DO4HMqaK.js} +2 -2
- package/dist/api.js +9 -9
- package/dist/{runtime-JPrGlV7h.js → approval-auth-BY6uuApE.js} +2 -9
- package/dist/{approval-handler.runtime-C-XYgcxE.js → approval-handler.runtime-Co6EVTqY.js} +4 -4
- package/dist/{approval-reactions-DtL47gSK.js → approval-reactions-cs3Ox9Ow.js} +67 -189
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-CmbWaYlm.js → channel-zIopSllO.js} +64 -99
- package/dist/{channel.runtime-BRDaqr5-.js → channel.runtime-CpDBElG8.js} +3 -3
- package/dist/{client-BazXTH7O.js → client-CvnR8_XA.js} +31 -34
- package/dist/{client-adapter-mXGeEHQJ.js → client-adapter-D9SNPaNx.js} +13 -6
- package/dist/{config-schema-Y3dFGwdL.js → config-schema-CkMIK7zp.js} +4 -5
- package/dist/contract-api.js +1 -1
- package/dist/{doctor-contract-api-Dcte-QYB.js → doctor-contract-api-Dnp5eQQJ.js} +19 -22
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{install-signal-cli-qJF7iC4h.js → install-signal-cli-Cpiyk0k1.js} +8 -5
- package/dist/{monitor-BvIzkrYW.js → monitor-BLFIkpH0.js} +305 -142
- package/dist/{probe-Br9abaGp.js → probe-B0E_cXQw.js} +23 -7
- package/dist/question-reactions-BaatFqJ7.js +80 -0
- package/dist/{reaction-runtime-api-BjeDyKcz.js → reaction-runtime-api-YGD6hhDh.js} +10 -21
- package/dist/reaction-runtime-api.js +1 -1
- package/dist/rpc-context-dXSy4NtF.js +15 -0
- package/dist/runtime-api.js +8 -9
- package/dist/{send-B_Ks4MZr.js → send-BNl5folj.js} +14 -23
- package/dist/{send.runtime-CbuXycZT.js → send.runtime-DnMoKk27.js} +1 -1
- package/dist/{transport-detection-Da06-LOL.js → transport-detection-D_M79R5f.js} +60 -148
- package/dist/{transport-detection.runtime-D_190UUL.js → transport-detection.runtime-DKuuIHvf.js} +1 -1
- package/dist/{transport-probes.runtime-CV6Qs0Og.js → transport-probes.runtime-BsJdp0oI.js} +1 -1
- package/openclaw.plugin.json +4 -1
- package/package.json +5 -5
- package/dist/approval-resolver-B3m0D2R0.js +0 -16
- package/dist/question-reactions-Ds48FtEu.js +0 -109
- package/dist/rpc-context-CZUoE0-A.js +0 -17
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { a as isSignalManagedNativeConnectionUrlForBind, i as assignSignalManagedNativePort, l as normalizeSignalTransportHost, o as isValidSignalManagedNativePort, r as allocateSignalManagedNativePort, s as resolveLocalSignalTransportPort, u as normalizeSignalTransportUrl } from "./transport-policy-DxvSMHp9.js";
|
|
2
|
-
import { a as resolveSignalAccountConfig, i as resolveSignalAccount, n as listSignalAccountIds, o as resolveSignalReplyToMode, r as resolveDefaultSignalAccountId, s as resolveSignalTransport } from "./accounts-
|
|
2
|
+
import { a as resolveSignalAccountConfig, i as resolveSignalAccount, n as listSignalAccountIds, o as resolveSignalReplyToMode, r as resolveDefaultSignalAccountId, s as resolveSignalTransport } from "./accounts-DO4HMqaK.js";
|
|
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
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-
|
|
7
|
-
import { t as SignalChannelConfigSchema } from "./config-schema-
|
|
4
|
+
import { i as resolveSignalTarget, r as listSignalAliasDirectoryEntries } from "./approval-auth-BY6uuApE.js";
|
|
5
|
+
import { c as resolveSignalReactionLevel, d as markdownToSignalTextChunks, l as formatSignalMediaText, m as signalApprovalCapability, o as materializeSignalPresentationFallback, p as shouldSuppressLocalSignalExecApprovalPrompt, r as resolveSignalReplyContextWithPersistence, s as signalMessageActions, t as detectSignalTransport } from "./transport-detection-D_M79R5f.js";
|
|
6
|
+
import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-Dnp5eQQJ.js";
|
|
7
|
+
import { t as SignalChannelConfigSchema } from "./config-schema-CkMIK7zp.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";
|
|
11
|
-
import { createReplyToFanout, defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
|
|
11
|
+
import { createAccountStatusSink, createReplyToFanout, defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
|
|
12
12
|
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
|
|
13
13
|
import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result";
|
|
14
14
|
import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
|
|
@@ -213,8 +213,8 @@ async function probeSignalTransport(params) {
|
|
|
213
213
|
accountId: params.accountId,
|
|
214
214
|
overrides: managedTransportOptions(params.transport)
|
|
215
215
|
}) : params.transport);
|
|
216
|
-
if (resolved.kind === "container") return (params.probeContainer ?? (await import("./transport-probes.runtime-
|
|
217
|
-
return (params.probeNative ?? (await import("./transport-probes.runtime-
|
|
216
|
+
if (resolved.kind === "container") return (params.probeContainer ?? (await import("./transport-probes.runtime-BsJdp0oI.js")).containerCheck)(resolved.baseUrl, timeoutMs, params.account);
|
|
217
|
+
return (params.probeNative ?? (await import("./transport-probes.runtime-BsJdp0oI.js")).nativeCheck)(resolved.baseUrl, timeoutMs);
|
|
218
218
|
}
|
|
219
219
|
function writeSignalAccountTransport(params) {
|
|
220
220
|
const transport = normalizeTransport(params.transport);
|
|
@@ -324,6 +324,7 @@ function parseSignalAllowFromEntries(raw) {
|
|
|
324
324
|
});
|
|
325
325
|
}
|
|
326
326
|
function buildSignalSetupPatch(input) {
|
|
327
|
+
const account = normalizeSignalAccountInput(input.signalNumber);
|
|
327
328
|
const transport = input.httpUrl ? {
|
|
328
329
|
kind: input.signalTransport ?? "external-native",
|
|
329
330
|
url: normalizeSignalTransportUrl(input.httpUrl)
|
|
@@ -334,7 +335,7 @@ function buildSignalSetupPatch(input) {
|
|
|
334
335
|
...input.httpPort ? { httpPort: Number(input.httpPort) } : {}
|
|
335
336
|
} : void 0;
|
|
336
337
|
return {
|
|
337
|
-
...
|
|
338
|
+
...account ? { account } : {},
|
|
338
339
|
...transport ? { transport } : {}
|
|
339
340
|
};
|
|
340
341
|
}
|
|
@@ -463,6 +464,7 @@ const signalSetupAdapterBase = createPatchedAccountSetupAdapter({
|
|
|
463
464
|
} catch {
|
|
464
465
|
return "Signal --http-host must be a hostname or IP address.";
|
|
465
466
|
}
|
|
467
|
+
if (input.signalNumber !== void 0 && !normalizeSignalAccountInput(input.signalNumber)) return INVALID_SIGNAL_ACCOUNT_ERROR;
|
|
466
468
|
if (input.signalTransport === "container" && !normalizeSignalAccountInput(input.signalNumber) && !normalizeSignalAccountInput(resolveSignalSetupAccount({
|
|
467
469
|
cfg,
|
|
468
470
|
accountId
|
|
@@ -568,7 +570,7 @@ function createSignalSetupWizardProxy(loadWizard) {
|
|
|
568
570
|
const signalDoctor = {
|
|
569
571
|
normalizeCompatibilityConfig,
|
|
570
572
|
cleanStaleConfig: async ({ cfg }) => {
|
|
571
|
-
const { detectSignalTransport } = await import("./transport-detection.runtime-
|
|
573
|
+
const { detectSignalTransport } = await import("./transport-detection.runtime-DKuuIHvf.js");
|
|
572
574
|
return await migrateLegacySignalTransportConfig({
|
|
573
575
|
cfg,
|
|
574
576
|
detect: detectSignalTransport
|
|
@@ -579,7 +581,7 @@ const signalDoctor = {
|
|
|
579
581
|
//#region extensions/signal/src/shared.ts
|
|
580
582
|
const SIGNAL_CHANNEL = "signal";
|
|
581
583
|
async function loadSignalChannelRuntime() {
|
|
582
|
-
return await import("./channel.runtime-
|
|
584
|
+
return await import("./channel.runtime-CpDBElG8.js");
|
|
583
585
|
}
|
|
584
586
|
const signalSetupWizard = createSignalSetupWizardProxy(async () => (await loadSignalChannelRuntime()).signalSetupWizard);
|
|
585
587
|
const signalConfigAdapter = {
|
|
@@ -625,6 +627,7 @@ const signalSecurityAdapter = createRestrictSendersChannelSecurity({
|
|
|
625
627
|
groupPolicyPath: "channels.signal.groupPolicy",
|
|
626
628
|
groupAllowFromPath: "channels.signal.groupAllowFrom",
|
|
627
629
|
mentionGated: false,
|
|
630
|
+
findingTitle: "Signal security warning",
|
|
628
631
|
policyPathSuffix: "dmPolicy",
|
|
629
632
|
normalizeDmEntry: (raw) => normalizeE164(raw.replace(/^signal:/i, "").trim())
|
|
630
633
|
});
|
|
@@ -663,10 +666,10 @@ function createSignalPluginBase(params) {
|
|
|
663
666
|
}
|
|
664
667
|
//#endregion
|
|
665
668
|
//#region extensions/signal/src/channel.ts
|
|
666
|
-
const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-
|
|
667
|
-
const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-
|
|
668
|
-
const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-
|
|
669
|
-
const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-
|
|
669
|
+
const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-BLFIkpH0.js").then((n) => n.n));
|
|
670
|
+
const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-B0E_cXQw.js").then((n) => n.n));
|
|
671
|
+
const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-DnMoKk27.js"));
|
|
672
|
+
const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-cs3Ox9Ow.js").then((n) => n.n));
|
|
670
673
|
async function resolveSignalSendContext(params) {
|
|
671
674
|
return {
|
|
672
675
|
send: resolveOutboundSendDep(params.deps, "signal") ?? (await loadSignalSendRuntime()).sendMessageSignal,
|
|
@@ -685,21 +688,29 @@ function resolveSignalSendTarget(params) {
|
|
|
685
688
|
})?.to ?? params.to.trim();
|
|
686
689
|
}
|
|
687
690
|
async function sendSignalOutbound(params) {
|
|
688
|
-
const
|
|
689
|
-
const
|
|
691
|
+
const accountId = params.accountId ?? void 0;
|
|
692
|
+
const { send, maxBytes } = await resolveSignalSendContext({
|
|
693
|
+
...params,
|
|
694
|
+
accountId
|
|
695
|
+
});
|
|
696
|
+
const to = resolveSignalSendTarget({
|
|
697
|
+
...params,
|
|
698
|
+
accountId
|
|
699
|
+
});
|
|
690
700
|
const replyOptions = await resolveSignalReplyOptions({
|
|
691
701
|
cfg: params.cfg,
|
|
692
702
|
to,
|
|
693
|
-
accountId
|
|
703
|
+
accountId,
|
|
694
704
|
replyToId: params.replyToId
|
|
695
705
|
});
|
|
696
706
|
return await send(to, params.text, {
|
|
697
707
|
cfg: params.cfg,
|
|
698
708
|
...params.mediaUrl ? { mediaUrl: params.mediaUrl } : {},
|
|
709
|
+
...params.mediaAccess ? { mediaAccess: params.mediaAccess } : {},
|
|
699
710
|
...params.mediaLocalRoots?.length ? { mediaLocalRoots: params.mediaLocalRoots } : {},
|
|
700
711
|
...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {},
|
|
701
712
|
maxBytes,
|
|
702
|
-
accountId
|
|
713
|
+
accountId,
|
|
703
714
|
...replyOptions
|
|
704
715
|
});
|
|
705
716
|
}
|
|
@@ -729,9 +740,7 @@ function inferSignalTargetChatType(rawTo) {
|
|
|
729
740
|
if (!to) return;
|
|
730
741
|
if (/^signal:/i.test(to)) to = to.replace(/^signal:/i, "").trim();
|
|
731
742
|
if (!to) return;
|
|
732
|
-
|
|
733
|
-
if (lower.startsWith("group:")) return "group";
|
|
734
|
-
if (lower.startsWith("username:") || lower.startsWith("u:")) return "direct";
|
|
743
|
+
if (normalizeLowercaseStringOrEmpty(to).startsWith("group:")) return "group";
|
|
735
744
|
return "direct";
|
|
736
745
|
}
|
|
737
746
|
function attachSignalVisibleText(result, visibleText) {
|
|
@@ -740,6 +749,7 @@ function attachSignalVisibleText(result, visibleText) {
|
|
|
740
749
|
...result,
|
|
741
750
|
meta: {
|
|
742
751
|
...meta,
|
|
752
|
+
visibleText,
|
|
743
753
|
signalVisibleText: visibleText
|
|
744
754
|
}
|
|
745
755
|
};
|
|
@@ -748,28 +758,14 @@ const signalMessageAdapter = defineChannelMessageAdapter({
|
|
|
748
758
|
id: "signal",
|
|
749
759
|
durableFinal: { capabilities: {
|
|
750
760
|
text: true,
|
|
751
|
-
media: true
|
|
761
|
+
media: true,
|
|
762
|
+
payload: true,
|
|
763
|
+
replyTo: true,
|
|
764
|
+
messageSendingHooks: true
|
|
752
765
|
} },
|
|
753
766
|
send: {
|
|
754
|
-
text:
|
|
755
|
-
|
|
756
|
-
to: ctx.to,
|
|
757
|
-
text: ctx.text,
|
|
758
|
-
accountId: ctx.accountId ?? void 0,
|
|
759
|
-
deps: ctx.deps,
|
|
760
|
-
replyToId: ctx.replyToId ?? void 0
|
|
761
|
-
}),
|
|
762
|
-
media: async (ctx) => await sendSignalOutbound({
|
|
763
|
-
cfg: ctx.cfg,
|
|
764
|
-
to: ctx.to,
|
|
765
|
-
text: ctx.text,
|
|
766
|
-
mediaUrl: ctx.mediaUrl,
|
|
767
|
-
mediaLocalRoots: ctx.mediaLocalRoots,
|
|
768
|
-
mediaReadFile: ctx.mediaReadFile,
|
|
769
|
-
accountId: ctx.accountId ?? void 0,
|
|
770
|
-
deps: ctx.deps,
|
|
771
|
-
replyToId: ctx.replyToId ?? void 0
|
|
772
|
-
})
|
|
767
|
+
text: sendSignalOutbound,
|
|
768
|
+
media: sendSignalOutbound
|
|
773
769
|
}
|
|
774
770
|
});
|
|
775
771
|
function buildSignalBaseSessionKey(params) {
|
|
@@ -819,14 +815,15 @@ async function sendFormattedSignalText(ctx) {
|
|
|
819
815
|
text: ctx.text,
|
|
820
816
|
styles: []
|
|
821
817
|
}];
|
|
818
|
+
const effectiveReplyToMode = ctx.replyToMode ?? resolveSignalReplyToMode({
|
|
819
|
+
cfg: ctx.cfg,
|
|
820
|
+
accountId: ctx.accountId,
|
|
821
|
+
chatType: inferSignalTargetChatType(to)
|
|
822
|
+
});
|
|
822
823
|
const nextReplyToId = createReplyToFanout({
|
|
823
824
|
replyToId: ctx.replyToId,
|
|
824
825
|
replyToIdSource: ctx.replyToIdSource,
|
|
825
|
-
replyToMode:
|
|
826
|
-
cfg: ctx.cfg,
|
|
827
|
-
accountId: ctx.accountId,
|
|
828
|
-
chatType: inferSignalTargetChatType(to)
|
|
829
|
-
})
|
|
826
|
+
replyToMode: effectiveReplyToMode
|
|
830
827
|
});
|
|
831
828
|
const results = [];
|
|
832
829
|
for (const chunk of chunks) {
|
|
@@ -881,6 +878,7 @@ async function sendFormattedSignalMedia(ctx) {
|
|
|
881
878
|
return attachChannelToResult("signal", attachSignalVisibleText(await send(to, formatted.text, {
|
|
882
879
|
cfg: ctx.cfg,
|
|
883
880
|
mediaUrl: ctx.mediaUrl,
|
|
881
|
+
...ctx.mediaAccess ? { mediaAccess: ctx.mediaAccess } : {},
|
|
884
882
|
mediaLocalRoots: ctx.mediaLocalRoots,
|
|
885
883
|
...ctx.mediaReadFile ? { mediaReadFile: ctx.mediaReadFile } : {},
|
|
886
884
|
maxBytes,
|
|
@@ -898,7 +896,7 @@ async function registerDeliveredSignalApprovalPayloadForReactions(params) {
|
|
|
898
896
|
const targetAuthor = normalizeOptionalString(account.config.account);
|
|
899
897
|
const targetAuthorUuid = normalizeOptionalString(account.config.accountUuid);
|
|
900
898
|
if (!targetAuthor && !targetAuthorUuid) return;
|
|
901
|
-
const { registerSignalQuestionReactionTargetForDeliveredPayload } = await import("./question-reactions-
|
|
899
|
+
const { registerSignalQuestionReactionTargetForDeliveredPayload } = await import("./question-reactions-BaatFqJ7.js").then((n) => n.n);
|
|
902
900
|
registerSignalQuestionReactionTargetForDeliveredPayload({
|
|
903
901
|
cfg: params.cfg,
|
|
904
902
|
target: {
|
|
@@ -1047,9 +1045,13 @@ const signalPlugin = createChatChannelPlugin({
|
|
|
1047
1045
|
lastProbeAt: snapshot.lastProbeAt ?? null
|
|
1048
1046
|
}),
|
|
1049
1047
|
probeAccount: async ({ account, timeoutMs }) => {
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1052
|
-
|
|
1048
|
+
const { probeSignalAccount } = await loadSignalProbeModule();
|
|
1049
|
+
return await probeSignalAccount({
|
|
1050
|
+
baseUrl: account.baseUrl,
|
|
1051
|
+
timeoutMs,
|
|
1052
|
+
transportKind: account.transport.kind,
|
|
1053
|
+
account: account.config.account
|
|
1054
|
+
});
|
|
1053
1055
|
},
|
|
1054
1056
|
formatCapabilitiesProbe: ({ probe }) => probe?.version ? [{ text: `Signal daemon: ${probe.version}` }] : [],
|
|
1055
1057
|
resolveAccountSnapshot: ({ account }) => ({
|
|
@@ -1062,10 +1064,11 @@ const signalPlugin = createChatChannelPlugin({
|
|
|
1062
1064
|
}),
|
|
1063
1065
|
gateway: { startAccount: async (ctx) => {
|
|
1064
1066
|
const account = ctx.account;
|
|
1065
|
-
|
|
1067
|
+
const statusSink = createAccountStatusSink({
|
|
1066
1068
|
accountId: account.accountId,
|
|
1067
|
-
|
|
1069
|
+
setStatus: ctx.setStatus
|
|
1068
1070
|
});
|
|
1071
|
+
statusSink({ baseUrl: account.baseUrl });
|
|
1069
1072
|
ctx.log?.info(`[${account.accountId}] starting provider (${account.baseUrl})`);
|
|
1070
1073
|
const { monitorSignalProvider } = await loadSignalMonitorModule();
|
|
1071
1074
|
return await monitorSignalProvider({
|
|
@@ -1074,7 +1077,8 @@ const signalPlugin = createChatChannelPlugin({
|
|
|
1074
1077
|
runtime: ctx.runtime,
|
|
1075
1078
|
channelRuntime: ctx.channelRuntime,
|
|
1076
1079
|
abortSignal: ctx.abortSignal,
|
|
1077
|
-
mediaMaxMb: account.config.mediaMaxMb
|
|
1080
|
+
mediaMaxMb: account.config.mediaMaxMb,
|
|
1081
|
+
statusSink
|
|
1078
1082
|
});
|
|
1079
1083
|
} },
|
|
1080
1084
|
message: signalMessageAdapter
|
|
@@ -1153,54 +1157,15 @@ const signalPlugin = createChatChannelPlugin({
|
|
|
1153
1157
|
payload,
|
|
1154
1158
|
hint
|
|
1155
1159
|
}),
|
|
1156
|
-
afterDeliverPayload:
|
|
1157
|
-
renderPresentation:
|
|
1158
|
-
sendFormattedText:
|
|
1159
|
-
|
|
1160
|
-
to,
|
|
1161
|
-
text,
|
|
1162
|
-
accountId,
|
|
1163
|
-
deps,
|
|
1164
|
-
replyToId,
|
|
1165
|
-
replyToIdSource,
|
|
1166
|
-
replyToMode,
|
|
1167
|
-
abortSignal,
|
|
1168
|
-
onDeliveryResult
|
|
1169
|
-
}),
|
|
1170
|
-
sendFormattedMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId, abortSignal }) => await sendFormattedSignalMedia({
|
|
1171
|
-
cfg,
|
|
1172
|
-
to,
|
|
1173
|
-
text,
|
|
1174
|
-
mediaUrl,
|
|
1175
|
-
mediaLocalRoots,
|
|
1176
|
-
mediaReadFile,
|
|
1177
|
-
accountId,
|
|
1178
|
-
deps,
|
|
1179
|
-
replyToId,
|
|
1180
|
-
abortSignal
|
|
1181
|
-
})
|
|
1160
|
+
afterDeliverPayload: registerDeliveredSignalApprovalPayloadForReactions,
|
|
1161
|
+
renderPresentation: renderSignalApprovalPayloadForReactions,
|
|
1162
|
+
sendFormattedText: sendFormattedSignalText,
|
|
1163
|
+
sendFormattedMedia: sendFormattedSignalMedia
|
|
1182
1164
|
},
|
|
1183
1165
|
attachedResults: {
|
|
1184
1166
|
channel: "signal",
|
|
1185
|
-
sendText:
|
|
1186
|
-
|
|
1187
|
-
to,
|
|
1188
|
-
text,
|
|
1189
|
-
accountId: accountId ?? void 0,
|
|
1190
|
-
deps,
|
|
1191
|
-
replyToId
|
|
1192
|
-
}),
|
|
1193
|
-
sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId }) => await sendSignalOutbound({
|
|
1194
|
-
cfg,
|
|
1195
|
-
to,
|
|
1196
|
-
text,
|
|
1197
|
-
mediaUrl,
|
|
1198
|
-
mediaLocalRoots,
|
|
1199
|
-
mediaReadFile,
|
|
1200
|
-
accountId: accountId ?? void 0,
|
|
1201
|
-
deps,
|
|
1202
|
-
replyToId
|
|
1203
|
-
})
|
|
1167
|
+
sendText: sendSignalOutbound,
|
|
1168
|
+
sendMedia: sendSignalOutbound
|
|
1204
1169
|
}
|
|
1205
1170
|
}
|
|
1206
1171
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-
|
|
2
|
-
import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-
|
|
3
|
-
import { i as installSignalCli } from "./install-signal-cli-
|
|
1
|
+
import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-DO4HMqaK.js";
|
|
2
|
+
import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-zIopSllO.js";
|
|
3
|
+
import { i as installSignalCli } from "./install-signal-cli-Cpiyk0k1.js";
|
|
4
4
|
import { detectBinary } from "openclaw/plugin-sdk/setup-tools";
|
|
5
5
|
import { createDetectedBinaryStatus, createSetupTranslator, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
|
6
6
|
//#region extensions/signal/src/setup-surface.ts
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { detectMime, parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
|
|
1
|
+
import { detectMime, extractOriginalFilename, parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
|
|
2
2
|
import { parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
3
|
-
import
|
|
4
|
-
import { formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
3
|
+
import { coerceErrorMessage, formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
5
4
|
import { resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
|
|
6
5
|
import { readResponseTextPrefix, readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
|
7
6
|
import { readRegularFile } from "openclaw/plugin-sdk/security-runtime";
|
|
@@ -24,6 +23,7 @@ const SIGNAL_REST_ERROR_RESPONSE_MAX_BYTES = 16 * 1024;
|
|
|
24
23
|
const SIGNAL_REST_SUCCESS_RESPONSE_MAX_BYTES = 16 * 1024 * 1024;
|
|
25
24
|
const WS_MAX_PAYLOAD = 1024 * 1024;
|
|
26
25
|
const WS_HANDSHAKE_MS = 3e4;
|
|
26
|
+
const WS_SHUTDOWN_DRAIN_TIMEOUT_MS = 1500;
|
|
27
27
|
const DEFAULT_SIGNAL_CONTAINER_MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024;
|
|
28
28
|
const CONTAINER_TEXT_STYLE_MARKERS = {
|
|
29
29
|
BOLD: "**",
|
|
@@ -148,7 +148,7 @@ async function containerCheck(baseUrl, timeoutMs = DEFAULT_TIMEOUT_MS$1, account
|
|
|
148
148
|
return {
|
|
149
149
|
ok: false,
|
|
150
150
|
status: null,
|
|
151
|
-
error:
|
|
151
|
+
error: coerceErrorMessage(err)
|
|
152
152
|
};
|
|
153
153
|
} finally {
|
|
154
154
|
await releaseUnreadResponseBody(res);
|
|
@@ -181,7 +181,7 @@ function containerReceiveCheck(normalizedBaseUrl, account, timeoutMs) {
|
|
|
181
181
|
settle({
|
|
182
182
|
ok: false,
|
|
183
183
|
status: null,
|
|
184
|
-
error:
|
|
184
|
+
error: coerceErrorMessage(err)
|
|
185
185
|
});
|
|
186
186
|
return;
|
|
187
187
|
}
|
|
@@ -205,7 +205,7 @@ function containerReceiveCheck(normalizedBaseUrl, account, timeoutMs) {
|
|
|
205
205
|
settle({
|
|
206
206
|
ok: false,
|
|
207
207
|
status: null,
|
|
208
|
-
error:
|
|
208
|
+
error: coerceErrorMessage(err)
|
|
209
209
|
});
|
|
210
210
|
});
|
|
211
211
|
ws.once("close", (code, reason) => {
|
|
@@ -297,7 +297,12 @@ async function streamContainerEvents(params) {
|
|
|
297
297
|
let settled = false;
|
|
298
298
|
let eventChain = Promise.resolve();
|
|
299
299
|
let abortHandler;
|
|
300
|
+
let shutdownDrainTimer;
|
|
300
301
|
const cleanup = () => {
|
|
302
|
+
if (shutdownDrainTimer) {
|
|
303
|
+
clearTimeout(shutdownDrainTimer);
|
|
304
|
+
shutdownDrainTimer = void 0;
|
|
305
|
+
}
|
|
301
306
|
if (abortHandler) {
|
|
302
307
|
params.abortSignal?.removeEventListener("abort", abortHandler);
|
|
303
308
|
abortHandler = void 0;
|
|
@@ -321,12 +326,13 @@ async function streamContainerEvents(params) {
|
|
|
321
326
|
handshakeTimeout: WS_HANDSHAKE_MS
|
|
322
327
|
});
|
|
323
328
|
} catch (err) {
|
|
324
|
-
logError(`[signal-ws] failed to create WebSocket: ${
|
|
329
|
+
logError(`[signal-ws] failed to create WebSocket: ${coerceErrorMessage(err)}`);
|
|
325
330
|
reject(toErrorObject(err, "Non-Error rejection"));
|
|
326
331
|
return;
|
|
327
332
|
}
|
|
328
333
|
ws.on("open", () => {
|
|
329
334
|
log("[signal-ws] connected");
|
|
335
|
+
params.onStreamOpen?.();
|
|
330
336
|
});
|
|
331
337
|
ws.on("message", (data) => {
|
|
332
338
|
if (settled) return;
|
|
@@ -338,17 +344,17 @@ async function streamContainerEvents(params) {
|
|
|
338
344
|
await params.onEvent(envelope);
|
|
339
345
|
});
|
|
340
346
|
eventChain.catch((err) => {
|
|
341
|
-
logError(`[signal-ws] receive handler failed: ${
|
|
347
|
+
logError(`[signal-ws] receive handler failed: ${coerceErrorMessage(err)}`);
|
|
342
348
|
rejectOnce(err);
|
|
343
349
|
ws.close();
|
|
344
350
|
});
|
|
345
351
|
}
|
|
346
352
|
} catch (err) {
|
|
347
|
-
logError(`[signal-ws] parse error: ${
|
|
353
|
+
logError(`[signal-ws] parse error: ${coerceErrorMessage(err)}`);
|
|
348
354
|
}
|
|
349
355
|
});
|
|
350
356
|
ws.on("error", (err) => {
|
|
351
|
-
logError(`[signal-ws] error: ${
|
|
357
|
+
logError(`[signal-ws] error: ${coerceErrorMessage(err)}`);
|
|
352
358
|
});
|
|
353
359
|
ws.on("close", (code, reason) => {
|
|
354
360
|
const reasonStr = reason?.toString() || "no reason";
|
|
@@ -364,10 +370,16 @@ async function streamContainerEvents(params) {
|
|
|
364
370
|
if (params.abortSignal) {
|
|
365
371
|
abortHandler = () => {
|
|
366
372
|
log("[signal-ws] aborted, closing connection");
|
|
373
|
+
shutdownDrainTimer = setTimeout(() => {
|
|
374
|
+
logError("[signal-ws] shutdown timed out draining accepted receive events; messages may be lost");
|
|
375
|
+
ws.terminate();
|
|
376
|
+
resolveOnce();
|
|
377
|
+
}, WS_SHUTDOWN_DRAIN_TIMEOUT_MS);
|
|
378
|
+
shutdownDrainTimer.unref?.();
|
|
367
379
|
ws.close();
|
|
368
|
-
resolveOnce();
|
|
369
380
|
};
|
|
370
381
|
params.abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
382
|
+
if (params.abortSignal.aborted) abortHandler();
|
|
371
383
|
}
|
|
372
384
|
});
|
|
373
385
|
}
|
|
@@ -388,7 +400,7 @@ async function filesToBase64DataUris(filePaths, maxAttachmentBytes) {
|
|
|
388
400
|
buffer,
|
|
389
401
|
filePath
|
|
390
402
|
}) ?? "application/octet-stream";
|
|
391
|
-
const filename =
|
|
403
|
+
const filename = extractOriginalFilename(filePath).replace(/[,;#]/g, "_");
|
|
392
404
|
const b64 = buffer.toString("base64");
|
|
393
405
|
results.push(`data:${mime};filename=${filename};base64,${b64}`);
|
|
394
406
|
}
|
|
@@ -492,7 +504,7 @@ async function containerSendReceipt(params) {
|
|
|
492
504
|
return true;
|
|
493
505
|
}
|
|
494
506
|
/**
|
|
495
|
-
*
|
|
507
|
+
* Add or remove a message reaction via the bbernhard container REST API.
|
|
496
508
|
*/
|
|
497
509
|
async function containerSendReaction(params) {
|
|
498
510
|
const payload = {
|
|
@@ -505,23 +517,7 @@ async function containerSendReaction(params) {
|
|
|
505
517
|
return await containerRestRequest(`/v1/reactions/${encodeURIComponent(params.account)}`, {
|
|
506
518
|
baseUrl: params.baseUrl,
|
|
507
519
|
timeoutMs: params.timeoutMs
|
|
508
|
-
}, "POST", payload) ?? {};
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Remove a reaction from a message via bbernhard container REST API.
|
|
512
|
-
*/
|
|
513
|
-
async function containerRemoveReaction(params) {
|
|
514
|
-
const payload = {
|
|
515
|
-
recipient: params.recipient,
|
|
516
|
-
reaction: params.emoji,
|
|
517
|
-
target_author: params.targetAuthor,
|
|
518
|
-
timestamp: params.targetTimestamp
|
|
519
|
-
};
|
|
520
|
-
if (params.groupId) payload.group_id = params.groupId;
|
|
521
|
-
return await containerRestRequest(`/v1/reactions/${encodeURIComponent(params.account)}`, {
|
|
522
|
-
baseUrl: params.baseUrl,
|
|
523
|
-
timeoutMs: params.timeoutMs
|
|
524
|
-
}, "DELETE", payload) ?? {};
|
|
520
|
+
}, params.remove ? "DELETE" : "POST", payload) ?? {};
|
|
525
521
|
}
|
|
526
522
|
/**
|
|
527
523
|
* Strip the "uuid:" prefix that native signal-cli accepts but the container API rejects.
|
|
@@ -605,7 +601,7 @@ async function containerRpcRequest(method, params, opts) {
|
|
|
605
601
|
const groupId = p.groupIds?.[0] ?? void 0;
|
|
606
602
|
const formattedGroupId = groupId ? formatGroupIdForContainer(groupId) : void 0;
|
|
607
603
|
const effectiveRecipient = formattedGroupId || recipient || "";
|
|
608
|
-
|
|
604
|
+
return await containerSendReaction({
|
|
609
605
|
baseUrl: opts.baseUrl,
|
|
610
606
|
account: p.account ?? "",
|
|
611
607
|
recipient: effectiveRecipient,
|
|
@@ -613,9 +609,9 @@ async function containerRpcRequest(method, params, opts) {
|
|
|
613
609
|
targetAuthor: stripUuidPrefix(p.targetAuthor ?? recipient),
|
|
614
610
|
targetTimestamp: p.targetTimestamp,
|
|
615
611
|
groupId: formattedGroupId,
|
|
616
|
-
timeoutMs: opts.timeoutMs
|
|
617
|
-
|
|
618
|
-
|
|
612
|
+
timeoutMs: opts.timeoutMs,
|
|
613
|
+
remove: Boolean(p.remove)
|
|
614
|
+
});
|
|
619
615
|
}
|
|
620
616
|
case "getAttachment": {
|
|
621
617
|
const attachmentId = p.id;
|
|
@@ -864,6 +860,7 @@ async function streamSignalEvents(params) {
|
|
|
864
860
|
const url = resolveSignalEndpointUrl(params.baseUrl, "/api/v1/events");
|
|
865
861
|
if (params.account) url.searchParams.set("account", params.account);
|
|
866
862
|
const { response, cleanup } = await openSignalEventStream(url, params.abortSignal, params.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
863
|
+
params.onStreamOpen?.();
|
|
867
864
|
const decoder = new TextDecoder();
|
|
868
865
|
let buffer = "";
|
|
869
866
|
let bufferedBytes = 0;
|
|
@@ -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-
|
|
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
|
|
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
|
|
69
|
-
if (!isRecord
|
|
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];
|
package/dist/contract-api.js
CHANGED
|
@@ -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-
|
|
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 };
|