@openclaw/signal 2026.7.1 → 2026.7.2-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 (28) hide show
  1. package/dist/api.js +8 -8
  2. package/dist/{approval-handler.runtime-DDQ4ZRyc.js → approval-handler.runtime-I1SMFwwR.js} +4 -4
  3. package/dist/{approval-reactions-UFmUPD0A.js → approval-reactions-ChcS2rQN.js} +34 -25
  4. package/dist/{approval-resolver-BR0MioAA.js → approval-resolver-B3m0D2R0.js} +2 -1
  5. package/dist/{channel-Cnhy1RwG.js → channel-DK8XZHPe.js} +132 -42
  6. package/dist/channel-config-api.js +1 -1
  7. package/dist/channel-plugin-api.js +1 -1
  8. package/dist/{channel.runtime-CQN0RaFx.js → channel.runtime-BbDh5UIr.js} +3 -2
  9. package/dist/{client-adapter-C9mB2Jz8.js → client-adapter-aEM0kGhC.js} +52 -18
  10. package/dist/config-api-DIg1lInT.js +3 -0
  11. package/dist/{config-schema-BiojLEsX.js → config-schema-CfVNH0DB.js} +7 -9
  12. package/dist/contract-api.js +3 -3
  13. package/dist/doctor-contract-api.js +16 -0
  14. package/dist/{identity-C8-yk4J9.js → identity-BF8taj7g.js} +7 -4
  15. package/dist/{install-signal-cli-ik8VPaGg.js → install-signal-cli-CtusY3tN.js} +43 -32
  16. package/dist/{monitor-Bee8O5Ay.js → monitor-BdzH3U64.js} +331 -126
  17. package/dist/{probe-Cnht8Ihg.js → probe-CbWkI24J.js} +1 -1
  18. package/dist/{reaction-runtime-api-EQ7cc7-Y.js → reaction-runtime-api-DifyinAU.js} +1 -1
  19. package/dist/reaction-runtime-api.js +1 -1
  20. package/dist/{message-actions-3OLDgjis.js → reply-authors-osU_SY4J.js} +212 -9
  21. package/dist/{approval-auth-CsHNcAiy.js → runtime-BZ9hnS3a.js} +34 -24
  22. package/dist/runtime-api.js +9 -9
  23. package/dist/{send-CUJy6WPt.js → send-BWtA6h3J.js} +14 -9
  24. package/dist/{send.runtime-CEi5oyCG.js → send.runtime-D4WBNNgn.js} +1 -1
  25. package/npm-shrinkwrap.json +2 -2
  26. package/openclaw.plugin.json +72 -48
  27. package/package.json +4 -4
  28. package/dist/config-api-KS-qhQvD.js +0 -2
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-Bz4HtP0g.js";
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-C8-yk4J9.js";
3
- import { i as markdownToSignalTextChunks, n as resolveSignalReactionLevel, r as markdownToSignalText, t as signalMessageActions } from "./message-actions-3OLDgjis.js";
4
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-EQ7cc7-Y.js";
5
- import { a as normalizeSignalAccountInput, l as signalSetupAdapter, n as createSignalPluginBase, r as signalSetupWizard, t as signalPlugin, u as resolveSignalOutboundTarget } from "./channel-Cnhy1RwG.js";
6
- import { a as looksLikeArchive, n as extractSignalCliArchive, o as pickAsset, r as installSignalCli } from "./install-signal-cli-ik8VPaGg.js";
7
- import { t as monitorSignalProvider } from "./monitor-Bee8O5Ay.js";
8
- import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-CUJy6WPt.js";
9
- import { t as probeSignal } from "./probe-Cnht8Ihg.js";
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-BF8taj7g.js";
3
+ import { a as resolveSignalReactionLevel, i as signalMessageActions, o as markdownToSignalText, s as markdownToSignalTextChunks } from "./reply-authors-osU_SY4J.js";
4
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-DifyinAU.js";
5
+ import { a as normalizeSignalAccountInput, l as signalSetupAdapter, n as createSignalPluginBase, r as signalSetupWizard, t as signalPlugin, u as resolveSignalOutboundTarget } from "./channel-DK8XZHPe.js";
6
+ import { i as installSignalCli, o as looksLikeArchive, r as extractSignalCliArchive, s as pickAsset } from "./install-signal-cli-CtusY3tN.js";
7
+ import { t as monitorSignalProvider } from "./monitor-BdzH3U64.js";
8
+ import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-BWtA6h3J.js";
9
+ import { t as probeSignal } from "./probe-CbWkI24J.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-Bz4HtP0g.js";
2
- import { d as normalizeSignalMessagingTarget } from "./identity-C8-yk4J9.js";
3
- import { i as resolveSignalTarget } from "./approval-auth-CsHNcAiy.js";
4
- import { d as unregisterSignalApprovalReactionTarget, i as hasSignalApprovalReactionApprovers, l as resolveSignalApprovalConversationKey, o as registerSignalApprovalReactionTarget, u as resolveSignalApprovalTargetAuthorKeys } from "./approval-reactions-UFmUPD0A.js";
5
- import { r as sendTypingSignal, t as sendMessageSignal } from "./send-CUJy6WPt.js";
2
+ import { d as normalizeSignalMessagingTarget } from "./identity-BF8taj7g.js";
3
+ import { o as resolveSignalTarget } from "./runtime-BZ9hnS3a.js";
4
+ import { d as unregisterSignalApprovalReactionTarget, i as hasSignalApprovalReactionApprovers, l as resolveSignalApprovalConversationKey, o as registerSignalApprovalReactionTarget, u as resolveSignalApprovalTargetAuthorKeys } from "./approval-reactions-ChcS2rQN.js";
5
+ import { r as sendTypingSignal, t as sendMessageSignal } from "./send-BWtA6h3J.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,20 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { d as normalizeSignalMessagingTarget, l as looksLikeUuid } from "./identity-C8-yk4J9.js";
3
- import { i as resolveSignalTarget, n as signalApprovalAuth, t as getSignalApprovalApprovers } from "./approval-auth-CsHNcAiy.js";
2
+ import { d as normalizeSignalMessagingTarget, l as looksLikeUuid } from "./identity-BF8taj7g.js";
3
+ import { i as signalApprovalAuth, o as resolveSignalTarget, r as getSignalApprovalApprovers, t as getOptionalSignalRuntime } from "./runtime-BZ9hnS3a.js";
4
4
  import { createLazyRuntimeModule } 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, resolveApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
