@openclaw/signal 2026.6.11 → 2026.7.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.
@@ -1,6 +1,7 @@
1
- import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId } from "./accounts-hOCHbEhX.js";
1
+ import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId } from "./accounts-B7Rz3_xV.js";
2
2
  import { c as resolveSignalSender, d as normalizeSignalMessagingTarget, l as looksLikeUuid, o as resolveSignalPeerId, s as resolveSignalRecipient, u as looksLikeSignalTargetId } from "./identity-B6O4k8xg.js";
3
- import { i as markdownToSignalTextChunks, n as resolveSignalReactionLevel, o as shouldSuppressLocalSignalExecApprovalPrompt, s as signalApprovalCapability, t as signalMessageActions } from "./message-actions-Bue0g2Kc.js";
3
+ import { i as resolveSignalTarget, r as listSignalAliasDirectoryEntries } from "./approval-auth-DPVK9A_l.js";
4
+ import { i as markdownToSignalTextChunks, n as resolveSignalReactionLevel, o as shouldSuppressLocalSignalExecApprovalPrompt, s as signalApprovalCapability, t as signalMessageActions } from "./message-actions-Cs9XckSd.js";
4
5
  import { t as SignalChannelConfigSchema } from "./config-schema-BiojLEsX.js";
5
6
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
6
7
  import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
@@ -9,12 +10,14 @@ import { defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/pl
9
10
  import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
10
11
  import { attachChannelToResult, attachChannelToResults } from "openclaw/plugin-sdk/channel-send-result";
11
12
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
13
+ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
12
14
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
13
15
  import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
14
16
  import { chunkText, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
15
17
  import { buildOutboundBaseSessionKey } from "openclaw/plugin-sdk/routing";
16
18
  import { buildBaseChannelStatusSummary, collectStatusIssuesFromLastError, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
17
19
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringifiedEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
20
+ import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
18
21
  import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
19
22
  import { createChannelPluginBase, getChatChannelMeta } from "openclaw/plugin-sdk/core";
20
23
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, createCliPathTextInput, createDelegatedSetupWizardProxy, createDelegatedTextInputShouldPrompt, createPatchedAccountSetupAdapter, createSetupInputPresenceValidator, createSetupTranslator, mergeAllowFromEntries, parseSetupEntriesAllowingWildcard, patchChannelConfigForAccount, promptParsedAllowFromForAccount, setAccountAllowFromForChannel, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
@@ -176,9 +179,7 @@ function createSignalCliPathTextInput(shouldPrompt) {
176
179
  accountId,
177
180
  credentialValues
178
181
  }),
179
- shouldPrompt,
180
- helpTitle: "Signal",
181
- helpLines: ["signal-cli not found. Install it, then rerun this step or set channels.signal.cliPath."]
182
+ shouldPrompt
182
183
  });
183
184
  }
