@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.
- package/dist/api.js +7 -7
- package/dist/{approval-handler.runtime-C-XYgcxE.js → approval-handler.runtime-Bi5yNhnj.js} +2 -2
- package/dist/{approval-reactions-DtL47gSK.js → approval-reactions-BulCzhdB.js} +15 -45
- package/dist/{channel-CmbWaYlm.js → channel-CzDJMDtX.js} +50 -91
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-BRDaqr5-.js → channel.runtime-D12iYzJB.js} +2 -2
- 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-DiN2hKnG.js} +128 -67
- package/dist/{probe-Br9abaGp.js → probe-C_THuQzn.js} +23 -7
- package/dist/question-reactions-ByjH5qST.js +80 -0
- package/dist/{reaction-runtime-api-BjeDyKcz.js → reaction-runtime-api-Cf6QHcE5.js} +8 -19
- package/dist/reaction-runtime-api.js +1 -1
- package/dist/runtime-api.js +7 -7
- package/dist/{send-B_Ks4MZr.js → send-BvGgByMd.js} +12 -3
- package/dist/{send.runtime-CbuXycZT.js → send.runtime-CtTBBrjL.js} +1 -1
- package/dist/{transport-detection-Da06-LOL.js → transport-detection-BItHawMq.js} +50 -145
- package/dist/{transport-detection.runtime-D_190UUL.js → transport-detection.runtime-DoiwPcrG.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
|
@@ -2,25 +2,24 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
|
2
2
|
import { i as resolveSignalAccount, o as resolveSignalReplyToMode } from "./accounts-DrStJjiK.js";
|
|
3
3
|
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 } from "./identity-BQ4OzXXk.js";
|
|
4
4
|
import { t as getOptionalSignalRuntime } from "./runtime-JPrGlV7h.js";
|
|
5
|
-
import { i as materializeSignalPresentationFallback, n as registerSignalReplyContext, o as resolveSignalReactionLevel, s as formatSignalMediaText, u as isSignalNativeApprovalHandlerConfigured } from "./transport-detection-
|
|
6
|
-
import { n as signalRpcRequest, r as streamSignalEvents, t as signalCheck } from "./client-adapter-
|
|
7
|
-
import { n as sendReactionSignal } from "./reaction-runtime-api-
|
|
8
|
-
import { a as maybeResolveSignalApprovalReaction, l as resolveSignalApprovalConversationKey, s as registerSignalApprovalReactionTargetForDeliveredPayload, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-
|
|
9
|
-
import { r as registerSignalQuestionReactionTargetForDeliveredPayload, t as maybeResolveSignalQuestionReaction } from "./question-reactions-
|
|
10
|
-
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-
|
|
5
|
+
import { i as materializeSignalPresentationFallback, n as registerSignalReplyContext, o as resolveSignalReactionLevel, s as formatSignalMediaText, u as isSignalNativeApprovalHandlerConfigured } from "./transport-detection-BItHawMq.js";
|
|
6
|
+
import { n as signalRpcRequest, r as streamSignalEvents, t as signalCheck } from "./client-adapter-D9SNPaNx.js";
|
|
7
|
+
import { n as sendReactionSignal } from "./reaction-runtime-api-Cf6QHcE5.js";
|
|
8
|
+
import { a as maybeResolveSignalApprovalReaction, l as resolveSignalApprovalConversationKey, s as registerSignalApprovalReactionTargetForDeliveredPayload, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-BulCzhdB.js";
|
|
9
|
+
import { r as registerSignalQuestionReactionTargetForDeliveredPayload, t as maybeResolveSignalQuestionReaction } from "./question-reactions-ByjH5qST.js";
|
|
10
|
+
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-BvGgByMd.js";
|
|
11
11
|
import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
12
12
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
13
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 { normalizeNullableString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
15
|
+
import { asPositiveSafeInteger, isRecord, 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, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
19
|
-
import nodePath from "node:path";
|
|
18
|
+
import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, logInboundDrop, matchesMentionPatterns, readAgentRunTerminalOutcome, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toHistoryMediaEntries, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
20
19
|
import { collectErrorGraphCandidates, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
21
20
|
import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
|
|
22
|
-
import { isRecord as isRecord$1 } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
23
21
|
import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
22
|
+
import path from "node:path";
|
|
24
23
|
import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
|
|
25
24
|
import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
26
25
|
import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
@@ -45,6 +44,7 @@ import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-ru
|
|
|
45
44
|
import { listChatCommands, maybeResolveTextAlias, normalizeCommandBody } from "openclaw/plugin-sdk/command-auth-native";
|
|
46
45
|
import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
|
|
47
46
|
import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
|
|
47
|
+
import { channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
|
|
48
48
|
//#region extensions/signal/src/daemon.ts
|
|
49
49
|
const SIGNAL_DAEMON_STOP_KILL_TIMEOUT_MS = 1500;
|
|
50
50
|
function formatSignalDaemonExit(exit) {
|
|
@@ -72,7 +72,7 @@ function bindSignalCliOutput(params) {
|
|
|
72
72
|
function resolveSignalCliConfigPath(raw) {
|
|
73
73
|
const value = raw.trim();
|
|
74
74
|
if (value === "~") return os.homedir();
|
|
75
|
-
if (value.startsWith("~/") || value.startsWith("~\\")) return
|
|
75
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) return path.join(os.homedir(), value.slice(2));
|
|
76
76
|
return value;
|
|
77
77
|
}
|
|
78
78
|
function buildDaemonArgs(opts) {
|
|
@@ -180,6 +180,37 @@ function spawnSignalDaemon(opts) {
|
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
//#endregion
|
|
183
|
+
//#region extensions/signal/src/daemon-lifecycle.ts
|
|
184
|
+
function createSignalDaemonLifecycle(params) {
|
|
185
|
+
let daemonHandle = null;
|
|
186
|
+
let daemonStopRequested = false;
|
|
187
|
+
let daemonStopPromise;
|
|
188
|
+
let daemonExitError;
|
|
189
|
+
const daemonAbortController = new AbortController();
|
|
190
|
+
const abortSignal = params.abortSignal ? AbortSignal.any([params.abortSignal, daemonAbortController.signal]) : daemonAbortController.signal;
|
|
191
|
+
const stop = () => {
|
|
192
|
+
if (daemonStopPromise) return daemonStopPromise;
|
|
193
|
+
daemonStopRequested = true;
|
|
194
|
+
if (!daemonAbortController.signal.aborted) daemonAbortController.abort(params.abortSignal?.reason ?? /* @__PURE__ */ new Error("Signal monitor stopped"));
|
|
195
|
+
daemonStopPromise = daemonHandle?.stop() ?? Promise.resolve();
|
|
196
|
+
return daemonStopPromise;
|
|
197
|
+
};
|
|
198
|
+
const attach = (handle) => {
|
|
199
|
+
daemonHandle = handle;
|
|
200
|
+
handle.exited.then((exit) => {
|
|
201
|
+
if (daemonStopRequested || params.abortSignal?.aborted) return;
|
|
202
|
+
daemonExitError = new Error(formatSignalDaemonExit(exit));
|
|
203
|
+
if (!daemonAbortController.signal.aborted) daemonAbortController.abort(daemonExitError);
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
return {
|
|
207
|
+
attach,
|
|
208
|
+
stop,
|
|
209
|
+
getExitError: () => daemonExitError,
|
|
210
|
+
abortSignal
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
//#endregion
|
|
183
214
|
//#region extensions/signal/src/monitor/access-policy.ts
|
|
184
215
|
const SIGNAL_UUID_KIND = "plugin:signal-uuid";
|
|
185
216
|
const SIGNAL_GROUP_KIND = "plugin:signal-group";
|
|
@@ -274,6 +305,7 @@ async function resolveSignalAccessState(params) {
|
|
|
274
305
|
kind: isGroup ? "group" : "direct",
|
|
275
306
|
id: isGroup ? params.groupId ?? "unknown" : params.sender.raw
|
|
276
307
|
},
|
|
308
|
+
contextBinding: params.contextBinding,
|
|
277
309
|
...isGroup ? { event: { mayPair: false } } : {},
|
|
278
310
|
dmPolicy: params.dmPolicy,
|
|
279
311
|
groupPolicy: params.groupPolicy,
|
|
@@ -606,7 +638,7 @@ function createSignalEventHandler(deps) {
|
|
|
606
638
|
});
|
|
607
639
|
const replyThreading = resolveBatchedReplyThreadingPolicy(replyToMode, entry.isBatched === true);
|
|
608
640
|
const media = await toInboundMediaFactsWithMetadata(entry.media);
|
|
609
|
-
const ctxPayload = buildChannelInboundEventContext({
|
|
641
|
+
const ctxPayload = (deps.channelRuntime?.inbound.buildContext ?? buildChannelInboundEventContext)({
|
|
610
642
|
channel: "signal",
|
|
611
643
|
supplemental: { quote: entry.replyToBody ? {
|
|
612
644
|
body: entry.replyToBody,
|
|
@@ -650,6 +682,7 @@ function createSignalEventHandler(deps) {
|
|
|
650
682
|
} } : {},
|
|
651
683
|
commands: { authorized: entry.commandAuthorized }
|
|
652
684
|
},
|
|
685
|
+
channelIngress: entry.channelIngress,
|
|
653
686
|
media,
|
|
654
687
|
extra: {
|
|
655
688
|
GroupSubject: entry.isGroup ? entry.groupName ?? void 0 : void 0,
|
|
@@ -838,13 +871,16 @@ function createSignalEventHandler(deps) {
|
|
|
838
871
|
onToolStart: async (payload) => {
|
|
839
872
|
const toolName = payload.name?.trim();
|
|
840
873
|
if (toolName) await statusReactionController.setTool(toolName);
|
|
874
|
+
return false;
|
|
841
875
|
},
|
|
842
876
|
onCompactionStart: async () => {
|
|
843
877
|
await statusReactionController.setCompacting();
|
|
878
|
+
return false;
|
|
844
879
|
},
|
|
845
880
|
onCompactionEnd: async () => {
|
|
846
881
|
statusReactionController.cancelPending();
|
|
847
882
|
await statusReactionController.setThinking();
|
|
883
|
+
return false;
|
|
848
884
|
}
|
|
849
885
|
} : {},
|
|
850
886
|
onModelSelected
|
|
@@ -854,9 +890,10 @@ function createSignalEventHandler(deps) {
|
|
|
854
890
|
if (!statusReactionController) return;
|
|
855
891
|
const hasFinalResponse = result.dispatched && hasVisibleInboundReplyDispatch(result.dispatchResult);
|
|
856
892
|
const hasDeliveryFailure = result.dispatched && hasSignalStatusReplyDeliveryFailure(result.dispatchResult);
|
|
893
|
+
const hasAgentRunFailure = result.dispatched && readAgentRunTerminalOutcome(result.dispatchResult) === "failed";
|
|
857
894
|
finalizeSignalStatusReaction({
|
|
858
895
|
controller: statusReactionController,
|
|
859
|
-
outcome: hasFinalResponse && !hasDeliveryFailure ? "done" : "error"
|
|
896
|
+
outcome: hasFinalResponse && !hasDeliveryFailure && !hasAgentRunFailure ? "done" : "error"
|
|
860
897
|
}).catch((err) => {
|
|
861
898
|
logVerbose(`signal: status reaction finalize failed: ${String(err)}`);
|
|
862
899
|
});
|
|
@@ -867,9 +904,16 @@ function createSignalEventHandler(deps) {
|
|
|
867
904
|
async function flushSignalInboundEntries(entries, lifecycle, settle) {
|
|
868
905
|
const last = entries.at(-1);
|
|
869
906
|
if (!last) return;
|
|
907
|
+
const channelIngress = await resolveSignalBatchChannelIngress(entries, last);
|
|
908
|
+
if (channelIngress.some((entry) => !entry.senderAccess.allowed)) {
|
|
909
|
+
logVerbose("signal: authorization changed before dispatch");
|
|
910
|
+
await settle();
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
870
913
|
if (entries.length === 1) {
|
|
871
914
|
await handleSignalInboundMessage({
|
|
872
915
|
...last,
|
|
916
|
+
channelIngress,
|
|
873
917
|
turnAdoptionLifecycle: lifecycle
|
|
874
918
|
});
|
|
875
919
|
await settle();
|
|
@@ -888,10 +932,30 @@ function createSignalEventHandler(deps) {
|
|
|
888
932
|
turnAdoptionLifecycle: lifecycle,
|
|
889
933
|
isBatched: true,
|
|
890
934
|
nativeReplyBody: last.nativeReplyBody ?? last.bodyText,
|
|
891
|
-
media: entries.flatMap((entry) => entry.media ?? [])
|
|
935
|
+
media: entries.flatMap((entry) => entry.media ?? []),
|
|
936
|
+
channelIngress
|
|
892
937
|
});
|
|
893
938
|
await settle();
|
|
894
939
|
}
|
|
940
|
+
async function resolveSignalBatchChannelIngress(entries, last) {
|
|
941
|
+
if (last.boundChannelIngress) return last.boundChannelIngress;
|
|
942
|
+
const route = resolveSignalInboundRoute({
|
|
943
|
+
cfg: deps.cfg,
|
|
944
|
+
accountId: deps.accountId,
|
|
945
|
+
isGroup: last.isGroup,
|
|
946
|
+
groupId: last.groupId,
|
|
947
|
+
senderPeerId: last.senderPeerId
|
|
948
|
+
});
|
|
949
|
+
const contextBinding = {
|
|
950
|
+
agentId: route.agentId,
|
|
951
|
+
sessionKey: route.sessionKey,
|
|
952
|
+
...last.messageId ? { messageId: last.messageId } : {},
|
|
953
|
+
inboundEventKind: "user_request"
|
|
954
|
+
};
|
|
955
|
+
const resolved = await Promise.all(entries.flatMap((entry) => entry.resolveChannelIngress ? [entry.resolveChannelIngress(contextBinding)] : (entry.channelIngress ?? []).map(async (ingress) => ingress)));
|
|
956
|
+
last.boundChannelIngress = resolved;
|
|
957
|
+
return resolved;
|
|
958
|
+
}
|
|
895
959
|
async function retrySignalInboundFlush(entries, lifecycle, settle, initialError) {
|
|
896
960
|
let lastError = initialError;
|
|
897
961
|
for (const [attemptIndex, delayMs] of RETRYABLE_FLUSH_RETRY_DELAYS_MS.entries()) {
|
|
@@ -1017,6 +1081,7 @@ function createSignalEventHandler(deps) {
|
|
|
1017
1081
|
if (!deps.shouldEmitSignalReactionNotification({
|
|
1018
1082
|
mode: deps.reactionMode,
|
|
1019
1083
|
account: deps.account,
|
|
1084
|
+
accountUuid: deps.accountUuid,
|
|
1020
1085
|
targets,
|
|
1021
1086
|
sender: params.sender,
|
|
1022
1087
|
allowlist: deps.reactionAllowlist
|
|
@@ -1077,7 +1142,7 @@ function createSignalEventHandler(deps) {
|
|
|
1077
1142
|
const isGroup = Boolean(groupId);
|
|
1078
1143
|
const hasControlCommandInMessage = isControlCommandMessage(messageText, deps.cfg);
|
|
1079
1144
|
const senderDisplay = formatSignalSenderDisplay(sender);
|
|
1080
|
-
const
|
|
1145
|
+
const resolveChannelIngress = async (contextBinding) => await resolveSignalAccessState({
|
|
1081
1146
|
accountId: deps.accountId,
|
|
1082
1147
|
dmPolicy: deps.dmPolicy,
|
|
1083
1148
|
groupPolicy: deps.groupPolicy,
|
|
@@ -1087,8 +1152,10 @@ function createSignalEventHandler(deps) {
|
|
|
1087
1152
|
groupId,
|
|
1088
1153
|
isGroup,
|
|
1089
1154
|
cfg: deps.cfg,
|
|
1090
|
-
hasControlCommand: hasControlCommandInMessage
|
|
1155
|
+
hasControlCommand: hasControlCommandInMessage,
|
|
1156
|
+
contextBinding
|
|
1091
1157
|
});
|
|
1158
|
+
const { senderAccess, commandAccess } = await resolveChannelIngress();
|
|
1092
1159
|
const quoteText = normalizeOptionalString(dataMessage?.quote?.text) ?? "";
|
|
1093
1160
|
const { contextVisibilityMode, quoteSenderAllowed, visibleQuoteText, visibleQuoteSender } = resolveSignalQuoteContext({
|
|
1094
1161
|
cfg: deps.cfg,
|
|
@@ -1218,8 +1285,8 @@ function createSignalEventHandler(deps) {
|
|
|
1218
1285
|
sender: envelope.sourceName ?? senderDisplay,
|
|
1219
1286
|
body: messageText || visibleQuoteText,
|
|
1220
1287
|
media: toHistoryMediaEntries(pendingMedia),
|
|
1221
|
-
timestamp:
|
|
1222
|
-
messageId
|
|
1288
|
+
timestamp: inboundTimestamp,
|
|
1289
|
+
messageId
|
|
1223
1290
|
}
|
|
1224
1291
|
});
|
|
1225
1292
|
await registerSignalReplyContext({
|
|
@@ -1349,7 +1416,8 @@ function createSignalEventHandler(deps) {
|
|
|
1349
1416
|
replyToBody: visibleQuoteText || void 0,
|
|
1350
1417
|
replyToSender: visibleQuoteSender,
|
|
1351
1418
|
replyToIsQuote: visibleQuoteText ? true : void 0,
|
|
1352
|
-
turnAdoptionLifecycle
|
|
1419
|
+
turnAdoptionLifecycle,
|
|
1420
|
+
resolveChannelIngress
|
|
1353
1421
|
};
|
|
1354
1422
|
pendingInboundRegistry.cancelPendingOnAbort(entry, debouncer.cancelKey);
|
|
1355
1423
|
const inboundLane = resolveSignalControlLaneKey(deps.accountId, entry) ? controlDebouncer : debouncer;
|
|
@@ -1374,7 +1442,7 @@ function registerSignalReactionTargetsForDeliveredPayload(params) {
|
|
|
1374
1442
|
const SIGNAL_INGRESS_DRAIN_INTERVAL_MS = 1e3;
|
|
1375
1443
|
const SignalIngressPermanentError = createChannelIngressError("SignalIngressPermanentError", { withReason: true });
|
|
1376
1444
|
function normalizeTimestamp(value) {
|
|
1377
|
-
return
|
|
1445
|
+
return asPositiveSafeInteger(value) ?? null;
|
|
1378
1446
|
}
|
|
1379
1447
|
function parseReceiveEnvelope(event) {
|
|
1380
1448
|
if (event.event !== "receive" || !event.data) return null;
|
|
@@ -1384,18 +1452,18 @@ function parseReceiveEnvelope(event) {
|
|
|
1384
1452
|
} catch (error) {
|
|
1385
1453
|
throw new SignalIngressPermanentError("parse-error", "Signal receive event contains invalid JSON", { cause: error });
|
|
1386
1454
|
}
|
|
1387
|
-
if (!isRecord
|
|
1388
|
-
return isRecord
|
|
1455
|
+
if (!isRecord(parsed)) throw new SignalIngressPermanentError("parse-error", "Signal receive event must contain a JSON object");
|
|
1456
|
+
return isRecord(parsed.envelope) ? parsed.envelope : null;
|
|
1389
1457
|
}
|
|
1390
1458
|
function resolveDataMessage(envelope) {
|
|
1391
|
-
if (isRecord
|
|
1392
|
-
return isRecord
|
|
1459
|
+
if (isRecord(envelope.dataMessage)) return envelope.dataMessage;
|
|
1460
|
+
return isRecord(envelope.editMessage?.dataMessage) ? envelope.editMessage.dataMessage : null;
|
|
1393
1461
|
}
|
|
1394
1462
|
function inspectSignalIngressEvent(event) {
|
|
1395
1463
|
const envelope = parseReceiveEnvelope(event);
|
|
1396
1464
|
if (!envelope || "syncMessage" in envelope) return null;
|
|
1397
1465
|
const dataMessage = resolveDataMessage(envelope);
|
|
1398
|
-
const reactionMessage = isRecord
|
|
1466
|
+
const reactionMessage = isRecord(envelope.reactionMessage) ? envelope.reactionMessage : null;
|
|
1399
1467
|
if (!dataMessage && !reactionMessage) return null;
|
|
1400
1468
|
const senderUuid = normalizeNullableString(envelope.sourceUuid);
|
|
1401
1469
|
const senderNumber = normalizeNullableString(envelope.sourceNumber);
|
|
@@ -1403,12 +1471,13 @@ function inspectSignalIngressEvent(event) {
|
|
|
1403
1471
|
if (!senderKey) throw new SignalIngressPermanentError("missing-sender", "Signal dispatchable envelope is missing sourceUuid/sourceNumber");
|
|
1404
1472
|
const timestamp = normalizeTimestamp(envelope.timestamp) ?? normalizeTimestamp(dataMessage?.timestamp);
|
|
1405
1473
|
if (timestamp === null) throw new SignalIngressPermanentError("missing-timestamp", "Signal dispatchable envelope is missing a stable timestamp");
|
|
1406
|
-
const dataGroup = isRecord
|
|
1407
|
-
const reactionGroup = isRecord
|
|
1474
|
+
const dataGroup = isRecord(dataMessage?.groupInfo) ? dataMessage.groupInfo : null;
|
|
1475
|
+
const reactionGroup = isRecord(reactionMessage?.groupInfo) ? reactionMessage.groupInfo : null;
|
|
1408
1476
|
const groupId = normalizeNullableString(dataGroup?.groupId) ?? normalizeNullableString(reactionGroup?.groupId);
|
|
1409
1477
|
return {
|
|
1410
1478
|
eventId: JSON.stringify([senderKey, timestamp]),
|
|
1411
|
-
laneKey: groupId ? `group:${groupId}` : `direct:${senderKey}
|
|
1479
|
+
laneKey: groupId ? `group:${groupId}` : `direct:${senderKey}`,
|
|
1480
|
+
...senderUuid && senderNumber ? { numberAliasEventId: JSON.stringify([`number:${senderNumber}`, timestamp]) } : {}
|
|
1412
1481
|
};
|
|
1413
1482
|
}
|
|
1414
1483
|
function resolveSignalIngressNonRetryableFailure(error) {
|
|
@@ -1425,8 +1494,9 @@ async function startSignalIngressMonitor(params) {
|
|
|
1425
1494
|
if (!pluginRuntime) throw new Error("Signal runtime not initialized for durable ingress");
|
|
1426
1495
|
queue = pluginRuntime.state.openChannelIngressQueue({ accountId: params.accountId });
|
|
1427
1496
|
}
|
|
1497
|
+
const ingressQueue = queue;
|
|
1428
1498
|
const monitor = createChannelIngressMonitor({
|
|
1429
|
-
queue,
|
|
1499
|
+
queue: ingressQueue,
|
|
1430
1500
|
inspect: (event) => inspectSignalIngressEvent(event),
|
|
1431
1501
|
payload: {
|
|
1432
1502
|
version: 1,
|
|
@@ -1446,10 +1516,15 @@ async function startSignalIngressMonitor(params) {
|
|
|
1446
1516
|
createClaimError: (_kind, claim) => new SignalIngressPermanentError("unsupported-event", `Signal ingress row ${claim.id} has an invalid payload`)
|
|
1447
1517
|
},
|
|
1448
1518
|
deliver: (event, lifecycle) => params.dispatch(event, lifecycle),
|
|
1519
|
+
onDurableAdmission: async (_event, { facts }) => {
|
|
1520
|
+
const { numberAliasEventId } = facts;
|
|
1521
|
+
if (!numberAliasEventId) return;
|
|
1522
|
+
if (!await ingressQueue.complete(numberAliasEventId)) await ingressQueue.complete(facts.eventId);
|
|
1523
|
+
},
|
|
1449
1524
|
pollIntervalMs: SIGNAL_INGRESS_DRAIN_INTERVAL_MS,
|
|
1450
1525
|
retention: {
|
|
1451
1526
|
pruneIntervalMs: 0,
|
|
1452
|
-
completedMaxEntries:
|
|
1527
|
+
completedMaxEntries: 2e3,
|
|
1453
1528
|
failedMaxEntries: 1e3
|
|
1454
1529
|
},
|
|
1455
1530
|
appendRetryDelaysMs: [0],
|
|
@@ -1477,7 +1552,14 @@ const DEFAULT_RECONNECT_POLICY = {
|
|
|
1477
1552
|
factor: 2,
|
|
1478
1553
|
jitter: .2
|
|
1479
1554
|
};
|
|
1480
|
-
|
|
1555
|
+
function publishSignalRecovering(statusSink, lastError) {
|
|
1556
|
+
statusSink?.({
|
|
1557
|
+
connected: false,
|
|
1558
|
+
lifecycle: "recovering",
|
|
1559
|
+
...lastError ? { lastError } : {}
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEvent, timeoutMs, transportKind, policy, statusSink }) {
|
|
1481
1563
|
const reconnectPolicy = {
|
|
1482
1564
|
...DEFAULT_RECONNECT_POLICY,
|
|
1483
1565
|
...policy
|
|
@@ -1496,6 +1578,9 @@ async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEven
|
|
|
1496
1578
|
abortSignal,
|
|
1497
1579
|
timeoutMs,
|
|
1498
1580
|
transportKind,
|
|
1581
|
+
onStreamOpen: () => {
|
|
1582
|
+
statusSink?.(channelReadyPatch());
|
|
1583
|
+
},
|
|
1499
1584
|
onEvent: async (event) => {
|
|
1500
1585
|
reconnectAttempts = 0;
|
|
1501
1586
|
await onEvent(event);
|
|
@@ -1506,6 +1591,7 @@ async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEven
|
|
|
1506
1591
|
}
|
|
1507
1592
|
});
|
|
1508
1593
|
if (abortSignal?.aborted) return;
|
|
1594
|
+
publishSignalRecovering(statusSink);
|
|
1509
1595
|
reconnectAttempts += 1;
|
|
1510
1596
|
const delayMs = computeBackoff(reconnectPolicy, reconnectAttempts);
|
|
1511
1597
|
logReconnectVerbose(`Signal stream ended, reconnecting in ${delayMs / 1e3}s...`);
|
|
@@ -1513,6 +1599,7 @@ async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEven
|
|
|
1513
1599
|
} catch (err) {
|
|
1514
1600
|
if (abortSignal?.aborted) return;
|
|
1515
1601
|
runtime.error?.(`Signal stream error: ${String(err)}`);
|
|
1602
|
+
publishSignalRecovering(statusSink, String(err));
|
|
1516
1603
|
reconnectAttempts += 1;
|
|
1517
1604
|
const delayMs = computeBackoff(reconnectPolicy, reconnectAttempts);
|
|
1518
1605
|
runtime.log?.(`Signal connection lost, reconnecting in ${delayMs / 1e3}s...`);
|
|
@@ -1546,36 +1633,6 @@ function createSignalMonitorTaskRunner(runtime) {
|
|
|
1546
1633
|
}
|
|
1547
1634
|
};
|
|
1548
1635
|
}
|
|
1549
|
-
function createSignalDaemonLifecycle(params) {
|
|
1550
|
-
let daemonHandle = null;
|
|
1551
|
-
let daemonStopRequested = false;
|
|
1552
|
-
let daemonStopPromise;
|
|
1553
|
-
let daemonExitError;
|
|
1554
|
-
const daemonAbortController = new AbortController();
|
|
1555
|
-
const abortSignal = params.abortSignal ? AbortSignal.any([params.abortSignal, daemonAbortController.signal]) : daemonAbortController.signal;
|
|
1556
|
-
const stop = () => {
|
|
1557
|
-
if (daemonStopPromise) return daemonStopPromise;
|
|
1558
|
-
daemonStopRequested = true;
|
|
1559
|
-
if (!daemonAbortController.signal.aborted) daemonAbortController.abort(params.abortSignal?.reason ?? /* @__PURE__ */ new Error("Signal monitor stopped"));
|
|
1560
|
-
daemonStopPromise = daemonHandle?.stop() ?? Promise.resolve();
|
|
1561
|
-
return daemonStopPromise;
|
|
1562
|
-
};
|
|
1563
|
-
const attach = (handle) => {
|
|
1564
|
-
daemonHandle = handle;
|
|
1565
|
-
handle.exited.then((exit) => {
|
|
1566
|
-
if (daemonStopRequested || params.abortSignal?.aborted) return;
|
|
1567
|
-
daemonExitError = new Error(formatSignalDaemonExit(exit));
|
|
1568
|
-
if (!daemonAbortController.signal.aborted) daemonAbortController.abort(daemonExitError);
|
|
1569
|
-
});
|
|
1570
|
-
};
|
|
1571
|
-
const getExitError = () => daemonExitError;
|
|
1572
|
-
return {
|
|
1573
|
-
attach,
|
|
1574
|
-
stop,
|
|
1575
|
-
getExitError,
|
|
1576
|
-
abortSignal
|
|
1577
|
-
};
|
|
1578
|
-
}
|
|
1579
1636
|
function resolveSignalReactionTargets(reaction) {
|
|
1580
1637
|
const targets = [];
|
|
1581
1638
|
const uuid = reaction.targetAuthorUuid?.trim();
|
|
@@ -1603,16 +1660,17 @@ function isSignalReactionMessage(reaction) {
|
|
|
1603
1660
|
return Boolean(emoji && typeof timestamp === "number" && timestamp > 0 && hasTarget);
|
|
1604
1661
|
}
|
|
1605
1662
|
function shouldEmitSignalReactionNotification(params) {
|
|
1606
|
-
const { mode, account, targets, sender, allowlist } = params;
|
|
1663
|
+
const { mode, account, accountUuid, targets, sender, allowlist } = params;
|
|
1607
1664
|
const effectiveMode = mode ?? "own";
|
|
1608
1665
|
if (effectiveMode === "off") return false;
|
|
1609
1666
|
if (effectiveMode === "own") {
|
|
1610
|
-
const accountId = account
|
|
1611
|
-
|
|
1612
|
-
|
|
1667
|
+
const accountId = normalizeOptionalString(account);
|
|
1668
|
+
const normalizedAccountUuid = normalizeOptionalString(accountUuid);
|
|
1669
|
+
if (!accountId && !normalizedAccountUuid || !targets || targets.length === 0) return false;
|
|
1670
|
+
const normalizedAccount = accountId ? normalizeE164(accountId) : void 0;
|
|
1613
1671
|
return targets.some((target) => {
|
|
1614
|
-
if (target.kind === "uuid") return accountId === target.id ||
|
|
1615
|
-
return normalizedAccount === target.id;
|
|
1672
|
+
if (target.kind === "uuid") return [accountId, normalizedAccountUuid].some((candidate) => candidate === target.id || candidate === `uuid:${target.id}`);
|
|
1673
|
+
return Boolean(normalizedAccount) && normalizedAccount === target.id;
|
|
1616
1674
|
});
|
|
1617
1675
|
}
|
|
1618
1676
|
if (effectiveMode === "allowlist") {
|
|
@@ -1893,6 +1951,7 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1893
1951
|
});
|
|
1894
1952
|
const handleEvent = createSignalEventHandler({
|
|
1895
1953
|
runtime,
|
|
1954
|
+
channelRuntime: opts.channelRuntime,
|
|
1896
1955
|
abortSignal: daemonLifecycle.abortSignal,
|
|
1897
1956
|
runTrackedTask: (task) => {
|
|
1898
1957
|
monitorTaskRunner.runTask(task);
|
|
@@ -1943,6 +2002,7 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1943
2002
|
timeoutMs: 0,
|
|
1944
2003
|
transportKind,
|
|
1945
2004
|
policy: opts.reconnectPolicy,
|
|
2005
|
+
statusSink: opts.statusSink,
|
|
1946
2006
|
onEvent: (event) => monitorTaskRunner.runTask(async () => await ingressMonitor?.receive(event))
|
|
1947
2007
|
});
|
|
1948
2008
|
const daemonExitError = daemonLifecycle.getExitError();
|
|
@@ -1950,6 +2010,7 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1950
2010
|
} catch (err) {
|
|
1951
2011
|
const daemonExitError = daemonLifecycle.getExitError();
|
|
1952
2012
|
if (opts.abortSignal?.aborted && !daemonExitError) return;
|
|
2013
|
+
if (daemonExitError) publishSignalRecovering(opts.statusSink, daemonExitError.message);
|
|
1953
2014
|
throw err;
|
|
1954
2015
|
} finally {
|
|
1955
2016
|
await ingressMonitor?.stop();
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { t as detectSignalTransport } from "./transport-detection-
|
|
3
|
-
import { n as signalRpcRequest, t as signalCheck } from "./client-adapter-
|
|
2
|
+
import { t as detectSignalTransport } from "./transport-detection-BItHawMq.js";
|
|
3
|
+
import { n as signalRpcRequest, t as signalCheck } from "./client-adapter-D9SNPaNx.js";
|
|
4
4
|
import { runChannelProbe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
5
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
6
|
//#region extensions/signal/src/probe.ts
|
|
7
|
-
var probe_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
var probe_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
probeSignal: () => probeSignal,
|
|
9
|
+
probeSignalAccount: () => probeSignalAccount
|
|
10
|
+
});
|
|
8
11
|
function parseSignalVersion(value) {
|
|
9
12
|
if (typeof value === "string" && value.trim()) return value.trim();
|
|
10
13
|
if (typeof value === "object" && value !== null) {
|
|
11
|
-
const version = value
|
|
14
|
+
const { version, versions } = value;
|
|
12
15
|
if (typeof version === "string" && version.trim()) return version.trim();
|
|
16
|
+
if (Array.isArray(versions)) {
|
|
17
|
+
const normalizedVersions = versions.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean);
|
|
18
|
+
if (normalizedVersions.length > 0) return normalizedVersions.join(", ");
|
|
19
|
+
}
|
|
13
20
|
}
|
|
14
21
|
return null;
|
|
15
22
|
}
|
|
16
|
-
async function
|
|
23
|
+
async function probeSignalTransport(baseUrl, timeoutMs, options, account) {
|
|
17
24
|
return await runChannelProbe(void 0, async () => {
|
|
18
25
|
const result = {
|
|
19
26
|
ok: false,
|
|
@@ -30,7 +37,10 @@ async function probeSignal(baseUrl, timeoutMs, options = {}) {
|
|
|
30
37
|
error: formatErrorMessage(error)
|
|
31
38
|
};
|
|
32
39
|
}
|
|
33
|
-
const check = await signalCheck(baseUrl, timeoutMs, {
|
|
40
|
+
const check = await signalCheck(baseUrl, timeoutMs, {
|
|
41
|
+
transportKind,
|
|
42
|
+
...account && transportKind === "container" ? { account } : {}
|
|
43
|
+
});
|
|
34
44
|
if (!check.ok) return {
|
|
35
45
|
...result,
|
|
36
46
|
status: check.status ?? null,
|
|
@@ -47,11 +57,17 @@ async function probeSignal(baseUrl, timeoutMs, options = {}) {
|
|
|
47
57
|
}
|
|
48
58
|
return {
|
|
49
59
|
...result,
|
|
50
|
-
ok:
|
|
60
|
+
ok: result.error === null,
|
|
51
61
|
status: check.status ?? null
|
|
52
62
|
};
|
|
53
63
|
});
|
|
54
64
|
}
|
|
65
|
+
async function probeSignal(baseUrl, timeoutMs, options = {}) {
|
|
66
|
+
return await probeSignalTransport(baseUrl, timeoutMs, options);
|
|
67
|
+
}
|
|
68
|
+
async function probeSignalAccount(params) {
|
|
69
|
+
return await probeSignalTransport(params.baseUrl, params.timeoutMs, { transportKind: params.transportKind }, params.account);
|
|
70
|
+
}
|
|
55
71
|
async function resolveProbeTransportKind(baseUrl, timeoutMs, options) {
|
|
56
72
|
if (options.transportKind) return options.transportKind;
|
|
57
73
|
if (options.apiMode === "container") return "container";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
+
import { o as resolveSignalTarget } from "./runtime-JPrGlV7h.js";
|
|
3
|
+
import { l as resolveSignalApprovalConversationKey, u as resolveSignalApprovalTargetAuthorKeys } from "./approval-reactions-BulCzhdB.js";
|
|
4
|
+
import { createQuestionReactionTargetStore, questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
|
|
5
|
+
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
|
6
|
+
//#region extensions/signal/src/question-reactions.ts
|
|
7
|
+
var question_reactions_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
maybeResolveSignalQuestionReaction: () => maybeResolveSignalQuestionReaction,
|
|
9
|
+
registerSignalQuestionReactionTargetForDeliveredPayload: () => registerSignalQuestionReactionTargetForDeliveredPayload
|
|
10
|
+
});
|
|
11
|
+
function buildKey(identity) {
|
|
12
|
+
const values = [
|
|
13
|
+
identity.accountId,
|
|
14
|
+
identity.conversationKey,
|
|
15
|
+
identity.messageId
|
|
16
|
+
].map((value) => value.trim());
|
|
17
|
+
return values.every(Boolean) ? values.join(":") : null;
|
|
18
|
+
}
|
|
19
|
+
const questionReactionTargets = createQuestionReactionTargetStore({
|
|
20
|
+
channel: "signal",
|
|
21
|
+
channelDisplayName: "Signal",
|
|
22
|
+
buildKey,
|
|
23
|
+
identityMatches: (stored, incoming) => Boolean(stored && incoming?.some((authorKey) => stored.includes(authorKey))),
|
|
24
|
+
registerChannelDelivery: questionGatewayRuntime.registerChannelDelivery,
|
|
25
|
+
resolveReaction: questionGatewayRuntime.resolveReaction
|
|
26
|
+
});
|
|
27
|
+
function resolveConversationKey(params) {
|
|
28
|
+
try {
|
|
29
|
+
return resolveSignalTarget({
|
|
30
|
+
cfg: params.cfg,
|
|
31
|
+
accountId: params.accountId,
|
|
32
|
+
input: params.to
|
|
33
|
+
})?.to ?? resolveSignalApprovalConversationKey(params.to);
|
|
34
|
+
} catch {
|
|
35
|
+
return resolveSignalApprovalConversationKey(params.to);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function registerSignalQuestionReactionTargetForDeliveredPayload(params) {
|
|
39
|
+
const binding = questionGatewayRuntime.readReactionBinding(params.payload);
|
|
40
|
+
if (params.target.channel !== "signal" || !binding) return false;
|
|
41
|
+
const conversationKey = resolveConversationKey({
|
|
42
|
+
cfg: params.cfg,
|
|
43
|
+
...params.target
|
|
44
|
+
});
|
|
45
|
+
const targetAuthorKeys = resolveSignalApprovalTargetAuthorKeys(params);
|
|
46
|
+
if (!conversationKey || targetAuthorKeys.length === 0) return false;
|
|
47
|
+
const accountId = normalizeAccountId(params.target.accountId ?? void 0);
|
|
48
|
+
let registered = false;
|
|
49
|
+
for (const result of params.results) {
|
|
50
|
+
const messageId = result.channel === "signal" ? result.messageId.trim() : "";
|
|
51
|
+
if (!messageId || messageId === "unknown") continue;
|
|
52
|
+
registered = questionReactionTargets.register(binding, {
|
|
53
|
+
accountId,
|
|
54
|
+
conversationKey,
|
|
55
|
+
messageId
|
|
56
|
+
}, targetAuthorKeys) || registered;
|
|
57
|
+
}
|
|
58
|
+
return registered;
|
|
59
|
+
}
|
|
60
|
+
async function maybeResolveSignalQuestionReaction(params) {
|
|
61
|
+
if (params.isRemove) return false;
|
|
62
|
+
const optionIndex = questionGatewayRuntime.resolveReactionIndex(params.reactionKey);
|
|
63
|
+
if (optionIndex === void 0) return false;
|
|
64
|
+
const authorKeys = resolveSignalApprovalTargetAuthorKeys(params);
|
|
65
|
+
return await questionReactionTargets.resolve({
|
|
66
|
+
identities: [{
|
|
67
|
+
accountId: params.accountId,
|
|
68
|
+
conversationKey: params.conversationKey,
|
|
69
|
+
messageId: params.messageId
|
|
70
|
+
}],
|
|
71
|
+
optionIndex,
|
|
72
|
+
cfg: params.cfg,
|
|
73
|
+
senderId: params.actorId,
|
|
74
|
+
gatewayUrl: params.gatewayUrl,
|
|
75
|
+
metadata: authorKeys,
|
|
76
|
+
logDebug: params.logDebug
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { question_reactions_exports as n, registerSignalQuestionReactionTargetForDeliveredPayload as r, maybeResolveSignalQuestionReaction as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as resolveSignalAccount } from "./accounts-DrStJjiK.js";
|
|
2
|
-
import { n as signalRpcRequest } from "./client-adapter-
|
|
2
|
+
import { n as signalRpcRequest } from "./client-adapter-D9SNPaNx.js";
|
|
3
3
|
import { t as resolveSignalRpcContext } from "./rpc-context-CZUoE0-A.js";
|
|
4
4
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
5
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
@@ -37,16 +37,17 @@ async function sendReactionSignalCore(params) {
|
|
|
37
37
|
const { baseUrl, account } = resolveSignalRpcContext(params.opts, accountInfo);
|
|
38
38
|
const normalizedRecipient = normalizeSignalUuid(params.recipient);
|
|
39
39
|
const groupId = params.opts.groupId?.trim();
|
|
40
|
-
|
|
41
|
-
if (!
|
|
40
|
+
const operation = `Signal reaction${params.remove ? " removal" : ""}`;
|
|
41
|
+
if (!normalizedRecipient && !groupId) throw new Error(`Recipient or groupId is required for ${operation}`);
|
|
42
|
+
if (!Number.isFinite(params.targetTimestamp) || params.targetTimestamp <= 0) throw new Error(`Valid targetTimestamp is required for ${operation}`);
|
|
42
43
|
const normalizedEmoji = params.emoji?.trim();
|
|
43
|
-
if (!normalizedEmoji) throw new Error(
|
|
44
|
+
if (!normalizedEmoji) throw new Error(`Emoji is required for ${operation}`);
|
|
44
45
|
const targetAuthorParams = resolveTargetAuthorParams({
|
|
45
46
|
targetAuthor: params.opts.targetAuthor,
|
|
46
47
|
targetAuthorUuid: params.opts.targetAuthorUuid,
|
|
47
48
|
fallback: normalizedRecipient
|
|
48
49
|
});
|
|
49
|
-
if (groupId && !targetAuthorParams.targetAuthor) throw new Error(params.
|
|
50
|
+
if (groupId && !targetAuthorParams.targetAuthor) throw new Error(`targetAuthor is required for group reaction${params.remove ? " removal" : "s"}`);
|
|
50
51
|
const requestParams = {
|
|
51
52
|
emoji: normalizedEmoji,
|
|
52
53
|
targetTimestamp: params.targetTimestamp,
|
|
@@ -78,13 +79,7 @@ async function sendReactionSignal(recipient, targetTimestamp, emoji, opts) {
|
|
|
78
79
|
targetTimestamp,
|
|
79
80
|
emoji,
|
|
80
81
|
remove: false,
|
|
81
|
-
opts
|
|
82
|
-
errors: {
|
|
83
|
-
missingRecipient: "Recipient or groupId is required for Signal reaction",
|
|
84
|
-
invalidTargetTimestamp: "Valid targetTimestamp is required for Signal reaction",
|
|
85
|
-
missingEmoji: "Emoji is required for Signal reaction",
|
|
86
|
-
missingTargetAuthor: "targetAuthor is required for group reactions"
|
|
87
|
-
}
|
|
82
|
+
opts
|
|
88
83
|
});
|
|
89
84
|
}
|
|
90
85
|
/**
|
|
@@ -100,13 +95,7 @@ async function removeReactionSignal(recipient, targetTimestamp, emoji, opts) {
|
|
|
100
95
|
targetTimestamp,
|
|
101
96
|
emoji,
|
|
102
97
|
remove: true,
|
|
103
|
-
opts
|
|
104
|
-
errors: {
|
|
105
|
-
missingRecipient: "Recipient or groupId is required for Signal reaction removal",
|
|
106
|
-
invalidTargetTimestamp: "Valid targetTimestamp is required for Signal reaction removal",
|
|
107
|
-
missingEmoji: "Emoji is required for Signal reaction removal",
|
|
108
|
-
missingTargetAuthor: "targetAuthor is required for group reaction removal"
|
|
109
|
-
}
|
|
98
|
+
opts
|
|
110
99
|
});
|
|
111
100
|
}
|
|
112
101
|
//#endregion
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-
|
|
1
|
+
import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-Cf6QHcE5.js";
|
|
2
2
|
export { removeReactionSignal, sendReactionSignal };
|