@openclaw/signal 2026.11.3 → 2026.11.5-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/.setup/{accounts-B0Pba1-q.mjs → accounts-enJKL3ci.mjs} +4 -8
- package/dist/.setup/api-CrasQEKI.mjs +14 -0
- package/dist/.setup/{api-CbN3mye4.mjs → api-DljZsfUn.mjs} +9 -11
- package/dist/.setup/{approval-auth-DhUKkSkA.mjs → approval-auth-B_5Ytx8K.mjs} +7 -11
- package/dist/.setup/{approval-handler.runtime-CsEcBZoc.mjs → approval-handler.runtime-0RbVmTxx.mjs} +7 -8
- package/dist/.setup/{approval-reactions-JsqCEOHK.mjs → approval-reactions-CvqVSSx8.mjs} +16 -24
- package/dist/.setup/{channel-CM-rLLPN.mjs → channel-ByJj8fSh.mjs} +417 -372
- package/dist/.setup/{client-Duwqbgqi.mjs → client-CesmEjRc.mjs} +170 -186
- package/dist/.setup/{config-schema-DvxZ18SD.mjs → config-schema-BCmW0BLB.mjs} +2 -5
- package/dist/.setup/{doctor-contract-api-BIdVW0PF.mjs → doctor-contract-api-CcLwIhsD.mjs} +88 -95
- package/dist/.setup/{identity-B3JyPqGO.mjs → identity-vKtR3DrM.mjs} +39 -2
- package/dist/.setup/{install-signal-cli-hYVLYGXe.mjs → install-signal-cli-DvLDZfpP.mjs} +95 -109
- package/dist/.setup/{transport-url-CAC0JcuI.mjs → legacy-transport-D_cZC3bS.mjs} +18 -1
- package/dist/.setup/{monitor-C6u1JV2C.mjs → monitor-Cf5sihwl.mjs} +166 -239
- package/dist/.setup/{probe-D_93QCe0.mjs → probe-Caq5Y4kA.mjs} +3 -3
- package/dist/.setup/{send-CM7-016e.mjs → send-BJuOWLky.mjs} +34 -66
- package/dist/.setup/{setup-surface-DvKLwYrl.mjs → setup-surface-DQ1yFZmY.mjs} +3 -3
- package/dist/.setup/{transport-detection-CmlgOybe.mjs → transport-detection-DvR6X_UQ.mjs} +3 -3
- package/dist/.setup/{transport-policy-B6C_LogW.mjs → transport-policy-zIR3lRUj.mjs} +1 -1
- package/dist/.setup/transport-probes.runtime-CoH6UFtc.mjs +1 -0
- package/dist/.source-module-urls/b02c526df8b90083105b63e5b51d5c8bbfe02676df72f6be8dd8f825817b32b9.json +1 -0
- package/dist/api.js +9 -11
- package/dist/channel-config-api.js +1 -2
- package/dist/channel-plugin-api.js +1 -2
- package/dist/contract-api.js +3 -4
- package/dist/doctor-contract-api.js +1 -2
- package/dist/runtime-api.js +1 -2
- package/dist/setup-entry.js +1 -1
- package/node_modules/@openclaw/fs-safe/CHANGELOG.md +94 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-path-admission.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/copy-root-file-sync.js +8 -1
- package/node_modules/@openclaw/fs-safe/dist/file-open-error.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/file-open-error.js +14 -0
- package/node_modules/@openclaw/fs-safe/dist/file-sync.d.ts +2 -1
- package/node_modules/@openclaw/fs-safe/dist/file-sync.js +6 -1
- package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-config.js +14 -3
- package/node_modules/@openclaw/fs-safe/dist/native-operations.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.js +9 -2
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +40 -32
- package/node_modules/@openclaw/fs-safe/dist/output.js +6 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path.js +5 -1
- package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +25 -2
- package/node_modules/@openclaw/fs-safe/dist/publication-handle.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/publication-handle.js +32 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.d.ts +2 -1
- package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +19 -9
- package/node_modules/@openclaw/fs-safe/dist/publish-file.js +23 -24
- package/node_modules/@openclaw/fs-safe/dist/publish-rename-fallback.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-rename-fallback.js +102 -0
- package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-entry.d.ts +3 -1
- package/node_modules/@openclaw/fs-safe/dist/root-directory-entry.js +8 -5
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +2 -1
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +19 -9
- package/node_modules/@openclaw/fs-safe/dist/root-file-final-admission.js +3 -3
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.d.ts +2 -2
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +27 -13
- package/node_modules/@openclaw/fs-safe/dist/root-path.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +18 -3
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +68 -21
- package/node_modules/@openclaw/fs-safe/dist/watch-io-error.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-io-error.js +27 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-io-worker.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-io-worker.js +93 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-io.d.ts +47 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-io.js +236 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/watch-native.js +3 -3
- package/node_modules/@openclaw/fs-safe/dist/watch-probe.d.ts +16 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-probe.js +135 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.js +86 -24
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +78 -16
- package/node_modules/@openclaw/fs-safe/dist/watch-stream.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +23 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-types.d.ts +3 -1
- package/node_modules/@openclaw/fs-safe/dist/watch.js +60 -13
- package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.exe +0 -0
- package/node_modules/@openclaw/fs-safe/docs/advanced.md +5 -2
- package/node_modules/@openclaw/fs-safe/docs/compiler-qualification.md +392 -0
- package/node_modules/@openclaw/fs-safe/docs/config.md +7 -1
- package/node_modules/@openclaw/fs-safe/docs/contributing.md +25 -5
- package/node_modules/@openclaw/fs-safe/docs/copy.md +10 -0
- package/node_modules/@openclaw/fs-safe/docs/durability.md +9 -3
- package/node_modules/@openclaw/fs-safe/docs/errors.md +13 -0
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +6 -4
- package/node_modules/@openclaw/fs-safe/docs/native-helper.md +6 -4
- package/node_modules/@openclaw/fs-safe/docs/output.md +4 -2
- package/node_modules/@openclaw/fs-safe/docs/path.md +5 -2
- package/node_modules/@openclaw/fs-safe/docs/permissions.md +15 -0
- package/node_modules/@openclaw/fs-safe/docs/security-model.md +9 -0
- package/node_modules/@openclaw/fs-safe/docs/staged-file.md +2 -0
- package/node_modules/@openclaw/fs-safe/docs/testing.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/watch.md +62 -5
- package/node_modules/@openclaw/fs-safe/docs/writing.md +6 -1
- package/node_modules/@openclaw/fs-safe/package.json +18 -16
- package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-freebsd-arm64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-freebsd-arm64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-freebsd-x64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-freebsd-x64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
- package/node_modules/zod/package.json +1 -1
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/zod/v4/core/versions.js +1 -1
- package/openclaw.plugin.json +0 -30
- package/package.json +6 -8
- package/dist/.setup/api-CJBtD3lT.mjs +0 -16
- package/dist/.setup/client-adapter-Chnbch_z.mjs +0 -30
- package/dist/.setup/legacy-transport-QIpaMNST.mjs +0 -18
- package/dist/.setup/normalize-D7kSomXt.mjs +0 -39
- package/dist/.setup/reaction-runtime-api-mdO4k0yv.mjs +0 -65
- package/dist/.setup/reaction-targets-BgPLDHBf.mjs +0 -72
- package/dist/.setup/rpc-context-BAXcX7dI.mjs +0 -13
- package/dist/.setup/transport-probes.runtime-D-xIMRcn.mjs +0 -2
- package/dist/reaction-runtime-api.js +0 -2
- package/node_modules/ws/LICENSE +0 -20
- package/node_modules/ws/README.md +0 -548
- package/node_modules/ws/browser.js +0 -8
- package/node_modules/ws/index.js +0 -22
- package/node_modules/ws/lib/buffer-util.js +0 -131
- package/node_modules/ws/lib/constants.js +0 -19
- package/node_modules/ws/lib/event-target.js +0 -292
- package/node_modules/ws/lib/extension.js +0 -203
- package/node_modules/ws/lib/limiter.js +0 -55
- package/node_modules/ws/lib/permessage-deflate.js +0 -530
- package/node_modules/ws/lib/receiver.js +0 -743
- package/node_modules/ws/lib/sender.js +0 -607
- package/node_modules/ws/lib/stream.js +0 -161
- package/node_modules/ws/lib/subprotocol.js +0 -62
- package/node_modules/ws/lib/validation.js +0 -152
- package/node_modules/ws/lib/websocket-server.js +0 -562
- package/node_modules/ws/lib/websocket.js +0 -1421
- package/node_modules/ws/package.json +0 -74
- package/node_modules/ws/wrapper.mjs +0 -21
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
import { o as __exportAll } from "./doctor-contract-api-
|
|
2
|
-
import {
|
|
3
|
-
import { i as resolveSignalAccount, o as resolveSignalReplyToMode } from "./accounts-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { a as prepareSignalSocketPath, t as SignalSseRejectionError } from "./client-Duwqbgqi.mjs";
|
|
8
|
-
import { n as signalRpcRequest, r as streamSignalEvents, t as signalCheck } from "./client-adapter-Chnbch_z.mjs";
|
|
9
|
-
import { n as sendReactionSignal } from "./reaction-runtime-api-mdO4k0yv.mjs";
|
|
1
|
+
import { o as __exportAll } from "./doctor-contract-api-CcLwIhsD.mjs";
|
|
2
|
+
import { o as normalizeSignalTransportHost } from "./legacy-transport-D_cZC3bS.mjs";
|
|
3
|
+
import { i as resolveSignalAccount, o as resolveSignalReplyToMode } from "./accounts-enJKL3ci.mjs";
|
|
4
|
+
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-vKtR3DrM.mjs";
|
|
5
|
+
import { A as isSignalNativeApprovalHandlerConfigured, C as signalCheck, D as formatSignalMediaText, E as resolveSignalReactionLevel, T as streamSignalEvents, _ as materializeSignalPresentationFallback, a as formatSignalDaemonDroppedEnvNotice, g as registerSignalReplyContext, i as buildSignalDaemonEnv, o as listSignalDaemonDroppedEnvHints, w as signalRpcRequest, x as sendReactionSignal } from "./channel-ByJj8fSh.mjs";
|
|
6
|
+
import { a as prepareSignalSocketPath, t as SignalSseRejectionError } from "./client-CesmEjRc.mjs";
|
|
10
7
|
import { n as getSignalRuntime, t as getOptionalSignalRuntime } from "./runtime-8sxUF217.mjs";
|
|
11
|
-
import { i as maybeResolveSignalApprovalReaction, s as resolveSignalApprovalConversationKey, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-
|
|
12
|
-
import { n as
|
|
13
|
-
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-CM7-016e.mjs";
|
|
8
|
+
import { i as maybeResolveSignalApprovalReaction, o as registerSignalApprovalReactionTargetForDeliveredPayload, s as resolveSignalApprovalConversationKey, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-CvqVSSx8.mjs";
|
|
9
|
+
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-BJuOWLky.mjs";
|
|
14
10
|
import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
15
11
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
16
12
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
|
17
13
|
import { asPositiveSafeInteger, isRecord, normalizeNullableString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
14
|
import path from "node:path";
|
|
19
15
|
import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
|
|
20
|
-
import { normalizeE164
|
|
16
|
+
import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
21
17
|
import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, logInboundDrop, matchesMentionPatterns, readAgentRunTerminalOutcome, resolveInboundDebounceMs, resolveInboundMentionDecision, resolveInboundSessionEnvelopeContextAsync, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toHistoryMediaEntries, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
22
18
|
import { canonicalizeBase64, detectMime, estimateBase64DecodedBytes, kindFromMime, saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
|
|
23
|
-
import { resolvePromptHistoryLimit } from "openclaw/plugin-sdk/number-runtime";
|
|
19
|
+
import { asPositiveFiniteNumber, resolvePromptHistoryLimit } from "openclaw/plugin-sdk/number-runtime";
|
|
24
20
|
import { ensurePortAvailable, extractErrorCode, formatErrorMessage, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
|
|
25
21
|
import os from "node:os";
|
|
26
22
|
import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention, resolveChannelGroups, resolveChannelGroupsConfigPath } from "openclaw/plugin-sdk/channel-policy";
|
|
@@ -28,7 +24,7 @@ import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runti
|
|
|
28
24
|
import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
29
25
|
import { chunkTextWithMode, createReplyReferencePlanner, resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
|
|
30
26
|
import { captureRuntimeConfigAsyncReader, createRuntimeConfigReader } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
31
|
-
import { computeBackoff, createNonExitingRuntime, createSubsystemLogger, danger, logVerbose,
|
|
27
|
+
import { computeBackoff, createNonExitingRuntime, createSubsystemLogger, danger, logVerbose, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
32
28
|
import { resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
33
29
|
import { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
|
|
34
30
|
import { createInterface } from "node:readline";
|
|
@@ -106,14 +102,11 @@ async function waitForSignalDaemonReady(params) {
|
|
|
106
102
|
}
|
|
107
103
|
});
|
|
108
104
|
}
|
|
109
|
-
function isRecoverableSignalCliReceiveException(line) {
|
|
110
|
-
return /\breceive exception:\s+.*\binvalid PreKey message:\s+decryption failed\b/i.test(line);
|
|
111
|
-
}
|
|
112
105
|
function classifySignalCliLogLine(line) {
|
|
113
106
|
const trimmed = line.trim();
|
|
114
107
|
if (!trimmed) return null;
|
|
115
108
|
if (/\bERROR\b/.test(trimmed)) return "error";
|
|
116
|
-
if (
|
|
109
|
+
if (/\breceive exception:\s+.*\binvalid PreKey message:\s+decryption failed\b/i.test(trimmed)) return "log";
|
|
117
110
|
if (/\b(FAILED|SEVERE|EXCEPTION)\b/i.test(trimmed)) return "error";
|
|
118
111
|
return "log";
|
|
119
112
|
}
|
|
@@ -131,7 +124,7 @@ function resolveSignalCliConfigPath(raw) {
|
|
|
131
124
|
if (value.startsWith("~/") || value.startsWith("~\\")) return path.join(os.homedir(), value.slice(2));
|
|
132
125
|
return value;
|
|
133
126
|
}
|
|
134
|
-
function
|
|
127
|
+
function spawnSignalDaemon(opts) {
|
|
135
128
|
const args = [];
|
|
136
129
|
if (opts.configPath?.trim()) args.push("--config", resolveSignalCliConfigPath(opts.configPath));
|
|
137
130
|
if (opts.account) args.push("-a", opts.account);
|
|
@@ -144,10 +137,6 @@ function buildDaemonArgs(opts) {
|
|
|
144
137
|
if (opts.ignoreAttachments) args.push("--ignore-attachments");
|
|
145
138
|
if (opts.ignoreStories) args.push("--ignore-stories");
|
|
146
139
|
if (opts.sendReadReceipts) args.push("--send-read-receipts");
|
|
147
|
-
return args;
|
|
148
|
-
}
|
|
149
|
-
function spawnSignalDaemon(opts) {
|
|
150
|
-
const args = buildDaemonArgs(opts);
|
|
151
140
|
warnSignalDaemonDroppedEnvOnce();
|
|
152
141
|
const child = spawnOomScoreAdjusted(opts.cliPath, args, {
|
|
153
142
|
env: buildSignalDaemonEnv(),
|
|
@@ -235,35 +224,6 @@ function spawnSignalDaemon(opts) {
|
|
|
235
224
|
};
|
|
236
225
|
}
|
|
237
226
|
//#endregion
|
|
238
|
-
//#region extensions/signal/src/daemon-lifecycle.ts
|
|
239
|
-
function createSignalDaemonLifecycle(params) {
|
|
240
|
-
let daemonHandle = null;
|
|
241
|
-
let daemonStopPromise;
|
|
242
|
-
let daemonExitError;
|
|
243
|
-
const daemonAbortController = new AbortController();
|
|
244
|
-
const abortSignal = params.abortSignal ? AbortSignal.any([params.abortSignal, daemonAbortController.signal]) : daemonAbortController.signal;
|
|
245
|
-
const stop = () => {
|
|
246
|
-
if (daemonStopPromise) return daemonStopPromise;
|
|
247
|
-
daemonAbortController.abort(params.abortSignal?.reason ?? /* @__PURE__ */ new Error("Signal monitor stopped"));
|
|
248
|
-
daemonStopPromise = daemonHandle?.stop() ?? Promise.resolve();
|
|
249
|
-
return daemonStopPromise;
|
|
250
|
-
};
|
|
251
|
-
const attach = (handle) => {
|
|
252
|
-
daemonHandle = handle;
|
|
253
|
-
handle.exited.then((exit) => {
|
|
254
|
-
if (abortSignal.aborted) return;
|
|
255
|
-
daemonExitError = new Error(formatSignalDaemonExit(exit));
|
|
256
|
-
daemonAbortController.abort(daemonExitError);
|
|
257
|
-
});
|
|
258
|
-
};
|
|
259
|
-
return {
|
|
260
|
-
attach,
|
|
261
|
-
stop,
|
|
262
|
-
getExitError: () => daemonExitError,
|
|
263
|
-
abortSignal
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
//#endregion
|
|
267
227
|
//#region extensions/signal/src/native-reply.ts
|
|
268
228
|
function resolveSignalNativeReplyId(params) {
|
|
269
229
|
if (params.payload.replyToCurrent === false) return;
|
|
@@ -471,41 +431,26 @@ function resolveSignalControlLaneKey(accountId, entry) {
|
|
|
471
431
|
return conversationId ? `signal:${accountId}:${conversationId}:control` : null;
|
|
472
432
|
}
|
|
473
433
|
function createSignalPendingInboundRegistry(accountId) {
|
|
474
|
-
const trackedEntries = /* @__PURE__ */ new
|
|
475
|
-
const countsByConversation = /* @__PURE__ */ new Map();
|
|
434
|
+
const trackedEntries = /* @__PURE__ */ new Map();
|
|
476
435
|
const track = (entry) => {
|
|
477
|
-
if (trackedEntries.has(entry)) return;
|
|
478
436
|
const conversationKey = resolveSignalInboundConversationKey(accountId, entry);
|
|
479
437
|
const inboundKey = resolveSignalInboundDebounceKey(accountId, entry);
|
|
480
438
|
if (!conversationKey || !inboundKey) return;
|
|
481
|
-
const counts = countsByConversation.get(conversationKey) ?? /* @__PURE__ */ new Map();
|
|
482
|
-
counts.set(inboundKey, (counts.get(inboundKey) ?? 0) + 1);
|
|
483
|
-
countsByConversation.set(conversationKey, counts);
|
|
484
439
|
trackedEntries.set(entry, {
|
|
485
440
|
conversationKey,
|
|
486
441
|
inboundKey
|
|
487
442
|
});
|
|
488
443
|
};
|
|
489
444
|
const complete = (entries) => {
|
|
490
|
-
for (const entry of entries)
|
|
491
|
-
const tracked = trackedEntries.get(entry);
|
|
492
|
-
if (!tracked) continue;
|
|
493
|
-
trackedEntries.delete(entry);
|
|
494
|
-
const counts = countsByConversation.get(tracked.conversationKey);
|
|
495
|
-
const nextCount = (counts?.get(tracked.inboundKey) ?? 0) - 1;
|
|
496
|
-
if (nextCount > 0) {
|
|
497
|
-
counts?.set(tracked.inboundKey, nextCount);
|
|
498
|
-
continue;
|
|
499
|
-
}
|
|
500
|
-
counts?.delete(tracked.inboundKey);
|
|
501
|
-
if (counts?.size === 0) countsByConversation.delete(tracked.conversationKey);
|
|
502
|
-
}
|
|
445
|
+
for (const entry of entries) trackedEntries.delete(entry);
|
|
503
446
|
};
|
|
504
447
|
const cancelPendingOnAbort = (entry, cancelKey) => {
|
|
505
448
|
if (!entry.commandAuthorized || !isAbortRequestText(entry.commandBody)) return;
|
|
506
449
|
const conversationKey = resolveSignalInboundConversationKey(accountId, entry);
|
|
507
450
|
if (!conversationKey) return;
|
|
508
|
-
|
|
451
|
+
const inboundKeys = /* @__PURE__ */ new Set();
|
|
452
|
+
for (const tracked of trackedEntries.values()) if (tracked.conversationKey === conversationKey) inboundKeys.add(tracked.inboundKey);
|
|
453
|
+
for (const inboundKey of inboundKeys) cancelKey(inboundKey);
|
|
509
454
|
};
|
|
510
455
|
return {
|
|
511
456
|
track,
|
|
@@ -606,9 +551,8 @@ function renderSignalMentions(message, mentions) {
|
|
|
606
551
|
//#endregion
|
|
607
552
|
//#region extensions/signal/src/monitor/reactions.ts
|
|
608
553
|
function resolveSignalStatusReactionTimestamp(params) {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
554
|
+
const value = typeof params.timestamp === "number" ? params.timestamp : Number(params.messageId);
|
|
555
|
+
return asPositiveFiniteNumber(value) ?? null;
|
|
612
556
|
}
|
|
613
557
|
function resolveSignalReactionTargets(reaction) {
|
|
614
558
|
const targets = [];
|
|
@@ -710,7 +654,7 @@ function createSignalEventHandler(deps) {
|
|
|
710
654
|
agentId: route.agentId,
|
|
711
655
|
sessionKey: route.sessionKey
|
|
712
656
|
});
|
|
713
|
-
|
|
657
|
+
let combinedBody = formatInboundEnvelope({
|
|
714
658
|
channel: "Signal",
|
|
715
659
|
from: fromLabel,
|
|
716
660
|
timestamp: entry.timestamp ?? void 0,
|
|
@@ -723,7 +667,6 @@ function createSignalEventHandler(deps) {
|
|
|
723
667
|
previousTimestamp,
|
|
724
668
|
envelope: envelopeOptions
|
|
725
669
|
});
|
|
726
|
-
let combinedBody = body;
|
|
727
670
|
const historyKey = entry.isGroup ? entry.groupId ?? "unknown" : void 0;
|
|
728
671
|
if (entry.isGroup && historyKey) combinedBody = createChannelHistoryWindow({ historyMap: deps.groupHistories }).buildPendingContext({
|
|
729
672
|
historyKey,
|
|
@@ -803,10 +746,6 @@ function createSignalEventHandler(deps) {
|
|
|
803
746
|
ReplyThreading: replyThreading
|
|
804
747
|
}
|
|
805
748
|
});
|
|
806
|
-
if (shouldLogVerbose()) {
|
|
807
|
-
const preview = truncateUtf16Safe(body, 200).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
808
|
-
logVerbose(`signal inbound: from=${ctxPayload.From} len=${body.length} preview="${preview}"`);
|
|
809
|
-
}
|
|
810
749
|
const statusReactionTimestamp = resolveSignalStatusReactionTimestamp(entry);
|
|
811
750
|
const statusReactionsConfig = cfg.messages?.statusReactions;
|
|
812
751
|
const signalReactionLevel = resolveSignalReactionLevel({
|
|
@@ -854,21 +793,26 @@ function createSignalEventHandler(deps) {
|
|
|
854
793
|
}
|
|
855
794
|
}) : null;
|
|
856
795
|
if (statusReactionController) statusReactionController.setQueued();
|
|
796
|
+
const sendTyping = async (stop) => {
|
|
797
|
+
if (ctxPayload.To) {
|
|
798
|
+
const { baseUrl, account, accountId } = deps;
|
|
799
|
+
await sendTypingSignal(ctxPayload.To, {
|
|
800
|
+
cfg,
|
|
801
|
+
baseUrl,
|
|
802
|
+
account,
|
|
803
|
+
accountId,
|
|
804
|
+
stop
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
};
|
|
857
808
|
const { onModelSelected, typingCallbacks, ...replyPipeline } = createChannelMessageReplyPipeline({
|
|
858
809
|
cfg,
|
|
859
810
|
agentId: route.agentId,
|
|
860
811
|
channel: "signal",
|
|
861
812
|
accountId: route.accountId,
|
|
862
813
|
typing: {
|
|
863
|
-
start:
|
|
864
|
-
|
|
865
|
-
await sendTypingSignal(ctxPayload.To, {
|
|
866
|
-
cfg,
|
|
867
|
-
baseUrl: deps.baseUrl,
|
|
868
|
-
account: deps.account,
|
|
869
|
-
accountId: deps.accountId
|
|
870
|
-
});
|
|
871
|
-
},
|
|
814
|
+
start: () => sendTyping(),
|
|
815
|
+
stop: () => sendTyping(true),
|
|
872
816
|
onStartError: (err) => {
|
|
873
817
|
logTypingFailure({
|
|
874
818
|
log: logVerbose,
|
|
@@ -1089,7 +1033,7 @@ function createSignalEventHandler(deps) {
|
|
|
1089
1033
|
...last.messageId ? { messageId: last.messageId } : {},
|
|
1090
1034
|
inboundEventKind: "user_request"
|
|
1091
1035
|
};
|
|
1092
|
-
return await Promise.all(entries.
|
|
1036
|
+
return await Promise.all(entries.map((entry) => entry.resolveChannelIngress(contextBinding)));
|
|
1093
1037
|
}
|
|
1094
1038
|
const flushDebouncedSignalInboundEntries = (entries, createFlush) => {
|
|
1095
1039
|
const { lifecycle, settle } = fanInChannelIngressLifecycles(entries.map((entry) => entry.turnAdoptionLifecycle));
|
|
@@ -1148,95 +1092,17 @@ function createSignalEventHandler(deps) {
|
|
|
1148
1092
|
onFlush: (entries, createFlush) => trackSignalInboundFlush(flushDebouncedSignalInboundEntries(entries, createFlush)),
|
|
1149
1093
|
onError: reportSignalInboundFlushError
|
|
1150
1094
|
});
|
|
1151
|
-
async function handleReactionOnlyInbound(params) {
|
|
1152
|
-
if (params.hasBodyContent) return false;
|
|
1153
|
-
if (params.reaction.isRemove) return true;
|
|
1154
|
-
const emojiLabel = normalizeOptionalString(params.reaction.emoji) ?? "emoji";
|
|
1155
|
-
const senderName = params.envelope.sourceName ?? params.senderDisplay;
|
|
1156
|
-
logVerbose(`signal reaction: ${emojiLabel} from ${senderName}`);
|
|
1157
|
-
const groupId = params.reaction.groupInfo?.groupId ?? void 0;
|
|
1158
|
-
const groupName = params.reaction.groupInfo?.groupName ?? void 0;
|
|
1159
|
-
const isGroup = Boolean(groupId);
|
|
1160
|
-
const messageId = params.reaction.targetSentTimestamp ? String(params.reaction.targetSentTimestamp) : "unknown";
|
|
1161
|
-
const conversationKey = resolveSignalApprovalConversationKey(groupId ? `group:${groupId}` : `signal:${resolveSignalRecipient(params.sender)}`);
|
|
1162
|
-
if (conversationKey && await maybeResolveSignalApprovalReaction({
|
|
1163
|
-
cfg: params.cfg,
|
|
1164
|
-
accountId: deps.accountId,
|
|
1165
|
-
conversationKey,
|
|
1166
|
-
messageId,
|
|
1167
|
-
reactionKey: emojiLabel,
|
|
1168
|
-
actorId: formatSignalSenderId(params.sender),
|
|
1169
|
-
targetAuthor: params.reaction.targetAuthor,
|
|
1170
|
-
targetAuthorUuid: params.reaction.targetAuthorUuid,
|
|
1171
|
-
logVerboseMessage: logVerbose
|
|
1172
|
-
})) return true;
|
|
1173
|
-
if (params.accessDecision.decision !== "allow") {
|
|
1174
|
-
logVerbose(`Blocked signal reaction sender ${params.senderDisplay} (${params.accessDecision.reasonCode})`);
|
|
1175
|
-
return true;
|
|
1176
|
-
}
|
|
1177
|
-
if (conversationKey && await maybeResolveSignalQuestionReaction({
|
|
1178
|
-
cfg: params.cfg,
|
|
1179
|
-
accountId: deps.accountId,
|
|
1180
|
-
conversationKey,
|
|
1181
|
-
messageId,
|
|
1182
|
-
reactionKey: emojiLabel,
|
|
1183
|
-
isRemove: Boolean(params.reaction.isRemove),
|
|
1184
|
-
actorId: formatSignalSenderId(params.sender),
|
|
1185
|
-
targetAuthor: params.reaction.targetAuthor,
|
|
1186
|
-
targetAuthorUuid: params.reaction.targetAuthorUuid,
|
|
1187
|
-
logDebug: logVerbose
|
|
1188
|
-
})) return true;
|
|
1189
|
-
const targets = resolveSignalReactionTargets(params.reaction);
|
|
1190
|
-
if (!shouldEmitSignalReactionNotification({
|
|
1191
|
-
mode: deps.reactionMode,
|
|
1192
|
-
account: deps.account,
|
|
1193
|
-
accountUuid: deps.accountUuid,
|
|
1194
|
-
targets,
|
|
1195
|
-
sender: params.sender,
|
|
1196
|
-
allowlist: deps.reactionAllowlist
|
|
1197
|
-
})) return true;
|
|
1198
|
-
const senderPeerId = resolveSignalPeerId(params.sender);
|
|
1199
|
-
const route = resolveSignalInboundRoute({
|
|
1200
|
-
cfg: params.cfg,
|
|
1201
|
-
accountId: deps.accountId,
|
|
1202
|
-
isGroup,
|
|
1203
|
-
groupId,
|
|
1204
|
-
senderPeerId
|
|
1205
|
-
});
|
|
1206
|
-
const groupLabel = isGroup ? `${groupName ?? "Signal Group"} id:${groupId}` : void 0;
|
|
1207
|
-
const text = buildSignalReactionSystemEventText({
|
|
1208
|
-
emojiLabel,
|
|
1209
|
-
actorLabel: senderName,
|
|
1210
|
-
messageId,
|
|
1211
|
-
targetLabel: targets[0]?.display,
|
|
1212
|
-
groupLabel
|
|
1213
|
-
});
|
|
1214
|
-
const contextKey = [
|
|
1215
|
-
"signal",
|
|
1216
|
-
"reaction",
|
|
1217
|
-
"added",
|
|
1218
|
-
messageId,
|
|
1219
|
-
formatSignalSenderId(params.sender),
|
|
1220
|
-
emojiLabel,
|
|
1221
|
-
groupId ?? ""
|
|
1222
|
-
].filter(Boolean).join(":");
|
|
1223
|
-
enqueueSystemEvent(text, {
|
|
1224
|
-
sessionKey: route.sessionKey,
|
|
1225
|
-
contextKey
|
|
1226
|
-
});
|
|
1227
|
-
return true;
|
|
1228
|
-
}
|
|
1229
1095
|
return async (event, turnAdoptionLifecycle, preparedPayload) => {
|
|
1230
1096
|
if (event.event !== "receive" || !event.data) return;
|
|
1231
1097
|
const cfg = readConfig();
|
|
1232
1098
|
let payload = preparedPayload ?? null;
|
|
1233
1099
|
if (!preparedPayload) try {
|
|
1234
1100
|
payload = JSON.parse(event.data);
|
|
1235
|
-
} catch
|
|
1236
|
-
deps.runtime.error?.(
|
|
1101
|
+
} catch {
|
|
1102
|
+
deps.runtime.error?.("failed to parse event: invalid JSON");
|
|
1237
1103
|
return;
|
|
1238
1104
|
}
|
|
1239
|
-
if (payload?.exception?.message) deps.runtime.error?.(
|
|
1105
|
+
if (payload?.exception?.message) deps.runtime.error?.("receive exception");
|
|
1240
1106
|
const envelope = payload?.envelope;
|
|
1241
1107
|
if (!envelope) return;
|
|
1242
1108
|
const sender = resolveSignalSender(envelope);
|
|
@@ -1276,15 +1142,70 @@ function createSignalEventHandler(deps) {
|
|
|
1276
1142
|
});
|
|
1277
1143
|
if (quoteText && !visibleQuoteText && isGroup) logVerbose(`signal: drop quote context (mode=${contextVisibilityMode}, sender_allowed=${quoteSenderAllowed ? "yes" : "no"})`);
|
|
1278
1144
|
const hasBodyContent = Boolean(messageText || visibleQuoteText) || Boolean(!reaction && dataMessage?.attachments?.length);
|
|
1279
|
-
if (reaction &&
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
reaction
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1145
|
+
if (reaction && !hasBodyContent) {
|
|
1146
|
+
if (reaction.isRemove) return;
|
|
1147
|
+
const emojiLabel = normalizeOptionalString(reaction.emoji) ?? "emoji";
|
|
1148
|
+
const reactionSenderName = envelope.sourceName ?? senderDisplay;
|
|
1149
|
+
const reactionGroupId = reaction.groupInfo?.groupId ?? void 0;
|
|
1150
|
+
const reactionGroupName = reaction.groupInfo?.groupName ?? void 0;
|
|
1151
|
+
const isReactionGroup = Boolean(reactionGroupId);
|
|
1152
|
+
const reactionMessageId = reaction.targetSentTimestamp ? String(reaction.targetSentTimestamp) : "unknown";
|
|
1153
|
+
const conversationKey = resolveSignalApprovalConversationKey(reactionGroupId ? `group:${reactionGroupId}` : `signal:${resolveSignalRecipient(sender)}`);
|
|
1154
|
+
if (conversationKey && await maybeResolveSignalApprovalReaction({
|
|
1155
|
+
cfg,
|
|
1156
|
+
accountId: deps.accountId,
|
|
1157
|
+
conversationKey,
|
|
1158
|
+
messageId: reactionMessageId,
|
|
1159
|
+
reactionKey: emojiLabel,
|
|
1160
|
+
actorId: formatSignalSenderId(sender),
|
|
1161
|
+
targetAuthor: reaction.targetAuthor,
|
|
1162
|
+
targetAuthorUuid: reaction.targetAuthorUuid,
|
|
1163
|
+
logVerboseMessage: logVerbose
|
|
1164
|
+
})) return;
|
|
1165
|
+
if (senderAccess.decision !== "allow") {
|
|
1166
|
+
logVerbose(`Blocked signal reaction sender ${senderDisplay} (${senderAccess.reasonCode})`);
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const targets = resolveSignalReactionTargets(reaction);
|
|
1170
|
+
if (!shouldEmitSignalReactionNotification({
|
|
1171
|
+
mode: deps.reactionMode,
|
|
1172
|
+
account: deps.account,
|
|
1173
|
+
accountUuid: deps.accountUuid,
|
|
1174
|
+
targets,
|
|
1175
|
+
sender,
|
|
1176
|
+
allowlist: deps.reactionAllowlist
|
|
1177
|
+
})) return;
|
|
1178
|
+
const reactionSenderPeerId = resolveSignalPeerId(sender);
|
|
1179
|
+
const reactionRoute = resolveSignalInboundRoute({
|
|
1180
|
+
cfg,
|
|
1181
|
+
accountId: deps.accountId,
|
|
1182
|
+
isGroup: isReactionGroup,
|
|
1183
|
+
groupId: reactionGroupId,
|
|
1184
|
+
senderPeerId: reactionSenderPeerId
|
|
1185
|
+
});
|
|
1186
|
+
const groupLabel = isReactionGroup ? `${reactionGroupName ?? "Signal Group"} id:${reactionGroupId}` : void 0;
|
|
1187
|
+
const text = buildSignalReactionSystemEventText({
|
|
1188
|
+
emojiLabel,
|
|
1189
|
+
actorLabel: reactionSenderName,
|
|
1190
|
+
messageId: reactionMessageId,
|
|
1191
|
+
targetLabel: targets[0]?.display,
|
|
1192
|
+
groupLabel
|
|
1193
|
+
});
|
|
1194
|
+
const contextKey = [
|
|
1195
|
+
"signal",
|
|
1196
|
+
"reaction",
|
|
1197
|
+
"added",
|
|
1198
|
+
reactionMessageId,
|
|
1199
|
+
formatSignalSenderId(sender),
|
|
1200
|
+
emojiLabel,
|
|
1201
|
+
reactionGroupId ?? ""
|
|
1202
|
+
].filter(Boolean).join(":");
|
|
1203
|
+
enqueueSystemEvent(text, {
|
|
1204
|
+
sessionKey: reactionRoute.sessionKey,
|
|
1205
|
+
contextKey
|
|
1206
|
+
});
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1288
1209
|
if (!dataMessage) return;
|
|
1289
1210
|
const senderRecipient = resolveSignalRecipient(sender);
|
|
1290
1211
|
const senderPeerId = resolveSignalPeerId(sender);
|
|
@@ -1462,9 +1383,9 @@ function createSignalEventHandler(deps) {
|
|
|
1462
1383
|
kind: kindFromMime(contentType) ?? "unknown"
|
|
1463
1384
|
};
|
|
1464
1385
|
} else unavailableAttachmentCount += 1;
|
|
1465
|
-
} catch
|
|
1386
|
+
} catch {
|
|
1466
1387
|
unavailableAttachmentCount += 1;
|
|
1467
|
-
deps.runtime.error?.(danger(
|
|
1388
|
+
deps.runtime.error?.(danger("attachment fetch failed"));
|
|
1468
1389
|
}
|
|
1469
1390
|
}
|
|
1470
1391
|
let bodyText = messageText;
|
|
@@ -1517,7 +1438,6 @@ function createSignalEventHandler(deps) {
|
|
|
1517
1438
|
media: mediaFacts,
|
|
1518
1439
|
commandAuthorized,
|
|
1519
1440
|
canDetectMention,
|
|
1520
|
-
requireMention,
|
|
1521
1441
|
wasMentioned: effectiveWasMentioned,
|
|
1522
1442
|
replyToBody: visibleQuoteText || void 0,
|
|
1523
1443
|
replyToSender: visibleQuoteSender,
|
|
@@ -1643,14 +1563,6 @@ const DEFAULT_RECONNECT_POLICY = {
|
|
|
1643
1563
|
factor: 2,
|
|
1644
1564
|
jitter: .2
|
|
1645
1565
|
};
|
|
1646
|
-
function isPermanentSignalSseRejection(error) {
|
|
1647
|
-
if (!(error instanceof SignalSseRejectionError)) return false;
|
|
1648
|
-
return error.status >= 400 && error.status < 500 && ![
|
|
1649
|
-
408,
|
|
1650
|
-
425,
|
|
1651
|
-
429
|
|
1652
|
-
].includes(error.status);
|
|
1653
|
-
}
|
|
1654
1566
|
function publishSignalRecovering(statusSink, lastError) {
|
|
1655
1567
|
statusSink?.({
|
|
1656
1568
|
connected: false,
|
|
@@ -1664,6 +1576,7 @@ async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEven
|
|
|
1664
1576
|
...policy
|
|
1665
1577
|
};
|
|
1666
1578
|
let reconnectAttempts = 0;
|
|
1579
|
+
let lastEventId;
|
|
1667
1580
|
for (;;) {
|
|
1668
1581
|
if (abortSignal?.aborted) break;
|
|
1669
1582
|
let lastError;
|
|
@@ -1674,12 +1587,14 @@ async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEven
|
|
|
1674
1587
|
abortSignal,
|
|
1675
1588
|
timeoutMs,
|
|
1676
1589
|
transportKind,
|
|
1590
|
+
...lastEventId ? { lastEventId } : {},
|
|
1677
1591
|
onStreamOpen: () => {
|
|
1678
1592
|
statusSink?.(channelReadyPatch());
|
|
1679
1593
|
},
|
|
1680
1594
|
onEvent: async (event) => {
|
|
1681
1595
|
reconnectAttempts = 0;
|
|
1682
1596
|
await onEvent(event);
|
|
1597
|
+
if (event.id !== void 0) lastEventId = event.id || void 0;
|
|
1683
1598
|
},
|
|
1684
1599
|
logger: {
|
|
1685
1600
|
log: runtime.log,
|
|
@@ -1691,7 +1606,11 @@ async function runSignalSseLoop({ baseUrl, account, abortSignal, runtime, onEven
|
|
|
1691
1606
|
} catch (err) {
|
|
1692
1607
|
if (abortSignal?.aborted) return;
|
|
1693
1608
|
runtime.error?.(`Signal stream error: ${String(err)}`);
|
|
1694
|
-
if (
|
|
1609
|
+
if (err instanceof SignalSseRejectionError && err.status >= 400 && err.status < 500 && ![
|
|
1610
|
+
408,
|
|
1611
|
+
425,
|
|
1612
|
+
429
|
|
1613
|
+
].includes(err.status)) {
|
|
1695
1614
|
lastError = `Signal daemon rejected the event stream: ${err.message}. Check the configured account and daemon URL, fix the daemon or proxy response, then restart the channel.`;
|
|
1696
1615
|
runtime.log?.(`Signal reconnect stopped: ${lastError}`);
|
|
1697
1616
|
statusSink?.(channelBlockedPatch(lastError, { connected: false }));
|
|
@@ -1739,36 +1658,6 @@ function deriveSignalAttachmentRpcMaxResponseBytes(maxBytes) {
|
|
|
1739
1658
|
if (!Number.isFinite(maxBytes) || maxBytes <= 0) return;
|
|
1740
1659
|
return Math.ceil(maxBytes * SIGNAL_BASE64_OVERHEAD_NUMERATOR / SIGNAL_BASE64_OVERHEAD_DENOMINATOR) + SIGNAL_ATTACHMENT_RPC_RESPONSE_HEADROOM_BYTES;
|
|
1741
1660
|
}
|
|
1742
|
-
async function fetchAttachment(params) {
|
|
1743
|
-
const { attachment } = params;
|
|
1744
|
-
if (!attachment?.id) return null;
|
|
1745
|
-
if (typeof attachment.size === "number" && attachment.size > params.maxBytes) throw new Error(`Signal attachment ${attachment.id} exceeds ${(params.maxBytes / 1048576).toFixed(0)}MB limit`);
|
|
1746
|
-
const rpcParams = { id: attachment.id };
|
|
1747
|
-
if (params.account) rpcParams.account = params.account;
|
|
1748
|
-
if (params.groupId) rpcParams.groupId = params.groupId;
|
|
1749
|
-
else if (params.sender) rpcParams.recipient = params.sender;
|
|
1750
|
-
else return null;
|
|
1751
|
-
const result = await signalRpcRequest("getAttachment", rpcParams, {
|
|
1752
|
-
baseUrl: params.baseUrl,
|
|
1753
|
-
maxResponseBytes: deriveSignalAttachmentRpcMaxResponseBytes(params.maxBytes),
|
|
1754
|
-
transportKind: params.transportKind
|
|
1755
|
-
});
|
|
1756
|
-
if (!result?.data) return null;
|
|
1757
|
-
if (estimateBase64DecodedBytes(result.data) > params.maxBytes) throw new Error(`Signal attachment ${attachment.id} exceeds ${(params.maxBytes / 1048576).toFixed(0)}MB limit`);
|
|
1758
|
-
const canonicalData = canonicalizeBase64(result.data);
|
|
1759
|
-
if (!canonicalData) throw new Error(`Signal attachment ${attachment.id} returned malformed base64 data`);
|
|
1760
|
-
const buffer = Buffer.from(canonicalData, "base64");
|
|
1761
|
-
const originalFilename = normalizeOptionalString(attachment.filename ?? void 0);
|
|
1762
|
-
const contentType = normalizeOptionalString(attachment.contentType ?? void 0) ?? await detectMime({
|
|
1763
|
-
buffer,
|
|
1764
|
-
filePath: originalFilename
|
|
1765
|
-
});
|
|
1766
|
-
const saved = await saveMediaBuffer(buffer, contentType, "inbound", params.maxBytes, originalFilename);
|
|
1767
|
-
return {
|
|
1768
|
-
path: saved.path,
|
|
1769
|
-
contentType: saved.contentType
|
|
1770
|
-
};
|
|
1771
|
-
}
|
|
1772
1661
|
async function deliverReplies(params) {
|
|
1773
1662
|
const { replies, target, baseUrl, account, accountUuid, accountId, runtime, maxBytes, textLimit, chunkMode } = params;
|
|
1774
1663
|
const replyToMode = resolveSignalReplyToMode({
|
|
@@ -1826,7 +1715,7 @@ async function deliverReplies(params) {
|
|
|
1826
1715
|
sendText: send,
|
|
1827
1716
|
sendMedia: ({ mediaUrl, caption }) => send(caption ?? "", mediaUrl)
|
|
1828
1717
|
}) !== "empty") {
|
|
1829
|
-
await
|
|
1718
|
+
await registerSignalApprovalReactionTargetForDeliveredPayload({
|
|
1830
1719
|
cfg: params.cfg,
|
|
1831
1720
|
target: {
|
|
1832
1721
|
channel: "signal",
|
|
@@ -1883,9 +1772,16 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1883
1772
|
const autoStart = Boolean(managedTransport) && (opts.autoStart ?? true);
|
|
1884
1773
|
const startupTimeoutMs = Math.min(12e4, Math.max(1e3, opts.startupTimeoutMs ?? managedTransport?.startupTimeoutMs ?? 3e4));
|
|
1885
1774
|
const readReceiptsViaDaemon = autoStart && sendReadReceipts;
|
|
1886
|
-
const
|
|
1775
|
+
const callerAbortSignal = opts.abortSignal;
|
|
1776
|
+
let daemonExitError;
|
|
1777
|
+
const daemonAbortController = new AbortController();
|
|
1778
|
+
const abortSignal = callerAbortSignal ? AbortSignal.any([callerAbortSignal, daemonAbortController.signal]) : daemonAbortController.signal;
|
|
1887
1779
|
const monitorTaskRunner = createSignalMonitorTaskRunner(runtime);
|
|
1888
1780
|
let daemonHandle = null;
|
|
1781
|
+
const stopDaemon = () => {
|
|
1782
|
+
daemonAbortController.abort(callerAbortSignal?.reason ?? /* @__PURE__ */ new Error("Signal monitor stopped"));
|
|
1783
|
+
return daemonHandle?.stop() ?? Promise.resolve();
|
|
1784
|
+
};
|
|
1889
1785
|
let ingressMonitor;
|
|
1890
1786
|
const startupDeadline = Date.now() + startupTimeoutMs;
|
|
1891
1787
|
if (autoStart) {
|
|
@@ -1922,20 +1818,23 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1922
1818
|
sendReadReceipts,
|
|
1923
1819
|
runtime
|
|
1924
1820
|
});
|
|
1925
|
-
|
|
1821
|
+
daemonHandle.exited.then((exit) => {
|
|
1822
|
+
if (abortSignal.aborted) return;
|
|
1823
|
+
daemonExitError = new Error(formatSignalDaemonExit(exit));
|
|
1824
|
+
daemonAbortController.abort(daemonExitError);
|
|
1825
|
+
});
|
|
1926
1826
|
}
|
|
1927
|
-
const onAbort = () => void
|
|
1827
|
+
const onAbort = () => void stopDaemon();
|
|
1928
1828
|
opts.abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
1929
1829
|
try {
|
|
1930
1830
|
if (daemonHandle) {
|
|
1931
1831
|
await waitForSignalDaemonReady({
|
|
1932
1832
|
baseUrl,
|
|
1933
|
-
abortSignal
|
|
1833
|
+
abortSignal,
|
|
1934
1834
|
startupDeadlineMs: startupDeadline,
|
|
1935
1835
|
runtime,
|
|
1936
1836
|
waitForTransportReadyFn
|
|
1937
1837
|
});
|
|
1938
|
-
const daemonExitError = daemonLifecycle.getExitError();
|
|
1939
1838
|
if (daemonExitError) throw daemonExitError;
|
|
1940
1839
|
}
|
|
1941
1840
|
registerChannelRuntimeContext({
|
|
@@ -1957,7 +1856,7 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1957
1856
|
const handleEvent = createSignalEventHandler({
|
|
1958
1857
|
runtime,
|
|
1959
1858
|
channelRuntime: opts.channelRuntime,
|
|
1960
|
-
abortSignal
|
|
1859
|
+
abortSignal,
|
|
1961
1860
|
runTrackedTask: (task) => {
|
|
1962
1861
|
monitorTaskRunner.runTask(task);
|
|
1963
1862
|
},
|
|
@@ -1980,10 +1879,40 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1980
1879
|
ignoreAttachments,
|
|
1981
1880
|
sendReadReceipts,
|
|
1982
1881
|
readReceiptsViaDaemon,
|
|
1983
|
-
fetchAttachment: (
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1882
|
+
fetchAttachment: async (attachmentInput) => {
|
|
1883
|
+
const params = {
|
|
1884
|
+
...attachmentInput,
|
|
1885
|
+
transportKind
|
|
1886
|
+
};
|
|
1887
|
+
const { attachment } = params;
|
|
1888
|
+
if (!attachment?.id) return null;
|
|
1889
|
+
if (typeof attachment.size === "number" && attachment.size > params.maxBytes) throw new Error(`Signal attachment ${attachment.id} exceeds ${(params.maxBytes / 1048576).toFixed(0)}MB limit`);
|
|
1890
|
+
const rpcParams = { id: attachment.id };
|
|
1891
|
+
if (params.account) rpcParams.account = params.account;
|
|
1892
|
+
if (params.groupId) rpcParams.groupId = params.groupId;
|
|
1893
|
+
else if (params.sender) rpcParams.recipient = params.sender;
|
|
1894
|
+
else return null;
|
|
1895
|
+
const result = await signalRpcRequest("getAttachment", rpcParams, {
|
|
1896
|
+
baseUrl: params.baseUrl,
|
|
1897
|
+
maxResponseBytes: deriveSignalAttachmentRpcMaxResponseBytes(params.maxBytes),
|
|
1898
|
+
transportKind: params.transportKind
|
|
1899
|
+
});
|
|
1900
|
+
if (!result?.data) return null;
|
|
1901
|
+
if (estimateBase64DecodedBytes(result.data) > params.maxBytes) throw new Error(`Signal attachment ${attachment.id} exceeds ${(params.maxBytes / 1048576).toFixed(0)}MB limit`);
|
|
1902
|
+
const canonicalData = canonicalizeBase64(result.data);
|
|
1903
|
+
if (!canonicalData) throw new Error(`Signal attachment ${attachment.id} returned malformed base64 data`);
|
|
1904
|
+
const buffer = Buffer.from(canonicalData, "base64");
|
|
1905
|
+
const originalFilename = normalizeOptionalString(attachment.filename ?? void 0);
|
|
1906
|
+
const contentType = normalizeOptionalString(attachment.contentType ?? void 0) ?? await detectMime({
|
|
1907
|
+
buffer,
|
|
1908
|
+
filePath: originalFilename
|
|
1909
|
+
});
|
|
1910
|
+
const saved = await saveMediaBuffer(buffer, contentType, "inbound", params.maxBytes, originalFilename);
|
|
1911
|
+
return {
|
|
1912
|
+
path: saved.path,
|
|
1913
|
+
contentType: saved.contentType
|
|
1914
|
+
};
|
|
1915
|
+
},
|
|
1987
1916
|
deliverReplies: (params) => deliverReplies({
|
|
1988
1917
|
...params,
|
|
1989
1918
|
cfg,
|
|
@@ -1998,7 +1927,7 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
1998
1927
|
await runSignalSseLoop({
|
|
1999
1928
|
baseUrl,
|
|
2000
1929
|
account,
|
|
2001
|
-
abortSignal
|
|
1930
|
+
abortSignal,
|
|
2002
1931
|
runtime,
|
|
2003
1932
|
timeoutMs: 0,
|
|
2004
1933
|
transportKind,
|
|
@@ -2006,16 +1935,14 @@ async function monitorSignalProvider(opts = {}) {
|
|
|
2006
1935
|
statusSink: opts.statusSink,
|
|
2007
1936
|
onEvent: (event) => monitorTaskRunner.runTask(async () => await ingressMonitor?.receive(event))
|
|
2008
1937
|
});
|
|
2009
|
-
const daemonExitError = daemonLifecycle.getExitError();
|
|
2010
1938
|
if (daemonExitError) throw daemonExitError;
|
|
2011
1939
|
} catch (err) {
|
|
2012
|
-
const daemonExitError = daemonLifecycle.getExitError();
|
|
2013
1940
|
if (opts.abortSignal?.aborted && !daemonExitError) return;
|
|
2014
1941
|
if (daemonExitError) publishSignalRecovering(opts.statusSink, daemonExitError.message);
|
|
2015
1942
|
throw err;
|
|
2016
1943
|
} finally {
|
|
2017
1944
|
await ingressMonitor?.stop();
|
|
2018
|
-
await Promise.all([
|
|
1945
|
+
await Promise.all([stopDaemon(), monitorTaskRunner.waitForIdle()]);
|
|
2019
1946
|
opts.abortSignal?.removeEventListener("abort", onAbort);
|
|
2020
1947
|
}
|
|
2021
1948
|
}
|