@emotion-machine/claw-messenger 0.1.13 → 0.1.15
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 +11 -2
- package/dist/channel.d.ts +2 -1
- package/dist/channel.js +11 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/outbound/send.js +2 -2
- package/dist/runtime.d.ts +1 -1
- package/package.json +7 -3
- package/src/types/openclaw.d.ts +19 -61
package/README.md
CHANGED
|
@@ -57,8 +57,17 @@ The plugin registers two tools your agent can call:
|
|
|
57
57
|
2. Create an API key from the dashboard
|
|
58
58
|
3. Install the plugin: `openclaw plugins install @emotion-machine/claw-messenger`
|
|
59
59
|
4. Add the config above with your API key
|
|
60
|
-
5.
|
|
60
|
+
5. Restart OpenClaw so the channel connects
|
|
61
|
+
6. Check the listener before the first controlled send:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
curl https://claw-messenger.onrender.com/api/agent/readiness \
|
|
65
|
+
-H "Authorization: Bearer ${CLAW_API_KEY}"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Continue only after the response is `{"ready":true,"action":"send_controlled_test"}`. If the action is `connect_agent`, restart OpenClaw and check again. Keep the key in the authorization header, never in the URL.
|
|
69
|
+
7. Send one message to a phone you control, reply in the same thread, and confirm the reply reaches your agent
|
|
61
70
|
|
|
62
71
|
## License
|
|
63
72
|
|
|
64
|
-
UNLICENSED
|
|
73
|
+
UNLICENSED
|
package/dist/channel.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChannelPlugin } from "openclaw/plugin-sdk";
|
|
1
|
+
import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
2
2
|
import { type ClawMessengerConfig } from "./config.js";
|
|
3
3
|
import { WsClient } from "./ws/client.js";
|
|
4
4
|
import { type SendResult } from "./outbound/send.js";
|
|
@@ -21,4 +21,5 @@ export declare function createGroup(to: string[], text: string): Promise<{
|
|
|
21
21
|
ok: boolean;
|
|
22
22
|
} & SendResult>;
|
|
23
23
|
export declare const clawMessengerPlugin: ChannelPlugin<ResolvedAccount>;
|
|
24
|
+
export declare function handleInboundMessage(data: Record<string, unknown>, accountId: string, account: ResolvedAccount, ctx: any): Promise<void>;
|
|
24
25
|
export {};
|
package/dist/channel.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DEFAULT_ACCOUNT_ID as OPENCLAW_DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildChannelConfigSchema, formatPairingApproveHint, normalizeAccountId, } from "openclaw/plugin-sdk/channel-plugin-common";
|
|
2
2
|
import { ClawMessengerConfigSchema } from "./config.js";
|
|
3
3
|
import { isInboundMessageEvent, normalizeInboundMessage, validateInboundRoute, } from "./inbound.js";
|
|
4
4
|
import { getRuntime } from "./runtime.js";
|
|
@@ -25,7 +25,7 @@ function hasAccountId(value) {
|
|
|
25
25
|
}
|
|
26
26
|
function normalizeAccountIdCompat(accountId) {
|
|
27
27
|
const fallback = hasAccountId(accountId) ? accountId.trim() : FALLBACK_ACCOUNT_ID;
|
|
28
|
-
const normalize =
|
|
28
|
+
const normalize = normalizeAccountId;
|
|
29
29
|
if (typeof normalize === "function") {
|
|
30
30
|
try {
|
|
31
31
|
const normalized = normalize(fallback);
|
|
@@ -38,7 +38,7 @@ function normalizeAccountIdCompat(accountId) {
|
|
|
38
38
|
}
|
|
39
39
|
return fallback;
|
|
40
40
|
}
|
|
41
|
-
const DEFAULT_ACCOUNT_ID = normalizeAccountIdCompat(
|
|
41
|
+
const DEFAULT_ACCOUNT_ID = normalizeAccountIdCompat(OPENCLAW_DEFAULT_ACCOUNT_ID);
|
|
42
42
|
const MESSAGE_TOOL_ACTIONS = ["send", "react"];
|
|
43
43
|
function resolveAccount(cfg, accountId) {
|
|
44
44
|
const cloudConfig = (cfg.channels?.["claw-messenger"] ?? {});
|
|
@@ -121,7 +121,7 @@ export const clawMessengerPlugin = {
|
|
|
121
121
|
const ws = wsClients.get(account.accountId);
|
|
122
122
|
if (!ws)
|
|
123
123
|
throw new Error("Not connected to claw-messenger");
|
|
124
|
-
await sendText(ws, id,
|
|
124
|
+
await sendText(ws, id, PAIRING_APPROVED_MESSAGE, account.preferredService);
|
|
125
125
|
},
|
|
126
126
|
},
|
|
127
127
|
capabilities: {
|
|
@@ -133,7 +133,7 @@ export const clawMessengerPlugin = {
|
|
|
133
133
|
blockStreaming: true,
|
|
134
134
|
},
|
|
135
135
|
reload: { configPrefixes: ["channels.claw-messenger"] },
|
|
136
|
-
configSchema:
|
|
136
|
+
configSchema: buildChannelConfigSchema(ClawMessengerConfigSchema),
|
|
137
137
|
config: {
|
|
138
138
|
listAccountIds: () => [DEFAULT_ACCOUNT_ID],
|
|
139
139
|
resolveAccount: (cfg, accountId) => resolveAccount(cfg, accountId),
|
|
@@ -167,7 +167,7 @@ export const clawMessengerPlugin = {
|
|
|
167
167
|
allowFrom: account.config.allowFrom ?? [],
|
|
168
168
|
policyPath: "channels.claw-messenger.dmPolicy",
|
|
169
169
|
allowFromPath: "channels.claw-messenger.",
|
|
170
|
-
approveHint:
|
|
170
|
+
approveHint: formatPairingApproveHint("claw-messenger"),
|
|
171
171
|
}),
|
|
172
172
|
collectWarnings: ({ cfg }) => {
|
|
173
173
|
const account = resolveAccount(cfg);
|
|
@@ -439,7 +439,7 @@ export const clawMessengerPlugin = {
|
|
|
439
439
|
// versions doesn't include it. Newer OpenClaw calls this; older versions ignore it.
|
|
440
440
|
clawMessengerPlugin.describeMessageTool = describeClawMessageTool;
|
|
441
441
|
// -- Inbound message handler --
|
|
442
|
-
async function handleInboundMessage(data, accountId, account, ctx) {
|
|
442
|
+
export async function handleInboundMessage(data, accountId, account, ctx) {
|
|
443
443
|
const normalized = normalizeInboundMessage(data);
|
|
444
444
|
if (!normalized.ok) {
|
|
445
445
|
ctx.log?.warn?.(`[${accountId}] Dropping inbound message: ${normalized.reason}`);
|
|
@@ -488,7 +488,10 @@ async function handleInboundMessage(data, accountId, account, ctx) {
|
|
|
488
488
|
agentId: route.agentId,
|
|
489
489
|
});
|
|
490
490
|
const envelopeOptions = runtime.channel.reply.resolveEnvelopeFormatOptions(cfg);
|
|
491
|
-
const previousTimestamp = runtime.channel.session.readSessionUpdatedAt(
|
|
491
|
+
const previousTimestamp = runtime.channel.session.readSessionUpdatedAt({
|
|
492
|
+
storePath,
|
|
493
|
+
sessionKey: routeSessionKey,
|
|
494
|
+
});
|
|
492
495
|
const rawBody = text || (allMedia.length > 0 ? "<media:image>" : "");
|
|
493
496
|
if (!rawBody)
|
|
494
497
|
return;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
1
|
+
import { emptyPluginConfigSchema, } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
3
|
import { clawMessengerPlugin, getConnectionStatus, getWsClient, createGroup } from "./channel.js";
|
|
4
4
|
import { setRuntime, getRuntime } from "./runtime.js";
|
|
@@ -99,7 +99,7 @@ const plugin = {
|
|
|
99
99
|
const ws = getWsClient(status.accountId);
|
|
100
100
|
const diagnostics = ws?.getDiagnostics() ?? { errors: [], connectionLog: [] };
|
|
101
101
|
const report = {
|
|
102
|
-
plugin_version: "0.1.
|
|
102
|
+
plugin_version: "0.1.15",
|
|
103
103
|
node_version: process.version,
|
|
104
104
|
connected: status.connected,
|
|
105
105
|
server_url: status.serverUrl,
|
package/dist/outbound/send.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
|
|
2
2
|
function stripLegacyNamespacePrefix(target) {
|
|
3
3
|
let normalized = target.trim();
|
|
4
4
|
while (normalized.startsWith("claw-messenger:") || normalized.startsWith("linq:")) {
|
|
@@ -21,7 +21,7 @@ function fallbackNormalizeE164(input) {
|
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
23
23
|
function normalizeE164Compat(input) {
|
|
24
|
-
const sdkNormalize = typeof
|
|
24
|
+
const sdkNormalize = typeof normalizeE164 === "function" ? normalizeE164 : null;
|
|
25
25
|
if (sdkNormalize) {
|
|
26
26
|
try {
|
|
27
27
|
return sdkNormalize(input);
|
package/dist/runtime.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emotion-machine/claw-messenger",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "iMessage, RCS & SMS channel plugin for OpenClaw
|
|
3
|
+
"version": "0.1.15",
|
|
4
|
+
"description": "iMessage, RCS & SMS channel plugin for OpenClaw agents, powered by Claw Messenger, the Mac-free iMessage API for AI agents. Send and receive real texts from Linux, Docker, Windows, or any cloud. No phone or Mac required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"openclaw",
|
|
19
19
|
"openclaw-plugin",
|
|
20
20
|
"imessage",
|
|
21
|
+
"imessage-api",
|
|
22
|
+
"ai-agents",
|
|
23
|
+
"no-mac",
|
|
24
|
+
"claw-messenger",
|
|
21
25
|
"rcs",
|
|
22
26
|
"sms",
|
|
23
27
|
"emotion-machine",
|
|
@@ -33,7 +37,7 @@
|
|
|
33
37
|
"build": "tsc",
|
|
34
38
|
"dev": "tsc --watch",
|
|
35
39
|
"clean": "rm -rf dist",
|
|
36
|
-
"test": "npm run build && node --test tests/*.test.mjs",
|
|
40
|
+
"test": "npm run build && node --loader ./tests/openclaw-loader.mjs --test tests/*.test.mjs",
|
|
37
41
|
"prepare": "test -d dist || npm run build",
|
|
38
42
|
"prepublishOnly": "npm run clean && npm run build"
|
|
39
43
|
},
|
package/src/types/openclaw.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Type declarations for
|
|
2
|
+
* Type declarations for the focused OpenClaw plugin SDK subpaths used here.
|
|
3
3
|
*
|
|
4
4
|
* These are derived from the runtime shapes in openclaw's compiled JS.
|
|
5
|
-
*
|
|
5
|
+
* They mirror the subset needed by the plugin without making OpenClaw a runtime dependency.
|
|
6
6
|
*/
|
|
7
|
-
declare module "openclaw/plugin-sdk" {
|
|
7
|
+
declare module "openclaw/plugin-sdk/channel-core" {
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
|
|
10
10
|
// ── Config ──
|
|
@@ -199,7 +199,7 @@ declare module "openclaw/plugin-sdk" {
|
|
|
199
199
|
};
|
|
200
200
|
session: {
|
|
201
201
|
resolveStorePath(store: any, opts?: { agentId?: string }): string;
|
|
202
|
-
readSessionUpdatedAt(
|
|
202
|
+
readSessionUpdatedAt(ctx: { storePath: string; sessionKey: string }): number | null;
|
|
203
203
|
recordSessionMetaFromInbound(ctx: any): Promise<void>;
|
|
204
204
|
recordInboundSession(ctx: any): void;
|
|
205
205
|
updateLastRoute(ctx: any): void;
|
|
@@ -220,7 +220,14 @@ declare module "openclaw/plugin-sdk" {
|
|
|
220
220
|
[key: string]: any;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
declare module "openclaw/plugin-sdk/plugin-entry" {
|
|
226
|
+
import type {
|
|
227
|
+
ChannelPlugin,
|
|
228
|
+
OpenclawConfig,
|
|
229
|
+
PluginRuntime,
|
|
230
|
+
} from "openclaw/plugin-sdk/channel-core";
|
|
224
231
|
|
|
225
232
|
export interface OpenclawPluginApi {
|
|
226
233
|
id: string;
|
|
@@ -246,66 +253,17 @@ declare module "openclaw/plugin-sdk" {
|
|
|
246
253
|
on(hookName: string, handler: any, opts?: any): void;
|
|
247
254
|
}
|
|
248
255
|
|
|
249
|
-
|
|
256
|
+
export function emptyPluginConfigSchema(): any;
|
|
257
|
+
}
|
|
250
258
|
|
|
259
|
+
declare module "openclaw/plugin-sdk/channel-plugin-common" {
|
|
251
260
|
export const DEFAULT_ACCOUNT_ID: string;
|
|
252
261
|
export const PAIRING_APPROVED_MESSAGE: string;
|
|
253
|
-
|
|
254
|
-
export function normalizeAccountId(accountId?: string | null): string;
|
|
255
|
-
export function normalizeE164(input: string): string | null;
|
|
256
262
|
export function buildChannelConfigSchema(schema: any): any;
|
|
257
|
-
export function emptyPluginConfigSchema(): any;
|
|
258
|
-
export function getChatChannelMeta(channel: string): any;
|
|
259
263
|
export function formatPairingApproveHint(channel: string): string;
|
|
264
|
+
export function normalizeAccountId(accountId?: string | null): string;
|
|
265
|
+
}
|
|
260
266
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
sectionKey: string;
|
|
264
|
-
accountId: string;
|
|
265
|
-
enabled: boolean;
|
|
266
|
-
allowTopLevel?: boolean;
|
|
267
|
-
}): OpenclawConfig;
|
|
268
|
-
|
|
269
|
-
export function deleteAccountFromConfigSection(ctx: {
|
|
270
|
-
cfg: OpenclawConfig;
|
|
271
|
-
sectionKey: string;
|
|
272
|
-
accountId: string;
|
|
273
|
-
clearBaseFields?: string[];
|
|
274
|
-
}): OpenclawConfig;
|
|
275
|
-
|
|
276
|
-
export function registerPluginHttpRoute(params: {
|
|
277
|
-
path: string;
|
|
278
|
-
pluginId?: string;
|
|
279
|
-
accountId?: string;
|
|
280
|
-
source?: string;
|
|
281
|
-
log?: (msg: string) => void;
|
|
282
|
-
handler: (req: any, res: any) => Promise<void> | void;
|
|
283
|
-
registry?: any;
|
|
284
|
-
fallbackPath?: string;
|
|
285
|
-
}): () => void;
|
|
286
|
-
|
|
287
|
-
export function normalizePluginHttpPath(path?: string, fallback?: string): string | null;
|
|
288
|
-
|
|
289
|
-
// ── Ack Reactions ──
|
|
290
|
-
|
|
291
|
-
export function resolveAckReaction(cfg: OpenclawConfig, agentId?: string): string | undefined;
|
|
292
|
-
|
|
293
|
-
export function shouldAckReaction(params: {
|
|
294
|
-
scope: string;
|
|
295
|
-
isDirect: boolean;
|
|
296
|
-
isGroup: boolean;
|
|
297
|
-
isMentionableGroup?: boolean;
|
|
298
|
-
requireMention?: boolean;
|
|
299
|
-
canDetectMention?: boolean;
|
|
300
|
-
effectiveWasMentioned?: boolean;
|
|
301
|
-
shouldBypassMention?: boolean;
|
|
302
|
-
}): boolean;
|
|
303
|
-
|
|
304
|
-
// Config schemas
|
|
305
|
-
export const IMessageConfigSchema: any;
|
|
306
|
-
export const TelegramConfigSchema: any;
|
|
307
|
-
export const DiscordConfigSchema: any;
|
|
308
|
-
export const SlackConfigSchema: any;
|
|
309
|
-
export const SignalConfigSchema: any;
|
|
310
|
-
export const WhatsAppConfigSchema: any;
|
|
267
|
+
declare module "openclaw/plugin-sdk/account-resolution" {
|
|
268
|
+
export function normalizeE164(input: string): string | null;
|
|
311
269
|
}
|