@openclaw/signal 2026.9.2 → 2026.9.4

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.
Files changed (28) hide show
  1. package/dist/api.js +7 -7
  2. package/dist/{approval-handler.runtime-Dsg_GE8N.js → approval-handler.runtime-DCPJkIqo.js} +2 -2
  3. package/dist/{approval-reactions-D-nkbsvm.js → approval-reactions-CjhdkJ8P.js} +24 -53
  4. package/dist/{channel-B-A_5_Vz.js → channel-CyQvEuyA.js} +28 -27
  5. package/dist/channel-config-api.js +1 -1
  6. package/dist/channel-plugin-api.js +1 -1
  7. package/dist/{channel.runtime-LfE0qPMj.js → channel.runtime--koF_1H0.js} +3 -3
  8. package/dist/{client-BmpTN7R3.js → client-B3C0ciqU.js} +6 -1
  9. package/dist/{client-adapter-CDyW9LrQ.js → client-adapter-CNc5wzzs.js} +1 -1
  10. package/dist/{config-schema-CHihQTOp.js → config-schema-DfEbpMVQ.js} +10 -37
  11. package/dist/contract-api.js +1 -1
  12. package/dist/{doctor-contract-api-C18u1hW0.js → doctor-contract-api-D0SnglP4.js} +40 -78
  13. package/dist/doctor-contract-api.js +1 -1
  14. package/dist/{monitor-D7Slr0-A.js → monitor-BiNWxMB3.js} +40 -77
  15. package/dist/{probe-CtO2EIfg.js → probe-kOJqyjWz.js} +3 -3
  16. package/dist/{question-reactions-CsVOpHg_.js → question-reactions-BFR9Mf-O.js} +2 -2
  17. package/dist/{reaction-runtime-api-7FQFT_qb.js → reaction-runtime-api-CWqDv5-q.js} +1 -1
  18. package/dist/reaction-runtime-api.js +1 -1
  19. package/dist/{rolldown-runtime-D7D4PA-g.js → rolldown-runtime-8H4AJuhK.js} +1 -0
  20. package/dist/runtime-api.js +7 -7
  21. package/dist/{send-DuH2ntJt.js → send-Bz0x0JC1.js} +2 -2
  22. package/dist/{send.runtime-BLiqhyHW.js → send.runtime-CeV1p7Sq.js} +1 -1
  23. package/dist/{transport-detection-BcDiypLn.js → transport-detection-Do2pYMAH.js} +4 -3
  24. package/dist/{transport-detection.runtime-DYuvIa7s.js → transport-detection.runtime-QasZp3BE.js} +1 -1
  25. package/dist/{transport-probes.runtime-B7kr_6Zu.js → transport-probes.runtime-DV7x4VWu.js} +1 -1
  26. package/openclaw.plugin.json +3 -0
  27. package/package.json +4 -4
  28. package/dist/{install-signal-cli-7tEL37_j.js → install-signal-cli-QlEIfWBv.js} +1 -1
package/dist/api.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-DO4HMqaK.js";
2
2
  import { n as normalizeSignalMessagingTarget, t as looksLikeSignalTargetId } from "./normalize-l_b99hap.js";
3
3
  import { a as normalizeSignalAllowRecipient, c as resolveSignalSender, i as isSignalSenderAllowed, l as looksLikeUuid, n as formatSignalSenderDisplay, o as resolveSignalPeerId, r as formatSignalSenderId, s as resolveSignalRecipient, t as formatSignalPairingIdLine } from "./identity-YXPmgFMu.js";
4
- import { c as resolveSignalReactionLevel, d as markdownToSignalTextChunks, s as signalMessageActions, t as detectSignalTransport, u as markdownToSignalText } from "./transport-detection-BcDiypLn.js";
5
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-7FQFT_qb.js";
6
- import { a as normalizeSignalAccountInput, d as probeSignalTransport, f as writeSignalAccountTransport, l as signalSetupContract, n as createSignalPluginBase, p as resolveSignalOutboundTarget, r as signalSetupWizard, t as signalPlugin, u as prepareSignalManagedNativeTransport } from "./channel-B-A_5_Vz.js";
7
- import { i as installSignalCli } from "./install-signal-cli-7tEL37_j.js";
8
- import { t as monitorSignalProvider } from "./monitor-D7Slr0-A.js";
9
- import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-DuH2ntJt.js";
10
- import { t as probeSignal } from "./probe-CtO2EIfg.js";
4
+ import { c as resolveSignalReactionLevel, d as markdownToSignalTextChunks, s as signalMessageActions, t as detectSignalTransport, u as markdownToSignalText } from "./transport-detection-Do2pYMAH.js";
5
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-CWqDv5-q.js";
6
+ import { a as normalizeSignalAccountInput, d as probeSignalTransport, f as writeSignalAccountTransport, l as signalSetupContract, n as createSignalPluginBase, p as resolveSignalOutboundTarget, r as signalSetupWizard, t as signalPlugin, u as prepareSignalManagedNativeTransport } from "./channel-CyQvEuyA.js";
7
+ import { i as installSignalCli } from "./install-signal-cli-QlEIfWBv.js";
8
+ import { t as monitorSignalProvider } from "./monitor-BiNWxMB3.js";
9
+ import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-Bz0x0JC1.js";
10
+ import { t as probeSignal } from "./probe-kOJqyjWz.js";
11
11
  //#region extensions/signal/src/channel.setup.ts