7
+ import { addApprovalReactionHintToText, buildApprovalReactionHint, createApprovalReactionTargetStore, hasApprovalReactionHintText, listApprovalReactionBindings, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
8
8
  import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
9
- import { matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
10
9
  import { getExecApprovalReplyMetadata } from "openclaw/plugin-sdk/approval-reply-runtime";
11
- import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
12
- //#region extensions/signal/src/runtime.ts
13
- const { setRuntime: setSignalRuntime, getRuntime: getSignalRuntime, tryGetRuntime: getOptionalSignalRuntime, clearRuntime: clearSignalRuntime } = createPluginRuntimeStore({
14
- pluginId: "signal",
15
- errorMessage: "Signal runtime not initialized"
16
- });
17
- //#endregion
10
+ import { matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
18
11
  //#region extensions/signal/src/approval-reactions.ts
19
12
  var approval_reactions_exports = /* @__PURE__ */ __exportAll({
20
13
  addSignalApprovalReactionHintToStructuredPayload: () => addSignalApprovalReactionHintToStructuredPayload,
@@ -35,7 +28,7 @@ var approval_reactions_exports = /* @__PURE__ */ __exportAll({
35
28
  const PERSISTENT_NAMESPACE = "signal.approval-reactions.v2";
36
29
  const PERSISTENT_MAX_ENTRIES = 1e3;
37
30
  const DEFAULT_REACTION_TARGET_TTL_MS = 1440 * 60 * 1e3;
38
- const resolverRuntimeLoader = createLazyRuntimeModule(() => import("./approval-resolver-BR0MioAA.js"));
31
+ const resolverRuntimeLoader = createLazyRuntimeModule(() => import("./approval-resolver-B3m0D2R0.js"));
39
32
  const signalApprovalReactionTargets = createApprovalReactionTargetStore({
40
33
  namespace: PERSISTENT_NAMESPACE,
41
34
  maxEntries: PERSISTENT_MAX_ENTRIES,
@@ -45,9 +38,6 @@ const signalApprovalReactionTargets = createApprovalReactionTargetStore({
45
38
  readPersistedTarget
46
39
  });
47
40
  const loadApprovalResolver = resolverRuntimeLoader;
48
- function resolveApprovalKindFromId(approvalId) {
49
- return approvalId.startsWith("plugin:") ? "plugin" : "exec";
50
- }
51
41
  function resolveApprovalForwardingConfig(params) {
52
42
  return params.approvalKind === "plugin" ? params.cfg.approvals?.plugin : params.cfg.approvals?.exec;
53
43
  }
@@ -224,12 +214,16 @@ function extractSignalApprovalPromptBinding(text) {
224
214
  const idHeaderMatch = lines.map((line) => line.match(APPROVAL_ID_LINE_RE)).find((match) => Boolean(match));
225
215
  if (!idHeaderMatch) return null;
226
216
  const approvalId = idHeaderMatch[1];
227
- const approvalKind = resolveStandaloneApprovalPromptKind(text) ?? resolveApprovalKindFromId(approvalId);
217
+ if (!approvalId) return null;
218
+ const approvalKind = resolveStandaloneApprovalPromptKind(text);
219
+ if (!approvalKind) return null;
228
220
  const allowedDecisions = [];
229
221
  for (const line of lines) {
230
222
  const match = line.match(APPROVE_REPLY_COMMAND_LINE_RE);
231
- if (!match || match[1] !== approvalId) continue;
232
- for (const decisionText of match[2].split(/[\s|,]+/)) {
223
+ const commandApprovalId = match?.[1];
224
+ const decisionList = match?.[2];
225
+ if (commandApprovalId !== approvalId || !decisionList) continue;
226
+ for (const decisionText of decisionList.split(/[\s|,]+/)) {
233
227
  const decision = normalizeApprovalDecision(decisionText);
234
228
  if (decision && !allowedDecisions.includes(decision)) allowedDecisions.push(decision);
235
229
  }
@@ -257,7 +251,7 @@ function buildTargetRoute(params) {
257
251
  return isSignalApprovalReactionRouteStillEnabled({
258
252
  cfg: params.cfg,
259
253
  target: {
260
- approvalKind: params.approvalKind ?? resolveApprovalKindFromId(params.approvalId),
254
+ approvalKind: params.approvalKind,
261
255
  route
262
256
  }
263
257
  }) ? route : null;
@@ -300,7 +294,7 @@ function registerSignalApprovalReactionTarget(params) {
300
294
  const approvalId = params.approvalId.trim();
301
295
  const targetAuthorKeys = Array.from(new Set(params.targetAuthorKeys.map((entry) => normalizeSignalApprovalTargetAuthorKey(entry)).filter((entry) => Boolean(entry))));
302
296
  const allowedDecisions = listSignalApprovalReactionBindings(params.allowedDecisions).map((binding) => binding.decision);
303
- if (!params.routeAllowed || !key || !approvalId || allowedDecisions.length === 0) return null;
297
+ if (!params.routeAllowed || params.approvalKind !== "exec" && params.approvalKind !== "plugin" || !key || !approvalId || allowedDecisions.length === 0) return null;
304
298
  if (targetAuthorKeys.length === 0) return null;
305
299
  const route = params.route.deliveryMode === "target" ? {
306
300
  deliveryMode: "target",
@@ -315,7 +309,7 @@ function registerSignalApprovalReactionTarget(params) {
315
309
  };
316
310
  const target = {
317
311
  approvalId,
318
- approvalKind: params.approvalKind ?? resolveApprovalKindFromId(approvalId),
312
+ approvalKind: params.approvalKind,
319
313
  allowedDecisions,
320
314
  targetAuthorKeys,
321
315
  route
@@ -323,6 +317,10 @@ function registerSignalApprovalReactionTarget(params) {
323
317
  signalApprovalReactionTargets.register(key, target, { ttlMs: params.ttlMs });
324
318
  return target;
325
319
  }
320
+ function formatSignalApprovalTerminalTruth(approval) {
321
+ const decision = "decision" in approval ? ` decision=${approval.decision}` : "";
322
+ return `status=${approval.status}${decision}`;
323
+ }
326
324
  function addSignalApprovalReactionHintToStructuredPayload(params) {
327
325
  const metadata = getExecApprovalReplyMetadata(params.payload);
328
326
  if (!metadata?.allowedDecisions || metadata.allowedDecisions.length === 0) return null;
@@ -449,7 +447,7 @@ function resolveTarget(params) {
449
447
  const target = params.target;
450
448
  if (!target) return null;
451
449
  if (params.targetAuthorKeys.length === 0 || !params.targetAuthorKeys.some((key) => target.targetAuthorKeys.includes(key))) return null;
452
- const resolved = resolveApprovalReactionTarget({
450
+ const resolved = resolveTypedApprovalReactionTarget({
453
451
  target,
454
452
  reactionKey: params.reactionKey
455
453
  });
@@ -513,14 +511,25 @@ async function maybeResolveSignalApprovalReaction(params) {
513
511
  }
514
512
  const { isApprovalNotFoundError, resolveSignalApproval } = await loadApprovalResolver();
515
513
  try {
516
- await resolveSignalApproval({
514
+ const result = await resolveSignalApproval({
517
515
  cfg: params.cfg,
518
516
  approvalId: target.approvalId,
517
+ approvalKind: target.approvalKind,
519
518
  decision: target.decision,
520
519
  senderId: actorId,
521
520
  gatewayUrl: params.gatewayUrl
522
521
  });
523
- params.logVerboseMessage?.(`signal: approval reaction resolved id=${target.approvalId} sender=${actorId} decision=${target.decision}`);
522
+ const terminalTruth = formatSignalApprovalTerminalTruth(result.approval);
523
+ unregisterSignalApprovalReactionTarget({
524
+ accountId: params.accountId,
525
+ conversationKey: params.conversationKey,
526
+ messageId: params.messageId
527
+ });
528
+ if (!result.applied) {
529
+ params.logVerboseMessage?.(`signal: approval reaction already resolved id=${target.approvalId} sender=${actorId} ${terminalTruth}`);
530
+ return true;
531
+ }
532
+ params.logVerboseMessage?.(`signal: approval reaction resolved id=${target.approvalId} sender=${actorId} ${terminalTruth}`);
524
533
  return true;
525
534
  } catch (error) {
526
535
  if (isApprovalNotFoundError(error)) {
@@ -541,4 +550,4 @@ function clearSignalApprovalReactionTargetsForTest() {
541
550
  resolverRuntimeLoader.clear();
542
551
  }
543
552
  //#endregion
544
- export { maybeResolveSignalApprovalReaction as a, registerSignalApprovalReactionTargetForOutboundMessage as c, unregisterSignalApprovalReactionTarget as d, setSignalRuntime as f, 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 };
553
+ 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,9 +2,10 @@ import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
2
2
  import { resolveApprovalOverGateway } from "openclaw/plugin-sdk/approval-gateway-runtime";
3
3
  //#region extensions/signal/src/approval-resolver.ts
4
4
  async function resolveSignalApproval(params) {
5
- await resolveApprovalOverGateway({
5
+ return await resolveApprovalOverGateway({
6
6
  cfg: params.cfg,
7
7
  approvalId: params.approvalId,
8
+ approvalKind: params.approvalKind,
8
9
  decision: params.decision,
9
10
  senderId: params.senderId,
10
11
  gatewayUrl: params.gatewayUrl,
@@ -1,12 +1,12 @@
1
1
  import { a as resolveSignalReplyToMode, i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId } from "./accounts-Bz4HtP0g.js";
2
- import { c as resolveSignalSender, d as normalizeSignalMessagingTarget, l as looksLikeUuid, o as resolveSignalPeerId, s as resolveSignalRecipient, u as looksLikeSignalTargetId } from "./identity-C8-yk4J9.js";
3
- import { i as resolveSignalTarget, r as listSignalAliasDirectoryEntries } from "./approval-auth-CsHNcAiy.js";
4
- import { i as markdownToSignalTextChunks, n as resolveSignalReactionLevel, o as shouldSuppressLocalSignalExecApprovalPrompt, s as signalApprovalCapability, t as signalMessageActions } from "./message-actions-3OLDgjis.js";
5
- import { t as SignalChannelConfigSchema } from "./config-schema-BiojLEsX.js";
2
+ import { c as resolveSignalSender, d as normalizeSignalMessagingTarget, l as looksLikeUuid, o as resolveSignalPeerId, s as resolveSignalRecipient, u as looksLikeSignalTargetId } from "./identity-BF8taj7g.js";
3
+ import { a as listSignalAliasDirectoryEntries, o as resolveSignalTarget } from "./runtime-BZ9hnS3a.js";
4
+ import { a as resolveSignalReactionLevel, i as signalMessageActions, l as shouldSuppressLocalSignalExecApprovalPrompt, n as resolveSignalReplyContextWithPersistence, r as materializeSignalPresentationFallback, s as markdownToSignalTextChunks, u as signalApprovalCapability } from "./reply-authors-osU_SY4J.js";
5
+ import { t as SignalChannelConfigSchema } from "./config-schema-CfVNH0DB.js";
6
6
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
7
7
  import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
8
8
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
9
- import { defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
9
+ import { createReplyToFanout, defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
10
10
  import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
11
11
  import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result";
12
12
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
@@ -27,11 +27,11 @@ import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "op
27
27
  import { createRestrictSendersChannelSecurity } from "openclaw/plugin-sdk/channel-policy";
28
28
  //#region extensions/signal/src/outbound-session.ts
29
29
  function resolveSignalOutboundTarget(target) {
30
- const stripped = target.replace(/^signal:/i, "").trim();
31
- const lowered = normalizeLowercaseStringOrEmpty(stripped);
30
+ const normalized = normalizeSignalMessagingTarget(target);
31
+ if (!normalized) return null;
32
+ const lowered = normalizeLowercaseStringOrEmpty(normalized);
32
33
  if (lowered.startsWith("group:")) {
33
- const groupId = stripped.slice(6).trim();
34
- if (!groupId) return null;
34
+ const groupId = normalized.slice(6);
35
35
  return {
36
36
  peer: {
37
37
  kind: "group",
@@ -42,10 +42,16 @@ function resolveSignalOutboundTarget(target) {
42
42
  to: `group:${groupId}`
43
43
  };
44
44
  }
45
- let recipient = stripped.trim();
46
- if (lowered.startsWith("username:")) recipient = stripped.slice(9).trim();
47
- else if (lowered.startsWith("u:")) recipient = stripped.slice(2).trim();
48
- if (!recipient) return null;
45
+ if (lowered.startsWith("username:")) return {
46
+ peer: {
47
+ kind: "direct",
48
+ id: normalized
49
+ },
50
+ chatType: "direct",
51
+ from: `signal:${normalized}`,
52
+ to: `signal:${normalized}`
53
+ };
54
+ const recipient = normalized;
49
55
  const uuidCandidate = normalizeLowercaseStringOrEmpty(recipient).startsWith("uuid:") ? recipient.slice(5) : recipient;
50
56
  const sender = resolveSignalSender({
51
57
  sourceUuid: looksLikeUuid(uuidCandidate) ? uuidCandidate : null,
@@ -240,7 +246,7 @@ function createSignalSetupWizardProxy(loadWizard) {
240
246
  //#region extensions/signal/src/shared.ts
241
247
  const SIGNAL_CHANNEL = "signal";
242
248
  async function loadSignalChannelRuntime() {
243
- return await import("./channel.runtime-CQN0RaFx.js");
249
+ return await import("./channel.runtime-BbDh5UIr.js");
244
250
  }
245
251
  const signalSetupWizard = createSignalSetupWizardProxy(async () => (await loadSignalChannelRuntime()).signalSetupWizard);
246
252
  const signalConfigAdapter = {
@@ -326,10 +332,10 @@ function createSignalPluginBase(params) {
326
332
  }
327
333
  //#endregion
328
334
  //#region extensions/signal/src/channel.ts
329
- const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-Bee8O5Ay.js").then((n) => n.n));
330
- const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-Cnht8Ihg.js").then((n) => n.n));
331
- const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-CEi5oyCG.js"));
332
- const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-UFmUPD0A.js").then((n) => n.r));
335
+ const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-BdzH3U64.js").then((n) => n.n));
336
+ const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-CbWkI24J.js").then((n) => n.n));
337
+ const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-D4WBNNgn.js"));
338
+ const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-ChcS2rQN.js").then((n) => n.r));
333
339
  async function resolveSignalSendContext(params) {
334
340
  return {
335
341
  send: resolveOutboundSendDep(params.deps, "signal") ?? (await loadSignalSendRuntime()).sendMessageSignal,
@@ -349,15 +355,53 @@ function resolveSignalSendTarget(params) {
349
355
  }
350
356
  async function sendSignalOutbound(params) {
351
357
  const { send, maxBytes } = await resolveSignalSendContext(params);
352
- return await send(resolveSignalSendTarget(params), params.text, {
358
+ const to = resolveSignalSendTarget(params);
359
+ const replyOptions = await resolveSignalReplyOptions({
360
+ cfg: params.cfg,
361
+ to,
362
+ accountId: params.accountId,
363
+ replyToId: params.replyToId
364
+ });
365
+ return await send(to, params.text, {
353
366
  cfg: params.cfg,
354
367
  ...params.mediaUrl ? { mediaUrl: params.mediaUrl } : {},
355
368
  ...params.mediaLocalRoots?.length ? { mediaLocalRoots: params.mediaLocalRoots } : {},
356
369
  ...params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {},
357
370
  maxBytes,
358
- accountId: params.accountId ?? void 0
371
+ accountId: params.accountId ?? void 0,
372
+ ...replyOptions
373
+ });
374
+ }
375
+ function resolveSignalReplyOptions(params) {
376
+ const replyToId = normalizeOptionalString(params.replyToId);
377
+ if (!replyToId) return Promise.resolve({});
378
+ const accountId = resolveSignalAccount({
379
+ cfg: params.cfg,
380
+ accountId: params.accountId
381
+ }).accountId;
382
+ return resolveSignalReplyContextWithPersistence({
383
+ accountId,
384
+ to: params.to,
385
+ replyToId
386
+ }).then((persistedContext) => {
387
+ const replyToAuthor = persistedContext?.ambiguous === true ? void 0 : persistedContext?.author;
388
+ return {
389
+ replyToId,
390
+ ...replyToAuthor ? { replyToAuthor } : {},
391
+ ...persistedContext?.body ? { replyToBody: persistedContext.body } : {}
392
+ };
359
393
  });
360
394
  }
395
+ function inferSignalTargetChatType(rawTo) {
396
+ let to = rawTo.trim();
397
+ if (!to) return;
398
+ if (/^signal:/i.test(to)) to = to.replace(/^signal:/i, "").trim();
399
+ if (!to) return;
400
+ const lower = normalizeLowercaseStringOrEmpty(to);
401
+ if (lower.startsWith("group:")) return "group";
402
+ if (lower.startsWith("username:") || lower.startsWith("u:")) return "direct";
403
+ return "direct";
404
+ }
361
405
  function attachSignalVisibleText(result, visibleText) {
362
406
  const meta = "meta" in result && result.meta && typeof result.meta === "object" ? result.meta : {};
363
407
  return {
@@ -380,7 +424,8 @@ const signalMessageAdapter = defineChannelMessageAdapter({
380
424
  to: ctx.to,
381
425
  text: ctx.text,
382
426
  accountId: ctx.accountId ?? void 0,
383
- deps: ctx.deps
427
+ deps: ctx.deps,
428
+ replyToId: ctx.replyToId ?? void 0
384
429
  }),
385
430
  media: async (ctx) => await sendSignalOutbound({
386
431
  cfg: ctx.cfg,
@@ -390,20 +435,11 @@ const signalMessageAdapter = defineChannelMessageAdapter({
390
435
  mediaLocalRoots: ctx.mediaLocalRoots,
391
436
  mediaReadFile: ctx.mediaReadFile,
392
437
  accountId: ctx.accountId ?? void 0,
393
- deps: ctx.deps
438
+ deps: ctx.deps,
439
+ replyToId: ctx.replyToId ?? void 0
394
440
  })
395
441
  }
396
442
  });
397
- function inferSignalTargetChatType(rawTo) {
398
- let to = rawTo.trim();
399
- if (!to) return;
400
- if (/^signal:/i.test(to)) to = to.replace(/^signal:/i, "").trim();
401
- if (!to) return;
402
- const lower = normalizeLowercaseStringOrEmpty(to);
403
- if (lower.startsWith("group:")) return "group";
404
- if (lower.startsWith("username:") || lower.startsWith("u:")) return "direct";
405
- return "direct";
406
- }
407
443
  function buildSignalBaseSessionKey(params) {
408
444
  return buildOutboundBaseSessionKey({
409
445
  ...params,
@@ -451,15 +487,32 @@ async function sendFormattedSignalText(ctx) {
451
487
  text: ctx.text,
452
488
  styles: []
453
489
  }];
490
+ const nextReplyToId = createReplyToFanout({
491
+ replyToId: ctx.replyToId,
492
+ replyToIdSource: ctx.replyToIdSource,
493
+ replyToMode: ctx.replyToMode ?? resolveSignalReplyToMode({
494
+ cfg: ctx.cfg,
495
+ accountId: ctx.accountId,
496
+ chatType: inferSignalTargetChatType(to)
497
+ })
498
+ });
454
499
  const results = [];
455
500
  for (const chunk of chunks) {
456
501
  ctx.abortSignal?.throwIfAborted();
502
+ const replyToId = nextReplyToId();
503
+ const replyOptions = await resolveSignalReplyOptions({
504
+ cfg: ctx.cfg,
505
+ to,
506
+ accountId: ctx.accountId,
507
+ replyToId
508
+ });
457
509
  const deliveryResult = attachChannelToResult("signal", attachSignalVisibleText(await send(to, chunk.text, {
458
510
  cfg: ctx.cfg,
459
511
  maxBytes,
460
512
  accountId: ctx.accountId ?? void 0,
461
513
  textMode: "plain",
462
- textStyles: chunk.styles
514
+ textStyles: chunk.styles,
515
+ ...replyOptions
463
516
  }), chunk.text));
464
517
  results.push(deliveryResult);
465
518
  await ctx.onDeliveryResult?.(deliveryResult);
@@ -487,6 +540,12 @@ async function sendFormattedSignalMedia(ctx) {
487
540
  text: ctx.text,
488
541
  styles: []
489
542
  };
543
+ const replyOptions = await resolveSignalReplyOptions({
544
+ cfg: ctx.cfg,
545
+ to,
546
+ accountId: ctx.accountId,
547
+ replyToId: ctx.replyToId
548
+ });
490
549
  return attachChannelToResult("signal", attachSignalVisibleText(await send(to, formatted.text, {
491
550
  cfg: ctx.cfg,
492
551
  mediaUrl: ctx.mediaUrl,
@@ -495,7 +554,8 @@ async function sendFormattedSignalMedia(ctx) {
495
554
  maxBytes,
496
555
  accountId: ctx.accountId ?? void 0,
497
556
  textMode: "plain",
498
- textStyles: formatted.styles
557
+ textStyles: formatted.styles,
558
+ ...replyOptions
499
559
  }), formatted.text));
500
560
  }
501
561
  async function registerDeliveredSignalApprovalPayloadForReactions(params) {
@@ -528,11 +588,12 @@ async function renderSignalApprovalPayloadForReactions(params) {
528
588
  const targetAuthorUuid = normalizeOptionalString(account.config.accountUuid);
529
589
  if (!targetAuthor && !targetAuthorUuid) return null;
530
590
  const { addSignalApprovalReactionHintToStructuredPayload } = await loadSignalApprovalReactionsModule();
591
+ const payload = materializeSignalPresentationFallback(params.payload, params.presentation);
531
592
  return addSignalApprovalReactionHintToStructuredPayload({
532
593
  cfg: params.ctx.cfg,
533
594
  accountId: params.ctx.accountId ?? void 0,
534
595
  to: params.ctx.to,
535
- payload: params.payload,
596
+ payload,
536
597
  targetAuthor,
537
598
  targetAuthorUuid
538
599
  });
@@ -678,7 +739,30 @@ const signalPlugin = createChatChannelPlugin({
678
739
  }
679
740
  } },
680
741
  security: signalSecurityAdapter,
681
- threading: { resolveReplyToMode: (params) => resolveSignalReplyToMode(params) },
742
+ threading: {
743
+ resolveReplyToMode: (params) => resolveSignalReplyToMode(params),
744
+ matchesToolContextTarget: ({ target, toolContext }) => {
745
+ const normalizedTarget = normalizeSignalMessagingTarget(target);
746
+ if (!normalizedTarget) return false;
747
+ return [toolContext.currentMessagingTarget, toolContext.currentChannelId].some((currentTarget) => currentTarget != null && normalizeSignalMessagingTarget(currentTarget) === normalizedTarget);
748
+ },
749
+ buildToolContext: ({ cfg, accountId, context, hasRepliedRef }) => {
750
+ const currentMessagingTarget = normalizeOptionalString(context.To);
751
+ const currentChatType = context.ChatType === "direct" || context.ChatType === "group" ? context.ChatType : void 0;
752
+ return {
753
+ currentChannelId: normalizeOptionalString(context.NativeChannelId) ?? currentMessagingTarget,
754
+ currentChatType,
755
+ currentMessagingTarget,
756
+ currentMessageId: context.ReplyToId ?? context.CurrentMessageId,
757
+ replyToMode: resolveSignalReplyToMode({
758
+ cfg,
759
+ accountId,
760
+ chatType: currentChatType
761
+ }),
762
+ hasRepliedRef
763
+ };
764
+ }
765
+ },
682
766
  outbound: {
683
767
  base: {
684
768
  deliveryMode: "direct",
@@ -722,16 +806,19 @@ const signalPlugin = createChatChannelPlugin({
722
806
  }),
723
807
  afterDeliverPayload: async (params) => await registerDeliveredSignalApprovalPayloadForReactions(params),
724
808
  renderPresentation: async (params) => await renderSignalApprovalPayloadForReactions(params),
725
- sendFormattedText: async ({ cfg, to, text, accountId, deps, abortSignal, onDeliveryResult }) => await sendFormattedSignalText({
809
+ sendFormattedText: async ({ cfg, to, text, accountId, deps, replyToId, replyToIdSource, replyToMode, abortSignal, onDeliveryResult }) => await sendFormattedSignalText({
726
810
  cfg,
727
811
  to,
728
812
  text,
729
813
  accountId,
730
814
  deps,
815
+ replyToId,
816
+ replyToIdSource,
817
+ replyToMode,
731
818
  abortSignal,
732
819
  onDeliveryResult
733
820
  }),
734
- sendFormattedMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps, abortSignal }) => await sendFormattedSignalMedia({
821
+ sendFormattedMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId, abortSignal }) => await sendFormattedSignalMedia({
735
822
  cfg,
736
823
  to,
737
824
  text,
@@ -740,19 +827,21 @@ const signalPlugin = createChatChannelPlugin({
740
827
  mediaReadFile,
741
828
  accountId,
742
829
  deps,
830
+ replyToId,
743
831
  abortSignal
744
832
  })
745
833
  },
746
834
  attachedResults: {
747
835
  channel: "signal",
748
- sendText: async ({ cfg, to, text, accountId, deps }) => await sendSignalOutbound({
836
+ sendText: async ({ cfg, to, text, accountId, deps, replyToId }) => await sendSignalOutbound({
749
837
  cfg,
750
838
  to,
751
839
  text,
752
840
  accountId: accountId ?? void 0,
753
- deps
841
+ deps,
842
+ replyToId
754
843
  }),
755
- sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps }) => await sendSignalOutbound({
844
+ sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId }) => await sendSignalOutbound({
756
845
  cfg,
757
846
  to,
758
847
  text,
@@ -760,7 +849,8 @@ const signalPlugin = createChatChannelPlugin({
760
849
  mediaLocalRoots,
761
850
  mediaReadFile,
762
851
  accountId: accountId ?? void 0,
763
- deps
852
+ deps,
853
+ replyToId
764
854
  })
765
855
  }
766
856
  }
@@ -1,2 +1,2 @@
1
- import { t as SignalChannelConfigSchema } from "./config-schema-BiojLEsX.js";
1
+ import { t as SignalChannelConfigSchema } from "./config-schema-CfVNH0DB.js";
2
2
  export { SignalChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as signalPlugin } from "./channel-Cnhy1RwG.js";
1
+ import { t as signalPlugin } from "./channel-DK8XZHPe.js";
2
2
  export { signalPlugin };
@@ -1,6 +1,6 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-Bz4HtP0g.js";
2
- import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-Cnhy1RwG.js";
3
- import { r as installSignalCli } from "./install-signal-cli-ik8VPaGg.js";
2
+ import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-DK8XZHPe.js";
3
+ import { i as installSignalCli } from "./install-signal-cli-CtusY3tN.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
@@ -43,6 +43,7 @@ const signalSetupWizard = {
43
43
  initialValue: !cliDetected
44
44
  })) return;
45
45
  try {
46
+ await options?.beforePersistentEffect?.();
46
47
  const result = await installSignalCli(runtime);
47
48
  if (result.ok && result.cliPath) {
48
49
  await prompter.note(`Installed signal-cli at ${result.cliPath}`, "Signal");