184
185
  const signalNumberTextInput = {
@@ -236,27 +237,45 @@ function createSignalSetupWizardProxy(loadWizard) {
236
237
  //#region extensions/signal/src/shared.ts
237
238
  const SIGNAL_CHANNEL = "signal";
238
239
  async function loadSignalChannelRuntime() {
239
- return await import("./channel.runtime-B0-YpkC4.js");
240
+ return await import("./channel.runtime-Ks7GIWM1.js");
240
241
  }
241
242
  const signalSetupWizard = createSignalSetupWizardProxy(async () => (await loadSignalChannelRuntime()).signalSetupWizard);
242
- const signalConfigAdapter = createScopedChannelConfigAdapter({
243
- sectionKey: SIGNAL_CHANNEL,
244
- listAccountIds: (cfg) => listSignalAccountIds(cfg),
245
- resolveAccount: adaptScopedAccountAccessor((params) => resolveSignalAccount(params)),
246
- defaultAccountId: (cfg) => resolveDefaultSignalAccountId(cfg),
247
- clearBaseFields: [
248
- "account",
249
- "configPath",
250
- "httpUrl",
251
- "httpHost",
252
- "httpPort",
253
- "cliPath",
254
- "name"
255
- ],
256
- resolveAllowFrom: (account) => account.config.allowFrom,
257
- formatAllowFrom: (allowFrom) => normalizeStringifiedEntries(allowFrom).map((entry) => entry === "*" ? "*" : normalizeE164(entry.replace(/^signal:/i, ""))).filter(Boolean),
258
- resolveDefaultTo: (account) => account.config.defaultTo
259
- });
243
+ const signalConfigAdapter = {
244
+ ...createScopedChannelConfigAdapter({
245
+ sectionKey: SIGNAL_CHANNEL,
246
+ listAccountIds: (cfg) => listSignalAccountIds(cfg),
247
+ resolveAccount: adaptScopedAccountAccessor((params) => resolveSignalAccount(params)),
248
+ defaultAccountId: (cfg) => resolveDefaultSignalAccountId(cfg),
249
+ clearBaseFields: [
250
+ "account",
251
+ "configPath",
252
+ "httpUrl",
253
+ "httpHost",
254
+ "httpPort",
255
+ "cliPath",
256
+ "name"
257
+ ],
258
+ resolveAllowFrom: (account) => account.config.allowFrom,
259
+ formatAllowFrom: (allowFrom) => normalizeStringifiedEntries(allowFrom).map((entry) => entry === "*" ? "*" : normalizeE164(entry.replace(/^signal:/i, ""))).filter(Boolean),
260
+ resolveDefaultTo: (account) => account.config.defaultTo
261
+ }),
262
+ resolveDefaultTo({ cfg, accountId }) {
263
+ const raw = resolveSignalAccount({
264
+ cfg,
265
+ accountId
266
+ }).config.defaultTo;
267
+ if (typeof raw !== "string" || !raw.trim()) return;
268
+ try {
269
+ return resolveSignalTarget({
270
+ cfg,
271
+ accountId,
272
+ input: raw
273
+ })?.to ?? raw.trim();
274
+ } catch {
275
+ return raw.trim();
276
+ }
277
+ }
278
+ };
260
279
  const signalSecurityAdapter = createRestrictSendersChannelSecurity({
261
280
  channelKey: SIGNAL_CHANNEL,
262
281
  resolveDmPolicy: (account) => account.config.dmPolicy,
@@ -304,21 +323,10 @@ function createSignalPluginBase(params) {
304
323
  }
305
324
  //#endregion
306
325
  //#region extensions/signal/src/channel.ts
307
- let signalMonitorModulePromise = null;
308
- let signalProbeModulePromise = null;
309
- let signalSendRuntimePromise = null;
310
- async function loadSignalMonitorModule() {
311
- signalMonitorModulePromise ??= import("./monitor-CUhIKHJo.js").then((n) => n.n);
312
- return await signalMonitorModulePromise;
313
- }
314
- async function loadSignalProbeModule() {
315
- signalProbeModulePromise ??= import("./probe-BQ_Izoya.js").then((n) => n.n);
316
- return await signalProbeModulePromise;
317
- }
318
- async function loadSignalSendRuntime() {
319
- signalSendRuntimePromise ??= import("./send.runtime-CfaZd8X4.js");
320
- return await signalSendRuntimePromise;
321
- }
326
+ const loadSignalMonitorModule = createLazyRuntimeModule(() => import("./monitor-C9SiyrFt.js").then((n) => n.n));
327
+ const loadSignalProbeModule = createLazyRuntimeModule(() => import("./probe-BL2BqTbG.js").then((n) => n.n));
328
+ const loadSignalSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-DgijYwpJ.js"));
329
+ const loadSignalApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-5x1kmQEq.js").then((n) => n.n));
322
330
  async function resolveSignalSendContext(params) {
323
331
  return {
324
332
  send: resolveOutboundSendDep(params.deps, "signal") ?? (await loadSignalSendRuntime()).sendMessageSignal,
@@ -329,9 +337,16 @@ async function resolveSignalSendContext(params) {
329
337
  })
330
338
  };
331
339
  }
340
+ function resolveSignalSendTarget(params) {
341
+ return resolveSignalTarget({
342
+ cfg: params.cfg,
343
+ accountId: params.accountId,
344
+ input: params.to
345
+ })?.to ?? params.to.trim();
346
+ }
332
347
  async function sendSignalOutbound(params) {
333
348
  const { send, maxBytes } = await resolveSignalSendContext(params);
334
- return await send(params.to, params.text, {
349
+ return await send(resolveSignalSendTarget(params), params.text, {
335
350
  cfg: params.cfg,
336
351
  ...params.mediaUrl ? { mediaUrl: params.mediaUrl } : {},
337
352
  ...params.mediaLocalRoots?.length ? { mediaLocalRoots: params.mediaLocalRoots } : {},
@@ -340,6 +355,16 @@ async function sendSignalOutbound(params) {
340
355
  accountId: params.accountId ?? void 0
341
356
  });
342
357
  }
358
+ function attachSignalVisibleText(result, visibleText) {
359
+ const meta = "meta" in result && result.meta && typeof result.meta === "object" ? result.meta : {};
360
+ return {
361
+ ...result,
362
+ meta: {
363
+ ...meta,
364
+ signalVisibleText: visibleText
365
+ }
366
+ };
367
+ }
343
368
  const signalMessageAdapter = defineChannelMessageAdapter({
344
369
  id: "signal",
345
370
  durableFinal: { capabilities: {
@@ -383,7 +408,7 @@ function buildSignalBaseSessionKey(params) {
383
408
  });
384
409
  }
385
410
  function resolveSignalOutboundSessionRoute(params) {
386
- const resolved = resolveSignalOutboundTarget(params.target);
411
+ const resolved = resolveSignalOutboundTarget(params.resolvedTarget?.to ?? params.target);
387
412
  if (!resolved) return null;
388
413
  const baseSessionKey = buildSignalBaseSessionKey({
389
414
  cfg: params.cfg,
@@ -404,6 +429,11 @@ async function sendFormattedSignalText(ctx) {
404
429
  deps: ctx.deps
405
430
  });
406
431
  const limit = resolveTextChunkLimit(ctx.cfg, "signal", ctx.accountId ?? void 0, { fallbackLimit: 4e3 });
432
+ const to = resolveSignalSendTarget({
433
+ cfg: ctx.cfg,
434
+ accountId: ctx.accountId ?? void 0,
435
+ to: ctx.to
436
+ });
407
437
  const tableMode = resolveMarkdownTableMode({
408
438
  cfg: ctx.cfg,
409
439
  channel: "signal",
@@ -417,14 +447,14 @@ async function sendFormattedSignalText(ctx) {
417
447
  const results = [];
418
448
  for (const chunk of chunks) {
419
449
  ctx.abortSignal?.throwIfAborted();
420
- const result = await send(ctx.to, chunk.text, {
450
+ const result = await send(to, chunk.text, {
421
451
  cfg: ctx.cfg,
422
452
  maxBytes,
423
453
  accountId: ctx.accountId ?? void 0,
424
454
  textMode: "plain",
425
455
  textStyles: chunk.styles
426
456
  });
427
- results.push(result);
457
+ results.push(attachSignalVisibleText(result, chunk.text));
428
458
  }
429
459
  return attachChannelToResults("signal", results);
430
460
  }
@@ -435,6 +465,11 @@ async function sendFormattedSignalMedia(ctx) {
435
465
  accountId: ctx.accountId ?? void 0,
436
466
  deps: ctx.deps
437
467
  });
468
+ const to = resolveSignalSendTarget({
469
+ cfg: ctx.cfg,
470
+ accountId: ctx.accountId ?? void 0,
471
+ to: ctx.to
472
+ });
438
473
  const tableMode = resolveMarkdownTableMode({
439
474
  cfg: ctx.cfg,
440
475
  channel: "signal",
@@ -444,7 +479,7 @@ async function sendFormattedSignalMedia(ctx) {
444
479
  text: ctx.text,
445
480
  styles: []
446
481
  };
447
- return attachChannelToResult("signal", await send(ctx.to, formatted.text, {
482
+ return attachChannelToResult("signal", attachSignalVisibleText(await send(to, formatted.text, {
448
483
  cfg: ctx.cfg,
449
484
  mediaUrl: ctx.mediaUrl,
450
485
  mediaLocalRoots: ctx.mediaLocalRoots,
@@ -453,7 +488,37 @@ async function sendFormattedSignalMedia(ctx) {
453
488
  accountId: ctx.accountId ?? void 0,
454
489
  textMode: "plain",
455
490
  textStyles: formatted.styles
456
- }));
491
+ }), formatted.text));
492
+ }
493
+ async function registerDeliveredSignalApprovalPayloadForReactions(params) {
494
+ const account = resolveSignalAccount({
495
+ cfg: params.cfg,
496
+ accountId: params.target.accountId ?? void 0
497
+ });
498
+ if (!account.config.account) return;
499
+ const { registerSignalApprovalReactionTargetForDeliveredPayload } = await loadSignalApprovalReactionsModule();
500
+ registerSignalApprovalReactionTargetForDeliveredPayload({
501
+ cfg: params.cfg,
502
+ target: params.target,
503
+ payload: params.payload,
504
+ results: params.results,
505
+ targetAuthor: account.config.account
506
+ });
507
+ }
508
+ async function renderSignalApprovalPayloadForReactions(params) {
509
+ const account = resolveSignalAccount({
510
+ cfg: params.ctx.cfg,
511
+ accountId: params.ctx.accountId ?? void 0
512
+ });
513
+ if (!account.config.account) return null;
514
+ const { addSignalApprovalReactionHintToStructuredPayload } = await loadSignalApprovalReactionsModule();
515
+ return addSignalApprovalReactionHintToStructuredPayload({
516
+ cfg: params.ctx.cfg,
517
+ accountId: params.ctx.accountId ?? void 0,
518
+ to: params.ctx.to,
519
+ payload: params.payload,
520
+ targetAuthor: account.config.account
521
+ });
457
522
  }
458
523
  const signalPlugin = createChatChannelPlugin({
459
524
  base: {
@@ -493,9 +558,44 @@ const signalPlugin = createChatChannelPlugin({
493
558
  resolveOutboundSessionRoute: (params) => resolveSignalOutboundSessionRoute(params),
494
559
  targetResolver: {
495
560
  looksLikeId: looksLikeSignalTargetId,
496
- hint: "<E.164|uuid:ID|group:ID|signal:group:ID|signal:+E.164>"
561
+ hint: "<E.164|uuid:ID|group:ID|signal:group:ID|signal:+E.164>",
562
+ resolveTarget: async ({ cfg, accountId, input }) => {
563
+ let target;
564
+ try {
565
+ target = resolveSignalTarget({
566
+ cfg,
567
+ accountId,
568
+ input
569
+ });
570
+ } catch {
571
+ return null;
572
+ }
573
+ if (!target) return null;
574
+ return {
575
+ to: target.to,
576
+ kind: target.kind,
577
+ display: target.source === "alias" ? target.alias : void 0,
578
+ source: target.source === "alias" ? "directory" : "normalized"
579
+ };
580
+ }
497
581
  }
498
582
  },
583
+ directory: {
584
+ listPeers: async ({ cfg, accountId, query, limit }) => listSignalAliasDirectoryEntries({
585
+ cfg,
586
+ accountId,
587
+ query,
588
+ limit,
589
+ kind: "user"
590
+ }),
591
+ listGroups: async ({ cfg, accountId, query, limit }) => listSignalAliasDirectoryEntries({
592
+ cfg,
593
+ accountId,
594
+ query,
595
+ limit,
596
+ kind: "group"
597
+ })
598
+ },
499
599
  heartbeat: {
500
600
  sendTyping: async ({ cfg, to, accountId }) => {
501
601
  await (await loadSignalSendRuntime()).sendTypingSignal(to, {
@@ -564,15 +664,46 @@ const signalPlugin = createChatChannelPlugin({
564
664
  outbound: {
565
665
  base: {
566
666
  deliveryMode: "direct",
667
+ resolveTarget: ({ cfg, to, accountId }) => {
668
+ const raw = to?.trim();
669
+ if (!raw) return {
670
+ ok: false,
671
+ error: /* @__PURE__ */ new Error("Signal target is required")
672
+ };
673
+ let target;
674
+ try {
675
+ target = resolveSignalTarget({
676
+ cfg: cfg ?? {},
677
+ accountId,
678
+ input: raw
679
+ });
680
+ } catch (error) {
681
+ return {
682
+ ok: false,
683
+ error: error instanceof Error ? error : new Error(String(error))
684
+ };
685
+ }
686
+ if (!target) return {
687
+ ok: false,
688
+ error: /* @__PURE__ */ new Error(`Unknown Signal alias or target "${raw}". Configure channels.signal.aliases.${raw.replace(/^signal:/i, "")} or use E.164, uuid:<id>, username:<name>, or group:<id>.`)
689
+ };
690
+ return {
691
+ ok: true,
692
+ to: target.to
693
+ };
694
+ },
567
695
  chunker: chunkText,
568
696
  chunkerMode: "text",
569
697
  textChunkLimit: 4e3,
698
+ sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text),
570
699
  shouldSuppressLocalPayloadPrompt: ({ cfg, accountId, payload, hint }) => shouldSuppressLocalSignalExecApprovalPrompt({
571
700
  cfg,
572
701
  accountId,
573
702
  payload,
574
703
  hint
575
704
  }),
705
+ afterDeliverPayload: async (params) => await registerDeliveredSignalApprovalPayloadForReactions(params),
706
+ renderPresentation: async (params) => await renderSignalApprovalPayloadForReactions(params),
576
707
  sendFormattedText: async ({ cfg, to, text, accountId, deps, abortSignal }) => await sendFormattedSignalText({
577
708
  cfg,
578
709
  to,
@@ -1,2 +1,2 @@
1
- import { t as signalPlugin } from "./channel-LmY2UpOt.js";
1
+ import { t as signalPlugin } from "./channel-BfWp-F-r.js";
2
2
  export { signalPlugin };
@@ -1,6 +1,6 @@
1
- import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-hOCHbEhX.js";
2
- import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-LmY2UpOt.js";
3
- import { r as installSignalCli } from "./install-signal-cli-CXgTF3de.js";
1
+ import { i as resolveSignalAccount, n as listSignalAccountIds } from "./accounts-B7Rz3_xV.js";
2
+ import { c as signalNumberTextInput, i as createSignalCliPathTextInput, o as signalCompletionNote, s as signalDmPolicy } from "./channel-BfWp-F-r.js";
3
+ import { r as installSignalCli } from "./install-signal-cli-TwhJ0DGy.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,11 +1,9 @@
1
- import { i as resolveSignalAccount } from "./accounts-hOCHbEhX.js";
2
1
  import { detectMime, parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
3
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
2
  import { asDateTimestampMs, parseStrictNonNegativeInteger, resolveExpiresAtMsFromDurationMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
5
- import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
6
3
  import fs from "node:fs/promises";
7
4
  import path from "node:path";
8
5
  import { resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
6
+ import { readProviderTextResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
9
7
  import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
10
8
  import WebSocket from "ws";
11
9
  import { Buffer as Buffer$1 } from "node:buffer";
@@ -176,12 +174,16 @@ async function containerRestRequest(endpoint, opts, method = "GET", body) {
176
174
  const res = await fetchWithTimeout(url, init, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS$2);
177
175
  if (res.status === 204) return;
178
176
  if (!res.ok) {
179
- const errorText = await res.text().catch(() => "");
177
+ const errorText = await readResponseTextLimited(res).catch(() => "");
180
178
  throw new Error(`Signal REST ${res.status}: ${errorText || res.statusText}`);
181
179
  }
182
- const text = await res.text();
180
+ const text = await readProviderTextResponse(res, "Signal REST");
183
181
  if (!text) return;
184
- return JSON.parse(text);
182
+ try {
183
+ return JSON.parse(text);
184
+ } catch {
185
+ throw new Error("Signal REST returned malformed JSON");
186
+ }
185
187
  }
186
188
  /**
187
189
  * Fetch attachment binary from bbernhard container.
@@ -948,127 +950,4 @@ async function streamSignalEvents(params) {
948
950
  });
949
951
  }
950
952
  //#endregion
951
- //#region extensions/signal/src/rpc-context.ts
952
- function resolveSignalRpcContext(opts, accountInfo) {
953
- const hasBaseUrl = Boolean(normalizeOptionalString(opts.baseUrl));
954
- const hasAccount = Boolean(normalizeOptionalString(opts.account));
955
- if ((!hasBaseUrl || !hasAccount) && !accountInfo) throw new Error("Signal account config is required when baseUrl or account is missing");
956
- const resolvedAccount = accountInfo;
957
- const baseUrl = normalizeOptionalString(opts.baseUrl) ?? resolvedAccount?.baseUrl;
958
- if (!baseUrl) throw new Error("Signal base URL is required");
959
- return {
960
- baseUrl,
961
- account: normalizeOptionalString(opts.account) ?? normalizeOptionalString(resolvedAccount?.config.account)
962
- };
963
- }
964
- //#endregion
965
- //#region extensions/signal/src/send-reactions.ts
966
- function normalizeSignalId(raw) {
967
- const trimmed = raw.trim();
968
- if (!trimmed) return "";
969
- return trimmed.replace(/^signal:/i, "").trim();
970
- }
971
- function normalizeSignalUuid(raw) {
972
- const trimmed = normalizeSignalId(raw);
973
- if (!trimmed) return "";
974
- if (normalizeLowercaseStringOrEmpty(trimmed).startsWith("uuid:")) return trimmed.slice(5).trim();
975
- return trimmed;
976
- }
977
- function resolveTargetAuthorParams(params) {
978
- const candidates = [
979
- params.targetAuthor,
980
- params.targetAuthorUuid,
981
- params.fallback
982
- ];
983
- for (const candidate of candidates) {
984
- const raw = candidate?.trim();
985
- if (!raw) continue;
986
- const normalized = normalizeSignalUuid(raw);
987
- if (normalized) return { targetAuthor: normalized };
988
- }
989
- return {};
990
- }
991
- async function sendReactionSignalCore(params) {
992
- const cfg = requireRuntimeConfig(params.opts.cfg, "Signal reactions");
993
- const apiMode = cfg.channels?.signal?.apiMode;
994
- const accountInfo = resolveSignalAccount({
995
- cfg,
996
- accountId: params.opts.accountId
997
- });
998
- const { baseUrl, account } = resolveSignalRpcContext(params.opts, accountInfo);
999
- const normalizedRecipient = normalizeSignalUuid(params.recipient);
1000
- const groupId = params.opts.groupId?.trim();
1001
- if (!normalizedRecipient && !groupId) throw new Error(params.errors.missingRecipient);
1002
- if (!Number.isFinite(params.targetTimestamp) || params.targetTimestamp <= 0) throw new Error(params.errors.invalidTargetTimestamp);
1003
- const normalizedEmoji = params.emoji?.trim();
1004
- if (!normalizedEmoji) throw new Error(params.errors.missingEmoji);
1005
- const targetAuthorParams = resolveTargetAuthorParams({
1006
- targetAuthor: params.opts.targetAuthor,
1007
- targetAuthorUuid: params.opts.targetAuthorUuid,
1008
- fallback: normalizedRecipient
1009
- });
1010
- if (groupId && !targetAuthorParams.targetAuthor) throw new Error(params.errors.missingTargetAuthor);
1011
- const requestParams = {
1012
- emoji: normalizedEmoji,
1013
- targetTimestamp: params.targetTimestamp,
1014
- ...params.remove ? { remove: true } : {},
1015
- ...targetAuthorParams
1016
- };
1017
- if (normalizedRecipient) requestParams.recipients = [normalizedRecipient];
1018
- if (groupId) requestParams.groupIds = [groupId];
1019
- if (account) requestParams.account = account;
1020
- return {
1021
- ok: true,
1022
- timestamp: (await signalRpcRequest("sendReaction", requestParams, {
1023
- baseUrl,
1024
- timeoutMs: params.opts.timeoutMs,
1025
- apiMode
1026
- }))?.timestamp
1027
- };
1028
- }
1029
- /**
1030
- * Send a Signal reaction to a message
1031
- * @param recipient - UUID or E.164 phone number of the message author
1032
- * @param targetTimestamp - Message ID (timestamp) to react to
1033
- * @param emoji - Emoji to react with
1034
- * @param opts - Optional account/connection overrides
1035
- */
1036
- async function sendReactionSignal(recipient, targetTimestamp, emoji, opts) {
1037
- return await sendReactionSignalCore({
1038
- recipient,
1039
- targetTimestamp,
1040
- emoji,
1041
- remove: false,
1042
- opts,
1043
- errors: {
1044
- missingRecipient: "Recipient or groupId is required for Signal reaction",
1045
- invalidTargetTimestamp: "Valid targetTimestamp is required for Signal reaction",
1046
- missingEmoji: "Emoji is required for Signal reaction",
1047
- missingTargetAuthor: "targetAuthor is required for group reactions"
1048
- }
1049
- });
1050
- }
1051
- /**
1052
- * Remove a Signal reaction from a message
1053
- * @param recipient - UUID or E.164 phone number of the message author
1054
- * @param targetTimestamp - Message ID (timestamp) to remove reaction from
1055
- * @param emoji - Emoji to remove
1056
- * @param opts - Optional account/connection overrides
1057
- */
1058
- async function removeReactionSignal(recipient, targetTimestamp, emoji, opts) {
1059
- return await sendReactionSignalCore({
1060
- recipient,
1061
- targetTimestamp,
1062
- emoji,
1063
- remove: true,
1064
- opts,
1065
- errors: {
1066
- missingRecipient: "Recipient or groupId is required for Signal reaction removal",
1067
- invalidTargetTimestamp: "Valid targetTimestamp is required for Signal reaction removal",
1068
- missingEmoji: "Emoji is required for Signal reaction removal",
1069
- missingTargetAuthor: "targetAuthor is required for group reaction removal"
1070
- }
1071
- });
1072
- }
1073
- //#endregion
1074
- export { signalRpcRequest as a, signalCheck as i, sendReactionSignal as n, streamSignalEvents as o, resolveSignalRpcContext as r, removeReactionSignal as t };
953
+ export { signalRpcRequest as n, streamSignalEvents as r, signalCheck as t };
@@ -1,3 +1,3 @@
1
1
  import { d as normalizeSignalMessagingTarget, i as isSignalSenderAllowed, u as looksLikeSignalTargetId } from "./identity-B6O4k8xg.js";
2
- import { a as looksLikeArchive, i as installSignalCliFromRelease, n as extractSignalCliArchive, o as pickAsset, r as installSignalCli, t as downloadToFile } from "./install-signal-cli-CXgTF3de.js";
2
+ import { a as looksLikeArchive, i as installSignalCliFromRelease, n as extractSignalCliArchive, o as pickAsset, r as installSignalCli, t as downloadToFile } from "./install-signal-cli-TwhJ0DGy.js";
3
3
  export { downloadToFile, extractSignalCliArchive, installSignalCli, installSignalCliFromRelease, isSignalSenderAllowed, looksLikeArchive, looksLikeSignalTargetId, normalizeSignalMessagingTarget, pickAsset };
@@ -1,6 +1,8 @@
1
1
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
2
3
  import fs from "node:fs/promises";
3
4
  import path from "node:path";
5
+ import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
4
6
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
7
  import { CONFIG_DIR, extractArchive, resolveBrewExecutable } from "openclaw/plugin-sdk/setup-tools";
6
8
  import { createWriteStream } from "node:fs";
@@ -50,7 +52,7 @@ function pickAsset(assets, platform, arch) {
50
52
  if (arch === "x64") return byName(/linux-native/) || byName(/linux/) || archives[0];
51
53
  return;
52
54
  }
53
- if (platform === "darwin") return byName(/macos|osx|darwin/) || archives[0];
55
+ if (platform === "darwin") return byName(/macos|osx|darwin/);
54
56
  if (platform === "win32") return byName(/windows|win/) || archives[0];
55
57
  return archives[0];
56
58
  }
@@ -130,7 +132,7 @@ async function installSignalCliViaBrew(runtime) {
130
132
  const brewExe = resolveBrewExecutable();
131
133
  if (!brewExe) return {
132
134
  ok: false,
133
- error: `No native signal-cli build is available for ${process.arch}. Install Homebrew (https://brew.sh) and try again, or install signal-cli manually.`
135
+ error: `No native signal-cli build is available for ${process.platform}/${process.arch}. Install Homebrew (https://brew.sh) and try again, or install signal-cli manually.`
134
136
  };
135
137
  runtime.log(`Installing signal-cli via Homebrew (${brewExe})…`);
136
138
  const result = await runPluginCommandWithTimeout({
@@ -143,7 +145,7 @@ async function installSignalCliViaBrew(runtime) {
143
145
  });
144
146
  if (result.code !== 0) return {
145
147
  ok: false,
146
- error: `brew install signal-cli failed (exit ${result.code}): ${result.stderr.trim().slice(0, 200)}`
148
+ error: `brew install signal-cli failed (exit ${result.code}): ${truncateUtf16Safe(result.stderr.trim(), 200)}`
147
149
  };
148
150
  const cliPath = await resolveBrewSignalCliPath(brewExe);
149
151
  if (!cliPath) return {
@@ -184,7 +186,7 @@ async function installSignalCliFromRelease(runtime) {
184
186
  error: `Failed to fetch release info (${response.status})`
185
187
  };
186
188
  try {
187
- payload = await response.json();
189
+ payload = await readProviderJsonResponse(response, "signal.release-info");
188
190
  } catch {
189
191
  return {
190
192
  ok: false,
@@ -236,7 +238,7 @@ async function installSignalCli(runtime) {
236
238
  ok: false,
237
239
  error: "Signal CLI auto-install is not supported on Windows yet."
238
240
  };
239
- if (process.platform !== "linux" || process.arch === "x64") return installSignalCliFromRelease(runtime);
241
+ if (process.platform === "linux" && process.arch === "x64") return installSignalCliFromRelease(runtime);
240
242
  return installSignalCliViaBrew(runtime);
241
243
  }
242
244
  //#endregion
@@ -1,40 +1,17 @@
1
- import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-hOCHbEhX.js";
2
- import { d as normalizeSignalMessagingTarget, l as looksLikeUuid } from "./identity-B6O4k8xg.js";
3
- import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-C_PQ45D9.js";
1
+ import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-B7Rz3_xV.js";
2
+ import { d as normalizeSignalMessagingTarget } from "./identity-B6O4k8xg.js";
3
+ import { n as signalApprovalAuth, t as getSignalApprovalApprovers } from "./approval-auth-DPVK9A_l.js";
4
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-BkAxQPGs.js";
4
5
  import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
5
6
  import { resolveReactionLevel } from "openclaw/plugin-sdk/status-helpers";
6
7
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
+ import { markdownToIR, renderMarkdownIRChunksWithinLimit } from "openclaw/plugin-sdk/text-chunking";
7
9
  import { createChannelApprovalCapability } from "openclaw/plugin-sdk/approval-delivery-runtime";
8
10
  import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
9
11
  import { createChannelApproverDmTargetResolver, createChannelNativeOriginTargetResolver, createNativeApprovalChannelRouteGates, createNativeApprovalForwardingFallbackSuppressor, shouldSuppressLocalNativeExecApprovalPrompt } from "openclaw/plugin-sdk/approval-native-runtime";
10
12
  import { buildApprovalReactionPendingContentForRequest } from "openclaw/plugin-sdk/approval-reaction-runtime";
11
- import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
12
- import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
13
- import { markdownToIR, renderMarkdownIRChunksWithinLimit } from "openclaw/plugin-sdk/text-chunking";
14
13
  import { createActionGate, jsonResult, readStringParam, resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
15
14
  import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
16
- //#region extensions/signal/src/approval-auth.ts
17
- function normalizeSignalApproverId(value) {
18
- const normalized = normalizeSignalMessagingTarget(String(value));
19
- if (!normalized || normalized.startsWith("group:") || normalized.startsWith("username:")) return;
20
- if (looksLikeUuid(normalized)) return `uuid:${normalized}`;
21
- const e164 = normalizeE164(normalized);
22
- return e164.length > 1 ? e164 : void 0;
23
- }
24
- function getSignalApprovalApprovers(params) {
25
- const account = resolveSignalAccount(params).config;
26
- return resolveApprovalApprovers({
27
- allowFrom: account.allowFrom,
28
- defaultTo: account.defaultTo,
29
- normalizeApprover: normalizeSignalApproverId
30
- });
31
- }
32
- const signalApprovalAuth = createResolvedApproverActionAuthAdapter({
33
- channelLabel: "Signal",
34
- resolveApprovers: getSignalApprovalApprovers,
35
- normalizeSenderId: (value) => normalizeSignalApproverId(value)
36
- });
37
- //#endregion
38
15
  //#region extensions/signal/src/approval-native.ts
39
16
  const DEFAULT_APPROVAL_FORWARDING_MODE = "session";
40
17
  function isSignalApprovalTransportEnabled(params) {
@@ -233,7 +210,7 @@ const signalApprovalCapability = createChannelApprovalCapability({
233
210
  accountId,
234
211
  request
235
212
  }),
236
- load: async () => (await import("./approval-handler.runtime-CeJI1wow.js")).signalApprovalNativeRuntime
213
+ load: async () => (await import("./approval-handler.runtime-BZLgs7EM.js")).signalApprovalNativeRuntime
237
214
  })
238
215
  });
239
216
  //#endregion
@@ -545,4 +522,4 @@ const signalMessageActions = {
545
522
  }
546
523
  };
547
524
  //#endregion
548
- export { isSignalNativeApprovalHandlerConfigured as a, getSignalApprovalApprovers as c, markdownToSignalTextChunks as i, signalApprovalAuth as l, resolveSignalReactionLevel as n, shouldSuppressLocalSignalExecApprovalPrompt as o, markdownToSignalText as r, signalApprovalCapability as s, signalMessageActions as t };
525
+ export { isSignalNativeApprovalHandlerConfigured as a, markdownToSignalTextChunks as i, resolveSignalReactionLevel as n, shouldSuppressLocalSignalExecApprovalPrompt as o, markdownToSignalText as r, signalApprovalCapability as s, signalMessageActions as t };