@openclaw/signal 0.0.0 → 2026.6.11

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 (49) hide show
  1. package/README.md +12 -2
  2. package/dist/accounts-hOCHbEhX.js +40 -0
  3. package/dist/api.js +16 -0
  4. package/dist/approval-handler.runtime-CeJI1wow.js +158 -0
  5. package/dist/approval-resolver-BR0MioAA.js +15 -0
  6. package/dist/channel-LmY2UpOt.js +619 -0
  7. package/dist/channel-config-api.js +2 -0
  8. package/dist/channel-entry.js +18 -0
  9. package/dist/channel-plugin-api.js +2 -0
  10. package/dist/channel.runtime-B0-YpkC4.js +65 -0
  11. package/dist/config-api-KS-qhQvD.js +2 -0
  12. package/dist/config-schema-BiojLEsX.js +27 -0
  13. package/dist/contract-api.js +3 -0
  14. package/dist/identity-B6O4k8xg.js +130 -0
  15. package/dist/index.js +18 -0
  16. package/dist/install-signal-cli-CXgTF3de.js +243 -0
  17. package/dist/message-actions-Bue0g2Kc.js +548 -0
  18. package/dist/monitor-CUhIKHJo.js +1404 -0
  19. package/dist/probe-BQ_Izoya.js +48 -0
  20. package/dist/reaction-runtime-api-C_PQ45D9.js +1074 -0
  21. package/dist/reaction-runtime-api.js +2 -0
  22. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  23. package/dist/runtime-api.js +18 -0
  24. package/dist/secret-contract-api.js +5 -0
  25. package/dist/send-CBlFUkY_.js +599 -0
  26. package/dist/send.runtime-CfaZd8X4.js +2 -0
  27. package/dist/setup-entry.js +11 -0
  28. package/node_modules/ws/LICENSE +20 -0
  29. package/node_modules/ws/README.md +548 -0
  30. package/node_modules/ws/browser.js +8 -0
  31. package/node_modules/ws/index.js +22 -0
  32. package/node_modules/ws/lib/buffer-util.js +131 -0
  33. package/node_modules/ws/lib/constants.js +19 -0
  34. package/node_modules/ws/lib/event-target.js +292 -0
  35. package/node_modules/ws/lib/extension.js +203 -0
  36. package/node_modules/ws/lib/limiter.js +55 -0
  37. package/node_modules/ws/lib/permessage-deflate.js +528 -0
  38. package/node_modules/ws/lib/receiver.js +760 -0
  39. package/node_modules/ws/lib/sender.js +607 -0
  40. package/node_modules/ws/lib/stream.js +161 -0
  41. package/node_modules/ws/lib/subprotocol.js +62 -0
  42. package/node_modules/ws/lib/validation.js +152 -0
  43. package/node_modules/ws/lib/websocket-server.js +562 -0
  44. package/node_modules/ws/lib/websocket.js +1407 -0
  45. package/node_modules/ws/package.json +70 -0
  46. package/node_modules/ws/wrapper.mjs +21 -0
  47. package/npm-shrinkwrap.json +36 -0
  48. package/openclaw.plugin.json +771 -0
  49. package/package.json +77 -7
