@openclaw/signal 2026.7.1 → 2026.7.2-beta.1

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
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { n as signalRpcRequest, t as signalCheck } from "./client-adapter-C9mB2Jz8.js";
2
+ import { n as signalRpcRequest, t as signalCheck } from "./client-adapter-aEM0kGhC.js";
3
3
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
4
4
  //#region extensions/signal/src/probe.ts
5
5
  var probe_exports = /* @__PURE__ */ __exportAll({ probeSignal: () => probeSignal });
@@ -1,5 +1,5 @@
1
1
  import { i as resolveSignalAccount } from "./accounts-Bz4HtP0g.js";
2
- import { n as signalRpcRequest } from "./client-adapter-C9mB2Jz8.js";
2
+ import { n as signalRpcRequest } from "./client-adapter-aEM0kGhC.js";
3
3
  import { t as resolveSignalRpcContext } from "./rpc-context-DsHWh2hc.js";
4
4
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -1,2 +1,2 @@
1
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-EQ7cc7-Y.js";
1
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-DifyinAU.js";
2
2
  export { removeReactionSignal, sendReactionSignal };
@@ -1,7 +1,8 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-Bz4HtP0g.js";
2
- import { d as normalizeSignalMessagingTarget } from "./identity-C8-yk4J9.js";
3
- import { n as signalApprovalAuth, t as getSignalApprovalApprovers } from "./approval-auth-CsHNcAiy.js";
4
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-EQ7cc7-Y.js";
2
+ import { d as normalizeSignalMessagingTarget } from "./identity-BF8taj7g.js";
3
+ import { i as signalApprovalAuth, r as getSignalApprovalApprovers, t as getOptionalSignalRuntime } from "./runtime-BZ9hnS3a.js";
4
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-DifyinAU.js";
5
+ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
5
6
  import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
6
7
  import { resolveReactionLevel } from "openclaw/plugin-sdk/status-helpers";
