@openclaw/signal 2026.7.2-beta.5 → 2026.8.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/api.js +7 -7
  2. package/dist/{approval-handler.runtime-C-XYgcxE.js → approval-handler.runtime-Bi5yNhnj.js} +2 -2
  3. package/dist/{approval-reactions-DtL47gSK.js → approval-reactions-BulCzhdB.js} +15 -45
  4. package/dist/{channel-CBIljGCH.js → channel-CzDJMDtX.js} +50 -91
  5. package/dist/channel-config-api.js +1 -1
  6. package/dist/channel-plugin-api.js +1 -1
  7. package/dist/{channel.runtime-B8GXmuol.js → channel.runtime-D12iYzJB.js} +2 -2
  8. package/dist/{client-BazXTH7O.js → client-CvnR8_XA.js} +31 -34
  9. package/dist/{client-adapter-mXGeEHQJ.js → client-adapter-D9SNPaNx.js} +13 -6
  10. package/dist/{config-schema-DLvpQPN5.js → config-schema-CkMIK7zp.js} +4 -7
  11. package/dist/contract-api.js +1 -1
  12. package/dist/{doctor-contract-api-DbUCknbC.js → doctor-contract-api-Dnp5eQQJ.js} +46 -54
  13. package/dist/doctor-contract-api.js +1 -1
  14. package/dist/{install-signal-cli-qJF7iC4h.js → install-signal-cli-Cpiyk0k1.js} +8 -5
  15. package/dist/{monitor-CHBkf7lk.js → monitor-DiN2hKnG.js} +177 -126
  16. package/dist/{probe-Br9abaGp.js → probe-C_THuQzn.js} +23 -7
  17. package/dist/question-reactions-ByjH5qST.js +80 -0
  18. package/dist/{reaction-runtime-api-BjeDyKcz.js → reaction-runtime-api-Cf6QHcE5.js} +8 -19
  19. package/dist/reaction-runtime-api.js +1 -1
  20. package/dist/runtime-api.js +7 -7
  21. package/dist/{send-B_Ks4MZr.js → send-BvGgByMd.js} +12 -3
  22. package/dist/{send.runtime-CbuXycZT.js → send.runtime-CtTBBrjL.js} +1 -1
  23. package/dist/{transport-detection-Da06-LOL.js → transport-detection-BItHawMq.js} +50 -145
  24. package/dist/{transport-detection.runtime-D_190UUL.js → transport-detection.runtime-DoiwPcrG.js} +1 -1
  25. package/dist/{transport-probes.runtime-CV6Qs0Og.js → transport-probes.runtime-BsJdp0oI.js} +1 -1
  26. package/openclaw.plugin.json +4 -1
  27. package/package.json +5 -5
  28. package/dist/approval-resolver-B3m0D2R0.js +0 -16
  29. package/dist/question-reactions-Ds48FtEu.js +0 -109
package/dist/api.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-DrStJjiK.js";
2
2
  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, u as looksLikeSignalTargetId } from "./identity-BQ4OzXXk.js";
3
- import { a as signalMessageActions, c as markdownToSignalText, l as markdownToSignalTextChunks, o as resolveSignalReactionLevel, t as detectSignalTransport } from "./transport-detection-Da06-LOL.js";
4
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-BjeDyKcz.js";
5
- 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-CBIljGCH.js";
6
- import { i as installSignalCli, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset } from "./install-signal-cli-qJF7iC4h.js";
7
- import { t as monitorSignalProvider } from "./monitor-CHBkf7lk.js";
8
- import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-B_Ks4MZr.js";
9
- import { t as probeSignal } from "./probe-Br9abaGp.js";
3
+ import { a as signalMessageActions, c as markdownToSignalText, l as markdownToSignalTextChunks, o as resolveSignalReactionLevel, t as detectSignalTransport } from "./transport-detection-BItHawMq.js";
4
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-Cf6QHcE5.js";
5
+ 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-CzDJMDtX.js";
6
+ import { i as installSignalCli, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset } from "./install-signal-cli-Cpiyk0k1.js";
7
+ import { t as monitorSignalProvider } from "./monitor-DiN2hKnG.js";
8
+ import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-BvGgByMd.js";
9
+ import { t as probeSignal } from "./probe-C_THuQzn.js";
10
10
  //#region extensions/signal/src/channel.setup.ts