@@ -0,0 +1,2 @@
1
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-C_PQ45D9.js";
2
+ export { removeReactionSignal, sendReactionSignal };
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };
@@ -0,0 +1,18 @@
1
+ import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-hOCHbEhX.js";
2
+ import { d as normalizeSignalMessagingTarget, u as looksLikeSignalTargetId } from "./identity-B6O4k8xg.js";
3
+ import { n as resolveSignalReactionLevel, t as signalMessageActions } from "./message-actions-Bue0g2Kc.js";
4
+ import { n as sendReactionSignal, t as removeReactionSignal } from "./reaction-runtime-api-C_PQ45D9.js";
5
+ import { n as buildChannelConfigSchema, t as SignalConfigSchema } from "./config-api-KS-qhQvD.js";
6
+ import { r as installSignalCli } from "./install-signal-cli-CXgTF3de.js";
7
+ import { t as monitorSignalProvider } from "./monitor-CUhIKHJo.js";
8
+ import { t as sendMessageSignal, u as setSignalRuntime } from "./send-CBlFUkY_.js";
9
+ import { t as probeSignal } from "./probe-BQ_Izoya.js";
10
+ import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
11
+ import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
12
+ import { buildBaseAccountStatusSnapshot, buildBaseChannelStatusSummary, collectStatusIssuesFromLastError, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
13
+ import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
14
+ import { DEFAULT_ACCOUNT_ID, applyAccountNameToChannelSection, deleteAccountFromConfigSection, emptyPluginConfigSchema, formatPairingApproveHint, getChatChannelMeta, migrateBaseNameToDefaultAccount, normalizeAccountId, setAccountEnabledInConfigSection } from "openclaw/plugin-sdk/core";
15
+ import { detectBinary, formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
16
+ import { chunkText } from "openclaw/plugin-sdk/reply-runtime";
17
+ import { resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy";
18
+ export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, SignalConfigSchema, applyAccountNameToChannelSection, buildBaseAccountStatusSnapshot, buildBaseChannelStatusSummary, buildChannelConfigSchema, chunkText, collectStatusIssuesFromLastError, createDefaultChannelRuntimeState, deleteAccountFromConfigSection, detectBinary, emptyPluginConfigSchema, formatCliCommand, formatDocsLink, formatPairingApproveHint, getChatChannelMeta, installSignalCli, listEnabledSignalAccounts, listSignalAccountIds, looksLikeSignalTargetId, migrateBaseNameToDefaultAccount, monitorSignalProvider, normalizeAccountId, normalizeE164, normalizeSignalMessagingTarget, probeSignal, removeReactionSignal, resolveAllowlistProviderRuntimeGroupPolicy, resolveChannelMediaMaxBytes, resolveDefaultGroupPolicy, resolveDefaultSignalAccountId, resolveSignalAccount, resolveSignalReactionLevel, sendMessageSignal, sendReactionSignal, setAccountEnabledInConfigSection, setSignalRuntime, signalMessageActions };
@@ -0,0 +1,5 @@
1
+ //#region extensions/signal/secret-contract-api.ts
2
+ const secretTargetRegistryEntries = [];
3
+ function collectRuntimeConfigAssignments() {}
4
+ //#endregion
5
+ export { collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -0,0 +1,599 @@
1
+ import { i as resolveSignalAccount } from "./accounts-hOCHbEhX.js";
2
+ import { d as normalizeSignalMessagingTarget, l as looksLikeUuid } from "./identity-B6O4k8xg.js";
3
+ import { c as getSignalApprovalApprovers, l as signalApprovalAuth, r as markdownToSignalText } from "./message-actions-Bue0g2Kc.js";
4
+ import { a as signalRpcRequest, r as resolveSignalRpcContext } from "./reaction-runtime-api-C_PQ45D9.js";
5
+ import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
6
+ import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
7
+ import { kindFromMime, resolveOutboundAttachmentFromUrl } from "openclaw/plugin-sdk/media-runtime";
8
+ import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
9
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
10
+ import { buildApprovalReactionHint, createApprovalReactionTargetStore, listApprovalReactionBindings, resolveApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
11
+ import { normalizeE164 } from "openclaw/plugin-sdk/text-utility-runtime";
12
+ import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
13
+ import { matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
14
+ import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
15
+ //#region extensions/signal/src/runtime.ts
16
+ const { setRuntime: setSignalRuntime, getRuntime: getSignalRuntime, tryGetRuntime: getOptionalSignalRuntime, clearRuntime: clearSignalRuntime } = createPluginRuntimeStore({
17
+ pluginId: "signal",
18
+ errorMessage: "Signal runtime not initialized"
19
+ });
20
+ //#endregion
21
+ //#region extensions/signal/src/approval-reactions.ts
22
+ const PERSISTENT_NAMESPACE = "signal.approval-reactions";
23
+ const PERSISTENT_MAX_ENTRIES = 1e3;
24
+ const DEFAULT_REACTION_TARGET_TTL_MS = 1440 * 60 * 1e3;
25
+ let resolverRuntimePromise;
26
+ const signalApprovalReactionTargets = createApprovalReactionTargetStore({
27
+ namespace: PERSISTENT_NAMESPACE,
28
+ maxEntries: PERSISTENT_MAX_ENTRIES,
29
+ defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS,
30
+ openStore: (storeParams) => getOptionalSignalRuntime()?.state.openKeyedStore(storeParams),
31
+ logPersistentError: reportPersistentApprovalReactionError,
32
+ readPersistedTarget
33
+ });
34
+ function loadApprovalResolver() {
35
+ resolverRuntimePromise ??= import("./approval-resolver-BR0MioAA.js");
36
+ return resolverRuntimePromise;
37
+ }
38
+ function resolveApprovalKindFromId(approvalId) {
39
+ return approvalId.startsWith("plugin:") ? "plugin" : "exec";
40
+ }
41
+ function resolveApprovalForwardingConfig(params) {
42
+ return params.approvalKind === "plugin" ? params.cfg.approvals?.plugin : params.cfg.approvals?.exec;
43
+ }
44
+ function normalizeApprovalForwardingMode(mode) {
45
+ return mode ?? "session";
46
+ }
47
+ function approvalModeIncludesSession(mode) {
48
+ return mode === "session" || mode === "both";
49
+ }
50
+ function approvalModeIncludesTargets(mode) {
51
+ return mode === "targets" || mode === "both";
52
+ }
53
+ function matchesSignalApprovalReactionFilters(params) {
54
+ return matchesApprovalRequestFilters({
55
+ request: {
56
+ agentId: params.route.agentId,
57
+ sessionKey: params.route.sessionKey
58
+ },
59
+ agentFilter: params.config.agentFilter,
60
+ sessionFilter: params.config.sessionFilter,
61
+ fallbackAgentIdFromSessionKey: true
62
+ });
63
+ }
64
+ function targetAccountMatches(params) {
65
+ const configuredAccountId = normalizeOptionalString(params.configuredAccountId);
66
+ if (!configuredAccountId) return true;
67
+ const routeAccountId = normalizeOptionalString(params.routeAccountId);
68
+ return Boolean(routeAccountId && normalizeAccountId(routeAccountId) === normalizeAccountId(configuredAccountId));
69
+ }
70
+ function hasMatchingSignalApprovalReactionTarget(params) {
71
+ return (params.config.targets ?? []).some((target) => {
72
+ if (normalizeLowercaseStringOrEmpty(target.channel) !== "signal") return false;
73
+ const configuredTo = normalizeSignalMessagingTarget(target.to);
74
+ if (!configuredTo || configuredTo !== params.route.to) return false;
75
+ return targetAccountMatches({
76
+ routeAccountId: params.route.accountId,
77
+ configuredAccountId: target.accountId
78
+ });
79
+ });
80
+ }
81
+ function isSignalApprovalReactionRouteStillEnabled(params) {
82
+ const config = resolveApprovalForwardingConfig({
83
+ cfg: params.cfg,
84
+ approvalKind: params.target.approvalKind
85
+ });
86
+ if (!config?.enabled) return false;
87
+ const mode = normalizeApprovalForwardingMode(config.mode);
88
+ if (params.target.route.deliveryMode === "target") return approvalModeIncludesTargets(mode) && matchesSignalApprovalReactionFilters({
89
+ config,
90
+ route: params.target.route
91
+ }) && hasMatchingSignalApprovalReactionTarget({
92
+ config,
93
+ route: params.target.route
94
+ });
95
+ if (!approvalModeIncludesSession(mode)) return false;
96
+ return matchesSignalApprovalReactionFilters({
97
+ config,
98
+ route: params.target.route
99
+ });
100
+ }
101
+ function resolveSignalApprovalConversationKey(to) {
102
+ return normalizeSignalMessagingTarget(to) ?? null;
103
+ }
104
+ function normalizeSignalApprovalTargetAuthorKey(value) {
105
+ const normalized = normalizeOptionalString(value);
106
+ if (!normalized) return null;
107
+ const withoutSignalPrefix = normalized.replace(/^signal:/i, "").trim();
108
+ if (normalizeLowercaseStringOrEmpty(withoutSignalPrefix).startsWith("uuid:")) {
109
+ const uuid = withoutSignalPrefix.slice(5).trim().toLowerCase();
110
+ return uuid ? `uuid:${uuid}` : null;
111
+ }
112
+ if (looksLikeUuid(withoutSignalPrefix)) return `uuid:${withoutSignalPrefix.toLowerCase()}`;
113
+ return normalizeE164(withoutSignalPrefix);
114
+ }
115
+ function resolveSignalApprovalTargetAuthorKeys(params) {
116
+ const targetAuthorUuid = normalizeOptionalString(params.targetAuthorUuid);
117
+ const keys = [targetAuthorUuid ? `uuid:${targetAuthorUuid.replace(/^uuid:/i, "").trim().toLowerCase()}` : null, params.targetAuthor ? normalizeSignalApprovalTargetAuthorKey(params.targetAuthor) : null].filter((key) => Boolean(key));
118
+ return Array.from(new Set(keys));
119
+ }
120
+ function buildReactionTargetKey(params) {
121
+ const accountId = params.accountId.trim();
122
+ const conversationKey = params.conversationKey.trim();
123
+ const messageId = params.messageId.trim();
124
+ if (!accountId || !conversationKey || !messageId || messageId === "unknown") return null;
125
+ return `${accountId}:${conversationKey}:${messageId}`;
126
+ }
127
+ function reportPersistentApprovalReactionError(error) {
128
+ try {
129
+ getOptionalSignalRuntime()?.logging.getChildLogger({
130
+ plugin: "signal",
131
+ feature: "approval-reaction-state"
132
+ }).warn("Signal persistent approval reaction state failed", { error: String(error) });
133
+ } catch {}
134
+ }
135
+ function readPersistedTarget(target) {
136
+ const value = target;
137
+ if (!value || typeof value.approvalId !== "string" || value.approvalKind !== "exec" && value.approvalKind !== "plugin" || !value.route || value.route.deliveryMode !== "session" && value.route.deliveryMode !== "target" || !Array.isArray(value.targetAuthorKeys) || !Array.isArray(value.allowedDecisions)) return null;
138
+ const targetRouteTo = value.route.deliveryMode === "target" && typeof value.route.to === "string" ? normalizeSignalMessagingTarget(value.route.to) : null;
139
+ if (value.route.deliveryMode === "target" && !targetRouteTo) return null;
140
+ const route = value.route.deliveryMode === "target" ? {
141
+ deliveryMode: "target",
142
+ to: targetRouteTo,
143
+ ...typeof value.route.accountId === "string" ? { accountId: value.route.accountId } : {},
144
+ ...typeof value.route.agentId === "string" ? { agentId: value.route.agentId } : {},
145
+ ...typeof value.route.sessionKey === "string" ? { sessionKey: value.route.sessionKey } : {}
146
+ } : {
147
+ deliveryMode: "session",
148
+ ...typeof value.route.agentId === "string" ? { agentId: value.route.agentId } : {},
149
+ ...typeof value.route.sessionKey === "string" ? { sessionKey: value.route.sessionKey } : {}
150
+ };
151
+ return {
152
+ approvalId: value.approvalId,
153
+ approvalKind: value.approvalKind,
154
+ allowedDecisions: value.allowedDecisions,
155
+ targetAuthorKeys: value.targetAuthorKeys,
156
+ route
157
+ };
158
+ }
159
+ function listSignalApprovalReactionBindings(allowedDecisions) {
160
+ return listApprovalReactionBindings({ allowedDecisions });
161
+ }
162
+ function buildSignalApprovalReactionHint(allowedDecisions) {
163
+ return buildApprovalReactionHint({ allowedDecisions });
164
+ }
165
+ function insertSignalApprovalReactionHintNearHeader(params) {
166
+ const lines = params.text.split(/\r?\n/);
167
+ const idLineIndex = lines.findIndex((line) => /^ID:\s*\S+/.test(line.trim()));
168
+ if (idLineIndex >= 0) {
169
+ const before = lines.slice(0, idLineIndex + 1).join("\n");
170
+ const after = lines.slice(idLineIndex + 1).join("\n").replace(/^\n+/, "");
171
+ return after ? `${before}\n\n${params.hint}\n\n${after}` : `${before}\n\n${params.hint}`;
172
+ }
173
+ return `${params.hint}\n\n${params.text}`;
174
+ }
175
+ function addSignalApprovalReactionHintToText(params) {
176
+ if (/(^|\n)React with:\s*(\n|$)/i.test(params.text)) return params.text;
177
+ const hint = buildSignalApprovalReactionHint(params.allowedDecisions);
178
+ return hint ? insertSignalApprovalReactionHintNearHeader({
179
+ text: params.text,
180
+ hint
181
+ }) : params.text;
182
+ }
183
+ function normalizeApprovalDecision(value) {
184
+ const normalized = value.trim().toLowerCase();
185
+ if (normalized === "always") return "allow-always";
186
+ if (normalized === "allow-once" || normalized === "allow-always" || normalized === "deny") return normalized;
187
+ return null;
188
+ }
189
+ function extractSignalApprovalPromptBinding(text) {
190
+ const allowedDecisions = [];
191
+ let approvalId = "";
192
+ for (const line of text.split(/\r?\n/)) {
193
+ const match = line.match(/\/approve(?:@[^\s]+)?\s+([A-Za-z0-9][A-Za-z0-9._:-]*)\s+(.+)$/i);
194
+ if (!match) continue;
195
+ if (approvalId && match[1] !== approvalId) continue;
196
+ approvalId ||= match[1];
197
+ for (const decisionText of match[2].split(/[\s|,]+/)) {
198
+ const decision = normalizeApprovalDecision(decisionText);
199
+ if (decision && !allowedDecisions.includes(decision)) allowedDecisions.push(decision);
200
+ }
201
+ }
202
+ return approvalId && allowedDecisions.length > 0 ? {
203
+ approvalId,
204
+ allowedDecisions
205
+ } : null;
206
+ }
207
+ function buildTargetRoute(params) {
208
+ const to = normalizeSignalMessagingTarget(params.to);
209
+ if (!to) return null;
210
+ const route = {
211
+ deliveryMode: "target",
212
+ to,
213
+ ...normalizeOptionalString(params.accountId) ? { accountId: normalizeOptionalString(params.accountId) } : {},
214
+ ...normalizeOptionalString(params.agentId) ? { agentId: normalizeOptionalString(params.agentId) } : {},
215
+ ...normalizeOptionalString(params.sessionKey) ? { sessionKey: normalizeOptionalString(params.sessionKey) } : {}
216
+ };
217
+ return isSignalApprovalReactionRouteStillEnabled({
218
+ cfg: params.cfg,
219
+ target: {
220
+ approvalKind: resolveApprovalKindFromId(params.approvalId),
221
+ route
222
+ }
223
+ }) ? route : null;
224
+ }
225
+ function shouldAppendSignalApprovalReactionHintForOutboundMessage(params) {
226
+ const binding = extractSignalApprovalPromptBinding(params.text);
227
+ if (!binding) return false;
228
+ if (resolveSignalApprovalTargetAuthorKeys(params).length === 0) return false;
229
+ if (!hasSignalApprovalReactionApprovers({
230
+ cfg: params.cfg,
231
+ accountId: params.accountId
232
+ })) return false;
233
+ return Boolean(buildTargetRoute({
234
+ cfg: params.cfg,
235
+ accountId: params.accountId,
236
+ to: params.to,
237
+ approvalId: binding.approvalId,
238
+ agentId: params.agentId,
239
+ sessionKey: params.sessionKey
240
+ }));
241
+ }
242
+ function appendSignalApprovalReactionHintForOutboundMessage(params) {
243
+ const binding = extractSignalApprovalPromptBinding(params.text);
244
+ if (!binding || !shouldAppendSignalApprovalReactionHintForOutboundMessage({
245
+ ...params,
246
+ text: params.text
247
+ })) return params.text;
248
+ return addSignalApprovalReactionHintToText({
249
+ text: params.text,
250
+ allowedDecisions: binding.allowedDecisions
251
+ });
252
+ }
253
+ function hasSignalApprovalReactionApprovers(params) {
254
+ return getSignalApprovalApprovers(params).length > 0;
255
+ }
256
+ function registerSignalApprovalReactionTarget(params) {
257
+ const key = buildReactionTargetKey(params);
258
+ const approvalId = params.approvalId.trim();
259
+ const targetAuthorKeys = Array.from(new Set(params.targetAuthorKeys.map((entry) => normalizeSignalApprovalTargetAuthorKey(entry)).filter((entry) => Boolean(entry))));
260
+ const allowedDecisions = listSignalApprovalReactionBindings(params.allowedDecisions).map((binding) => binding.decision);
261
+ if (!params.routeAllowed || !key || !approvalId || allowedDecisions.length === 0) return null;
262
+ if (targetAuthorKeys.length === 0) return null;
263
+ const route = params.route.deliveryMode === "target" ? {
264
+ deliveryMode: "target",
265
+ to: params.route.to,
266
+ ...normalizeOptionalString(params.route.accountId) ? { accountId: normalizeOptionalString(params.route.accountId) } : {},
267
+ ...normalizeOptionalString(params.route.agentId) ? { agentId: normalizeOptionalString(params.route.agentId) } : {},
268
+ ...normalizeOptionalString(params.route.sessionKey) ? { sessionKey: normalizeOptionalString(params.route.sessionKey) } : {}
269
+ } : {
270
+ deliveryMode: "session",
271
+ ...normalizeOptionalString(params.route.agentId) ? { agentId: normalizeOptionalString(params.route.agentId) } : {},
272
+ ...normalizeOptionalString(params.route.sessionKey) ? { sessionKey: normalizeOptionalString(params.route.sessionKey) } : {}
273
+ };
274
+ const target = {
275
+ approvalId,
276
+ approvalKind: resolveApprovalKindFromId(approvalId),
277
+ allowedDecisions,
278
+ targetAuthorKeys,
279
+ route
280
+ };
281
+ signalApprovalReactionTargets.register(key, target, { ttlMs: params.ttlMs });
282
+ return target;
283
+ }
284
+ function registerSignalApprovalReactionTargetForOutboundMessage(params) {
285
+ const binding = extractSignalApprovalPromptBinding(params.text);
286
+ if (!binding) return false;
287
+ const conversationKey = resolveSignalApprovalConversationKey(params.to);
288
+ if (!conversationKey) return false;
289
+ const route = buildTargetRoute({
290
+ cfg: params.cfg,
291
+ accountId: params.accountId,
292
+ to: params.to,
293
+ approvalId: binding.approvalId,
294
+ agentId: params.agentId,
295
+ sessionKey: params.sessionKey
296
+ });
297
+ if (!route) return false;
298
+ return Boolean(registerSignalApprovalReactionTarget({
299
+ accountId: params.accountId,
300
+ conversationKey,
301
+ messageId: params.messageId,
302
+ approvalId: binding.approvalId,
303
+ allowedDecisions: binding.allowedDecisions,
304
+ targetAuthorKeys: resolveSignalApprovalTargetAuthorKeys(params),
305
+ route,
306
+ routeAllowed: true,
307
+ ttlMs: params.ttlMs
308
+ }));
309
+ }
310
+ function unregisterSignalApprovalReactionTarget(params) {
311
+ const key = buildReactionTargetKey(params);
312
+ if (!key) return;
313
+ signalApprovalReactionTargets.delete(key);
314
+ }
315
+ function resolveTarget(params) {
316
+ const target = params.target;
317
+ if (!target) return null;
318
+ if (params.targetAuthorKeys.length === 0 || !params.targetAuthorKeys.some((key) => target.targetAuthorKeys.includes(key))) return null;
319
+ const resolved = resolveApprovalReactionTarget({
320
+ target,
321
+ reactionKey: params.reactionKey
322
+ });
323
+ if (!resolved?.route) return null;
324
+ return {
325
+ approvalId: resolved.approvalId,
326
+ approvalKind: resolved.approvalKind,
327
+ decision: resolved.decision,
328
+ route: resolved.route
329
+ };
330
+ }
331
+ async function resolveSignalApprovalReactionTargetWithPersistence(params) {
332
+ const key = buildReactionTargetKey(params);
333
+ if (!key) return null;
334
+ const targetAuthorKeys = resolveSignalApprovalTargetAuthorKeys(params);
335
+ if (targetAuthorKeys.length === 0) return null;
336
+ return resolveTarget({
337
+ target: await signalApprovalReactionTargets.lookup(key),
338
+ reactionKey: params.reactionKey,
339
+ targetAuthorKeys
340
+ });
341
+ }
342
+ async function maybeResolveSignalApprovalReaction(params) {
343
+ const target = await resolveSignalApprovalReactionTargetWithPersistence({
344
+ accountId: params.accountId,
345
+ conversationKey: params.conversationKey,
346
+ messageId: params.messageId,
347
+ reactionKey: params.reactionKey,
348
+ targetAuthor: params.targetAuthor,
349
+ targetAuthorUuid: params.targetAuthorUuid
350
+ });
351
+ if (!target) return false;
352
+ if (!isSignalApprovalReactionRouteStillEnabled({
353
+ cfg: params.cfg,
354
+ target
355
+ })) {
356
+ params.logVerboseMessage?.(`signal: approval reaction denied id=${target.approvalId}; approval route is no longer enabled`);
357
+ return true;
358
+ }
359
+ const actorId = params.actorId?.trim();
360
+ if (!actorId) {
361
+ params.logVerboseMessage?.(`signal: approval reaction ignored for ${target.approvalId}; missing actor identity`);
362
+ return true;
363
+ }
364
+ if (getSignalApprovalApprovers({
365
+ cfg: params.cfg,
366
+ accountId: params.accountId
367
+ }).length === 0) {
368
+ params.logVerboseMessage?.(`signal: approval reaction denied id=${target.approvalId}; reactions require explicit approvers`);
369
+ return true;
370
+ }
371
+ if (!signalApprovalAuth.authorizeActorAction({
372
+ cfg: params.cfg,
373
+ accountId: params.accountId,
374
+ senderId: actorId,
375
+ action: "approve",
376
+ approvalKind: target.approvalKind
377
+ }).authorized) {
378
+ params.logVerboseMessage?.(`signal: approval reaction denied id=${target.approvalId} sender=${actorId}`);
379
+ return true;
380
+ }
381
+ const { isApprovalNotFoundError, resolveSignalApproval } = await loadApprovalResolver();
382
+ try {
383
+ await resolveSignalApproval({
384
+ cfg: params.cfg,
385
+ approvalId: target.approvalId,
386
+ decision: target.decision,
387
+ senderId: actorId,
388
+ gatewayUrl: params.gatewayUrl
389
+ });
390
+ params.logVerboseMessage?.(`signal: approval reaction resolved id=${target.approvalId} sender=${actorId} decision=${target.decision}`);
391
+ return true;
392
+ } catch (error) {
393
+ if (isApprovalNotFoundError(error)) {
394
+ unregisterSignalApprovalReactionTarget({
395
+ accountId: params.accountId,
396
+ conversationKey: params.conversationKey,
397
+ messageId: params.messageId
398
+ });
399
+ params.logVerboseMessage?.(`signal: approval reaction ignored for expired approval id=${target.approvalId} sender=${actorId}`);
400
+ return true;
401
+ }
402
+ params.logVerboseMessage?.(`signal: approval reaction failed id=${target.approvalId} sender=${actorId}: ${String(error)}`);
403
+ return true;
404
+ }
405
+ }
406
+ //#endregion
407
+ //#region extensions/signal/src/send.ts
408
+ async function resolveSignalRpcAccountInfo(opts) {
409
+ if (opts.baseUrl?.trim() && opts.account?.trim()) return;
410
+ if (!opts.cfg) throw new Error("Signal RPC account resolution requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
411
+ return resolveSignalAccount({
412
+ cfg: requireRuntimeConfig(opts.cfg, "Signal RPC account resolution"),
413
+ accountId: opts.accountId
414
+ });
415
+ }
416
+ function parseTarget(raw) {
417
+ let value = raw.trim();
418
+ if (!value) throw new Error("Signal recipient is required");
419
+ if (normalizeLowercaseStringOrEmpty(value).startsWith("signal:")) value = value.slice(7).trim();
420
+ const normalized = normalizeLowercaseStringOrEmpty(value);
421
+ if (normalized.startsWith("group:")) return {
422
+ type: "group",
423
+ groupId: value.slice(6).trim()
424
+ };
425
+ if (normalized.startsWith("username:")) return {
426
+ type: "username",
427
+ username: value.slice(9).trim()
428
+ };
429
+ if (normalized.startsWith("u:")) return {
430
+ type: "username",
431
+ username: value.trim()
432
+ };
433
+ return {
434
+ type: "recipient",
435
+ recipient: value
436
+ };
437
+ }
438
+ function buildTargetParams(target, allow) {
439
+ if (target.type === "recipient") {
440
+ if (!allow.recipient) return null;
441
+ return { recipient: [target.recipient] };
442
+ }
443
+ if (target.type === "group") {
444
+ if (!allow.group) return null;
445
+ return { groupId: target.groupId };
446
+ }
447
+ if (target.type === "username") {
448
+ if (!allow.username) return null;
449
+ return { username: [target.username] };
450
+ }
451
+ return null;
452
+ }
453
+ function createSignalSendReceipt(params) {
454
+ const messageId = params.messageId.trim();
455
+ const results = messageId && messageId !== "unknown" ? [{
456
+ channel: "signal",
457
+ messageId,
458
+ meta: { targetType: params.target.type }
459
+ }] : [];
460
+ if (results[0]) {
461
+ if (params.timestamp != null) results[0].timestamp = params.timestamp;
462
+ if (params.target.type === "group") results[0].chatId = params.target.groupId;
463
+ else if (params.target.type === "recipient") results[0].toJid = params.target.recipient;
464
+ else results[0].toJid = params.target.username;
465
+ }
466
+ return createMessageReceiptFromOutboundResults({
467
+ results,
468
+ kind: params.kind
469
+ });
470
+ }
471
+ async function sendMessageSignal(to, text, opts) {
472
+ const cfg = requireRuntimeConfig(opts.cfg, "Signal send");
473
+ const apiMode = cfg.channels?.signal?.apiMode;
474
+ const accountInfo = resolveSignalAccount({
475
+ cfg,
476
+ accountId: opts.accountId
477
+ });
478
+ const { baseUrl, account } = resolveSignalRpcContext(opts, accountInfo);
479
+ const target = parseTarget(to);
480
+ const outboundText = appendSignalApprovalReactionHintForOutboundMessage({
481
+ cfg,
482
+ accountId: accountInfo.accountId,
483
+ to,
484
+ text: text ?? "",
485
+ targetAuthor: account
486
+ });
487
+ let message = outboundText;
488
+ let messageFromPlaceholder = false;
489
+ let textStyles = [];
490
+ const textMode = opts.textMode ?? "markdown";
491
+ const maxBytes = (() => {
492
+ if (typeof opts.maxBytes === "number") return opts.maxBytes;
493
+ if (typeof accountInfo.config.mediaMaxMb === "number") return accountInfo.config.mediaMaxMb * 1024 * 1024;
494
+ if (typeof cfg.agents?.defaults?.mediaMaxMb === "number") return cfg.agents.defaults.mediaMaxMb * 1024 * 1024;
495
+ return 8 * 1024 * 1024;
496
+ })();
497
+ let attachments;
498
+ if (opts.mediaUrl?.trim()) {
499
+ const resolved = await resolveOutboundAttachmentFromUrl(opts.mediaUrl.trim(), maxBytes, {
500
+ mediaAccess: opts.mediaAccess,
501
+ localRoots: opts.mediaLocalRoots,
502
+ readFile: opts.mediaReadFile
503
+ });
504
+ attachments = [resolved.path];
505
+ const kind = kindFromMime(resolved.contentType ?? void 0);
506
+ if (!message && kind) {
507
+ message = kind === "image" ? "<media:image>" : `<media:${kind}>`;
508
+ messageFromPlaceholder = true;
509
+ }
510
+ }
511
+ if (message.trim() && !messageFromPlaceholder) if (textMode === "plain") textStyles = opts.textStyles ?? [];
512
+ else {
513
+ const tableMode = resolveMarkdownTableMode({
514
+ cfg,
515
+ channel: "signal",
516
+ accountId: accountInfo.accountId
517
+ });
518
+ const formatted = markdownToSignalText(message, { tableMode });
519
+ message = formatted.text;
520
+ textStyles = formatted.styles;
521
+ }
522
+ if (!message.trim() && (!attachments || attachments.length === 0)) throw new Error("Signal send requires text or media");
523
+ const params = { message };
524
+ if (textStyles.length > 0) params["text-style"] = textStyles.map((style) => `${style.start}:${style.length}:${style.style}`);
525
+ if (account) params.account = account;
526
+ if (attachments && attachments.length > 0) params.attachments = attachments;
527
+ const targetParams = buildTargetParams(target, {
528
+ recipient: true,
529
+ group: true,
530
+ username: true
531
+ });
532
+ if (!targetParams) throw new Error("Signal recipient is required");
533
+ Object.assign(params, targetParams);
534
+ const timestamp = (await signalRpcRequest("send", params, {
535
+ baseUrl,
536
+ timeoutMs: opts.timeoutMs,
537
+ apiMode
538
+ }))?.timestamp;
539
+ const messageId = timestamp ? String(timestamp) : "unknown";
540
+ registerSignalApprovalReactionTargetForOutboundMessage({
541
+ cfg,
542
+ accountId: accountInfo.accountId,
543
+ to,
544
+ messageId,
545
+ text: outboundText,
546
+ targetAuthor: account
547
+ });
548
+ return {
549
+ messageId,
550
+ timestamp,
551
+ receipt: createSignalSendReceipt({
552
+ messageId,
553
+ target,
554
+ kind: attachments && attachments.length > 0 ? "media" : "text",
555
+ ...timestamp != null ? { timestamp } : {}
556
+ })
557
+ };
558
+ }
559
+ async function sendTypingSignal(to, opts) {
560
+ const accountInfo = await resolveSignalRpcAccountInfo(opts);
561
+ const cfg = requireRuntimeConfig(opts.cfg, "Signal typing");
562
+ const { baseUrl, account } = resolveSignalRpcContext(opts, accountInfo);
563
+ const targetParams = buildTargetParams(parseTarget(to), {
564
+ recipient: true,
565
+ group: true
566
+ });
567
+ if (!targetParams) return false;
568
+ const params = { ...targetParams };
569
+ if (account) params.account = account;
570
+ if (opts.stop) params.stop = true;
571
+ await signalRpcRequest("sendTyping", params, {
572
+ baseUrl,
573
+ timeoutMs: opts.timeoutMs,
574
+ apiMode: cfg.channels?.signal?.apiMode
575
+ });
576
+ return true;
577
+ }
578
+ async function sendReadReceiptSignal(to, targetTimestamp, opts) {
579
+ if (!Number.isFinite(targetTimestamp) || targetTimestamp <= 0) return false;
580
+ const accountInfo = await resolveSignalRpcAccountInfo(opts);
581
+ const cfg = requireRuntimeConfig(opts.cfg, "Signal read receipt");
582
+ const { baseUrl, account } = resolveSignalRpcContext(opts, accountInfo);
583
+ const targetParams = buildTargetParams(parseTarget(to), { recipient: true });
584
+ if (!targetParams) return false;
585
+ const params = {
586
+ ...targetParams,
587
+ targetTimestamp,
588
+ type: opts.type ?? "read"
589
+ };
590
+ if (account) params.account = account;
591
+ await signalRpcRequest("sendReceipt", params, {
592
+ baseUrl,
593
+ timeoutMs: opts.timeoutMs,
594
+ apiMode: cfg.channels?.signal?.apiMode
595
+ });
596
+ return true;
597
+ }
598
+ //#endregion
599
+ export { maybeResolveSignalApprovalReaction as a, resolveSignalApprovalTargetAuthorKeys as c, hasSignalApprovalReactionApprovers as i, unregisterSignalApprovalReactionTarget as l, sendReadReceiptSignal as n, registerSignalApprovalReactionTarget as o, sendTypingSignal as r, resolveSignalApprovalConversationKey as s, sendMessageSignal as t, setSignalRuntime as u };
@@ -0,0 +1,2 @@
1
+ import { r as sendTypingSignal, t as sendMessageSignal } from "./send-CBlFUkY_.js";
2
+ export { sendMessageSignal, sendTypingSignal };
@@ -0,0 +1,11 @@
1
+ import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
2
+ //#region extensions/signal/setup-entry.ts
3
+ var setup_entry_default = defineBundledChannelSetupEntry({
4
+ importMetaUrl: import.meta.url,
5
+ plugin: {
6
+ specifier: "./api.js",
7
+ exportName: "signalSetupPlugin"
8
+ }
9
+ });
10
+ //#endregion
11
+ export { setup_entry_default as default };
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
2
+ Copyright (c) 2013 Arnout Kazemier and contributors
3
+ Copyright (c) 2016 Luigi Pinca and contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.