7
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -12,6 +13,8 @@ import { createChannelApproverDmTargetResolver, createChannelNativeOriginTargetR
12
13
  import { buildApprovalReactionPendingContentForRequest } from "openclaw/plugin-sdk/approval-reaction-runtime";
13
14
  import { createActionGate, jsonResult, readStringParam, resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
14
15
  import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
16
+ import { getExecApprovalReplyMetadata } from "openclaw/plugin-sdk/approval-reply-runtime";
17
+ import { isMessagePresentationInteractiveBlock, normalizeMessagePresentation, renderMessagePresentationFallbackText } from "openclaw/plugin-sdk/interactive-runtime";
15
18
  //#region extensions/signal/src/approval-native.ts
16
19
  const DEFAULT_APPROVAL_FORWARDING_MODE = "session";
17
20
  function isSignalApprovalTransportEnabled(params) {
@@ -205,12 +208,13 @@ const signalApprovalCapability = createChannelApprovalCapability({
205
208
  cfg,
206
209
  accountId
207
210
  }),
208
- shouldHandle: ({ cfg, accountId, context, request }) => Boolean(context) && shouldHandleSignalApprovalRequest({
211
+ shouldHandle: ({ cfg, accountId, context, approvalKind, request }) => Boolean(context) && shouldHandleSignalApprovalRequest({
209
212
  cfg,
210
213
  accountId,
214
+ approvalKind,
211
215
  request
212
216
  }),
213
- load: async () => (await import("./approval-handler.runtime-DDQ4ZRyc.js")).signalApprovalNativeRuntime
217
+ load: async () => (await import("./approval-handler.runtime-I1SMFwwR.js")).signalApprovalNativeRuntime
214
218
  })
215
219
  });
216
220
  //#endregion
@@ -342,7 +346,7 @@ function renderSignalText(ir) {
342
346
  cursor = link.end;
343
347
  }
344
348
  out += text.slice(cursor);
345
- const adjusted = applyInsertionsToStyles(ir.styles.map((span) => {
349
+ const mappedStyles = ir.styles.map((span) => {
346
350
  const mapped = mapStyle(span.style);
347
351
  if (!mapped) return null;
348
352
  return {
@@ -350,7 +354,13 @@ function renderSignalText(ir) {
350
354
  end: span.end,
351
355
  style: mapped
352
356
  };
353
- }).filter((span) => span !== null), insertions);
357
+ }).filter((span) => span !== null);
358
+ for (const annotation of ir.annotations ?? []) if (annotation.type === "assistant_transcript_role") mappedStyles.push({
359
+ start: annotation.start,
360
+ end: annotation.end,
361
+ style: "MONOSPACE"
362
+ });
363
+ const adjusted = applyInsertionsToStyles(mappedStyles, insertions);
354
364
  const trimmedText = out.trimEnd();
355
365
  const trimmedLength = trimmedText.length;
356
366
  return {
@@ -364,6 +374,7 @@ function renderSignalText(ir) {
364
374
  }
365
375
  function markdownToSignalText(markdown, options = {}) {
366
376
  return renderSignalText(markdownToIR(markdown ?? "", {
377
+ assistantTranscriptRoleHeaders: true,
367
378
  linkify: true,
368
379
  enableSpoilers: true,
369
380
  headingStyle: "bold",
@@ -374,6 +385,7 @@ function markdownToSignalText(markdown, options = {}) {
374
385
  function markdownToSignalTextChunks(markdown, limit, options = {}) {
375
386
  return renderMarkdownIRChunksWithinLimit({
376
387
  ir: markdownToIR(markdown ?? "", {
388
+ assistantTranscriptRoleHeaders: true,
377
389
  linkify: true,
378
390
  enableSpoilers: true,
379
391
  headingStyle: "bold",
@@ -381,6 +393,7 @@ function markdownToSignalTextChunks(markdown, limit, options = {}) {
381
393
  tableMode: options.tableMode
382
394
  }),
383
395
  limit,
396
+ assistantTranscriptRoleMessageBoundaries: true,
384
397
  renderChunk: renderSignalText,
385
398
  measureRendered: (rendered) => rendered.text.length
386
399
  }).map(({ rendered }) => rendered);
@@ -461,7 +474,16 @@ const signalMessageActions = {
461
474
  if (configuredAccounts.some((account) => createActionGate(account.config.actions)("reactions"))) actions.add("react");
462
475
  return { actions: Array.from(actions) };
463
476
  },
464
- supportsAction: ({ action }) => action !== "send",
477
+ supportsAction: ({ action }) => action === "react",
478
+ prepareSendPayload: ({ ctx, payload, replyToId, replyToIdSource }) => {
479
+ if (ctx.action !== "send") return null;
480
+ const normalizedReplyToId = replyToId?.trim();
481
+ if (!normalizedReplyToId) return payload;
482
+ return replyToIdSource === "implicit" ? payload : {
483
+ ...payload,
484
+ replyToId: normalizedReplyToId
485
+ };
486
+ },
465
487
  handleAction: async ({ action, params, cfg, accountId, toolContext }) => {
466
488
  if (action === "send") throw new Error("Send should be handled by outbound, not actions handler.");
467
489
  if (action === "react") {
@@ -522,4 +544,185 @@ const signalMessageActions = {
522
544
  }
523
545
  };
524
546
  //#endregion
525
- export { isSignalNativeApprovalHandlerConfigured as a, markdownToSignalTextChunks as i, resolveSignalReactionLevel as n, shouldSuppressLocalSignalExecApprovalPrompt as o, markdownToSignalText as r, signalApprovalCapability as s, signalMessageActions as t };
547
+ //#region extensions/signal/src/presentation-fallback.ts
548
+ /** Materialize presentation content once before Signal's text-only delivery funnels. */
549
+ function materializeSignalPresentationFallback(payload, presentationOverride) {
550
+ const presentation = presentationOverride ?? normalizeMessagePresentation(payload.presentation);
551
+ if (!presentation) return payload;
552
+ const currentText = payload.text?.trim() ?? "";
553
+ const presentationFallback = renderMessagePresentationFallbackText({ presentation: Boolean(getExecApprovalReplyMetadata(payload) && currentText) ? {
554
+ ...presentation,
555
+ blocks: presentation.blocks.filter((block) => !isMessagePresentationInteractiveBlock(block))
556
+ } : presentation });
557
+ const text = currentText.includes(presentationFallback) ? currentText : [currentText, presentationFallback].filter(Boolean).join("\n\n");
558
+ const { presentation: _presentation, ...withoutPresentation } = payload;
559
+ return {
560
+ ...withoutPresentation,
561
+ text
562
+ };
563
+ }
564
+ //#endregion
565
+ //#region extensions/signal/src/reply-authors.ts
566
+ const PERSISTENT_NAMESPACE = "signal.reply-authors.v1";
567
+ const PERSISTENT_MAX_ENTRIES = 5e3;
568
+ const DEFAULT_REPLY_AUTHOR_TTL_MS = 10080 * 60 * 1e3;
569
+ const memoryReplyContexts = /* @__PURE__ */ new Map();
570
+ let persistentStoreDisabled = false;
571
+ function openSignalReplyAuthorStore() {
572
+ if (persistentStoreDisabled) return;
573
+ const runtime = getOptionalSignalRuntime();
574
+ try {
575
+ return runtime?.state.openKeyedStore({
576
+ namespace: PERSISTENT_NAMESPACE,
577
+ maxEntries: PERSISTENT_MAX_ENTRIES,
578
+ defaultTtlMs: DEFAULT_REPLY_AUTHOR_TTL_MS
579
+ });
580
+ } catch (error) {
581
+ persistentStoreDisabled = true;
582
+ runtime?.logging.getChildLogger({
583
+ plugin: "signal",
584
+ feature: "reply-author-state"
585
+ }).warn("Signal persistent reply author state unavailable", { error: String(error) });
586
+ return;
587
+ }
588
+ }
589
+ function buildSignalReplyAuthorStoreKey(params) {
590
+ const conversationKey = normalizeSignalMessagingTarget(params.to);
591
+ const replyToId = normalizeOptionalString(params.replyToId);
592
+ if (!conversationKey || !replyToId) return;
593
+ return `account=${normalizeLowercaseStringOrEmpty(normalizeOptionalString(params.accountId) ?? DEFAULT_ACCOUNT_ID)}|to=${conversationKey}|id=${replyToId}`;
594
+ }
595
+ function pruneMemoryReplyContexts(now = Date.now()) {
596
+ for (const [key, record] of memoryReplyContexts) if (record.expiresAt <= now) memoryReplyContexts.delete(key);
597
+ while (memoryReplyContexts.size > PERSISTENT_MAX_ENTRIES) {
598
+ const oldestKey = memoryReplyContexts.keys().next().value;
599
+ if (!oldestKey) break;
600
+ memoryReplyContexts.delete(oldestKey);
601
+ }
602
+ }
603
+ function resolveReplyContext(record) {
604
+ if (!record) return;
605
+ if (record.kind === "ambiguous") return { ambiguous: true };
606
+ const author = normalizeOptionalString(record.author);
607
+ if (!author) return;
608
+ const body = normalizeOptionalString(record.body);
609
+ return {
610
+ author,
611
+ ...body ? { body } : {}
612
+ };
613
+ }
614
+ function resolveSourceTimestamp(value) {
615
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : Date.now();
616
+ }
617
+ function mergeReplyContext(current, next) {
618
+ if (!current) return next;
619
+ if (current.kind === "ambiguous") return current;
620
+ if (current.author !== next.author) {
621
+ const { author: _author, body: _body, ...identity } = next;
622
+ return {
623
+ ...identity,
624
+ kind: "ambiguous"
625
+ };
626
+ }
627
+ return next.sourceTimestamp >= current.sourceTimestamp ? next : current;
628
+ }
629
+ async function registerSignalReplyContext(params) {
630
+ const store = openSignalReplyAuthorStore();
631
+ const key = buildSignalReplyAuthorStoreKey(params);
632
+ const author = normalizeOptionalString(params.author);
633
+ const body = normalizeOptionalString(params.body);
634
+ const conversationKey = normalizeSignalMessagingTarget(params.to);
635
+ const replyToId = normalizeOptionalString(params.replyToId);
636
+ const accountKey = normalizeLowercaseStringOrEmpty(normalizeOptionalString(params.accountId) ?? DEFAULT_ACCOUNT_ID);
637
+ const sourceTimestamp = resolveSourceTimestamp(params.sourceTimestamp);
638
+ if (!key || !author || !conversationKey || !replyToId) return;
639
+ const registeredAt = Date.now();
640
+ const record = {
641
+ kind: "resolved",
642
+ author,
643
+ ...body ? { body } : {},
644
+ accountId: accountKey,
645
+ conversationKey,
646
+ replyToId,
647
+ sourceTimestamp,
648
+ registeredAt
649
+ };
650
+ const expiresAt = registeredAt + DEFAULT_REPLY_AUTHOR_TTL_MS;
651
+ if (!store) {
652
+ const next = mergeReplyContext(memoryReplyContexts.get(key), record);
653
+ memoryReplyContexts.set(key, {
654
+ ...next,
655
+ expiresAt
656
+ });
657
+ pruneMemoryReplyContexts(registeredAt);
658
+ return;
659
+ }
660
+ if (!store.update) {
661
+ const next = mergeReplyContext(memoryReplyContexts.get(key), record);
662
+ memoryReplyContexts.set(key, {
663
+ ...next,
664
+ expiresAt
665
+ });
666
+ pruneMemoryReplyContexts(registeredAt);
667
+ persistentStoreDisabled = true;
668
+ getOptionalSignalRuntime()?.logging.getChildLogger({
669
+ plugin: "signal",
670
+ feature: "reply-author-state"
671
+ }).warn("Signal persistent reply author state lacks atomic updates");
672
+ return;
673
+ }
674
+ let updateEvaluated = false;
675
+ let nextRecord;
676
+ try {
677
+ if (await store.update(key, (current) => {
678
+ updateEvaluated = true;
679
+ nextRecord = mergeReplyContext(current, record);
680
+ return nextRecord;
681
+ }) && nextRecord) memoryReplyContexts.set(key, {
682
+ ...nextRecord,
683
+ expiresAt
684
+ });
685
+ else memoryReplyContexts.delete(key);
686
+ pruneMemoryReplyContexts(registeredAt);
687
+ } catch (error) {
688
+ if (!updateEvaluated) try {
689
+ nextRecord = mergeReplyContext(await store.lookup(key), record);
690
+ } catch {
691
+ nextRecord = void 0;
692
+ }
693
+ const next = nextRecord;
694
+ if (next) memoryReplyContexts.set(key, {
695
+ ...next,
696
+ expiresAt
697
+ });
698
+ else if (updateEvaluated) memoryReplyContexts.delete(key);
699
+ pruneMemoryReplyContexts(registeredAt);
700
+ getOptionalSignalRuntime()?.logging.getChildLogger({
701
+ plugin: "signal",
702
+ feature: "reply-author-state"
703
+ }).warn("Signal persistent reply author state failed", { error: String(error) });
704
+ }
705
+ }
706
+ async function resolveSignalReplyContextWithPersistence(params) {
707
+ const store = openSignalReplyAuthorStore();
708
+ const key = buildSignalReplyAuthorStoreKey(params);
709
+ if (!key) return;
710
+ if (!store) {
711
+ pruneMemoryReplyContexts();
712
+ return resolveReplyContext(memoryReplyContexts.get(key));
713
+ }
714
+ pruneMemoryReplyContexts();
715
+ const memoryContext = resolveReplyContext(memoryReplyContexts.get(key));
716
+ if (memoryContext) return memoryContext;
717
+ try {
718
+ return resolveReplyContext(await store.lookup(key));
719
+ } catch (error) {
720
+ getOptionalSignalRuntime()?.logging.getChildLogger({
721
+ plugin: "signal",
722
+ feature: "reply-author-state"
723
+ }).warn("Signal persistent reply author lookup failed", { error: String(error) });
724
+ return;
725
+ }
726
+ }
727
+ //#endregion
728
+ export { resolveSignalReactionLevel as a, isSignalNativeApprovalHandlerConfigured as c, signalMessageActions as i, shouldSuppressLocalSignalExecApprovalPrompt as l, resolveSignalReplyContextWithPersistence as n, markdownToSignalText as o, materializeSignalPresentationFallback as r, markdownToSignalTextChunks as s, registerSignalReplyContext as t, signalApprovalCapability as u };
@@ -1,8 +1,9 @@
1
1
  import { i as resolveSignalAccount } from "./accounts-Bz4HtP0g.js";
2
- import { d as normalizeSignalMessagingTarget, l as looksLikeUuid, u as looksLikeSignalTargetId } from "./identity-C8-yk4J9.js";
2
+ import { d as normalizeSignalMessagingTarget, l as looksLikeUuid, u as looksLikeSignalTargetId } from "./identity-BF8taj7g.js";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
- import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
4
+ import { createChannelApprovalAuth } from "openclaw/plugin-sdk/approval-auth-runtime";
5
5
  import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
6
+ import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
6
7
  //#region extensions/signal/src/aliases.ts
7
8
  function normalizeAliasKey(raw) {
8
9
  const trimmed = raw.trim();
@@ -124,28 +125,37 @@ function normalizeSignalApproverId(value) {
124
125
  const e164 = normalizeE164(normalized);
125
126
  return e164.length > 1 ? e164 : void 0;
126
127
  }
127
- function getSignalApprovalApprovers(params) {
128
- const account = resolveSignalAccount(params).config;
129
- let defaultTo = account.defaultTo;
130
- if (typeof account.defaultTo === "string") try {
131
- defaultTo = resolveSignalTarget({
132
- cfg: params.cfg,
133
- accountId: params.accountId,
134
- input: account.defaultTo
135
- })?.to ?? account.defaultTo;
136
- } catch {
137
- defaultTo = account.defaultTo;
138
- }
139
- return resolveApprovalApprovers({
140
- allowFrom: account.allowFrom,
141
- defaultTo,
142
- normalizeApprover: normalizeSignalApproverId
143
- });
144
- }
145
- const signalApprovalAuth = createResolvedApproverActionAuthAdapter({
128
+ const signalApproval = createChannelApprovalAuth({
146
129
  channelLabel: "Signal",
147
- resolveApprovers: getSignalApprovalApprovers,
148
- normalizeSenderId: (value) => normalizeSignalApproverId(value)
130
+ resolveInputs: ({ cfg, accountId }) => {
131
+ const account = resolveSignalAccount({
132
+ cfg,
133
+ accountId
134
+ }).config;
135
+ let defaultTo = account.defaultTo;
136
+ if (typeof account.defaultTo === "string") try {
137
+ defaultTo = resolveSignalTarget({
138
+ cfg,
139
+ accountId,
140
+ input: account.defaultTo
141
+ })?.to ?? account.defaultTo;
142
+ } catch {
143
+ defaultTo = account.defaultTo;
144
+ }
145
+ return {
146
+ allowFrom: account.allowFrom,
147
+ defaultTo
148
+ };
149
+ },
150
+ normalizeApprover: normalizeSignalApproverId
151
+ });
152
+ const getSignalApprovalApprovers = signalApproval.resolveApprovers;
153
+ const signalApprovalAuth = signalApproval.approvalAuth;
154
+ //#endregion
155
+ //#region extensions/signal/src/runtime.ts
156
+ const { setRuntime: setSignalRuntime, tryGetRuntime: getOptionalSignalRuntime } = createPluginRuntimeStore({
157
+ pluginId: "signal",
158
+ errorMessage: "Signal runtime not initialized"
149
159
  });
150
160
  //#endregion
151
- export { resolveSignalTarget as i, signalApprovalAuth as n, listSignalAliasDirectoryEntries as r, getSignalApprovalApprovers as t };
161
+ export { listSignalAliasDirectoryEntries as a, signalApprovalAuth as i, setSignalRuntime as n, resolveSignalTarget as o, getSignalApprovalApprovers as r, getOptionalSignalRuntime as t };
@@ -1,13 +1,13 @@
1
1
  import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-Bz4HtP0g.js";
2
- import { d as normalizeSignalMessagingTarget, u as looksLikeSignalTargetId } from "./identity-C8-yk4J9.js";
3
- import { n as resolveSignalReactionLevel, 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 { n as buildChannelConfigSchema, t as SignalConfigSchema } from "./config-api-KS-qhQvD.js";
6
- import { r as installSignalCli } from "./install-signal-cli-ik8VPaGg.js";
7
- import { f as setSignalRuntime } from "./approval-reactions-UFmUPD0A.js";
8
- import { t as monitorSignalProvider } from "./monitor-Bee8O5Ay.js";
9
- import { t as sendMessageSignal } from "./send-CUJy6WPt.js";
10
- import { t as probeSignal } from "./probe-Cnht8Ihg.js";
2
+ import { d as normalizeSignalMessagingTarget, u as looksLikeSignalTargetId } from "./identity-BF8taj7g.js";
3
+ import { n as setSignalRuntime } from "./runtime-BZ9hnS3a.js";
4
+ import { a as resolveSignalReactionLevel, i as signalMessageActions } from "./reply-authors-osU_SY4J.js";
5
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-DifyinAU.js";
6
+ import { n as buildChannelConfigSchema, t as SignalConfigSchema } from "./config-api-DIg1lInT.js";
7
+ import { i as installSignalCli } from "./install-signal-cli-CtusY3tN.js";
8
+ import { t as monitorSignalProvider } from "./monitor-BdzH3U64.js";
9
+ import { t as sendMessageSignal } from "./send-BWtA6h3J.js";
10
+ import { t as probeSignal } from "./probe-CbWkI24J.js";
11
11
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
12
12
  import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
13
13
  import { buildBaseAccountStatusSnapshot, buildBaseChannelStatusSummary, collectStatusIssuesFromLastError, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
@@ -1,8 +1,9 @@
1
1
  import { i as resolveSignalAccount } from "./accounts-Bz4HtP0g.js";
2
- import { r as markdownToSignalText } from "./message-actions-3OLDgjis.js";
3
- import { n as signalRpcRequest } from "./client-adapter-C9mB2Jz8.js";
2
+ import { d as normalizeSignalMessagingTarget } from "./identity-BF8taj7g.js";
3
+ import { o as markdownToSignalText, t as registerSignalReplyContext } from "./reply-authors-osU_SY4J.js";
4
+ import { n as signalRpcRequest } from "./client-adapter-aEM0kGhC.js";
4
5
  import { t as resolveSignalRpcContext } from "./rpc-context-DsHWh2hc.js";
5
- import { c as registerSignalApprovalReactionTargetForOutboundMessage, n as appendSignalApprovalReactionHintForOutboundMessage } from "./approval-reactions-UFmUPD0A.js";
6
+ import { c as registerSignalApprovalReactionTargetForOutboundMessage, n as appendSignalApprovalReactionHintForOutboundMessage } from "./approval-reactions-ChcS2rQN.js";
6
7
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
7
8
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
8
9
  import { kindFromMime, resolveOutboundAttachmentFromUrl } from "openclaw/plugin-sdk/media-runtime";
@@ -18,9 +19,8 @@ async function resolveSignalRpcAccountInfo(opts) {
18
19
  });
19
20
  }
20
21
  function parseTarget(raw) {
21
- let value = raw.trim();
22
+ const value = normalizeSignalMessagingTarget(raw);
22
23
  if (!value) throw new Error("Signal recipient is required");
23
- if (normalizeLowercaseStringOrEmpty(value).startsWith("signal:")) value = value.slice(7).trim();
24
24
  const normalized = normalizeLowercaseStringOrEmpty(value);
25
25
  if (normalized.startsWith("group:")) return {
26
26
  type: "group",
@@ -30,10 +30,6 @@ function parseTarget(raw) {
30
30
  type: "username",
31
31
  username: value.slice(9).trim()
32
32
  };
33
- if (normalized.startsWith("u:")) return {
34
- type: "username",
35
- username: value.trim()
36
- };
37
33
  return {
38
34
  type: "recipient",
39
35
  recipient: value
@@ -193,6 +189,15 @@ async function sendMessageSignal(to, text, opts) {
193
189
  else result = await signalRpcRequest("send", params, sendOpts);
194
190
  const timestamp = result?.timestamp;
195
191
  const messageId = timestamp ? String(timestamp) : "unknown";
192
+ const replyAuthor = targetAuthor ?? targetAuthorUuid;
193
+ if (timestamp && replyAuthor) await registerSignalReplyContext({
194
+ accountId: accountInfo.accountId,
195
+ to,
196
+ replyToId: messageId,
197
+ author: replyAuthor,
198
+ body: message,
199
+ sourceTimestamp: timestamp
200
+ });
196
201
  registerSignalApprovalReactionTargetForOutboundMessage({
197
202
  cfg,
198
203
  accountId: accountInfo.accountId,
@@ -1,2 +1,2 @@
1
- import { r as sendTypingSignal, t as sendMessageSignal } from "./send-CUJy6WPt.js";
1
+ import { r as sendTypingSignal, t as sendMessageSignal } from "./send-BWtA6h3J.js";
2
2
  export { sendMessageSignal, sendTypingSignal };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/signal",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/signal",
9
- "version": "2026.7.1",
9
+ "version": "2026.7.2-beta.1",
10
10
  "dependencies": {
11
11
  "ws": "8.21.0"
12
12
  }
@@ -269,33 +269,45 @@
269
269
  "exclusiveMinimum": 0,
270
270
  "maximum": 9007199254740991
271
271
  },
272
- "chunkMode": {
273
- "type": "string",
274
- "enum": [
275
- "length",
276
- "newline"
277
- ]
278
- },
279
- "blockStreaming": {
280
- "type": "boolean"
281
- },
282
- "blockStreamingCoalesce": {
272
+ "streaming": {
283
273
  "type": "object",
284
274
  "properties": {
285
- "minChars": {
286
- "type": "integer",
287
- "exclusiveMinimum": 0,
288
- "maximum": 9007199254740991
289
- },
290
- "maxChars": {
291
- "type": "integer",
292
- "exclusiveMinimum": 0,
293
- "maximum": 9007199254740991
275
+ "chunkMode": {
276
+ "type": "string",
277
+ "enum": [
278
+ "length",
279
+ "newline"
280
+ ]
294
281
  },
295
- "idleMs": {
296
- "type": "integer",
297
- "minimum": 0,
298
- "maximum": 9007199254740991
282
+ "block": {
283
+ "type": "object",
284
+ "properties": {
285
+ "enabled": {
286
+ "type": "boolean"
287
+ },
288
+ "coalesce": {
289
+ "type": "object",
290
+ "properties": {
291
+ "minChars": {
292
+ "type": "integer",
293
+ "exclusiveMinimum": 0,
294
+ "maximum": 9007199254740991
295
+ },
296
+ "maxChars": {
297
+ "type": "integer",
298
+ "exclusiveMinimum": 0,
299
+ "maximum": 9007199254740991
300
+ },
301
+ "idleMs": {
302
+ "type": "integer",
303
+ "minimum": 0,
304
+ "maximum": 9007199254740991
305
+ }
306
+ },
307
+ "additionalProperties": false
308
+ }
309
+ },
310
+ "additionalProperties": false
299
311
  }
300
312
  },
301
313
  "additionalProperties": false
@@ -705,33 +717,45 @@
705
717
  "exclusiveMinimum": 0,
706
718
  "maximum": 9007199254740991
707
719
  },
708
- "chunkMode": {
709
- "type": "string",
710
- "enum": [
711
- "length",
712
- "newline"
713
- ]
714
- },
715
- "blockStreaming": {
716
- "type": "boolean"
717
- },
718
- "blockStreamingCoalesce": {
720
+ "streaming": {
719
721
  "type": "object",
720
722
  "properties": {
721
- "minChars": {
722
- "type": "integer",
723
- "exclusiveMinimum": 0,
724
- "maximum": 9007199254740991
725
- },
726
- "maxChars": {
727
- "type": "integer",
728
- "exclusiveMinimum": 0,
729
- "maximum": 9007199254740991
723
+ "chunkMode": {
724
+ "type": "string",
725
+ "enum": [
726
+ "length",
727
+ "newline"
728
+ ]
730
729
  },
731
- "idleMs": {
732
- "type": "integer",
733
- "minimum": 0,
734
- "maximum": 9007199254740991
730
+ "block": {
731
+ "type": "object",
732
+ "properties": {
733
+ "enabled": {
734
+ "type": "boolean"
735
+ },
736
+ "coalesce": {
737
+ "type": "object",
738
+ "properties": {
739
+ "minChars": {
740
+ "type": "integer",
741
+ "exclusiveMinimum": 0,
742
+ "maximum": 9007199254740991
743
+ },
744
+ "maxChars": {
745
+ "type": "integer",
746
+ "exclusiveMinimum": 0,
747
+ "maximum": 9007199254740991
748
+ },
749
+ "idleMs": {
750
+ "type": "integer",
751
+ "minimum": 0,
752
+ "maximum": 9007199254740991
753
+ }
754
+ },
755
+ "additionalProperties": false
756
+ }
757
+ },
758
+ "additionalProperties": false
735
759
  }
736
760
  },
737
761
  "additionalProperties": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/signal",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "description": "OpenClaw Signal channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -44,10 +44,10 @@
44
44
  "allowInvalidConfigRecovery": true
45
45
  },
46
46
  "compat": {
47
- "pluginApi": ">=2026.7.1"
47
+ "pluginApi": ">=2026.7.2-beta.1"
48
48
  },
49
49
  "build": {
50
- "openclawVersion": "2026.7.1",
50
+ "openclawVersion": "2026.7.2-beta.1",
51
51
  "bundledDist": false
52
52
  },
53
53
  "release": {
@@ -70,7 +70,7 @@
70
70
  "README.md"
71
71
  ],
72
72
  "peerDependencies": {
73
- "openclaw": ">=2026.7.1"
73
+ "openclaw": ">=2026.7.2-beta.1"
74
74
  },
75
75
  "peerDependenciesMeta": {
76
76
  "openclaw": {
@@ -1,2 +0,0 @@
1
- import { SignalConfigSchema, buildChannelConfigSchema } from "openclaw/plugin-sdk/bundled-channel-config-schema";
2
- export { buildChannelConfigSchema as n, SignalConfigSchema as t };