12
12
  const signalSetupPlugin = { ...createSignalPluginBase({
13
13
  setupWizard: signalSetupWizard,
@@ -1,8 +1,8 @@
1
1
  import { r as resolveDefaultSignalAccountId } from "./accounts-DO4HMqaK.js";
2
2
  import { n as normalizeSignalMessagingTarget } from "./normalize-l_b99hap.js";
3
3
  import { a as resolveSignalTarget } from "./approval-auth-pNCKKotV.js";
4
- import { a as registerSignalApprovalReactionTarget, c as resolveSignalApprovalTargetAuthorKeys, l as unregisterSignalApprovalReactionTarget, r as hasSignalApprovalReactionApprovers, s as resolveSignalApprovalConversationKey } from "./approval-reactions-D-nkbsvm.js";
5
- import { r as sendTypingSignal, t as sendMessageSignal } from "./send-DuH2ntJt.js";
4
+ import { a as registerSignalApprovalReactionTarget, c as resolveSignalApprovalTargetAuthorKeys, l as unregisterSignalApprovalReactionTarget, r as hasSignalApprovalReactionApprovers, s as resolveSignalApprovalConversationKey } from "./approval-reactions-CjhdkJ8P.js";
5
+ import { r as sendTypingSignal, t as sendMessageSignal } from "./send-Bz0x0JC1.js";
6
6
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
7
7
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
@@ -1,14 +1,13 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
1
+ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { n as normalizeSignalMessagingTarget } from "./normalize-l_b99hap.js";
3
3
  import { a as resolveSignalTarget, i as resolveSignalDeliveredConversationKey, n as signalApprovalAuth, t as getSignalApprovalApprovers } from "./approval-auth-pNCKKotV.js";
4
4
  import { l as looksLikeUuid } from "./identity-YXPmgFMu.js";
5
- import { i as getOptionalSignalRuntime } from "./transport-detection-BcDiypLn.js";
5
+ import { i as getOptionalSignalRuntime } from "./transport-detection-Do2pYMAH.js";
6
6
  import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
7
7
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
8
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
- import { addApprovalReactionHintToText, createApprovalReactionTargetStore, hasApprovalReactionHintText, listApprovalReactionBindings, readApprovalReactionDecisionList, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
9
+ import { addApprovalReactionHintToText, createApprovalReactionTargetStore, hasApprovalReactionHintText, listApprovalReactionBindings, readApprovalReactionTargetRecord, resolveTypedApprovalReactionTarget, settleApprovalReaction } from "openclaw/plugin-sdk/approval-reaction-runtime";
10
10
  import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
11
- import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
12
11
  import { getExecApprovalReplyMetadata } from "openclaw/plugin-sdk/approval-reply-runtime";
13
12
  import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
14
13
  import { matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
@@ -165,10 +164,9 @@ function buildReactionTargetKey(params) {
165
164
  return `${accountId}:${conversationKey}:${messageId}`;
166
165
  }
167
166
  function readPersistedTarget(target) {
167
+ const record = readApprovalReactionTargetRecord(target);
168
168
  const value = target;
169
- if (!value || typeof value.approvalId !== "string" || value.approvalKind !== "exec" && value.approvalKind !== "plugin" || !value.route || value.route.deliveryMode !== "session" && value.route.deliveryMode !== "target" || !Array.isArray(value.targetAuthorKeys)) return null;
170
- const allowedDecisions = readApprovalReactionDecisionList(value.allowedDecisions);
171
- if (!allowedDecisions) return null;
169
+ if (!record || !value?.route || value.route.deliveryMode !== "session" && value.route.deliveryMode !== "target" || !Array.isArray(value.targetAuthorKeys)) return null;
172
170
  const targetRouteTo = value.route.deliveryMode === "target" && typeof value.route.to === "string" ? normalizeSignalMessagingTarget(value.route.to) : null;
173
171
  if (value.route.deliveryMode === "target" && !targetRouteTo) return null;
174
172
  const route = value.route.deliveryMode === "target" ? {
@@ -183,9 +181,7 @@ function readPersistedTarget(target) {
183
181
  ...typeof value.route.sessionKey === "string" ? { sessionKey: value.route.sessionKey } : {}
184
182
  };
185
183
  return {
186
- approvalId: value.approvalId,
187
- approvalKind: value.approvalKind,
188
- allowedDecisions,
184
+ ...record,
189
185
  targetAuthorKeys: value.targetAuthorKeys,
190
186
  route
191
187
  };
@@ -359,26 +355,8 @@ async function maybeResolveSignalApprovalReaction(params) {
359
355
  params.logVerboseMessage?.(`signal: approval reaction ignored for ${target.approvalId}; missing actor identity`);
360
356
  return true;
361
357
  }
362
- if (getSignalApprovalApprovers({
363
- cfg: params.cfg,
364
- accountId: params.accountId
365
- }).length === 0) {
366
- params.logVerboseMessage?.(`signal: approval reaction denied id=${target.approvalId}; reactions require explicit approvers`);
367
- return true;
368
- }
369
- if (!signalApprovalAuth.authorizeActorAction({
370
- cfg: params.cfg,
371
- accountId: params.accountId,
372
- senderId: actorId,
373
- action: "approve",
374
- approvalKind: target.approvalKind
375
- }).authorized) {
376
- params.logVerboseMessage?.(`signal: approval reaction denied id=${target.approvalId} sender=${actorId}`);
377
- return true;
378
- }
379
- const resolveApprovalOverGateway = await loadResolveApprovalOverGateway();
380
- try {
381
- const result = await resolveApprovalOverGateway({
358
+ await settleApprovalReaction({
359
+ request: {
382
360
  cfg: params.cfg,
383
361
  approvalId: target.approvalId,
384
362
  approvalKind: target.approvalKind,
@@ -387,32 +365,25 @@ async function maybeResolveSignalApprovalReaction(params) {
387
365
  accountId: params.accountId,
388
366
  senderId: actorId,
389
367
  gatewayUrl: params.gatewayUrl
390
- });
391
- const terminalTruth = formatSignalApprovalTerminalTruth(result.approval);
392
- unregisterSignalApprovalReactionTarget({
368
+ },
369
+ approvers: getSignalApprovalApprovers({
370
+ cfg: params.cfg,
371
+ accountId: params.accountId
372
+ }),
373
+ authorizeActorAction: (input) => signalApprovalAuth.authorizeActorAction(input),
374
+ loadResolver: loadResolveApprovalOverGateway,
375
+ clearTarget: () => unregisterSignalApprovalReactionTarget({
393
376
  accountId: params.accountId,
394
377
  conversationKey: params.conversationKey,
395
378
  messageId: params.messageId
396
- });
397
- if (!result.applied) {
398
- params.logVerboseMessage?.(`signal: approval reaction already resolved id=${target.approvalId} sender=${actorId} ${terminalTruth}`);
399
- return true;
400
- }
401
- params.logVerboseMessage?.(`signal: approval reaction resolved id=${target.approvalId} sender=${actorId} ${terminalTruth}`);
402
- return true;
403
- } catch (error) {
404
- if (isApprovalNotFoundError(error)) {
405
- unregisterSignalApprovalReactionTarget({
406
- accountId: params.accountId,
407
- conversationKey: params.conversationKey,
408
- messageId: params.messageId
409
- });
410
- params.logVerboseMessage?.(`signal: approval reaction ignored for expired approval id=${target.approvalId} sender=${actorId}`);
411
- return true;
412
- }
413
- params.logVerboseMessage?.(`signal: approval reaction failed id=${target.approvalId} sender=${actorId}: ${String(error)}`);
414
- throw error;
415
- }
379
+ }),
380
+ onResolved: (result) => {
381
+ const outcome = result.applied ? "resolved" : "already resolved";
382
+ params.logVerboseMessage?.(`signal: approval reaction ${outcome} id=${target.approvalId} sender=${actorId} ${formatSignalApprovalTerminalTruth(result.approval)}`);
383
+ },
384
+ logVerboseMessage: params.logVerboseMessage
385
+ });
386
+ return true;
416
387
  }
417
388
  function clearSignalApprovalReactionTargetsForTest() {
418
389
  signalApprovalReactionTargets.clearForTest();
@@ -3,9 +3,9 @@ import { a as resolveSignalAccountConfig, i as resolveSignalAccount, n as listSi
3
3
  import { n as normalizeSignalMessagingTarget, t as looksLikeSignalTargetId } from "./normalize-l_b99hap.js";
4
4
  import { a as resolveSignalTarget, r as listSignalAliasDirectoryEntries } from "./approval-auth-pNCKKotV.js";
5
5
  import { c as resolveSignalSender, l as looksLikeUuid, o as resolveSignalPeerId, s as resolveSignalRecipient } from "./identity-YXPmgFMu.js";
6
- import { c as resolveSignalReactionLevel, d as markdownToSignalTextChunks, l as formatSignalMediaText, m as signalApprovalCapability, o as materializeSignalPresentationFallback, p as shouldSuppressLocalSignalExecApprovalPrompt, r as resolveSignalReplyContextWithPersistence, s as signalMessageActions, t as detectSignalTransport } from "./transport-detection-BcDiypLn.js";
7
- import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-C18u1hW0.js";
8
- import { t as SignalChannelConfigSchema } from "./config-schema-CHihQTOp.js";
6
+ import { c as resolveSignalReactionLevel, d as markdownToSignalTextChunks, l as formatSignalMediaText, m as signalApprovalCapability, o as materializeSignalPresentationFallback, p as shouldSuppressLocalSignalExecApprovalPrompt, r as resolveSignalReplyContextWithPersistence, s as signalMessageActions, t as detectSignalTransport } from "./transport-detection-Do2pYMAH.js";
7
+ import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-D0SnglP4.js";
8
+ import { t as SignalChannelConfigSchema } from "./config-schema-DfEbpMVQ.js";
9
9
  import { describeAccountSnapshot, resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/account-helpers";
10
10
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
11
11
  import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
@@ -28,7 +28,8 @@ import { createChannelPluginBase, getChatChannelMeta } from "openclaw/plugin-sdk
28
28
  import { parseAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
29
29
  import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
30
30
  import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
31
- import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2, createCliPathTextInput, createDelegatedSetupWizardProxy, createDelegatedTextInputShouldPrompt, createPatchedAccountSetupAdapter, createSetupInputPresenceValidator, createSetupTranslator, patchChannelConfigForAccount, promptParsedAllowFromForAccount, setAccountAllowFromForChannel, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
31
+ import { patchTopLevelChannelConfigSection } from "openclaw/plugin-sdk/setup";
32
+ import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2, createCliPathTextInput, createDelegatedSetupWizardProxy, createDelegatedTextInputShouldPrompt, createPatchedAccountSetupAdapter, createSetupInputPresenceValidator, createSetupTranslator as createSetupTranslator$1, patchChannelConfigForAccount, promptParsedAllowFromForAccount, setAccountAllowFromForChannel, setSetupChannelEnabled as setSetupChannelEnabled$1 } from "openclaw/plugin-sdk/setup-runtime";
32
33
  import { formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
33
34
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
34
35
  import { createRestrictSendersChannelSecurity } from "openclaw/plugin-sdk/channel-policy";
@@ -214,8 +215,8 @@ async function probeSignalTransport(params) {
214
215
  overrides: managedTransportOptions(params.transport)
215
216
  }) : params.transport;
216
217
  const resolved = resolveSignalTransport(transport);
217
- if (resolved.kind === "container") return (params.probeContainer ?? (await import("./transport-probes.runtime-B7kr_6Zu.js")).containerCheck)(resolved.baseUrl, timeoutMs, params.account);
218
- return (params.probeNative ?? (await import("./transport-probes.runtime-B7kr_6Zu.js")).nativeCheck)(resolved.baseUrl, timeoutMs);
218
+ if (resolved.kind === "container") return (params.probeContainer ?? (await import("./transport-probes.runtime-DV7x4VWu.js")).containerCheck)(resolved.baseUrl, timeoutMs, params.account);
219
+ return (params.probeNative ?? (await import("./transport-probes.runtime-DV7x4VWu.js")).nativeCheck)(resolved.baseUrl, timeoutMs);
219
220
  }
220
221
  function writeSignalAccountTransport(params) {
221
222
  const transport = normalizeTransport(params.transport);
@@ -247,7 +248,7 @@ function writeSignalAccountTransport(params) {
247
248
  }
248
249
  //#endregion
249
250
  //#region extensions/signal/src/setup-core.ts
250
- const t = createSetupTranslator();
251
+ const t = createSetupTranslator$1();
251
252
  const channel = "signal";
252
253
  const signalSetupFields = {
253
254
  signalNumber: {
@@ -484,17 +485,14 @@ function restorePromotedSignalDefaultAccount(cfg) {
484
485
  const accounts = { ...signal.accounts };
485
486
  if (Object.keys(remainingDefault).length === 0) delete accounts[DEFAULT_ACCOUNT_ID$2];
486
487
  else accounts[DEFAULT_ACCOUNT_ID$2] = remainingDefault;
487
- return {
488
- ...cfg,
489
- channels: {
490
- ...cfg.channels,
491
- signal: {
492
- ...signal,
493
- account,
494
- accounts
495
- }
488
+ return patchTopLevelChannelConfigSection({
489
+ cfg,
490
+ channel,
491
+ patch: {
492
+ account,
493
+ accounts
496
494
  }
497
- };
495
+ });
498
496
  }
499
497
  const signalSetupAdapter = {
500
498
  ...signalSetupAdapterBase,
@@ -564,7 +562,7 @@ function createSignalSetupWizardProxy(loadWizard) {
564
562
  })), signalNumberTextInput],
565
563
  completionNote: signalCompletionNote,
566
564
  dmPolicy: signalDmPolicy,
567
- disable: (cfg) => setSetupChannelEnabled(cfg, channel, false)
565
+ disable: (cfg) => setSetupChannelEnabled$1(cfg, channel, false)
568
566
  });
569
567
  }
570
568
  //#endregion
@@ -572,7 +570,7 @@ function createSignalSetupWizardProxy(loadWizard) {
572
570
  const signalDoctor = {
573
571
  normalizeCompatibilityConfig,
574
572
  cleanStaleConfig: async ({ cfg }) => {
575
- const { detectSignalTransport } = await import("./transport-detection.runtime-DYuvIa7s.js");
573
+ const { detectSignalTransport } = await import("./transport-detection.runtime-QasZp3BE.js");
576
574
  return await migrateLegacySignalTransportConfig({
577
575
  cfg,
578
576
  detect: detectSignalTransport
@@ -583,7 +581,7 @@ const signalDoctor = {
583
581
  //#region extensions/signal/src/shared.ts
584
582
  const SIGNAL_CHANNEL = "signal";
585
583
  async function loadSignalChannelRuntime() {
586
- return await import("./channel.runtime-LfE0qPMj.js");
584
+ return await import("./channel.runtime--koF_1H0.js");
587
585
  }
588
586
  const signalSetupWizard = createSignalSetupWizardProxy(async () => (await loadSignalChannelRuntime()).signalSetupWizard);
589
587
  const signalConfigAdapter = {
@@ -671,10 +669,10 @@ function createSignalPluginBase(params) {
671
669
  }
672
670
  //#endregion
673
671
  //#region extensions/signal/src/channel.ts
674
- const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-D7Slr0-A.js").then((n) => n.n));
675
- const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-CtO2EIfg.js").then((n) => n.n));
676
- const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-BLiqhyHW.js"));
677
- const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-D-nkbsvm.js").then((n) => n.n));
672
+ const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-BiNWxMB3.js").then((n) => n.n));
673
+ const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-kOJqyjWz.js").then((n) => n.n));
674
+ const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-CeV1p7Sq.js"));
675
+ const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-CjhdkJ8P.js").then((n) => n.n));
678
676
  async function resolveSignalSendContext(params) {
679
677
  return {
680
678
  send: resolveOutboundSendDep(params.deps, "signal") ?? (await loadSignalSendRuntime()).sendMessageSignal,
@@ -902,7 +900,7 @@ async function registerDeliveredSignalApprovalPayloadForReactions(params) {
902
900
  const targetAuthor = normalizeOptionalString(account.config.account);
903
901
  const targetAuthorUuid = normalizeOptionalString(account.config.accountUuid);
904
902
  if (!targetAuthor && !targetAuthorUuid) return;
905
- const { registerSignalQuestionReactionTargetForDeliveredPayload } = await import("./question-reactions-CsVOpHg_.js").then((n) => n.n);
903
+ const { registerSignalQuestionReactionTargetForDeliveredPayload } = await import("./question-reactions-BFR9Mf-O.js").then((n) => n.n);
906
904
  registerSignalQuestionReactionTargetForDeliveredPayload({
907
905
  cfg: params.cfg,
908
906
  target: {
@@ -1093,8 +1091,11 @@ const signalPlugin = createChatChannelPlugin({
1093
1091
  idLabel: "signalNumber",
1094
1092
  message: PAIRING_APPROVED_MESSAGE,
1095
1093
  normalizeAllowEntry: createPairingPrefixStripper(/^signal:/i),
1096
- notify: async ({ cfg, id, message }) => {
1097
- await (await loadSignalSendRuntime()).sendMessageSignal(id, message, { cfg });
1094
+ notify: async ({ cfg, id, message, accountId }) => {
1095
+ await (await loadSignalSendRuntime()).sendMessageSignal(id, message, {
1096
+ cfg,
1097
+ accountId
1098
+ });
1098
1099
  }
1099
1100
  } },
1100
1101
  security: signalSecurityAdapter,
@@ -1,2 +1,2 @@
1
- import { t as SignalChannelConfigSchema } from "./config-schema-CHihQTOp.js";
1
+ import { t as SignalChannelConfigSchema } from "./config-schema-DfEbpMVQ.js";
2
2
  export { SignalChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as signalPlugin } from "./channel-B-A_5_Vz.js";
1
+ import { t as signalPlugin } from "./channel-CyQvEuyA.js";
2
2
  export { signalPlugin };
@@ -1,8 +1,8 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-DO4HMqaK.js";
2
- import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-B-A_5_Vz.js";
3
- import { i as installSignalCli } from "./install-signal-cli-7tEL37_j.js";
4
- import { detectBinary } from "openclaw/plugin-sdk/setup-tools";
2
+ import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-CyQvEuyA.js";
3
+ import { i as installSignalCli } from "./install-signal-cli-QlEIfWBv.js";
5
4
  import { createDetectedBinaryStatus, createSetupTranslator, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
5
+ import { detectBinary } from "openclaw/plugin-sdk/setup-tools";
6
6
  //#region extensions/signal/src/setup-surface.ts
7
7
  const t = createSetupTranslator();
8
8
  const channel = "signal";
@@ -1,14 +1,19 @@
1
+ import { createRequire } from "node:module";
1
2
  import { detectMime, extractOriginalFilename, parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
2
3
  import { parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
3
4
  import { coerceErrorMessage, formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
4
5
  import { resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
5
6
  import { readResponseTextPrefix, readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
6
7
  import { readRegularFile } from "openclaw/plugin-sdk/security-runtime";
7
- import WebSocket from "ws";
8
+ import path from "node:path";
8
9
  import { Buffer as Buffer$1 } from "node:buffer";
9
10
  import http from "node:http";
10
11
  import https from "node:https";
11
12
  import { generateSecureUuid } from "openclaw/plugin-sdk/core";
13
+ //#region extensions/signal/src/ws-runtime.ts
14
+ const require = createRequire(import.meta.url);
15
+ const WebSocket = require(path.join(path.dirname(require.resolve("ws/package.json")), "index.js"));
16
+ //#endregion
12
17
  //#region extensions/signal/src/client-container.ts
13
18
  /**
14
19
  * Signal client for bbernhard/signal-cli-rest-api container.
@@ -1,4 +1,4 @@
1
- import { a as containerCheck, i as streamSignalEvents$1, n as signalCheck$1, o as containerRpcRequest, r as signalRpcRequest$1, s as streamContainerEvents } from "./client-BmpTN7R3.js";
1
+ import { a as containerCheck, i as streamSignalEvents$1, n as signalCheck$1, o as containerRpcRequest, r as signalRpcRequest$1, s as streamContainerEvents } from "./client-B3C0ciqU.js";
2
2
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
3
3
  //#region extensions/signal/src/client-adapter.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
1
  import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
2
2
  import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId, resolveAccountEntry } from "openclaw/plugin-sdk/account-resolution";
4
- import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, ReplyToModeSchema, buildChannelAccountSchemaParts, buildChannelConfigSchema, buildChannelReactionShape, buildGroupEntrySchema, requireAllowlistAllowFrom, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
4
+ import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, ReplyToModeSchema, buildChannelAccountSchemaParts, buildChannelConfigSchema, buildChannelReactionShape, buildGroupEntrySchema, refineChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-schema";
5
5
  import { z } from "zod";
6
6
  //#region extensions/signal/src/config-ui-hints.ts
7
7
  const signalChannelConfigUiHints = {
@@ -142,45 +142,18 @@ const SignalConfigSchemaBase = SignalAccountSchemaBase.extend({
142
142
  defaultAccount: z.string().optional()
143
143
  });
144
144
  function validateSignalConfigAllowFrom(value, ctx) {
145
- requireOpenAllowFrom({
146
- policy: value.dmPolicy,
147
- allowFrom: value.allowFrom,
148
- ctx,
149
- path: ["allowFrom"],
150
- message: "channels.signal.dmPolicy=\"open\" requires channels.signal.allowFrom to include \"*\""
151
- });
152
- requireAllowlistAllowFrom({
153
- policy: value.dmPolicy,
154
- allowFrom: value.allowFrom,
155
- ctx,
156
- path: ["allowFrom"],
157
- message: "channels.signal.dmPolicy=\"allowlist\" requires channels.signal.allowFrom to contain at least one sender ID"
145
+ refineChannelDmPolicy({
146
+ channelId: "signal",
147
+ value,
148
+ ctx
158
149
  });
159
150
  for (const [accountId, account] of Object.entries(value.accounts ?? {})) {
160
151
  if (!account) continue;
161
- const effectivePolicy = account.dmPolicy ?? value.dmPolicy;
162
- const effectiveAllowFrom = account.allowFrom ?? value.allowFrom;
163
- requireOpenAllowFrom({
164
- policy: effectivePolicy,
165
- allowFrom: effectiveAllowFrom,
166
- ctx,
167
- path: [
168
- "accounts",
169
- accountId,
170
- "allowFrom"
171
- ],
172
- message: "channels.signal.accounts.*.dmPolicy=\"open\" requires channels.signal.accounts.*.allowFrom (or channels.signal.allowFrom) to include \"*\""
173
- });
174
- requireAllowlistAllowFrom({
175
- policy: effectivePolicy,
176
- allowFrom: effectiveAllowFrom,
177
- ctx,
178
- path: [
179
- "accounts",
180
- accountId,
181
- "allowFrom"
182
- ],
183
- message: "channels.signal.accounts.*.dmPolicy=\"allowlist\" requires channels.signal.accounts.*.allowFrom (or channels.signal.allowFrom) to contain at least one sender ID"
152
+ refineChannelDmPolicy({
153
+ channelId: "signal",
154
+ value,
155
+ accountId,
156
+ ctx
184
157
  });
185
158
  }
186
159
  }
@@ -1,4 +1,4 @@
1
1
  import { n as normalizeSignalMessagingTarget, r as normalizeSignalReactionRecipient, t as looksLikeSignalTargetId } from "./normalize-l_b99hap.js";
2
2
  import { i as isSignalSenderAllowed } from "./identity-YXPmgFMu.js";
3
- import { a as installSignalCliFromRelease, i as installSignalCli, n as downloadToFile, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset, t as MAX_SIGNAL_CLI_EXTRACTED_BYTES } from "./install-signal-cli-7tEL37_j.js";
3
+ import { a as installSignalCliFromRelease, i as installSignalCli, n as downloadToFile, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset, t as MAX_SIGNAL_CLI_EXTRACTED_BYTES } from "./install-signal-cli-QlEIfWBv.js";
4
4
  export { MAX_SIGNAL_CLI_EXTRACTED_BYTES, downloadToFile, extractSignalCliArchive, installSignalCli, installSignalCliFromRelease, isSignalSenderAllowed, looksLikeArchive, looksLikeSignalTargetId, normalizeSignalMessagingTarget, normalizeSignalReactionRecipient, pickAsset };
@@ -293,76 +293,7 @@ function hasContainerTransportWithoutEffectiveAccount(cfg) {
293
293
  }
294
294
  return false;
295
295
  }
296
- async function migrateLegacySignalTransportConfig(params) {
297
- const signal = params.cfg.channels?.signal;
298
- if (!isRecord(signal)) return {
299
- config: params.cfg,
300
- changes: []
301
- };
302
- const accounts = isRecord(signal.accounts) ? signal.accounts : {};
303
- if (!(Object.hasOwn(signal, "apiMode") || hasLegacyFields(signal) || Object.values(accounts).some((entry) => isRecord(entry) && hasLegacyFields(entry)))) return {
304
- config: params.cfg,
305
- changes: []
306
- };
307
- const apiMode = signal.apiMode;
308
- const entries = [signal, ...Object.values(accounts).filter(isRecord)];
309
- const legacyResolutionEntries = entries.filter((_, index) => shouldMaterializeTransport(entries, index)).filter((entry) => !isSignalTransportConfig(entry.transport));
310
- const invalidDerivedEndpoint = findInvalidLegacyDerivedEndpoint(legacyResolutionEntries, signal);
311
- if (invalidDerivedEndpoint) return {
312
- config: params.cfg,
313
- changes: [],
314
- warnings: [invalidDerivedEndpoint === "port" ? PENDING_LEGACY_INVALID_PORT_WARNING : PENDING_LEGACY_INVALID_HOST_WARNING]
315
- };
316
- if (hasInvalidLegacyHttpUrl(legacyResolutionEntries, signal)) return {
317
- config: params.cfg,
318
- changes: [],
319
- warnings: [PENDING_LEGACY_INVALID_URL_WARNING]
320
- };
321
- if (!params.detect && legacyResolutionEntries.some((entry) => requiresDetection(entry, signal, apiMode))) return {
322
- config: params.cfg,
323
- changes: [],
324
- warnings: [PENDING_LEGACY_TRANSPORT_WARNING]
325
- };
326
- const resolvedTransports = await Promise.all(entries.map(async (entry, index) => !shouldMaterializeTransport(entries, index) ? void 0 : await resolveLegacyTransport({
327
- entry,
328
- parent: signal,
329
- apiMode,
330
- detect: params.detect
331
- })));
332
- if (hasInvalidManagedTransportPort(resolvedTransports)) return {
333
- config: params.cfg,
334
- changes: [],
335
- warnings: [PENDING_LEGACY_INVALID_PORT_WARNING]
336
- };
337
- const transports = allocateMigratedManagedPorts({
338
- entries,
339
- transports: resolvedTransports
340
- });
341
- if (transports.some((transport, index) => shouldMaterializeTransport(entries, index) && !transport)) return {
342
- config: params.cfg,
343
- changes: [],
344
- warnings: [PENDING_LEGACY_TRANSPORT_WARNING]
345
- };
346
- const next = applyMigratedSignalTransports({
347
- cfg: params.cfg,
348
- entries,
349
- transports
350
- });
351
- if (!next) return {
352
- config: params.cfg,
353
- changes: []
354
- };
355
- if (hasContainerTransportWithoutEffectiveAccount(next)) return {
356
- config: params.cfg,
357
- changes: [],
358
- warnings: [PENDING_LEGACY_CONTAINER_ACCOUNT_WARNING]
359
- };
360
- return {
361
- config: next,
362
- changes: ["Migrated channels.signal transport settings to concrete account-owned transport objects."]
363
- };
364
- }
365
- function migrateLegacySignalTransportConfigSync(cfg) {
296
+ function prepareLegacySignalTransportMigration(cfg) {
366
297
  const signal = cfg.channels?.signal;
367
298
  if (!isRecord(signal)) return {
368
299
  config: cfg,
@@ -373,6 +304,7 @@ function migrateLegacySignalTransportConfigSync(cfg) {
373
304
  config: cfg,
374
305
  changes: []
375
306
  };
307
+ const apiMode = signal.apiMode;
376
308
  const entries = [signal, ...Object.values(accounts).filter(isRecord)];
377
309
  const legacyResolutionEntries = entries.filter((_, index) => shouldMaterializeTransport(entries, index)).filter((entry) => !isSignalTransportConfig(entry.transport));
378
310
  const invalidDerivedEndpoint = findInvalidLegacyDerivedEndpoint(legacyResolutionEntries, signal);
@@ -386,14 +318,14 @@ function migrateLegacySignalTransportConfigSync(cfg) {
386
318
  changes: [],
387
319
  warnings: [PENDING_LEGACY_INVALID_URL_WARNING]
388
320
  };
389
- const resolvedTransports = entries.map((entry, index) => {
390
- if (!shouldMaterializeTransport(entries, index)) return;
391
- return resolveLegacyTransportWithoutDetection({
392
- entry,
393
- parent: signal,
394
- apiMode: signal.apiMode
395
- });
396
- });
321
+ return {
322
+ signal,
323
+ apiMode,
324
+ entries,
325
+ legacyResolutionEntries
326
+ };
327
+ }
328
+ function finishLegacySignalTransportMigration(cfg, entries, resolvedTransports) {
397
329
  if (hasInvalidManagedTransportPort(resolvedTransports)) return {
398
330
  config: cfg,
399
331
  changes: [],
@@ -427,6 +359,36 @@ function migrateLegacySignalTransportConfigSync(cfg) {
427
359
  changes: ["Migrated channels.signal transport settings to concrete account-owned transport objects."]
428
360
  };
429
361
  }
362
+ async function migrateLegacySignalTransportConfig(params) {
363
+ const prepared = prepareLegacySignalTransportMigration(params.cfg);
364
+ if ("config" in prepared) return prepared;
365
+ const { signal, apiMode, entries, legacyResolutionEntries } = prepared;
366
+ if (!params.detect && legacyResolutionEntries.some((entry) => requiresDetection(entry, signal, apiMode))) return {
367
+ config: params.cfg,
368
+ changes: [],
369
+ warnings: [PENDING_LEGACY_TRANSPORT_WARNING]
370
+ };
371
+ const resolvedTransports = await Promise.all(entries.map(async (entry, index) => !shouldMaterializeTransport(entries, index) ? void 0 : await resolveLegacyTransport({
372
+ entry,
373
+ parent: signal,
374
+ apiMode,
375
+ detect: params.detect
376
+ })));
377
+ return finishLegacySignalTransportMigration(params.cfg, entries, resolvedTransports);
378
+ }
379
+ function migrateLegacySignalTransportConfigSync(cfg) {
380
+ const prepared = prepareLegacySignalTransportMigration(cfg);
381
+ if ("config" in prepared) return prepared;
382
+ const { signal, apiMode, entries } = prepared;
383
+ return finishLegacySignalTransportMigration(cfg, entries, entries.map((entry, index) => {
384
+ if (!shouldMaterializeTransport(entries, index)) return;
385
+ return resolveLegacyTransportWithoutDetection({
386
+ entry,
387
+ parent: signal,
388
+ apiMode
389
+ });
390
+ }));
391
+ }
430
392
  //#endregion
431
393
  //#region extensions/signal/config-doctor-api.ts
432
394
  const RETIRED_SIGNAL_ACCOUNT_TRANSPORT_FIELDS = [
@@ -1,2 +1,2 @@
1
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-api-C18u1hW0.js";
1
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-api-D0SnglP4.js";
2
2
  export { legacyConfigRules, normalizeCompatibilityConfig };
@@ -1,15 +1,15 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
1
+ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { l as normalizeSignalTransportHost } from "./transport-policy-DxvSMHp9.js";
3
3
  import { i as resolveSignalAccount, o as resolveSignalReplyToMode } from "./accounts-DO4HMqaK.js";
4
4
  import { n as normalizeSignalMessagingTarget } from "./normalize-l_b99hap.js";
5
5
  import { a as normalizeSignalAllowRecipient, c as resolveSignalSender, i as isSignalSenderAllowed, l as looksLikeUuid, n as formatSignalSenderDisplay, o as resolveSignalPeerId, r as formatSignalSenderId, s as resolveSignalRecipient, t as formatSignalPairingIdLine } from "./identity-YXPmgFMu.js";
6
- import { c as resolveSignalReactionLevel, f as isSignalNativeApprovalHandlerConfigured, i as getOptionalSignalRuntime, l as formatSignalMediaText, n as registerSignalReplyContext, o as materializeSignalPresentationFallback } from "./transport-detection-BcDiypLn.js";
7
- import { t as SignalSseRejectionError } from "./client-BmpTN7R3.js";
8
- import { n as signalRpcRequest, r as streamSignalEvents, t as signalCheck } from "./client-adapter-CDyW9LrQ.js";
9
- import { n as sendReactionSignal } from "./reaction-runtime-api-7FQFT_qb.js";
10
- import { i as maybeResolveSignalApprovalReaction, o as registerSignalApprovalReactionTargetForDeliveredPayload, s as resolveSignalApprovalConversationKey, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-D-nkbsvm.js";
11
- import { r as registerSignalQuestionReactionTargetForDeliveredPayload, t as maybeResolveSignalQuestionReaction } from "./question-reactions-CsVOpHg_.js";
12
- import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-DuH2ntJt.js";
6
+ import { c as resolveSignalReactionLevel, f as isSignalNativeApprovalHandlerConfigured, i as getOptionalSignalRuntime, l as formatSignalMediaText, n as registerSignalReplyContext, o as materializeSignalPresentationFallback } from "./transport-detection-Do2pYMAH.js";
7
+ import { t as SignalSseRejectionError } from "./client-B3C0ciqU.js";
8
+ import { n as signalRpcRequest, r as streamSignalEvents, t as signalCheck } from "./client-adapter-CNc5wzzs.js";
9
+ import { n as sendReactionSignal } from "./reaction-runtime-api-CWqDv5-q.js";
10
+ import { i as maybeResolveSignalApprovalReaction, o as registerSignalApprovalReactionTargetForDeliveredPayload, s as resolveSignalApprovalConversationKey, t as addSignalApprovalReactionHintToStructuredPayload } from "./approval-reactions-CjhdkJ8P.js";
11
+ import { r as registerSignalQuestionReactionTargetForDeliveredPayload, t as maybeResolveSignalQuestionReaction } from "./question-reactions-BFR9Mf-O.js";
12
+ import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-Bz0x0JC1.js";
13
13
  import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
14
14
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
15
15
  import { resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
@@ -20,8 +20,8 @@ import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInbo
20
20
  import { canonicalizeBase64, detectMime, estimateBase64DecodedBytes, kindFromMime, saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
21
21
  import { collectErrorGraphCandidates, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
22
22
  import { ensurePortAvailable, extractErrorCode, formatErrorMessage as formatErrorMessage$1, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
23
- import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention, resolveChannelGroups, resolveChannelGroupsConfigPath } from "openclaw/plugin-sdk/channel-policy";
24
23
  import path from "node:path";
24
+ import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention, resolveChannelGroups, resolveChannelGroupsConfigPath } from "openclaw/plugin-sdk/channel-policy";
25
25
  import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
26
26
  import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
27
27
  import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
@@ -271,50 +271,30 @@ function createSignalNativeReplyIdPlan(params) {
271
271
  const replyToId = resolveSignalNativeReplyId(params);
272
272
  if (!replyToId) return {
273
273
  peek: () => void 0,
274
- use: () => void 0,
275
274
  markSent: () => void 0
276
275
  };
277
276
  const isExplicitReply = params.payload.replyToTag === true || params.payload.replyToCurrent === true;
278
- if (isSignalStatusNoticePayload(params.payload)) {
279
- const resolve = params.replyToMode === "off" ? () => void 0 : () => replyToId;
280
- return {
281
- peek: resolve,
282
- use: resolve,
283
- markSent: () => void 0
284
- };
285
- }
286
- if (isExplicitReply) {
287
- const resolve = () => replyToId;
288
- return {
289
- peek: resolve,
290
- use: resolve,
291
- markSent: () => void 0
292
- };
293
- }
277
+ if (isSignalStatusNoticePayload(params.payload)) return {
278
+ peek: params.replyToMode === "off" ? () => void 0 : () => replyToId,
279
+ markSent: () => void 0
280
+ };
281
+ if (isExplicitReply) return {
282
+ peek: () => replyToId,
283
+ markSent: () => void 0
284
+ };
294
285
  const planner = createReplyReferencePlanner({
295
286
  replyToMode: params.replyToMode,
296
287
  existingId: replyToId,
297
288
  hasReplied: params.replyContext?.state?.hasReplied
298
289
  });
299
- const syncState = () => {
300
- if (params.replyContext?.state) params.replyContext.state.hasReplied = planner.hasReplied();
301
- };
302
290
  return {
303
291
  peek: () => planner.peek(),
304
- use: () => {
305
- const nextReplyToId = planner.use();
306
- syncState();
307
- return nextReplyToId;
308
- },
309
292
  markSent: () => {
310
293
  planner.markSent();
311
- syncState();
294
+ if (params.replyContext?.state) params.replyContext.state.hasReplied = planner.hasReplied();
312
295
  }
313
296
  };
314
297
  }
315
- function createSignalNativeReplyIdResolver(params) {
316
- return createSignalNativeReplyIdPlan(params).use;
317
- }
318
298
  //#endregion
319
299
  //#region extensions/signal/src/monitor/access-policy.ts
320
300
  const SIGNAL_UUID_KIND = "plugin:signal-uuid";
@@ -1889,6 +1869,7 @@ async function deliverReplies(params) {
1889
1869
  accountId,
1890
1870
  chatType: params.chatType
1891
1871
  });
1872
+ const replyToAuthor = normalizeOptionalString(params.replyContext?.author);
1892
1873
  for (const payload of replies) {
1893
1874
  const deliveryResults = [];
1894
1875
  const presentationPayload = materializeSignalPresentationFallback(payload);
@@ -1901,12 +1882,29 @@ async function deliverReplies(params) {
1901
1882
  targetAuthorUuid: accountUuid
1902
1883
  }) ?? presentationPayload;
1903
1884
  const reply = resolveSendableOutboundReplyParts(deliveredPayload);
1904
- const nextNativeReply = createSignalNativeReplyResolver({
1885
+ const replyPlan = createSignalNativeReplyIdPlan({
1905
1886
  payload: deliveredPayload,
1906
1887
  replyContext: params.replyContext,
1907
1888
  replyToMode
1908
1889
  });
1909
- const recordDeliveryResult = (result, visibleText) => {
1890
+ const send = async (visibleText, mediaUrl) => {
1891
+ const replyToId = replyPlan.peek();
1892
+ const result = await sendMessageSignal(target, visibleText, {
1893
+ cfg: params.cfg,
1894
+ baseUrl,
1895
+ account,
1896
+ maxBytes,
1897
+ accountId,
1898
+ ...mediaUrl ? { mediaUrl } : {},
1899
+ ...replyToId ? {
1900
+ replyToId,
1901
+ ...replyToAuthor ? {
1902
+ replyToAuthor,
1903
+ replyToBody: params.replyContext?.body ?? ""
1904
+ } : {}
1905
+ } : {}
1906
+ });
1907
+ replyPlan.markSent();
1910
1908
  const messageId = typeof result?.messageId === "string" && result.messageId.trim() ? result.messageId.trim() : null;
1911
1909
  if (messageId) deliveryResults.push({
1912
1910
  channel: "signal",
@@ -1918,28 +1916,8 @@ async function deliverReplies(params) {
1918
1916
  payload: deliveredPayload,
1919
1917
  text: reply.text,
1920
1918
  chunkText: (value) => chunkTextWithMode(value, textLimit, chunkMode),
1921
- sendText: async (chunk) => {
1922
- recordDeliveryResult(await sendMessageSignal(target, chunk, {
1923
- cfg: params.cfg,
1924
- baseUrl,
1925
- account,
1926
- maxBytes,
1927
- accountId,
1928
- ...nextNativeReply()
1929
- }), chunk);
1930
- },
1931
- sendMedia: async ({ mediaUrl, caption }) => {
1932
- const visibleText = caption ?? "";
1933
- recordDeliveryResult(await sendMessageSignal(target, visibleText, {
1934
- cfg: params.cfg,
1935
- baseUrl,
1936
- account,
1937
- mediaUrl,
1938
- maxBytes,
1939
- accountId,
1940
- ...nextNativeReply()
1941
- }), visibleText);
1942
- }
1919
+ sendText: send,
1920
+ sendMedia: ({ mediaUrl, caption }) => send(caption ?? "", mediaUrl)
1943
1921
  }) !== "empty") {
1944
1922
  registerSignalReactionTargetsForDeliveredPayload({
1945
1923
  cfg: params.cfg,
@@ -1957,21 +1935,6 @@ async function deliverReplies(params) {
1957
1935
  }
1958
1936
  }
1959
1937
  }
1960
- function createSignalNativeReplyResolver(params) {
1961
- const nextReplyToId = createSignalNativeReplyIdResolver(params);
1962
- return () => {
1963
- const replyToId = nextReplyToId();
1964
- if (!replyToId) return {};
1965
- const replyToAuthor = normalizeOptionalString(params.replyContext?.author);
1966
- return {
1967
- replyToId,
1968
- ...replyToAuthor ? {
1969
- replyToAuthor,
1970
- replyToBody: params.replyContext?.body ?? ""
1971
- } : {}
1972
- };
1973
- };
1974
- }
1975
1938
  async function monitorSignalProvider(opts = {}) {
1976
1939
  const runtime = opts.runtime ?? createNonExitingRuntime();
1977
1940
  const cfg = opts.config ?? getRuntimeConfig();
@@ -1,6 +1,6 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { t as detectSignalTransport } from "./transport-detection-BcDiypLn.js";
3
- import { n as signalRpcRequest, t as signalCheck } from "./client-adapter-CDyW9LrQ.js";
1
+ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
+ import { t as detectSignalTransport } from "./transport-detection-Do2pYMAH.js";
3
+ import { n as signalRpcRequest, t as signalCheck } from "./client-adapter-CNc5wzzs.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
@@ -1,6 +1,6 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
1
+ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { i as resolveSignalDeliveredConversationKey } from "./approval-auth-pNCKKotV.js";
3
- import { c as resolveSignalApprovalTargetAuthorKeys } from "./approval-reactions-D-nkbsvm.js";
3
+ import { c as resolveSignalApprovalTargetAuthorKeys } from "./approval-reactions-CjhdkJ8P.js";
4
4
  import { createQuestionReactionTargetStore, questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
5
5
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
6
6
  //#region extensions/signal/src/question-reactions.ts
@@ -1,6 +1,6 @@
1
1
  import { i as resolveSignalAccount } from "./accounts-DO4HMqaK.js";
2
2
  import { r as normalizeSignalReactionRecipient } from "./normalize-l_b99hap.js";
3
- import { n as signalRpcRequest } from "./client-adapter-CDyW9LrQ.js";
3
+ import { n as signalRpcRequest } from "./client-adapter-CNc5wzzs.js";
4
4
  import { t as resolveSignalRpcContext } from "./rpc-context-dXSy4NtF.js";
5
5
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
6
6
  //#region extensions/signal/src/send-reactions.ts
@@ -1,2 +1,2 @@
1
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-7FQFT_qb.js";
1
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-CWqDv5-q.js";
2
2
  export { removeReactionSignal, sendReactionSignal };
@@ -1,3 +1,4 @@
1
+ import "node:module";
1
2
  //#region \0rolldown/runtime.js
2
3
  var __defProp = Object.defineProperty;
3
4
  var __exportAll = (all, no_symbols) => {
@@ -1,12 +1,12 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-DO4HMqaK.js";
2
2
  import { n as normalizeSignalMessagingTarget, t as looksLikeSignalTargetId } from "./normalize-l_b99hap.js";
3
- import { a as setSignalRuntime, c as resolveSignalReactionLevel, s as signalMessageActions } from "./transport-detection-BcDiypLn.js";
4
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-7FQFT_qb.js";
5
- import { n as SignalConfigSchema } from "./config-schema-CHihQTOp.js";
6
- import { i as installSignalCli } from "./install-signal-cli-7tEL37_j.js";
7
- import { t as monitorSignalProvider } from "./monitor-D7Slr0-A.js";
8
- import { t as sendMessageSignal } from "./send-DuH2ntJt.js";
9
- import { t as probeSignal } from "./probe-CtO2EIfg.js";
3
+ import { a as setSignalRuntime, c as resolveSignalReactionLevel, s as signalMessageActions } from "./transport-detection-Do2pYMAH.js";
4
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-CWqDv5-q.js";
5
+ import { n as SignalConfigSchema } from "./config-schema-DfEbpMVQ.js";
6
+ import { i as installSignalCli } from "./install-signal-cli-QlEIfWBv.js";
7
+ import { t as monitorSignalProvider } from "./monitor-BiNWxMB3.js";
8
+ import { t as sendMessageSignal } from "./send-Bz0x0JC1.js";
9
+ import { t as probeSignal } from "./probe-kOJqyjWz.js";
10
10
  import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/account-helpers";
11
11
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
12
12
  import { buildBaseAccountStatusSnapshot, buildBaseChannelStatusSummary, collectStatusIssuesFromLastError, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
@@ -1,7 +1,7 @@
1
1
  import { i as resolveSignalAccount } from "./accounts-DO4HMqaK.js";
2
2
  import { n as normalizeSignalMessagingTarget } from "./normalize-l_b99hap.js";
3
- import { n as registerSignalReplyContext, u as markdownToSignalText } from "./transport-detection-BcDiypLn.js";
4
- import { n as signalRpcRequest } from "./client-adapter-CDyW9LrQ.js";
3
+ import { n as registerSignalReplyContext, u as markdownToSignalText } from "./transport-detection-Do2pYMAH.js";
4
+ import { n as signalRpcRequest } from "./client-adapter-CNc5wzzs.js";
5
5
  import { t as resolveSignalRpcContext } from "./rpc-context-dXSy4NtF.js";
6
6
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
7
7
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
@@ -1,2 +1,2 @@
1
- import { r as sendTypingSignal, t as sendMessageSignal } from "./send-DuH2ntJt.js";
1
+ import { r as sendTypingSignal, t as sendMessageSignal } from "./send-Bz0x0JC1.js";
2
2
  export { sendMessageSignal, sendTypingSignal };
@@ -2,7 +2,7 @@ import { u as normalizeSignalTransportUrl } from "./transport-policy-DxvSMHp9.js
2
2
  import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-DO4HMqaK.js";
3
3
  import { n as normalizeSignalMessagingTarget, r as normalizeSignalReactionRecipient } from "./normalize-l_b99hap.js";
4
4
  import { n as signalApprovalAuth, t as getSignalApprovalApprovers } from "./approval-auth-pNCKKotV.js";
5
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-7FQFT_qb.js";
5
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-CWqDv5-q.js";
6
6
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
7
7
  import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
8
8
  import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
@@ -58,6 +58,7 @@ const signalApproval = createApproverRestrictedNativeApprovalCapabilityFromForwa
58
58
  }).manualFallbackPayload }
59
59
  },
60
60
  createNativeRuntime: (routing) => createLazyChannelApprovalNativeRuntimeAdapter({
61
+ capabilityBoundary: true,
61
62
  eventKinds: [
62
63
  "exec",
63
64
  "plugin",
@@ -73,7 +74,7 @@ const signalApproval = createApproverRestrictedNativeApprovalCapabilityFromForwa
73
74
  approvalKind,
74
75
  request
75
76
  }),
76
- load: async () => (await import("./approval-handler.runtime-Dsg_GE8N.js")).signalApprovalNativeRuntime
77
+ load: async () => (await import("./approval-handler.runtime-DCPJkIqo.js")).signalApprovalNativeRuntime
77
78
  })
78
79
  });
79
80
  const signalApprovalRouting = signalApproval.routing;
@@ -522,7 +523,7 @@ const DEFAULT_PROBE_TIMEOUT_MS = 1e4;
522
523
  async function detectSignalTransport(params) {
523
524
  const url = normalizeSignalTransportUrl(params.url);
524
525
  const timeoutMs = params.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;
525
- const probes = params.probeNative && params.probeContainer ? void 0 : await import("./transport-probes.runtime-B7kr_6Zu.js");
526
+ const probes = params.probeNative && params.probeContainer ? void 0 : await import("./transport-probes.runtime-DV7x4VWu.js");
526
527
  const probeNative = params.probeNative ?? probes?.nativeCheck;
527
528
  const probeContainer = params.probeContainer ?? probes?.containerCheck;
528
529
  if (!probeNative || !probeContainer) throw new Error("Signal transport probes are unavailable");
@@ -1,2 +1,2 @@
1
- import { t as detectSignalTransport } from "./transport-detection-BcDiypLn.js";
1
+ import { t as detectSignalTransport } from "./transport-detection-Do2pYMAH.js";
2
2
  export { detectSignalTransport };
@@ -1,2 +1,2 @@
1
- import { a as containerCheck, n as signalCheck } from "./client-BmpTN7R3.js";
1
+ import { a as containerCheck, n as signalCheck } from "./client-B3C0ciqU.js";
2
2
  export { containerCheck, signalCheck as nativeCheck };
@@ -1,5 +1,8 @@
1
1
  {
2
2
  "id": "signal",
3
+ "categories": [
4
+ "channels"
5
+ ],
3
6
  "name": "Signal",
4
7
  "description": "OpenClaw Signal channel plugin.",
5
8
  "doctorContract": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/signal",
3
- "version": "2026.9.2",
3
+ "version": "2026.9.4",
4
4
  "description": "OpenClaw Signal channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -93,10 +93,10 @@
93
93
  "allowInvalidConfigRecovery": true
94
94
  },
95
95
  "compat": {
96
- "pluginApi": ">=2026.9.2"
96
+ "pluginApi": ">=2026.9.4"
97
97
  },
98
98
  "build": {
99
- "openclawVersion": "2026.9.2",
99
+ "openclawVersion": "2026.9.4",
100
100
  "bundledDist": false
101
101
  },
102
102
  "release": {
@@ -118,7 +118,7 @@
118
118
  "README.md"
119
119
  ],
120
120
  "peerDependencies": {
121
- "openclaw": ">=2026.9.2"
121
+ "openclaw": ">=2026.9.4"
122
122
  },
123
123
  "peerDependenciesMeta": {
124
124
  "openclaw": {
@@ -1,10 +1,10 @@
1
1
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
2
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
3
3
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
4
+ import path from "node:path";
4
5
  import { CONFIG_DIR, extractArchive, resolveBrewExecutable } from "openclaw/plugin-sdk/setup-tools";
5
6
  import { createWriteStream } from "node:fs";
6
7
  import fs from "node:fs/promises";
7
- import path from "node:path";
8
8
  import { Readable, Transform } from "node:stream";
9
9
  import { pipeline } from "node:stream/promises";
10
10
  import { readProviderJsonObjectResponse } from "openclaw/plugin-sdk/provider-http";