11
11
  const signalSetupPlugin = { ...createSignalPluginBase({
12
12
  setupWizard: signalSetupWizard,
@@ -1,8 +1,8 @@
1
1
  import { r as resolveDefaultSignalAccountId } from "./accounts-DrStJjiK.js";
2
2
  import { d as normalizeSignalMessagingTarget } from "./identity-BQ4OzXXk.js";
3
3
  import { o as resolveSignalTarget } from "./runtime-JPrGlV7h.js";
4
- import { d as unregisterSignalApprovalReactionTarget, i as hasSignalApprovalReactionApprovers, l as resolveSignalApprovalConversationKey, o as registerSignalApprovalReactionTarget, u as resolveSignalApprovalTargetAuthorKeys } from "./approval-reactions-DtL47gSK.js";
5
- import { r as sendTypingSignal, t as sendMessageSignal } from "./send-B_Ks4MZr.js";
4
+ import { d as unregisterSignalApprovalReactionTarget, i as hasSignalApprovalReactionApprovers, l as resolveSignalApprovalConversationKey, o as registerSignalApprovalReactionTarget, u as resolveSignalApprovalTargetAuthorKeys } from "./approval-reactions-BulCzhdB.js";
5
+ import { r as sendTypingSignal, t as sendMessageSignal } from "./send-BvGgByMd.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,13 +1,15 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { d as normalizeSignalMessagingTarget, l as looksLikeUuid } from "./identity-BQ4OzXXk.js";
3
3
  import { i as signalApprovalAuth, o as resolveSignalTarget, r as getSignalApprovalApprovers, t as getOptionalSignalRuntime } from "./runtime-JPrGlV7h.js";
4
- import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
4
+ import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
5
5
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
6
6
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
- import { addApprovalReactionHintToText, buildApprovalReactionHint, createApprovalReactionTargetStore, hasApprovalReactionHintText, listApprovalReactionBindings, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
7
+ import { addApprovalReactionHintToText, buildApprovalReactionHint, createApprovalReactionTargetStore, extractApprovalReactionPromptBinding, hasApprovalReactionHintText, listApprovalReactionBindings, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
8
8
  import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
9
+ import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
9
10
  import { getExecApprovalReplyMetadata } from "openclaw/plugin-sdk/approval-reply-runtime";
10
11
  import { matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
12
+ import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
11
13
  //#region extensions/signal/src/approval-reactions.ts
12
14
  var approval_reactions_exports = /* @__PURE__ */ __exportAll({
13
15
  addSignalApprovalReactionHintToStructuredPayload: () => addSignalApprovalReactionHintToStructuredPayload,
@@ -28,16 +30,15 @@ var approval_reactions_exports = /* @__PURE__ */ __exportAll({
28
30
  const PERSISTENT_NAMESPACE = "signal.approval-reactions.v2";
29
31
  const PERSISTENT_MAX_ENTRIES = 1e3;
30
32
  const DEFAULT_REACTION_TARGET_TTL_MS = 1440 * 60 * 1e3;
31
- const resolverRuntimeLoader = createLazyRuntimeModule(() => import("./approval-resolver-B3m0D2R0.js"));
33
+ const loadResolveApprovalOverGateway = createLazyRuntimeSurface(() => import("openclaw/plugin-sdk/approval-gateway-runtime"), (runtime) => runtime.resolveApprovalOverGateway);
32
34
  const signalApprovalReactionTargets = createApprovalReactionTargetStore({
33
35
  namespace: PERSISTENT_NAMESPACE,
34
36
  maxEntries: PERSISTENT_MAX_ENTRIES,
35
37
  defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS,
36
38
  openStore: (storeParams) => getOptionalSignalRuntime()?.state.openKeyedStore(storeParams),
37
- logPersistentError: reportPersistentApprovalReactionError,
39
+ logPersistentError: createPluginStateErrorReporter(getOptionalSignalRuntime, "signal", "approval-reaction-state", "Signal persistent approval reaction state failed"),
38
40
  readPersistedTarget
39
41
  });
40
- const loadApprovalResolver = resolverRuntimeLoader;
41
42
  function resolveApprovalForwardingConfig(params) {
42
43
  return params.approvalKind === "plugin" ? params.cfg.approvals?.plugin : params.cfg.approvals?.exec;
43
44
  }
@@ -151,14 +152,6 @@ function buildReactionTargetKey(params) {
151
152
  if (!accountId || !conversationKey || !messageId || messageId === "unknown") return null;
152
153
  return `${accountId}:${conversationKey}:${messageId}`;
153
154
  }
154
- function reportPersistentApprovalReactionError(error) {
155
- try {
156
- getOptionalSignalRuntime()?.logging.getChildLogger({
157
- plugin: "signal",
158
- feature: "approval-reaction-state"
159
- }).warn("Signal persistent approval reaction state failed", { error: String(error) });
160
- } catch {}
161
- }
162
155
  function readPersistedTarget(target) {
163
156
  const value = target;
164
157
  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) || !Array.isArray(value.allowedDecisions)) return null;
@@ -201,38 +194,13 @@ function resolveStandaloneApprovalPromptKind(text) {
201
194
  function isStandaloneApprovalPromptText(text) {
202
195
  return resolveStandaloneApprovalPromptKind(text) !== null;
203
196
  }
204
- function normalizeApprovalDecision(value) {
205
- const normalized = value.trim().toLowerCase();
206
- if (normalized === "always") return "allow-always";
207
- if (normalized === "allow-once" || normalized === "allow-always" || normalized === "deny") return normalized;
208
- return null;
209
- }
210
- const APPROVAL_ID_LINE_RE = /^\s*ID:\s*([A-Za-z0-9][A-Za-z0-9._:-]*)\s*$/i;
211
- const APPROVE_REPLY_COMMAND_LINE_RE = /^\s*Reply with:\s*\/approve(?:@[^\s]+)?\s+([A-Za-z0-9][A-Za-z0-9._:-]*)\s+(.+)$/i;
212
197
  function extractSignalApprovalPromptBinding(text) {
213
- const lines = text.split(/\r?\n/).map((line) => line.replace(/\*\*/g, ""));
214
- const idHeaderMatch = lines.map((line) => line.match(APPROVAL_ID_LINE_RE)).find((match) => Boolean(match));
215
- if (!idHeaderMatch) return null;
216
- const approvalId = idHeaderMatch[1];
217
- if (!approvalId) return null;
218
198
  const approvalKind = resolveStandaloneApprovalPromptKind(text);
219
- if (!approvalKind) return null;
220
- const allowedDecisions = [];
221
- for (const line of lines) {
222
- const match = line.match(APPROVE_REPLY_COMMAND_LINE_RE);
223
- const commandApprovalId = match?.[1];
224
- const decisionList = match?.[2];
225
- if (commandApprovalId !== approvalId || !decisionList) continue;
226
- for (const decisionText of decisionList.split(/[\s|,]+/)) {
227
- const decision = normalizeApprovalDecision(decisionText);
228
- if (decision && !allowedDecisions.includes(decision)) allowedDecisions.push(decision);
229
- }
230
- }
231
- return allowedDecisions.length > 0 ? {
232
- approvalId,
199
+ return approvalKind ? extractApprovalReactionPromptBinding({
200
+ text,
233
201
  approvalKind,
234
- allowedDecisions
235
- } : null;
202
+ replyInstructionOnly: true
203
+ }) : null;
236
204
  }
237
205
  function buildTargetRoute(params) {
238
206
  const to = resolveSignalApprovalRouteTarget({
@@ -509,13 +477,15 @@ async function maybeResolveSignalApprovalReaction(params) {
509
477
  params.logVerboseMessage?.(`signal: approval reaction denied id=${target.approvalId} sender=${actorId}`);
510
478
  return true;
511
479
  }
512
- const { isApprovalNotFoundError, resolveSignalApproval } = await loadApprovalResolver();
480
+ const resolveApprovalOverGateway = await loadResolveApprovalOverGateway();
513
481
  try {
514
- const result = await resolveSignalApproval({
482
+ const result = await resolveApprovalOverGateway({
515
483
  cfg: params.cfg,
516
484
  approvalId: target.approvalId,
517
485
  approvalKind: target.approvalKind,
518
486
  decision: target.decision,
487
+ channel: "signal",
488
+ accountId: params.accountId,
519
489
  senderId: actorId,
520
490
  gatewayUrl: params.gatewayUrl
521
491
  });
@@ -547,7 +517,7 @@ async function maybeResolveSignalApprovalReaction(params) {
547
517
  }
548
518
  function clearSignalApprovalReactionTargetsForTest() {
549
519
  signalApprovalReactionTargets.clearForTest();
550
- resolverRuntimeLoader.clear();
520
+ loadResolveApprovalOverGateway.clear();
551
521
  }
552
522
  //#endregion
553
523
  export { maybeResolveSignalApprovalReaction as a, registerSignalApprovalReactionTargetForOutboundMessage as c, unregisterSignalApprovalReactionTarget as d, hasSignalApprovalReactionApprovers as i, resolveSignalApprovalConversationKey as l, appendSignalApprovalReactionHintForOutboundMessage as n, registerSignalApprovalReactionTarget as o, approval_reactions_exports as r, registerSignalApprovalReactionTargetForDeliveredPayload as s, addSignalApprovalReactionHintToStructuredPayload as t, resolveSignalApprovalTargetAuthorKeys as u };
@@ -2,13 +2,13 @@ import { a as isSignalManagedNativeConnectionUrlForBind, i as assignSignalManage
2
2
  import { a as resolveSignalAccountConfig, i as resolveSignalAccount, n as listSignalAccountIds, o as resolveSignalReplyToMode, r as resolveDefaultSignalAccountId, s as resolveSignalTransport } from "./accounts-DrStJjiK.js";
3
3
  import { c as resolveSignalSender, d as normalizeSignalMessagingTarget, l as looksLikeUuid, o as resolveSignalPeerId, s as resolveSignalRecipient, u as looksLikeSignalTargetId } from "./identity-BQ4OzXXk.js";
4
4
  import { a as listSignalAliasDirectoryEntries, o as resolveSignalTarget } from "./runtime-JPrGlV7h.js";
5
- import { a as signalMessageActions, d as shouldSuppressLocalSignalExecApprovalPrompt, f as signalApprovalCapability, i as materializeSignalPresentationFallback, l as markdownToSignalTextChunks, o as resolveSignalReactionLevel, r as resolveSignalReplyContextWithPersistence, s as formatSignalMediaText, t as detectSignalTransport } from "./transport-detection-Da06-LOL.js";
6
- import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-DbUCknbC.js";
7
- import { t as SignalChannelConfigSchema } from "./config-schema-DLvpQPN5.js";
5
+ import { a as signalMessageActions, d as shouldSuppressLocalSignalExecApprovalPrompt, f as signalApprovalCapability, i as materializeSignalPresentationFallback, l as markdownToSignalTextChunks, o as resolveSignalReactionLevel, r as resolveSignalReplyContextWithPersistence, s as formatSignalMediaText, t as detectSignalTransport } from "./transport-detection-BItHawMq.js";
6
+ import { i as migrateLegacySignalTransportConfig, n as normalizeCompatibilityConfig, r as clearLegacySignalTransportFieldsForAccount } from "./doctor-contract-api-Dnp5eQQJ.js";
7
+ import { t as SignalChannelConfigSchema } from "./config-schema-CkMIK7zp.js";
8
8
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
9
9
  import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
10
10
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
11
- import { createReplyToFanout, defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
11
+ import { createAccountStatusSink, createReplyToFanout, defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
12
12
  import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
13
13
  import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result";
14
14
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
@@ -213,8 +213,8 @@ async function probeSignalTransport(params) {
213
213
  accountId: params.accountId,
214
214
  overrides: managedTransportOptions(params.transport)
215
215
  }) : params.transport);
216
- if (resolved.kind === "container") return (params.probeContainer ?? (await import("./transport-probes.runtime-CV6Qs0Og.js")).containerCheck)(resolved.baseUrl, timeoutMs, params.account);
217
- return (params.probeNative ?? (await import("./transport-probes.runtime-CV6Qs0Og.js")).nativeCheck)(resolved.baseUrl, timeoutMs);
216
+ if (resolved.kind === "container") return (params.probeContainer ?? (await import("./transport-probes.runtime-BsJdp0oI.js")).containerCheck)(resolved.baseUrl, timeoutMs, params.account);
217
+ return (params.probeNative ?? (await import("./transport-probes.runtime-BsJdp0oI.js")).nativeCheck)(resolved.baseUrl, timeoutMs);
218
218
  }
219
219
  function writeSignalAccountTransport(params) {
220
220
  const transport = normalizeTransport(params.transport);
@@ -324,6 +324,7 @@ function parseSignalAllowFromEntries(raw) {
324
324
  });
325
325
  }
326
326
  function buildSignalSetupPatch(input) {
327
+ const account = normalizeSignalAccountInput(input.signalNumber);
327
328
  const transport = input.httpUrl ? {
328
329
  kind: input.signalTransport ?? "external-native",
329
330
  url: normalizeSignalTransportUrl(input.httpUrl)
@@ -334,7 +335,7 @@ function buildSignalSetupPatch(input) {
334
335
  ...input.httpPort ? { httpPort: Number(input.httpPort) } : {}
335
336
  } : void 0;
336
337
  return {
337
- ...input.signalNumber ? { account: input.signalNumber } : {},
338
+ ...account ? { account } : {},
338
339
  ...transport ? { transport } : {}
339
340
  };
340
341
  }
@@ -463,6 +464,7 @@ const signalSetupAdapterBase = createPatchedAccountSetupAdapter({
463
464
  } catch {
464
465
  return "Signal --http-host must be a hostname or IP address.";
465
466
  }
467
+ if (input.signalNumber !== void 0 && !normalizeSignalAccountInput(input.signalNumber)) return INVALID_SIGNAL_ACCOUNT_ERROR;
466
468
  if (input.signalTransport === "container" && !normalizeSignalAccountInput(input.signalNumber) && !normalizeSignalAccountInput(resolveSignalSetupAccount({
467
469
  cfg,
468
470
  accountId
@@ -568,7 +570,7 @@ function createSignalSetupWizardProxy(loadWizard) {
568
570
  const signalDoctor = {
569
571
  normalizeCompatibilityConfig,
570
572
  cleanStaleConfig: async ({ cfg }) => {
571
- const { detectSignalTransport } = await import("./transport-detection.runtime-D_190UUL.js");
573
+ const { detectSignalTransport } = await import("./transport-detection.runtime-DoiwPcrG.js");
572
574
  return await migrateLegacySignalTransportConfig({
573
575
  cfg,
574
576
  detect: detectSignalTransport
@@ -579,7 +581,7 @@ const signalDoctor = {
579
581
  //#region extensions/signal/src/shared.ts
580
582
  const SIGNAL_CHANNEL = "signal";
581
583
  async function loadSignalChannelRuntime() {
582
- return await import("./channel.runtime-B8GXmuol.js");
584
+ return await import("./channel.runtime-D12iYzJB.js");
583
585
  }
584
586
  const signalSetupWizard = createSignalSetupWizardProxy(async () => (await loadSignalChannelRuntime()).signalSetupWizard);
585
587
  const signalConfigAdapter = {
@@ -663,10 +665,10 @@ function createSignalPluginBase(params) {
663
665
  }
664
666
  //#endregion
665
667
  //#region extensions/signal/src/channel.ts
666
- const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-CHBkf7lk.js").then((n) => n.n));
667
- const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-Br9abaGp.js").then((n) => n.n));
668
- const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-CbuXycZT.js"));
669
- const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-DtL47gSK.js").then((n) => n.r));
668
+ const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-DiN2hKnG.js").then((n) => n.n));
669
+ const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-C_THuQzn.js").then((n) => n.n));
670
+ const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-CtTBBrjL.js"));
671
+ const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-BulCzhdB.js").then((n) => n.r));
670
672
  async function resolveSignalSendContext(params) {
671
673
  return {
672
674
  send: resolveOutboundSendDep(params.deps, "signal") ?? (await loadSignalSendRuntime()).sendMessageSignal,
@@ -685,21 +687,29 @@ function resolveSignalSendTarget(params) {
685
687
  })?.to ?? params.to.trim();
686
688
  }
687
689
  async function sendSignalOutbound(params) {
688
- const { send, maxBytes } = await resolveSignalSendContext(params);
689
- const to = resolveSignalSendTarget(params);
690
+ const accountId = params.accountId ?? void 0;
691
+ const { send, maxBytes } = await resolveSignalSendContext({
692
+ ...params,
693
+ accountId
694
+ });
695
+ const to = resolveSignalSendTarget({
696
+ ...params,
697
+ accountId
698
+ });
690
699
  const replyOptions = await resolveSignalReplyOptions({
691
700
  cfg: params.cfg,
692
701
  to,
693
- accountId: params.accountId,
702
+ accountId,
694
703
  replyToId: params.replyToId
695
704
  });
696
705
  return await send(to, params.text, {
697
706
  cfg: params.cfg,
698
707
  ...params.mediaUrl ? { mediaUrl: params.mediaUrl } : {},
708
+ ...params.mediaAccess ? { mediaAccess: params.mediaAccess } : {},
699
709
  ...params.mediaLocalRoots?.length ? { mediaLocalRoots: params.mediaLocalRoots } : {},
700
710
  ...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {},
701
711
  maxBytes,
702
- accountId: params.accountId ?? void 0,
712
+ accountId,
703
713
  ...replyOptions
704
714
  });
705
715
  }
@@ -729,9 +739,7 @@ function inferSignalTargetChatType(rawTo) {
729
739
  if (!to) return;
730
740
  if (/^signal:/i.test(to)) to = to.replace(/^signal:/i, "").trim();
731
741
  if (!to) return;
732
- const lower = normalizeLowercaseStringOrEmpty(to);
733
- if (lower.startsWith("group:")) return "group";
734
- if (lower.startsWith("username:") || lower.startsWith("u:")) return "direct";
742
+ if (normalizeLowercaseStringOrEmpty(to).startsWith("group:")) return "group";
735
743
  return "direct";
736
744
  }
737
745
  function attachSignalVisibleText(result, visibleText) {
@@ -751,25 +759,8 @@ const signalMessageAdapter = defineChannelMessageAdapter({
751
759
  media: true
752
760
  } },
753
761
  send: {
754
- text: async (ctx) => await sendSignalOutbound({
755
- cfg: ctx.cfg,
756
- to: ctx.to,
757
- text: ctx.text,
758
- accountId: ctx.accountId ?? void 0,
759
- deps: ctx.deps,
760
- replyToId: ctx.replyToId ?? void 0
761
- }),
762
- media: async (ctx) => await sendSignalOutbound({
763
- cfg: ctx.cfg,
764
- to: ctx.to,
765
- text: ctx.text,
766
- mediaUrl: ctx.mediaUrl,
767
- mediaLocalRoots: ctx.mediaLocalRoots,
768
- mediaReadFile: ctx.mediaReadFile,
769
- accountId: ctx.accountId ?? void 0,
770
- deps: ctx.deps,
771
- replyToId: ctx.replyToId ?? void 0
772
- })
762
+ text: sendSignalOutbound,
763
+ media: sendSignalOutbound
773
764
  }
774
765
  });
775
766
  function buildSignalBaseSessionKey(params) {
@@ -881,6 +872,7 @@ async function sendFormattedSignalMedia(ctx) {
881
872
  return attachChannelToResult("signal", attachSignalVisibleText(await send(to, formatted.text, {
882
873
  cfg: ctx.cfg,
883
874
  mediaUrl: ctx.mediaUrl,
875
+ ...ctx.mediaAccess ? { mediaAccess: ctx.mediaAccess } : {},
884
876
  mediaLocalRoots: ctx.mediaLocalRoots,
885
877
  ...ctx.mediaReadFile ? { mediaReadFile: ctx.mediaReadFile } : {},
886
878
  maxBytes,
@@ -898,7 +890,7 @@ async function registerDeliveredSignalApprovalPayloadForReactions(params) {
898
890
  const targetAuthor = normalizeOptionalString(account.config.account);
899
891
  const targetAuthorUuid = normalizeOptionalString(account.config.accountUuid);
900
892
  if (!targetAuthor && !targetAuthorUuid) return;
901
- const { registerSignalQuestionReactionTargetForDeliveredPayload } = await import("./question-reactions-Ds48FtEu.js").then((n) => n.n);
893
+ const { registerSignalQuestionReactionTargetForDeliveredPayload } = await import("./question-reactions-ByjH5qST.js").then((n) => n.n);
902
894
  registerSignalQuestionReactionTargetForDeliveredPayload({
903
895
  cfg: params.cfg,
904
896
  target: {
@@ -1047,9 +1039,13 @@ const signalPlugin = createChatChannelPlugin({
1047
1039
  lastProbeAt: snapshot.lastProbeAt ?? null
1048
1040
  }),
1049
1041
  probeAccount: async ({ account, timeoutMs }) => {
1050
- const baseUrl = account.baseUrl;
1051
- const { probeSignal } = await loadSignalProbeModule();
1052
- return await probeSignal(baseUrl, timeoutMs, { transportKind: account.transport.kind });
1042
+ const { probeSignalAccount } = await loadSignalProbeModule();
1043
+ return await probeSignalAccount({
1044
+ baseUrl: account.baseUrl,
1045
+ timeoutMs,
1046
+ transportKind: account.transport.kind,
1047
+ account: account.config.account
1048
+ });
1053
1049
  },
1054
1050
  formatCapabilitiesProbe: ({ probe }) => probe?.version ? [{ text: `Signal daemon: ${probe.version}` }] : [],
1055
1051
  resolveAccountSnapshot: ({ account }) => ({
@@ -1062,10 +1058,11 @@ const signalPlugin = createChatChannelPlugin({
1062
1058
  }),
1063
1059
  gateway: { startAccount: async (ctx) => {
1064
1060
  const account = ctx.account;
1065
- ctx.setStatus({
1061
+ const statusSink = createAccountStatusSink({
1066
1062
  accountId: account.accountId,
1067
- baseUrl: account.baseUrl
1063
+ setStatus: ctx.setStatus
1068
1064
  });
1065
+ statusSink({ baseUrl: account.baseUrl });
1069
1066
  ctx.log?.info(`[${account.accountId}] starting provider (${account.baseUrl})`);
1070
1067
  const { monitorSignalProvider } = await loadSignalMonitorModule();
1071
1068
  return await monitorSignalProvider({
@@ -1074,7 +1071,8 @@ const signalPlugin = createChatChannelPlugin({
1074
1071
  runtime: ctx.runtime,
1075
1072
  channelRuntime: ctx.channelRuntime,
1076
1073
  abortSignal: ctx.abortSignal,
1077
- mediaMaxMb: account.config.mediaMaxMb
1074
+ mediaMaxMb: account.config.mediaMaxMb,
1075
+ statusSink
1078
1076
  });
1079
1077
  } },
1080
1078
  message: signalMessageAdapter
@@ -1153,54 +1151,15 @@ const signalPlugin = createChatChannelPlugin({
1153
1151
  payload,
1154
1152
  hint
1155
1153
  }),
1156
- afterDeliverPayload: async (params) => await registerDeliveredSignalApprovalPayloadForReactions(params),
1157
- renderPresentation: async (params) => await renderSignalApprovalPayloadForReactions(params),
1158
- sendFormattedText: async ({ cfg, to, text, accountId, deps, replyToId, replyToIdSource, replyToMode, abortSignal, onDeliveryResult }) => await sendFormattedSignalText({
1159
- cfg,
1160
- to,
1161
- text,
1162
- accountId,
1163
- deps,
1164
- replyToId,
1165
- replyToIdSource,
1166
- replyToMode,
1167
- abortSignal,
1168
- onDeliveryResult
1169
- }),
1170
- sendFormattedMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId, abortSignal }) => await sendFormattedSignalMedia({
1171
- cfg,
1172
- to,
1173
- text,
1174
- mediaUrl,
1175
- mediaLocalRoots,
1176
- mediaReadFile,
1177
- accountId,
1178
- deps,
1179
- replyToId,
1180
- abortSignal
1181
- })
1154
+ afterDeliverPayload: registerDeliveredSignalApprovalPayloadForReactions,
1155
+ renderPresentation: renderSignalApprovalPayloadForReactions,
1156
+ sendFormattedText: sendFormattedSignalText,
1157
+ sendFormattedMedia: sendFormattedSignalMedia
1182
1158
  },
1183
1159
  attachedResults: {
1184
1160
  channel: "signal",
1185
- sendText: async ({ cfg, to, text, accountId, deps, replyToId }) => await sendSignalOutbound({
1186
- cfg,
1187
- to,
1188
- text,
1189
- accountId: accountId ?? void 0,
1190
- deps,
1191
- replyToId
1192
- }),
1193
- sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId }) => await sendSignalOutbound({
1194
- cfg,
1195
- to,
1196
- text,
1197
- mediaUrl,
1198
- mediaLocalRoots,
1199
- mediaReadFile,
1200
- accountId: accountId ?? void 0,
1201
- deps,
1202
- replyToId
1203
- })
1161
+ sendText: sendSignalOutbound,
1162
+ sendMedia: sendSignalOutbound
1204
1163
  }
1205
1164
  }
1206
1165
  });
@@ -1,2 +1,2 @@
1
- import { t as SignalChannelConfigSchema } from "./config-schema-DLvpQPN5.js";
1
+ import { t as SignalChannelConfigSchema } from "./config-schema-CkMIK7zp.js";
2
2
  export { SignalChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as signalPlugin } from "./channel-CBIljGCH.js";
1
+ import { t as signalPlugin } from "./channel-CzDJMDtX.js";
2
2
  export { signalPlugin };
@@ -1,6 +1,6 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-DrStJjiK.js";
2
- import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-CBIljGCH.js";
3
- import { i as installSignalCli } from "./install-signal-cli-qJF7iC4h.js";
2
+ import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-CzDJMDtX.js";
3
+ import { i as installSignalCli } from "./install-signal-cli-Cpiyk0k1.js";
4
4
  import { detectBinary } from "openclaw/plugin-sdk/setup-tools";
5
5
  import { createDetectedBinaryStatus, createSetupTranslator, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
6
6
  //#region extensions/signal/src/setup-surface.ts
@@ -1,7 +1,6 @@
1
- import { detectMime, parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
1
+ import { detectMime, extractOriginalFilename, parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
2
2
  import { parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
3
- import nodePath from "node:path";
4
- import { formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
3
+ import { coerceErrorMessage, formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
5
4
  import { resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
6
5
  import { readResponseTextPrefix, readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
7
6
  import { readRegularFile } from "openclaw/plugin-sdk/security-runtime";
@@ -24,6 +23,7 @@ const SIGNAL_REST_ERROR_RESPONSE_MAX_BYTES = 16 * 1024;
24
23
  const SIGNAL_REST_SUCCESS_RESPONSE_MAX_BYTES = 16 * 1024 * 1024;
25
24
  const WS_MAX_PAYLOAD = 1024 * 1024;
26
25
  const WS_HANDSHAKE_MS = 3e4;
26
+ const WS_SHUTDOWN_DRAIN_TIMEOUT_MS = 1500;
27
27
  const DEFAULT_SIGNAL_CONTAINER_MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024;
28
28
  const CONTAINER_TEXT_STYLE_MARKERS = {
29
29
  BOLD: "**",
@@ -148,7 +148,7 @@ async function containerCheck(baseUrl, timeoutMs = DEFAULT_TIMEOUT_MS$1, account
148
148
  return {
149
149
  ok: false,
150
150
  status: null,
151
- error: err instanceof Error ? err.message : String(err)
151
+ error: coerceErrorMessage(err)
152
152
  };
153
153
  } finally {
154
154
  await releaseUnreadResponseBody(res);
@@ -181,7 +181,7 @@ function containerReceiveCheck(normalizedBaseUrl, account, timeoutMs) {
181
181
  settle({
182
182
  ok: false,
183
183
  status: null,
184
- error: err instanceof Error ? err.message : String(err)
184
+ error: coerceErrorMessage(err)
185
185
  });
186
186
  return;
187
187
  }
@@ -205,7 +205,7 @@ function containerReceiveCheck(normalizedBaseUrl, account, timeoutMs) {
205
205
  settle({
206
206
  ok: false,
207
207
  status: null,
208
- error: err instanceof Error ? err.message : String(err)
208
+ error: coerceErrorMessage(err)
209
209
  });
210
210
  });
211
211
  ws.once("close", (code, reason) => {
@@ -297,7 +297,12 @@ async function streamContainerEvents(params) {
297
297
  let settled = false;
298
298
  let eventChain = Promise.resolve();
299
299
  let abortHandler;
300
+ let shutdownDrainTimer;
300
301
  const cleanup = () => {
302
+ if (shutdownDrainTimer) {
303
+ clearTimeout(shutdownDrainTimer);
304
+ shutdownDrainTimer = void 0;
305
+ }
301
306
  if (abortHandler) {
302
307
  params.abortSignal?.removeEventListener("abort", abortHandler);
303
308
  abortHandler = void 0;
@@ -321,12 +326,13 @@ async function streamContainerEvents(params) {
321
326
  handshakeTimeout: WS_HANDSHAKE_MS
322
327
  });
323
328
  } catch (err) {
324
- logError(`[signal-ws] failed to create WebSocket: ${err instanceof Error ? err.message : String(err)}`);
329
+ logError(`[signal-ws] failed to create WebSocket: ${coerceErrorMessage(err)}`);
325
330
  reject(toErrorObject(err, "Non-Error rejection"));
326
331
  return;
327
332
  }
328
333
  ws.on("open", () => {
329
334
  log("[signal-ws] connected");
335
+ params.onStreamOpen?.();
330
336
  });
331
337
  ws.on("message", (data) => {
332
338
  if (settled) return;
@@ -338,17 +344,17 @@ async function streamContainerEvents(params) {
338
344
  await params.onEvent(envelope);
339
345
  });
340
346
  eventChain.catch((err) => {
341
- logError(`[signal-ws] receive handler failed: ${err instanceof Error ? err.message : String(err)}`);
347
+ logError(`[signal-ws] receive handler failed: ${coerceErrorMessage(err)}`);
342
348
  rejectOnce(err);
343
349
  ws.close();
344
350
  });
345
351
  }
346
352
  } catch (err) {
347
- logError(`[signal-ws] parse error: ${err instanceof Error ? err.message : String(err)}`);
353
+ logError(`[signal-ws] parse error: ${coerceErrorMessage(err)}`);
348
354
  }
349
355
  });
350
356
  ws.on("error", (err) => {
351
- logError(`[signal-ws] error: ${err instanceof Error ? err.message : String(err)}`);
357
+ logError(`[signal-ws] error: ${coerceErrorMessage(err)}`);
352
358
  });
353
359
  ws.on("close", (code, reason) => {
354
360
  const reasonStr = reason?.toString() || "no reason";
@@ -364,10 +370,16 @@ async function streamContainerEvents(params) {
364
370
  if (params.abortSignal) {
365
371
  abortHandler = () => {
366
372
  log("[signal-ws] aborted, closing connection");
373
+ shutdownDrainTimer = setTimeout(() => {
374
+ logError("[signal-ws] shutdown timed out draining accepted receive events; messages may be lost");
375
+ ws.terminate();
376
+ resolveOnce();
377
+ }, WS_SHUTDOWN_DRAIN_TIMEOUT_MS);
378
+ shutdownDrainTimer.unref?.();
367
379
  ws.close();
368
- resolveOnce();
369
380
  };
370
381
  params.abortSignal.addEventListener("abort", abortHandler, { once: true });
382
+ if (params.abortSignal.aborted) abortHandler();
371
383
  }
372
384
  });
373
385
  }
@@ -388,7 +400,7 @@ async function filesToBase64DataUris(filePaths, maxAttachmentBytes) {
388
400
  buffer,
389
401
  filePath
390
402
  }) ?? "application/octet-stream";
391
- const filename = nodePath.basename(filePath);
403
+ const filename = extractOriginalFilename(filePath).replace(/[,;#]/g, "_");
392
404
  const b64 = buffer.toString("base64");
393
405
  results.push(`data:${mime};filename=${filename};base64,${b64}`);
394
406
  }
@@ -492,7 +504,7 @@ async function containerSendReceipt(params) {
492
504
  return true;
493
505
  }
494
506
  /**
495
- * Send a reaction to a message via bbernhard container REST API.
507
+ * Add or remove a message reaction via the bbernhard container REST API.
496
508
  */
497
509
  async function containerSendReaction(params) {
498
510
  const payload = {
@@ -505,23 +517,7 @@ async function containerSendReaction(params) {
505
517
  return await containerRestRequest(`/v1/reactions/${encodeURIComponent(params.account)}`, {
506
518
  baseUrl: params.baseUrl,
507
519
  timeoutMs: params.timeoutMs
508
- }, "POST", payload) ?? {};
509
- }
510
- /**
511
- * Remove a reaction from a message via bbernhard container REST API.
512
- */
513
- async function containerRemoveReaction(params) {
514
- const payload = {
515
- recipient: params.recipient,
516
- reaction: params.emoji,
517
- target_author: params.targetAuthor,
518
- timestamp: params.targetTimestamp
519
- };
520
- if (params.groupId) payload.group_id = params.groupId;
521
- return await containerRestRequest(`/v1/reactions/${encodeURIComponent(params.account)}`, {
522
- baseUrl: params.baseUrl,
523
- timeoutMs: params.timeoutMs
524
- }, "DELETE", payload) ?? {};
520
+ }, params.remove ? "DELETE" : "POST", payload) ?? {};
525
521
  }
526
522
  /**
527
523
  * Strip the "uuid:" prefix that native signal-cli accepts but the container API rejects.
@@ -605,7 +601,7 @@ async function containerRpcRequest(method, params, opts) {
605
601
  const groupId = p.groupIds?.[0] ?? void 0;
606
602
  const formattedGroupId = groupId ? formatGroupIdForContainer(groupId) : void 0;
607
603
  const effectiveRecipient = formattedGroupId || recipient || "";
608
- const reactionParams = {
604
+ return await containerSendReaction({
609
605
  baseUrl: opts.baseUrl,
610
606
  account: p.account ?? "",
611
607
  recipient: effectiveRecipient,
@@ -613,9 +609,9 @@ async function containerRpcRequest(method, params, opts) {
613
609
  targetAuthor: stripUuidPrefix(p.targetAuthor ?? recipient),
614
610
  targetTimestamp: p.targetTimestamp,
615
611
  groupId: formattedGroupId,
616
- timeoutMs: opts.timeoutMs
617
- };
618
- return await (p.remove ? containerRemoveReaction : containerSendReaction)(reactionParams);
612
+ timeoutMs: opts.timeoutMs,
613
+ remove: Boolean(p.remove)
614
+ });
619
615
  }
620
616
  case "getAttachment": {
621
617
  const attachmentId = p.id;
@@ -864,6 +860,7 @@ async function streamSignalEvents(params) {
864
860
  const url = resolveSignalEndpointUrl(params.baseUrl, "/api/v1/events");
865
861
  if (params.account) url.searchParams.set("account", params.account);
866
862
  const { response, cleanup } = await openSignalEventStream(url, params.abortSignal, params.timeoutMs ?? DEFAULT_TIMEOUT_MS);
863
+ params.onStreamOpen?.();
867
864
  const decoder = new TextDecoder();
868
865
  let buffer = "";
869
866
  let bufferedBytes = 0;