@openclaw/signal 2026.6.11 → 2026.7.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/{accounts-hOCHbEhX.js → accounts-B7Rz3_xV.js} +2 -1
- package/dist/api.js +8 -8
- package/dist/approval-auth-DPVK9A_l.js +151 -0
- package/dist/{approval-handler.runtime-CeJI1wow.js → approval-handler.runtime-BZLgs7EM.js} +28 -8
- package/dist/{send-CBlFUkY_.js → approval-reactions-5x1kmQEq.js} +137 -277
- package/dist/{channel-LmY2UpOt.js → channel-BfWp-F-r.js} +177 -46
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-B0-YpkC4.js → channel.runtime-Ks7GIWM1.js} +3 -3
- package/dist/{reaction-runtime-api-C_PQ45D9.js → client-adapter-Dm8-wT2n.js} +9 -130
- package/dist/contract-api.js +1 -1
- package/dist/{install-signal-cli-CXgTF3de.js → install-signal-cli-TwhJ0DGy.js} +7 -5
- package/dist/{message-actions-Bue0g2Kc.js → message-actions-Cs9XckSd.js} +7 -30
- package/dist/{monitor-CUhIKHJo.js → monitor-C9SiyrFt.js} +205 -37
- package/dist/{probe-BQ_Izoya.js → probe-BL2BqTbG.js} +1 -1
- package/dist/reaction-runtime-api-BkAxQPGs.js +115 -0
- package/dist/reaction-runtime-api.js +1 -1
- package/dist/rpc-context-DbFMe7am.js +17 -0
- package/dist/runtime-api.js +8 -7
- package/dist/send-CLzc3RUg.js +187 -0
- package/dist/{send.runtime-CfaZd8X4.js → send.runtime-DgijYwpJ.js} +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/openclaw.plugin.json +18 -0
- package/package.json +4 -4
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { i as resolveSignalAccount } from "./accounts-
|
|
2
|
+
import { i as resolveSignalAccount } from "./accounts-B7Rz3_xV.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-B6O4k8xg.js";
|
|
4
|
-
import { a as isSignalNativeApprovalHandlerConfigured } from "./message-actions-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { a as isSignalNativeApprovalHandlerConfigured, n as resolveSignalReactionLevel } from "./message-actions-Cs9XckSd.js";
|
|
5
|
+
import { n as signalRpcRequest, r as streamSignalEvents, t as signalCheck } from "./client-adapter-Dm8-wT2n.js";
|
|
6
|
+
import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-BkAxQPGs.js";
|
|
7
|
+
import { i as maybeResolveSignalApprovalReaction, o as registerSignalApprovalReactionTargetForDeliveredPayload, s as resolveSignalApprovalConversationKey, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-5x1kmQEq.js";
|
|
8
|
+
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-CLzc3RUg.js";
|
|
7
9
|
import { createChannelMessageReplyPipeline } from "openclaw/plugin-sdk/channel-outbound";
|
|
8
10
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
9
11
|
import { detectMime, estimateBase64DecodedBytes, kindFromMime, saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
|
|
10
12
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
|
11
13
|
import { normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
14
|
import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
|
|
13
|
-
import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
15
|
+
import { normalizeE164, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
14
16
|
import path from "node:path";
|
|
15
17
|
import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
16
18
|
import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
|
|
@@ -18,14 +20,14 @@ import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "opencla
|
|
|
18
20
|
import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
19
21
|
import { chunkTextWithMode, createReplyDispatcherWithTyping, dispatchInboundMessage, resolveChunkMode, resolveTextChunkLimit, settleReplyDispatcher } from "openclaw/plugin-sdk/reply-runtime";
|
|
20
22
|
import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
21
|
-
import { computeBackoff, createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
23
|
+
import { computeBackoff, createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, sleep, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
22
24
|
import { resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
23
25
|
import { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
|
|
24
26
|
import { spawn } from "node:child_process";
|
|
25
27
|
import os from "node:os";
|
|
26
28
|
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
|
27
|
-
import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
|
28
|
-
import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, runChannelInboundEvent, shouldDebounceTextInbound } from "openclaw/plugin-sdk/channel-inbound";
|
|
29
|
+
import { DEFAULT_EMOJIS, DEFAULT_TIMING, createStatusReactionController, logAckFailure, logTypingFailure, resolveAckReaction, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
|
30
|
+
import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, hasVisibleInboundReplyDispatch, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, runChannelInboundEvent, shouldDebounceTextInbound } from "openclaw/plugin-sdk/channel-inbound";
|
|
29
31
|
import { hasControlCommand } from "openclaw/plugin-sdk/command-auth-native";
|
|
30
32
|
import { recordInboundSession, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
|
|
31
33
|
import { createInternalHookEvent, fireAndForgetHook, toInternalMessageReceivedContext, triggerInternalHook } from "openclaw/plugin-sdk/hook-runtime";
|
|
@@ -363,6 +365,42 @@ function resolveSignalInboundRoute(params) {
|
|
|
363
365
|
}
|
|
364
366
|
});
|
|
365
367
|
}
|
|
368
|
+
function resolveSignalStatusReactionTimestamp(params) {
|
|
369
|
+
if (typeof params.timestamp === "number") return Number.isFinite(params.timestamp) && params.timestamp > 0 ? params.timestamp : null;
|
|
370
|
+
const parsed = Number(params.messageId);
|
|
371
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
372
|
+
}
|
|
373
|
+
function hasSignalStatusReplyDeliveryFailure(result) {
|
|
374
|
+
const failedCounts = result.failedCounts;
|
|
375
|
+
return (failedCounts?.tool ?? 0) > 0 || (failedCounts?.block ?? 0) > 0 || (failedCounts?.final ?? 0) > 0;
|
|
376
|
+
}
|
|
377
|
+
function resolveSignalStatusReactionEmojis(emojis) {
|
|
378
|
+
if (emojis?.stallHard !== void 0) return emojis;
|
|
379
|
+
return {
|
|
380
|
+
...emojis,
|
|
381
|
+
stallHard: DEFAULT_EMOJIS.stallSoft
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
async function finalizeSignalStatusReaction(params) {
|
|
385
|
+
if (params.outcome === "done") {
|
|
386
|
+
await params.controller.setDone();
|
|
387
|
+
if (params.removeAckAfterReply) {
|
|
388
|
+
await sleep(params.timing.doneHoldMs);
|
|
389
|
+
await params.controller.clear();
|
|
390
|
+
} else await params.controller.restoreInitial();
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
await params.controller.setError();
|
|
394
|
+
if (params.hasFinalResponse) {
|
|
395
|
+
if (params.removeAckAfterReply) {
|
|
396
|
+
await sleep(params.timing.errorHoldMs);
|
|
397
|
+
await params.controller.clear();
|
|
398
|
+
} else await params.controller.restoreInitial();
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (params.removeAckAfterReply) await sleep(params.timing.errorHoldMs);
|
|
402
|
+
await params.controller.restoreInitial();
|
|
403
|
+
}
|
|
366
404
|
function createSignalEventHandler(deps) {
|
|
367
405
|
async function handleSignalInboundMessage(entry) {
|
|
368
406
|
const fromLabel = formatInboundFromLabel({
|
|
@@ -473,9 +511,71 @@ function createSignalEventHandler(deps) {
|
|
|
473
511
|
extra: { GroupSubject: entry.isGroup ? entry.groupName ?? void 0 : void 0 }
|
|
474
512
|
});
|
|
475
513
|
if (shouldLogVerbose()) {
|
|
476
|
-
const preview = body
|
|
514
|
+
const preview = truncateUtf16Safe(body, 200).replace(/\\n/g, "\\\\n");
|
|
477
515
|
logVerbose(`signal inbound: from=${ctxPayload.From} len=${body.length} preview="${preview}"`);
|
|
478
516
|
}
|
|
517
|
+
const statusReactionTimestamp = resolveSignalStatusReactionTimestamp(entry);
|
|
518
|
+
const statusReactionsConfig = deps.cfg.messages?.statusReactions;
|
|
519
|
+
const signalReactionLevel = resolveSignalReactionLevel({
|
|
520
|
+
cfg: deps.cfg,
|
|
521
|
+
accountId: route.accountId
|
|
522
|
+
});
|
|
523
|
+
const ackReaction = resolveAckReaction(deps.cfg, route.agentId, {
|
|
524
|
+
channel: "signal",
|
|
525
|
+
accountId: route.accountId
|
|
526
|
+
});
|
|
527
|
+
const shouldSendStatusReaction = Boolean(ackReaction && shouldAckReaction({
|
|
528
|
+
scope: deps.cfg.messages?.ackReactionScope,
|
|
529
|
+
isDirect: !entry.isGroup,
|
|
530
|
+
isGroup: entry.isGroup,
|
|
531
|
+
isMentionableGroup: entry.isGroup,
|
|
532
|
+
requireMention: entry.requireMention === true,
|
|
533
|
+
canDetectMention: entry.canDetectMention === true,
|
|
534
|
+
effectiveWasMentioned: entry.wasMentioned === true
|
|
535
|
+
}));
|
|
536
|
+
const statusReactionTarget = `${entry.groupId ?? entry.senderRecipient}/${statusReactionTimestamp ?? "unknown"}`;
|
|
537
|
+
const signalReactionOpts = {
|
|
538
|
+
cfg: deps.cfg,
|
|
539
|
+
...deps.baseUrl ? { baseUrl: deps.baseUrl } : {},
|
|
540
|
+
...deps.account ? { account: deps.account } : {},
|
|
541
|
+
...deps.accountId ? { accountId: deps.accountId } : {},
|
|
542
|
+
...entry.isGroup && entry.groupId ? {
|
|
543
|
+
groupId: entry.groupId,
|
|
544
|
+
targetAuthor: entry.senderRecipient
|
|
545
|
+
} : {}
|
|
546
|
+
};
|
|
547
|
+
const statusReactionRecipient = entry.isGroup ? "" : entry.senderRecipient;
|
|
548
|
+
let currentStatusReactionEmoji = ackReaction;
|
|
549
|
+
const statusReactionController = statusReactionsConfig?.enabled === true && signalReactionLevel.level !== "off" && shouldSendStatusReaction && statusReactionTimestamp ? createStatusReactionController({
|
|
550
|
+
enabled: true,
|
|
551
|
+
adapter: {
|
|
552
|
+
setReaction: async (emoji) => {
|
|
553
|
+
await sendReactionSignal(statusReactionRecipient, statusReactionTimestamp, emoji, signalReactionOpts);
|
|
554
|
+
currentStatusReactionEmoji = emoji;
|
|
555
|
+
},
|
|
556
|
+
clearReaction: async () => {
|
|
557
|
+
if (!currentStatusReactionEmoji) return;
|
|
558
|
+
await removeReactionSignal(statusReactionRecipient, statusReactionTimestamp, currentStatusReactionEmoji, signalReactionOpts);
|
|
559
|
+
currentStatusReactionEmoji = "";
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
initialEmoji: ackReaction,
|
|
563
|
+
emojis: resolveSignalStatusReactionEmojis(statusReactionsConfig.emojis),
|
|
564
|
+
timing: statusReactionsConfig.timing,
|
|
565
|
+
onError: (err) => {
|
|
566
|
+
logAckFailure({
|
|
567
|
+
log: logVerbose,
|
|
568
|
+
channel: "signal",
|
|
569
|
+
target: statusReactionTarget,
|
|
570
|
+
error: err
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
}) : null;
|
|
574
|
+
const statusReactionTiming = {
|
|
575
|
+
...DEFAULT_TIMING,
|
|
576
|
+
...statusReactionsConfig?.timing
|
|
577
|
+
};
|
|
578
|
+
if (statusReactionController) statusReactionController.setQueued();
|
|
479
579
|
const { onModelSelected, typingCallbacks, ...replyPipeline } = createChannelMessageReplyPipeline({
|
|
480
580
|
cfg: deps.cfg,
|
|
481
581
|
agentId: route.agentId,
|
|
@@ -583,6 +683,7 @@ function createSignalEventHandler(deps) {
|
|
|
583
683
|
}),
|
|
584
684
|
runDispatch: async () => {
|
|
585
685
|
try {
|
|
686
|
+
if (statusReactionController) statusReactionController.setThinking();
|
|
586
687
|
return await dispatchInboundMessage({
|
|
587
688
|
ctx: ctxPayload,
|
|
588
689
|
cfg: deps.cfg,
|
|
@@ -590,6 +691,21 @@ function createSignalEventHandler(deps) {
|
|
|
590
691
|
replyOptions: {
|
|
591
692
|
...replyOptions,
|
|
592
693
|
disableBlockStreaming: typeof deps.blockStreaming === "boolean" ? !deps.blockStreaming : void 0,
|
|
694
|
+
...statusReactionController ? {
|
|
695
|
+
allowProgressCallbacksWhenSourceDeliverySuppressed: true,
|
|
696
|
+
allowToolLifecycleWhenProgressHidden: true,
|
|
697
|
+
onToolStart: async (payload) => {
|
|
698
|
+
const toolName = payload.name?.trim();
|
|
699
|
+
if (toolName) await statusReactionController.setTool(toolName);
|
|
700
|
+
},
|
|
701
|
+
onCompactionStart: async () => {
|
|
702
|
+
await statusReactionController.setCompacting();
|
|
703
|
+
},
|
|
704
|
+
onCompactionEnd: async () => {
|
|
705
|
+
statusReactionController.cancelPending();
|
|
706
|
+
await statusReactionController.setThinking();
|
|
707
|
+
}
|
|
708
|
+
} : {},
|
|
593
709
|
onModelSelected
|
|
594
710
|
}
|
|
595
711
|
});
|
|
@@ -597,7 +713,21 @@ function createSignalEventHandler(deps) {
|
|
|
597
713
|
markDispatchIdle();
|
|
598
714
|
}
|
|
599
715
|
}
|
|
600
|
-
})
|
|
716
|
+
}),
|
|
717
|
+
onFinalize: (result) => {
|
|
718
|
+
if (!statusReactionController) return;
|
|
719
|
+
const hasFinalResponse = result.dispatched && hasVisibleInboundReplyDispatch(result.dispatchResult);
|
|
720
|
+
const hasDeliveryFailure = result.dispatched && hasSignalStatusReplyDeliveryFailure(result.dispatchResult);
|
|
721
|
+
finalizeSignalStatusReaction({
|
|
722
|
+
controller: statusReactionController,
|
|
723
|
+
outcome: hasFinalResponse && !hasDeliveryFailure ? "done" : "error",
|
|
724
|
+
hasFinalResponse,
|
|
725
|
+
removeAckAfterReply: deps.cfg.messages?.removeAckAfterReply ?? false,
|
|
726
|
+
timing: statusReactionTiming
|
|
727
|
+
}).catch((err) => {
|
|
728
|
+
logVerbose(`signal: status reaction finalize failed: ${String(err)}`);
|
|
729
|
+
});
|
|
730
|
+
}
|
|
601
731
|
}
|
|
602
732
|
});
|
|
603
733
|
}
|
|
@@ -930,9 +1060,9 @@ function createSignalEventHandler(deps) {
|
|
|
930
1060
|
}
|
|
931
1061
|
const bodyText = messageText || placeholder || visibleQuoteText || "";
|
|
932
1062
|
if (!bodyText) return;
|
|
933
|
-
const
|
|
934
|
-
if (deps.sendReadReceipts && !deps.readReceiptsViaDaemon && !isGroup &&
|
|
935
|
-
await sendReadReceiptSignal(`signal:${senderRecipient}`,
|
|
1063
|
+
const inboundTimestamp = typeof envelope.timestamp === "number" ? envelope.timestamp : typeof dataMessage.timestamp === "number" ? dataMessage.timestamp : void 0;
|
|
1064
|
+
if (deps.sendReadReceipts && !deps.readReceiptsViaDaemon && !isGroup && inboundTimestamp) try {
|
|
1065
|
+
await sendReadReceiptSignal(`signal:${senderRecipient}`, inboundTimestamp, {
|
|
936
1066
|
cfg: deps.cfg,
|
|
937
1067
|
baseUrl: deps.baseUrl,
|
|
938
1068
|
account: deps.account,
|
|
@@ -941,9 +1071,9 @@ function createSignalEventHandler(deps) {
|
|
|
941
1071
|
} catch (err) {
|
|
942
1072
|
logVerbose(`signal read receipt failed for ${senderDisplay}: ${String(err)}`);
|
|
943
1073
|
}
|
|
944
|
-
else if (deps.sendReadReceipts && !deps.readReceiptsViaDaemon && !isGroup && !
|
|
1074
|
+
else if (deps.sendReadReceipts && !deps.readReceiptsViaDaemon && !isGroup && !inboundTimestamp) logVerbose(`signal read receipt skipped (missing timestamp) for ${senderDisplay}`);
|
|
945
1075
|
const senderName = envelope.sourceName ?? senderDisplay;
|
|
946
|
-
const messageId = typeof
|
|
1076
|
+
const messageId = typeof inboundTimestamp === "number" ? String(inboundTimestamp) : void 0;
|
|
947
1077
|
await inboundDebouncer.enqueue({
|
|
948
1078
|
senderName,
|
|
949
1079
|
senderDisplay,
|
|
@@ -954,13 +1084,15 @@ function createSignalEventHandler(deps) {
|
|
|
954
1084
|
isGroup,
|
|
955
1085
|
bodyText,
|
|
956
1086
|
commandBody: messageText,
|
|
957
|
-
timestamp:
|
|
1087
|
+
timestamp: inboundTimestamp,
|
|
958
1088
|
messageId,
|
|
959
1089
|
mediaPath,
|
|
960
1090
|
mediaType,
|
|
961
1091
|
mediaPaths: mediaPaths.length > 0 ? mediaPaths : void 0,
|
|
962
1092
|
mediaTypes: mediaTypes.length > 0 ? mediaTypes : void 0,
|
|
963
1093
|
commandAuthorized,
|
|
1094
|
+
canDetectMention,
|
|
1095
|
+
requireMention,
|
|
964
1096
|
wasMentioned: effectiveWasMentioned,
|
|
965
1097
|
replyToBody: visibleQuoteText || void 0,
|
|
966
1098
|
replyToSender: visibleQuoteSender,
|
|
@@ -1026,7 +1158,10 @@ async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEven
|
|
|
1026
1158
|
}
|
|
1027
1159
|
//#endregion
|
|
1028
1160
|
//#region extensions/signal/src/monitor.ts
|
|
1029
|
-
var monitor_exports = /* @__PURE__ */ __exportAll({
|
|
1161
|
+
var monitor_exports = /* @__PURE__ */ __exportAll({
|
|
1162
|
+
deliverReplies: () => deliverReplies,
|
|
1163
|
+
monitorSignalProvider: () => monitorSignalProvider
|
|
1164
|
+
});
|
|
1030
1165
|
function resolveRuntime(opts) {
|
|
1031
1166
|
return opts.runtime ?? createNonExitingRuntime();
|
|
1032
1167
|
}
|
|
@@ -1220,30 +1355,63 @@ async function fetchAttachment(params) {
|
|
|
1220
1355
|
}
|
|
1221
1356
|
async function deliverReplies(params) {
|
|
1222
1357
|
const { replies, target, baseUrl, account, accountId, runtime, maxBytes, textLimit, chunkMode } = params;
|
|
1223
|
-
for (const payload of replies)
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1358
|
+
for (const payload of replies) {
|
|
1359
|
+
const deliveryResults = [];
|
|
1360
|
+
const deliveredPayload = addSignalApprovalReactionHintToStructuredPayload({
|
|
1361
|
+
cfg: params.cfg,
|
|
1362
|
+
accountId,
|
|
1363
|
+
to: target,
|
|
1364
|
+
payload,
|
|
1365
|
+
targetAuthor: account
|
|
1366
|
+
}) ?? payload;
|
|
1367
|
+
const reply = resolveSendableOutboundReplyParts(deliveredPayload);
|
|
1368
|
+
const recordDeliveryResult = (result, visibleText) => {
|
|
1369
|
+
const messageId = typeof result?.messageId === "string" && result.messageId.trim() ? result.messageId.trim() : null;
|
|
1370
|
+
if (messageId) deliveryResults.push({
|
|
1371
|
+
channel: "signal",
|
|
1372
|
+
messageId,
|
|
1373
|
+
meta: { signalVisibleText: visibleText }
|
|
1234
1374
|
});
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1375
|
+
};
|
|
1376
|
+
if (await deliverTextOrMediaReply({
|
|
1377
|
+
payload: deliveredPayload,
|
|
1378
|
+
text: reply.text,
|
|
1379
|
+
chunkText: (value) => chunkTextWithMode(value, textLimit, chunkMode),
|
|
1380
|
+
sendText: async (chunk) => {
|
|
1381
|
+
recordDeliveryResult(await sendMessageSignal(target, chunk, {
|
|
1382
|
+
cfg: params.cfg,
|
|
1383
|
+
baseUrl,
|
|
1384
|
+
account,
|
|
1385
|
+
maxBytes,
|
|
1386
|
+
accountId
|
|
1387
|
+
}), chunk);
|
|
1388
|
+
},
|
|
1389
|
+
sendMedia: async ({ mediaUrl, caption }) => {
|
|
1390
|
+
const visibleText = caption ?? "";
|
|
1391
|
+
recordDeliveryResult(await sendMessageSignal(target, visibleText, {
|
|
1392
|
+
cfg: params.cfg,
|
|
1393
|
+
baseUrl,
|
|
1394
|
+
account,
|
|
1395
|
+
mediaUrl,
|
|
1396
|
+
maxBytes,
|
|
1397
|
+
accountId
|
|
1398
|
+
}), visibleText);
|
|
1399
|
+
}
|
|
1400
|
+
}) !== "empty") {
|
|
1401
|
+
registerSignalApprovalReactionTargetForDeliveredPayload({
|
|
1238
1402
|
cfg: params.cfg,
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1403
|
+
target: {
|
|
1404
|
+
channel: "signal",
|
|
1405
|
+
to: target,
|
|
1406
|
+
accountId
|
|
1407
|
+
},
|
|
1408
|
+
payload: deliveredPayload,
|
|
1409
|
+
results: deliveryResults,
|
|
1410
|
+
targetAuthor: account
|
|
1244
1411
|
});
|
|
1412
|
+
runtime.log?.(`delivered reply to ${target}`);
|
|
1245
1413
|
}
|
|
1246
|
-
}
|
|
1414
|
+
}
|
|
1247
1415
|
}
|
|
1248
1416
|
async function monitorSignalProvider(opts = {}) {
|
|
1249
1417
|
const runtime = resolveRuntime(opts);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
2
|
+
import { n as signalRpcRequest, t as signalCheck } from "./client-adapter-Dm8-wT2n.js";
|
|
3
3
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
4
4
|
//#region extensions/signal/src/probe.ts
|
|
5
5
|
var probe_exports = /* @__PURE__ */ __exportAll({ probeSignal: () => probeSignal });
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { i as resolveSignalAccount } from "./accounts-B7Rz3_xV.js";
|
|
2
|
+
import { n as signalRpcRequest } from "./client-adapter-Dm8-wT2n.js";
|
|
3
|
+
import { t as resolveSignalRpcContext } from "./rpc-context-DbFMe7am.js";
|
|
4
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
+
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
6
|
+
//#region extensions/signal/src/send-reactions.ts
|
|
7
|
+
function normalizeSignalId(raw) {
|
|
8
|
+
const trimmed = raw.trim();
|
|
9
|
+
if (!trimmed) return "";
|
|
10
|
+
return trimmed.replace(/^signal:/i, "").trim();
|
|
11
|
+
}
|
|
12
|
+
function normalizeSignalUuid(raw) {
|
|
13
|
+
const trimmed = normalizeSignalId(raw);
|
|
14
|
+
if (!trimmed) return "";
|
|
15
|
+
if (normalizeLowercaseStringOrEmpty(trimmed).startsWith("uuid:")) return trimmed.slice(5).trim();
|
|
16
|
+
return trimmed;
|
|
17
|
+
}
|
|
18
|
+
function resolveTargetAuthorParams(params) {
|
|
19
|
+
const candidates = [
|
|
20
|
+
params.targetAuthor,
|
|
21
|
+
params.targetAuthorUuid,
|
|
22
|
+
params.fallback
|
|
23
|
+
];
|
|
24
|
+
for (const candidate of candidates) {
|
|
25
|
+
const raw = candidate?.trim();
|
|
26
|
+
if (!raw) continue;
|
|
27
|
+
const normalized = normalizeSignalUuid(raw);
|
|
28
|
+
if (normalized) return { targetAuthor: normalized };
|
|
29
|
+
}
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
async function sendReactionSignalCore(params) {
|
|
33
|
+
const cfg = requireRuntimeConfig(params.opts.cfg, "Signal reactions");
|
|
34
|
+
const apiMode = cfg.channels?.signal?.apiMode;
|
|
35
|
+
const accountInfo = resolveSignalAccount({
|
|
36
|
+
cfg,
|
|
37
|
+
accountId: params.opts.accountId
|
|
38
|
+
});
|
|
39
|
+
const { baseUrl, account } = resolveSignalRpcContext(params.opts, accountInfo);
|
|
40
|
+
const normalizedRecipient = normalizeSignalUuid(params.recipient);
|
|
41
|
+
const groupId = params.opts.groupId?.trim();
|
|
42
|
+
if (!normalizedRecipient && !groupId) throw new Error(params.errors.missingRecipient);
|
|
43
|
+
if (!Number.isFinite(params.targetTimestamp) || params.targetTimestamp <= 0) throw new Error(params.errors.invalidTargetTimestamp);
|
|
44
|
+
const normalizedEmoji = params.emoji?.trim();
|
|
45
|
+
if (!normalizedEmoji) throw new Error(params.errors.missingEmoji);
|
|
46
|
+
const targetAuthorParams = resolveTargetAuthorParams({
|
|
47
|
+
targetAuthor: params.opts.targetAuthor,
|
|
48
|
+
targetAuthorUuid: params.opts.targetAuthorUuid,
|
|
49
|
+
fallback: normalizedRecipient
|
|
50
|
+
});
|
|
51
|
+
if (groupId && !targetAuthorParams.targetAuthor) throw new Error(params.errors.missingTargetAuthor);
|
|
52
|
+
const requestParams = {
|
|
53
|
+
emoji: normalizedEmoji,
|
|
54
|
+
targetTimestamp: params.targetTimestamp,
|
|
55
|
+
...params.remove ? { remove: true } : {},
|
|
56
|
+
...targetAuthorParams
|
|
57
|
+
};
|
|
58
|
+
if (normalizedRecipient) requestParams.recipients = [normalizedRecipient];
|
|
59
|
+
if (groupId) requestParams.groupIds = [groupId];
|
|
60
|
+
if (account) requestParams.account = account;
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
timestamp: (await signalRpcRequest("sendReaction", requestParams, {
|
|
64
|
+
baseUrl,
|
|
65
|
+
timeoutMs: params.opts.timeoutMs,
|
|
66
|
+
apiMode
|
|
67
|
+
}))?.timestamp
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Send a Signal reaction to a message
|
|
72
|
+
* @param recipient - UUID or E.164 phone number of the message author
|
|
73
|
+
* @param targetTimestamp - Message ID (timestamp) to react to
|
|
74
|
+
* @param emoji - Emoji to react with
|
|
75
|
+
* @param opts - Optional account/connection overrides
|
|
76
|
+
*/
|
|
77
|
+
async function sendReactionSignal(recipient, targetTimestamp, emoji, opts) {
|
|
78
|
+
return await sendReactionSignalCore({
|
|
79
|
+
recipient,
|
|
80
|
+
targetTimestamp,
|
|
81
|
+
emoji,
|
|
82
|
+
remove: false,
|
|
83
|
+
opts,
|
|
84
|
+
errors: {
|
|
85
|
+
missingRecipient: "Recipient or groupId is required for Signal reaction",
|
|
86
|
+
invalidTargetTimestamp: "Valid targetTimestamp is required for Signal reaction",
|
|
87
|
+
missingEmoji: "Emoji is required for Signal reaction",
|
|
88
|
+
missingTargetAuthor: "targetAuthor is required for group reactions"
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Remove a Signal reaction from a message
|
|
94
|
+
* @param recipient - UUID or E.164 phone number of the message author
|
|
95
|
+
* @param targetTimestamp - Message ID (timestamp) to remove reaction from
|
|
96
|
+
* @param emoji - Emoji to remove
|
|
97
|
+
* @param opts - Optional account/connection overrides
|
|
98
|
+
*/
|
|
99
|
+
async function removeReactionSignal(recipient, targetTimestamp, emoji, opts) {
|
|
100
|
+
return await sendReactionSignalCore({
|
|
101
|
+
recipient,
|
|
102
|
+
targetTimestamp,
|
|
103
|
+
emoji,
|
|
104
|
+
remove: true,
|
|
105
|
+
opts,
|
|
106
|
+
errors: {
|
|
107
|
+
missingRecipient: "Recipient or groupId is required for Signal reaction removal",
|
|
108
|
+
invalidTargetTimestamp: "Valid targetTimestamp is required for Signal reaction removal",
|
|
109
|
+
missingEmoji: "Emoji is required for Signal reaction removal",
|
|
110
|
+
missingTargetAuthor: "targetAuthor is required for group reaction removal"
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { sendReactionSignal as n, removeReactionSignal as t };
|
|
@@ -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-BkAxQPGs.js";
|
|
2
2
|
export { removeReactionSignal, sendReactionSignal };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "./accounts-B7Rz3_xV.js";
|
|
2
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
//#region extensions/signal/src/rpc-context.ts
|
|
4
|
+
function resolveSignalRpcContext(opts, accountInfo) {
|
|
5
|
+
const hasBaseUrl = Boolean(normalizeOptionalString(opts.baseUrl));
|
|
6
|
+
const hasAccount = Boolean(normalizeOptionalString(opts.account));
|
|
7
|
+
if ((!hasBaseUrl || !hasAccount) && !accountInfo) throw new Error("Signal account config is required when baseUrl or account is missing");
|
|
8
|
+
const resolvedAccount = accountInfo;
|
|
9
|
+
const baseUrl = normalizeOptionalString(opts.baseUrl) ?? resolvedAccount?.baseUrl;
|
|
10
|
+
if (!baseUrl) throw new Error("Signal base URL is required");
|
|
11
|
+
return {
|
|
12
|
+
baseUrl,
|
|
13
|
+
account: normalizeOptionalString(opts.account) ?? normalizeOptionalString(resolvedAccount?.config.account)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { resolveSignalRpcContext as t };
|
package/dist/runtime-api.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-
|
|
1
|
+
import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-B7Rz3_xV.js";
|
|
2
2
|
import { d as normalizeSignalMessagingTarget, u as looksLikeSignalTargetId } from "./identity-B6O4k8xg.js";
|
|
3
|
-
import { n as resolveSignalReactionLevel, t as signalMessageActions } from "./message-actions-
|
|
4
|
-
import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-
|
|
3
|
+
import { n as resolveSignalReactionLevel, t as signalMessageActions } from "./message-actions-Cs9XckSd.js";
|
|
4
|
+
import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-BkAxQPGs.js";
|
|
5
5
|
import { n as buildChannelConfigSchema, t as SignalConfigSchema } from "./config-api-KS-qhQvD.js";
|
|
6
|
-
import { r as installSignalCli } from "./install-signal-cli-
|
|
7
|
-
import {
|
|
8
|
-
import { t as
|
|
9
|
-
import { t as
|
|
6
|
+
import { r as installSignalCli } from "./install-signal-cli-TwhJ0DGy.js";
|
|
7
|
+
import { u as setSignalRuntime } from "./approval-reactions-5x1kmQEq.js";
|
|
8
|
+
import { t as monitorSignalProvider } from "./monitor-C9SiyrFt.js";
|
|
9
|
+
import { t as sendMessageSignal } from "./send-CLzc3RUg.js";
|
|
10
|
+
import { t as probeSignal } from "./probe-BL2BqTbG.js";
|
|
10
11
|
import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
|
|
11
12
|
import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
|
|
12
13
|
import { buildBaseAccountStatusSnapshot, buildBaseChannelStatusSummary, collectStatusIssuesFromLastError, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
|