@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.
- package/README.md +12 -2
- package/dist/accounts-hOCHbEhX.js +40 -0
- package/dist/api.js +16 -0
- package/dist/approval-handler.runtime-CeJI1wow.js +158 -0
- package/dist/approval-resolver-BR0MioAA.js +15 -0
- package/dist/channel-LmY2UpOt.js +619 -0
- package/dist/channel-config-api.js +2 -0
- package/dist/channel-entry.js +18 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-B0-YpkC4.js +65 -0
- package/dist/config-api-KS-qhQvD.js +2 -0
- package/dist/config-schema-BiojLEsX.js +27 -0
- package/dist/contract-api.js +3 -0
- package/dist/identity-B6O4k8xg.js +130 -0
- package/dist/index.js +18 -0
- package/dist/install-signal-cli-CXgTF3de.js +243 -0
- package/dist/message-actions-Bue0g2Kc.js +548 -0
- package/dist/monitor-CUhIKHJo.js +1404 -0
- package/dist/probe-BQ_Izoya.js +48 -0
- package/dist/reaction-runtime-api-C_PQ45D9.js +1074 -0
- package/dist/reaction-runtime-api.js +2 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/runtime-api.js +18 -0
- package/dist/secret-contract-api.js +5 -0
- package/dist/send-CBlFUkY_.js +599 -0
- package/dist/send.runtime-CfaZd8X4.js +2 -0
- package/dist/setup-entry.js +11 -0
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +22 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +528 -0
- package/node_modules/ws/lib/receiver.js +760 -0
- package/node_modules/ws/lib/sender.js +607 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +562 -0
- package/node_modules/ws/lib/websocket.js +1407 -0
- package/node_modules/ws/package.json +70 -0
- package/node_modules/ws/wrapper.mjs +21 -0
- package/npm-shrinkwrap.json +36 -0
- package/openclaw.plugin.json +771 -0
- package/package.json +77 -7
package/README.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Signal OpenClaw channel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Official OpenClaw channel plugin for Signal.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
openclaw plugins install @openclaw/signal
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Docs
|
|
12
|
+
|
|
13
|
+
See `docs/channels/signal.md` in the OpenClaw repository, or the published docs at `https://docs.openclaw.ai/channels/signal`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
+
import { createAccountListHelpers, normalizeAccountId, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
3
|
+
//#region extensions/signal/src/accounts.ts
|
|
4
|
+
const { listAccountIds, resolveDefaultAccountId } = createAccountListHelpers("signal", { implicitDefaultAccount: { channelKeys: ["account"] } });
|
|
5
|
+
const listSignalAccountIds = listAccountIds;
|
|
6
|
+
const resolveDefaultSignalAccountId = resolveDefaultAccountId;
|
|
7
|
+
function mergeSignalAccountConfig(cfg, accountId) {
|
|
8
|
+
return resolveMergedAccountConfig({
|
|
9
|
+
channelConfig: cfg.channels?.signal,
|
|
10
|
+
accounts: cfg.channels?.signal?.accounts,
|
|
11
|
+
accountId
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function resolveSignalAccount(params) {
|
|
15
|
+
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSignalAccountId(params.cfg));
|
|
16
|
+
const baseEnabled = params.cfg.channels?.signal?.enabled !== false;
|
|
17
|
+
const merged = mergeSignalAccountConfig(params.cfg, accountId);
|
|
18
|
+
const accountEnabled = merged.enabled !== false;
|
|
19
|
+
const enabled = baseEnabled && accountEnabled;
|
|
20
|
+
const host = normalizeOptionalString(merged.httpHost) ?? "127.0.0.1";
|
|
21
|
+
const port = merged.httpPort ?? 8080;
|
|
22
|
+
const baseUrl = normalizeOptionalString(merged.httpUrl) ?? `http://${host}:${port}`;
|
|
23
|
+
const configured = Boolean(normalizeOptionalString(merged.account) || normalizeOptionalString(merged.configPath) || normalizeOptionalString(merged.httpUrl) || normalizeOptionalString(merged.cliPath) || normalizeOptionalString(merged.httpHost) || typeof merged.httpPort === "number" || typeof merged.autoStart === "boolean");
|
|
24
|
+
return {
|
|
25
|
+
accountId,
|
|
26
|
+
enabled,
|
|
27
|
+
name: normalizeOptionalString(merged.name),
|
|
28
|
+
baseUrl,
|
|
29
|
+
configured,
|
|
30
|
+
config: merged
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function listEnabledSignalAccounts(cfg) {
|
|
34
|
+
return listSignalAccountIds(cfg).map((accountId) => resolveSignalAccount({
|
|
35
|
+
cfg,
|
|
36
|
+
accountId
|
|
37
|
+
})).filter((account) => account.enabled);
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { resolveSignalAccount as i, listSignalAccountIds as n, resolveDefaultSignalAccountId as r, listEnabledSignalAccounts as t };
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { i as resolveSignalAccount, n as listSignalAccountIds, r as resolveDefaultSignalAccountId, t as listEnabledSignalAccounts } from "./accounts-hOCHbEhX.js";
|
|
2
|
+
import { a as normalizeSignalAllowRecipient, c as resolveSignalSender, d as normalizeSignalMessagingTarget, i as isSignalSenderAllowed, l as looksLikeUuid, n as formatSignalSenderDisplay, o as resolveSignalPeerId, r as formatSignalSenderId, s as resolveSignalRecipient, t as formatSignalPairingIdLine, u as looksLikeSignalTargetId } from "./identity-B6O4k8xg.js";
|
|
3
|
+
import { i as markdownToSignalTextChunks, n as resolveSignalReactionLevel, r as markdownToSignalText, 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 { a as normalizeSignalAccountInput, l as signalSetupAdapter, n as createSignalPluginBase, r as signalSetupWizard, t as signalPlugin, u as resolveSignalOutboundTarget } from "./channel-LmY2UpOt.js";
|
|
6
|
+
import { a as looksLikeArchive, n as extractSignalCliArchive, o as pickAsset, r as installSignalCli } from "./install-signal-cli-CXgTF3de.js";
|
|
7
|
+
import { t as monitorSignalProvider } from "./monitor-CUhIKHJo.js";
|
|
8
|
+
import { n as sendReadReceiptSignal, r as sendTypingSignal, t as sendMessageSignal } from "./send-CBlFUkY_.js";
|
|
9
|
+
import { t as probeSignal } from "./probe-BQ_Izoya.js";
|
|
10
|
+
//#region extensions/signal/src/channel.setup.ts
|
|
11
|
+
const signalSetupPlugin = { ...createSignalPluginBase({
|
|
12
|
+
setupWizard: signalSetupWizard,
|
|
13
|
+
setup: signalSetupAdapter
|
|
14
|
+
}) };
|
|
15
|
+
//#endregion
|
|
16
|
+
export { extractSignalCliArchive, formatSignalPairingIdLine, formatSignalSenderDisplay, formatSignalSenderId, installSignalCli, isSignalSenderAllowed, listEnabledSignalAccounts, listSignalAccountIds, looksLikeArchive, looksLikeSignalTargetId, looksLikeUuid, markdownToSignalText, markdownToSignalTextChunks, monitorSignalProvider, normalizeSignalAccountInput, normalizeSignalAllowRecipient, normalizeSignalMessagingTarget, pickAsset, probeSignal, removeReactionSignal, resolveDefaultSignalAccountId, resolveSignalAccount, resolveSignalOutboundTarget, resolveSignalPeerId, resolveSignalReactionLevel, resolveSignalRecipient, resolveSignalSender, sendMessageSignal, sendReactionSignal, sendReadReceiptSignal, sendTypingSignal, signalMessageActions, signalPlugin, signalSetupPlugin };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { d as normalizeSignalMessagingTarget } from "./identity-B6O4k8xg.js";
|
|
2
|
+
import { c as resolveSignalApprovalTargetAuthorKeys, i as hasSignalApprovalReactionApprovers, l as unregisterSignalApprovalReactionTarget, o as registerSignalApprovalReactionTarget, r as sendTypingSignal, s as resolveSignalApprovalConversationKey, t as sendMessageSignal } from "./send-CBlFUkY_.js";
|
|
3
|
+
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
4
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
+
import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
6
|
+
import { buildApprovalReactionPendingContent } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
7
|
+
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
8
|
+
import { buildChannelApprovalExpiredText, buildChannelApprovalResolvedText, createChannelApprovalNativeRuntimeAdapter, resolvePreparedApprovalAccountId } from "openclaw/plugin-sdk/approval-handler-runtime";
|
|
9
|
+
//#region extensions/signal/src/approval-handler.runtime.ts
|
|
10
|
+
const log = createSubsystemLogger("signal/approvals");
|
|
11
|
+
function readSignalApprovalRuntimeContext(context) {
|
|
12
|
+
const value = context;
|
|
13
|
+
return {
|
|
14
|
+
baseUrl: typeof value?.baseUrl === "string" && value.baseUrl.trim() ? value.baseUrl.trim() : void 0,
|
|
15
|
+
account: typeof value?.account === "string" && value.account.trim() ? value.account.trim() : void 0,
|
|
16
|
+
accountUuid: typeof value?.accountUuid === "string" && value.accountUuid.trim() ? value.accountUuid.trim() : void 0
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function buildPendingPayload(params) {
|
|
20
|
+
return buildApprovalReactionPendingContent(params);
|
|
21
|
+
}
|
|
22
|
+
const signalApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
|
|
23
|
+
eventKinds: ["exec", "plugin"],
|
|
24
|
+
availability: {
|
|
25
|
+
isConfigured: ({ context }) => Boolean(context),
|
|
26
|
+
shouldHandle: ({ context }) => Boolean(context)
|
|
27
|
+
},
|
|
28
|
+
presentation: {
|
|
29
|
+
buildPendingPayload: ({ request, nowMs, view }) => buildPendingPayload({
|
|
30
|
+
request,
|
|
31
|
+
nowMs,
|
|
32
|
+
view
|
|
33
|
+
}),
|
|
34
|
+
buildResolvedResult: ({ request, resolved, view }) => ({
|
|
35
|
+
kind: "update",
|
|
36
|
+
payload: { text: buildChannelApprovalResolvedText({
|
|
37
|
+
request,
|
|
38
|
+
resolved,
|
|
39
|
+
view
|
|
40
|
+
}) }
|
|
41
|
+
}),
|
|
42
|
+
buildExpiredResult: ({ request, view }) => ({
|
|
43
|
+
kind: "update",
|
|
44
|
+
payload: { text: buildChannelApprovalExpiredText({
|
|
45
|
+
request,
|
|
46
|
+
view
|
|
47
|
+
}) }
|
|
48
|
+
})
|
|
49
|
+
},
|
|
50
|
+
transport: {
|
|
51
|
+
prepareTarget: ({ plannedTarget, accountId, context }) => {
|
|
52
|
+
const to = normalizeSignalMessagingTarget(plannedTarget.target.to);
|
|
53
|
+
if (!to) return null;
|
|
54
|
+
const runtimeContext = readSignalApprovalRuntimeContext(context);
|
|
55
|
+
const targetAuthorKeys = resolveSignalApprovalTargetAuthorKeys({
|
|
56
|
+
targetAuthor: runtimeContext.account,
|
|
57
|
+
targetAuthorUuid: runtimeContext.accountUuid
|
|
58
|
+
});
|
|
59
|
+
const prepared = {
|
|
60
|
+
to,
|
|
61
|
+
accountId: resolvePreparedApprovalAccountId({
|
|
62
|
+
plannedAccountId: plannedTarget.target.accountId,
|
|
63
|
+
contextAccountId: accountId,
|
|
64
|
+
fallbackAccountId: DEFAULT_ACCOUNT_ID
|
|
65
|
+
}),
|
|
66
|
+
...runtimeContext.baseUrl ? { baseUrl: runtimeContext.baseUrl } : {},
|
|
67
|
+
...runtimeContext.account ? { account: runtimeContext.account } : {},
|
|
68
|
+
...runtimeContext.accountUuid ? { accountUuid: runtimeContext.accountUuid } : {},
|
|
69
|
+
targetAuthorKeys
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
dedupeKey: `${prepared.accountId}:${buildChannelApprovalNativeTargetKey({ to: prepared.to })}`,
|
|
73
|
+
target: prepared
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
deliverPending: async ({ cfg, preparedTarget, pendingPayload }) => {
|
|
77
|
+
await sendTypingSignal(preparedTarget.to, {
|
|
78
|
+
cfg,
|
|
79
|
+
accountId: preparedTarget.accountId,
|
|
80
|
+
...preparedTarget.baseUrl ? { baseUrl: preparedTarget.baseUrl } : {},
|
|
81
|
+
...preparedTarget.account ? { account: preparedTarget.account } : {}
|
|
82
|
+
}).catch(() => {});
|
|
83
|
+
const reactionsActive = preparedTarget.targetAuthorKeys.length > 0 && hasSignalApprovalReactionApprovers({
|
|
84
|
+
cfg,
|
|
85
|
+
accountId: preparedTarget.accountId
|
|
86
|
+
});
|
|
87
|
+
const payload = reactionsActive ? pendingPayload.reactionPayload : pendingPayload.manualFallbackPayload;
|
|
88
|
+
const result = await sendMessageSignal(preparedTarget.to, payload.text ?? "", {
|
|
89
|
+
cfg,
|
|
90
|
+
accountId: preparedTarget.accountId,
|
|
91
|
+
...preparedTarget.baseUrl ? { baseUrl: preparedTarget.baseUrl } : {},
|
|
92
|
+
...preparedTarget.account ? { account: preparedTarget.account } : {},
|
|
93
|
+
textMode: "plain"
|
|
94
|
+
});
|
|
95
|
+
if (!result.messageId || result.messageId === "unknown") return null;
|
|
96
|
+
const conversationKey = resolveSignalApprovalConversationKey(preparedTarget.to);
|
|
97
|
+
if (!conversationKey) return null;
|
|
98
|
+
return {
|
|
99
|
+
accountId: preparedTarget.accountId,
|
|
100
|
+
to: preparedTarget.to,
|
|
101
|
+
conversationKey,
|
|
102
|
+
messageId: result.messageId,
|
|
103
|
+
targetAuthorKeys: preparedTarget.targetAuthorKeys,
|
|
104
|
+
reactionsActive,
|
|
105
|
+
...preparedTarget.baseUrl ? { baseUrl: preparedTarget.baseUrl } : {},
|
|
106
|
+
...preparedTarget.account ? { account: preparedTarget.account } : {}
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
updateEntry: async ({ cfg, entry, payload }) => {
|
|
110
|
+
await sendMessageSignal(entry.to, payload.text, {
|
|
111
|
+
cfg,
|
|
112
|
+
accountId: entry.accountId,
|
|
113
|
+
...entry.baseUrl ? { baseUrl: entry.baseUrl } : {},
|
|
114
|
+
...entry.account ? { account: entry.account } : {},
|
|
115
|
+
textMode: "plain"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
interactions: {
|
|
120
|
+
bindPending: ({ entry, request, view, pendingPayload }) => {
|
|
121
|
+
if (!entry.reactionsActive) return null;
|
|
122
|
+
return registerSignalApprovalReactionTarget({
|
|
123
|
+
accountId: entry.accountId,
|
|
124
|
+
conversationKey: entry.conversationKey,
|
|
125
|
+
messageId: entry.messageId,
|
|
126
|
+
approvalId: request.id,
|
|
127
|
+
allowedDecisions: pendingPayload.reactionPayload.allowedDecisions,
|
|
128
|
+
targetAuthorKeys: entry.targetAuthorKeys,
|
|
129
|
+
route: {
|
|
130
|
+
deliveryMode: "session",
|
|
131
|
+
...normalizeOptionalString(request.request.agentId) ? { agentId: normalizeOptionalString(request.request.agentId) } : {},
|
|
132
|
+
...normalizeOptionalString(request.request.sessionKey) ? { sessionKey: normalizeOptionalString(request.request.sessionKey) } : {}
|
|
133
|
+
},
|
|
134
|
+
routeAllowed: true,
|
|
135
|
+
ttlMs: Math.max(1, view.expiresAtMs - Date.now())
|
|
136
|
+
}) ? true : null;
|
|
137
|
+
},
|
|
138
|
+
unbindPending: ({ entry }) => {
|
|
139
|
+
unregisterSignalApprovalReactionTarget({
|
|
140
|
+
accountId: entry.accountId,
|
|
141
|
+
conversationKey: entry.conversationKey,
|
|
142
|
+
messageId: entry.messageId
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
cancelDelivered: ({ entry }) => {
|
|
146
|
+
unregisterSignalApprovalReactionTarget({
|
|
147
|
+
accountId: entry.accountId,
|
|
148
|
+
conversationKey: entry.conversationKey,
|
|
149
|
+
messageId: entry.messageId
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
observe: { onDeliveryError: ({ error, request }) => {
|
|
154
|
+
log.error(`signal approvals: failed to send request ${request.id}: ${String(error)}`);
|
|
155
|
+
} }
|
|
156
|
+
});
|
|
157
|
+
//#endregion
|
|
158
|
+
export { signalApprovalNativeRuntime };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
|
|
2
|
+
import { resolveApprovalOverGateway } from "openclaw/plugin-sdk/approval-gateway-runtime";
|
|
3
|
+
//#region extensions/signal/src/approval-resolver.ts
|
|
4
|
+
async function resolveSignalApproval(params) {
|
|
5
|
+
await resolveApprovalOverGateway({
|
|
6
|
+
cfg: params.cfg,
|
|
7
|
+
approvalId: params.approvalId,
|
|
8
|
+
decision: params.decision,
|
|
9
|
+
senderId: params.senderId,
|
|
10
|
+
gatewayUrl: params.gatewayUrl,
|
|
11
|
+
clientDisplayName: `Signal approval (${params.senderId?.trim() || "unknown"})`
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { isApprovalNotFoundError, resolveSignalApproval };
|