@coremail/lunkr-openclaw 1.0.0

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/docs/USAGE.md ADDED
@@ -0,0 +1,337 @@
1
+ # Lunkr Channel Plugin - Usage Guide
2
+
3
+ This document provides detailed information on using the Lunkr channel plugin for OpenClaw.
4
+
5
+ ## Bot Simulation
6
+
7
+ The Lunkr plugin simulates a bot by using the authenticated user's account to send and receive messages. This approach is called "Bot Simulation" because:
8
+
9
+ 1. **The bot is you**: The AI responds using your Lunkr account
10
+ 2. **Bot replies are marked**: Bot messages are prefixed with `[@!BotName]` to distinguish them from your regular messages
11
+ 3. **Self-triggering**: In normal chats, you trigger the bot by sending a message that starts with the command prefix
12
+
13
+ ### How Bot Simulation Works
14
+
15
+ ```
16
+ User (You) Lunkr Server OpenClaw
17
+ | | |
18
+ |-- "Hello" ----------------->| |
19
+ | | |
20
+ | |-- "Hello" ------------------>|
21
+ | | |
22
+ | | (Bot triggers AI) |
23
+ | | |
24
+ | |<-- "[@!Bot] Hi there!" ------|
25
+ | | |
26
+ |<-- "[@!Bot] Hi there!" ------| |
27
+ ```
28
+
29
+ ## Trigger Rules
30
+
31
+ The bot triggers based on where the message is sent and who sends it.
32
+
33
+ ### Bot Discussions (Recommended)
34
+
35
+ Bot Discussions are dedicated discussion groups where **all messages** trigger the AI agent.
36
+
37
+ ```
38
+ +---------------------------+
39
+ | Bot Discussion Group |
40
+ | |
41
+ | Alice: How do I reset? | --> Triggers AI
42
+ | Bob: Check settings | --> Triggers AI
43
+ | Bot: [@!Bot] To reset... | --> Does NOT trigger (bot reply)
44
+ +---------------------------+
45
+ ```
46
+
47
+ **Setup:**
48
+ ```yaml
49
+ channels:
50
+ lunkr:
51
+ botDiscussions:
52
+ "group-id-abc123":
53
+ name: "AI Assistant"
54
+ creatorUid: "admin-uid"
55
+ createdAt: "2024-01-01T00:00:00Z"
56
+ ```
57
+
58
+ ### Normal Groups and DMs
59
+
60
+ In regular groups and direct messages, only **you** can trigger the bot by prefixing your message with the command prefix (default: `/bot`).
61
+
62
+ ```
63
+ +---------------------------+
64
+ | Regular Group Chat |
65
+ | |
66
+ | Alice: Hello everyone | --> No trigger
67
+ | Bob: /bot What is AI? | --> Triggers AI (if Bob is you)
68
+ | You: /bot Explain X | --> Triggers AI
69
+ | Bot: [@!Bot] X is... | --> Does NOT trigger (bot reply)
70
+ +---------------------------+
71
+ ```
72
+
73
+ ### Trigger Summary Table
74
+
75
+ | Scenario | Message From | Message Content | Triggers AI? |
76
+ |----------|-------------|-----------------|--------------|
77
+ | Bot Discussion | Anyone | Anything | Yes |
78
+ | Bot Discussion | You (Bot reply) | `[@!BotName] ...` | No |
79
+ | Normal Group/DM | You | `/bot help` | Yes |
80
+ | Normal Group/DM | You | `Hello` | No |
81
+ | Normal Group/DM | Others | `/bot help` | No |
82
+ | Normal Group/DM | Others | `Hello` | No |
83
+
84
+ ## Configuration Reference
85
+
86
+ ### Complete Configuration Schema
87
+
88
+ ```yaml
89
+ channels:
90
+ lunkr:
91
+ # Enable this channel
92
+ enabled: true
93
+
94
+ # Bot display name (appears in bot replies)
95
+ botName: "AI Assistant"
96
+
97
+ # Command prefix for normal chats
98
+ commandPrefix: "/bot"
99
+
100
+ # Bot discussion groups (all messages trigger AI)
101
+ botDiscussions:
102
+ "discussion-id-1":
103
+ name: "Support Channel"
104
+ agentId: "support-agent" # Optional: route to specific agent
105
+ creatorUid: "user-123"
106
+ createdAt: "2024-01-15T10:30:00Z"
107
+
108
+ # Direct message policy
109
+ dmPolicy: "allow" # allow | deny | whitelist
110
+ allowFrom: # Whitelisted users (for dmPolicy: whitelist)
111
+ - "user-id-1"
112
+ - "user-id-2"
113
+
114
+ # Group message policy
115
+ groupPolicy: "allow" # allow | deny | whitelist
116
+ groups: # Whitelisted groups (for groupPolicy: whitelist)
117
+ - "group-id-1"
118
+ - "group-id-2"
119
+ ```
120
+
121
+ ### Policy Values
122
+
123
+ #### `dmPolicy`
124
+
125
+ | Value | Description |
126
+ |-------|-------------|
127
+ | `allow` | Accept DMs from all users (default) |
128
+ | `deny` | Reject all DMs to the bot |
129
+ | `whitelist` | Only accept DMs from users in `allowFrom` list |
130
+
131
+ #### `groupPolicy`
132
+
133
+ | Value | Description |
134
+ |-------|-------------|
135
+ | `allow` | Respond in all groups when triggered (default) |
136
+ | `deny` | Never respond in groups |
137
+ | `whitelist` | Only respond in groups in `groups` list |
138
+
139
+ ### Bot Discussion Configuration
140
+
141
+ Each bot discussion entry requires:
142
+
143
+ | Field | Type | Required | Description |
144
+ |-------|------|----------|-------------|
145
+ | `name` | string | Yes | Display name for this discussion |
146
+ | `agentId` | string | No | Agent ID to route messages to |
147
+ | `creatorUid` | string | Yes | User ID of the creator |
148
+ | `createdAt` | string/number | Yes | Creation timestamp (ISO or epoch ms) |
149
+
150
+ ## Multi-Agent Routing
151
+
152
+ You can route different Bot Discussions to different AI agents:
153
+
154
+ ```yaml
155
+ # In your OpenClaw config
156
+ agents:
157
+ sales-agent:
158
+ # Sales-specific agent configuration
159
+ support-agent:
160
+ # Support-specific agent configuration
161
+
162
+ channels:
163
+ lunkr:
164
+ botDiscussions:
165
+ "sales-group-id":
166
+ name: "Sales Bot"
167
+ agentId: "sales-agent"
168
+ creatorUid: "admin"
169
+ createdAt: "2024-01-01"
170
+ "support-group-id":
171
+ name: "Support Bot"
172
+ agentId: "support-agent"
173
+ creatorUid: "admin"
174
+ createdAt: "2024-01-01"
175
+ ```
176
+
177
+ When a message arrives in a Bot Discussion with an `agentId` configured, it is automatically routed to that specific agent.
178
+
179
+ ## Message Handling
180
+
181
+ ### Inbound Messages
182
+
183
+ Messages from Lunkr are processed as follows:
184
+
185
+ 1. **Receive**: Message arrives via Socket.IO real-time connection
186
+ 2. **Analyze**: Determine if message should trigger the bot
187
+ 3. **Convert**: Transform Lunkr format to OpenClaw format
188
+ 4. **Route**: Send to appropriate agent for processing
189
+
190
+ ### Outbound Messages
191
+
192
+ Bot replies are formatted with the `[@!BotName]` prefix:
193
+
194
+ ```
195
+ [@!AI Assistant] Here is my response to your question...
196
+ ```
197
+
198
+ This prefix helps distinguish bot messages from your regular messages.
199
+
200
+ ### Message Types Supported
201
+
202
+ | Type | Support |
203
+ |------|---------|
204
+ | Text | Full support |
205
+ | Images | Supported |
206
+ | Files | Supported |
207
+ | Reactions | Supported |
208
+ | Edits | Supported |
209
+ | Replies | Supported |
210
+
211
+ ## Security Considerations
212
+
213
+ ### Bot Reply Detection
214
+
215
+ The plugin identifies bot replies by checking if:
216
+ - The message is from the authenticated user (self)
217
+ - The content starts with `[@!<botName>]`
218
+
219
+ These messages are never re-processed by the bot to prevent loops.
220
+
221
+ ### Self-Message Triggering
222
+
223
+ In normal chats, only messages from the authenticated user that start with the command prefix trigger the bot. This prevents:
224
+ - Accidental triggers from other users
225
+ - Message loops from bot replies
226
+
227
+ ### Whitelist Security
228
+
229
+ When using whitelist policies:
230
+
231
+ ```yaml
232
+ dmPolicy: whitelist
233
+ allowFrom:
234
+ - "trusted-user-1"
235
+ - "trusted-user-2"
236
+ ```
237
+
238
+ Only messages from whitelisted users will be processed.
239
+
240
+ ### Pairing Flow
241
+
242
+ Users can request to be whitelisted via pairing:
243
+
244
+ 1. User sends a pairing request
245
+ 2. Admin approves with: `openclaw pairing approve lunkr <code>`
246
+ 3. User's ID is added to `allowFrom`
247
+
248
+ ## Examples
249
+
250
+ ### Example 1: Simple Bot Discussion
251
+
252
+ ```yaml
253
+ channels:
254
+ lunkr:
255
+ enabled: true
256
+ botName: "Helper"
257
+ botDiscussions:
258
+ "abc123":
259
+ name: "Help Channel"
260
+ creatorUid: "admin"
261
+ createdAt: "2024-01-01"
262
+ ```
263
+
264
+ Any message in group `abc123` triggers the bot.
265
+
266
+ ### Example 2: Restricted DM Access
267
+
268
+ ```yaml
269
+ channels:
270
+ lunkr:
271
+ enabled: true
272
+ dmPolicy: whitelist
273
+ allowFrom:
274
+ - "user-001"
275
+ - "user-002"
276
+ groupPolicy: deny
277
+ ```
278
+
279
+ Only `user-001` and `user-002` can DM the bot. No group messages are processed.
280
+
281
+ ### Example 3: Multi-Agent Setup
282
+
283
+ ```yaml
284
+ agents:
285
+ code-reviewer:
286
+ model: "claude-3"
287
+ systemPrompt: "You are a code reviewer..."
288
+
289
+ translator:
290
+ model: "gpt-4"
291
+ systemPrompt: "You are a translator..."
292
+
293
+ channels:
294
+ lunkr:
295
+ botDiscussions:
296
+ "code-review-group":
297
+ name: "Code Reviews"
298
+ agentId: "code-reviewer"
299
+ creatorUid: "dev-team"
300
+ createdAt: 1704067200000
301
+ "translation-group":
302
+ name: "Translations"
303
+ agentId: "translator"
304
+ creatorUid: "intl-team"
305
+ createdAt: 1704067200000
306
+ ```
307
+
308
+ ### Example 4: Custom Command Prefix
309
+
310
+ ```yaml
311
+ channels:
312
+ lunkr:
313
+ enabled: true
314
+ commandPrefix: "!"
315
+ ```
316
+
317
+ Now use `! help` instead of `/bot help` to trigger the bot in normal chats.
318
+
319
+ ## Troubleshooting
320
+
321
+ ### Bot Not Responding in Bot Discussion
322
+
323
+ 1. Verify the discussion ID matches your configuration
324
+ 2. Check that the message is not a bot reply (starts with `[@!...]`)
325
+ 3. Review gateway logs for errors
326
+
327
+ ### Wrong Agent Receiving Messages
328
+
329
+ 1. Check the `agentId` in the bot discussion configuration
330
+ 2. Verify the agent ID exists in your agents configuration
331
+ 3. Check for typos in the discussion ID mapping
332
+
333
+ ### DM Whitelist Not Working
334
+
335
+ 1. Ensure `dmPolicy` is set to `whitelist` (not `allow`)
336
+ 2. Verify user IDs in `allowFrom` are correct
337
+ 3. Remember to restart the gateway after config changes
@@ -0,0 +1,61 @@
1
+ {
2
+ "id": "lunkr",
3
+ "channels": ["lunkr"],
4
+ "skills": ["skills/lunkr"],
5
+ "configSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "enabled": {
10
+ "type": "boolean",
11
+ "default": true
12
+ },
13
+ "botName": {
14
+ "type": "string",
15
+ "default": "Bot"
16
+ },
17
+ "commandPrefix": {
18
+ "type": "string",
19
+ "default": "/bot"
20
+ },
21
+ "dmPolicy": {
22
+ "type": "string",
23
+ "enum": ["pairing", "allowlist", "any"],
24
+ "default": "pairing"
25
+ },
26
+ "allowFrom": {
27
+ "type": "array",
28
+ "items": { "type": "string" },
29
+ "default": []
30
+ },
31
+ "groupPolicy": {
32
+ "type": "string",
33
+ "enum": ["allowlist", "any"],
34
+ "default": "any"
35
+ },
36
+ "groups": {
37
+ "type": "object",
38
+ "additionalProperties": {
39
+ "type": "object",
40
+ "properties": {
41
+ "requireMention": { "type": "boolean", "default": true },
42
+ "enabled": { "type": "boolean", "default": true }
43
+ }
44
+ }
45
+ },
46
+ "botDiscussions": {
47
+ "type": "object",
48
+ "additionalProperties": {
49
+ "type": "object",
50
+ "properties": {
51
+ "name": { "type": "string" },
52
+ "agentId": { "type": "string" },
53
+ "creatorUid": { "type": "string" },
54
+ "createdAt": { "type": "number" }
55
+ },
56
+ "required": ["name", "creatorUid", "createdAt"]
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@coremail/lunkr-openclaw",
3
+ "version": "1.0.0",
4
+ "description": "OpenClaw Lunkr/Coremail channel plugin",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.ts"
13
+ }
14
+ },
15
+ "bin": {
16
+ "lunkr-cli": "./dist/bin/lunkr-cli.js"
17
+ },
18
+ "files": [
19
+ "dist/**/*.js",
20
+ "openclaw.plugin.json",
21
+ "skills/**",
22
+ "docs/**",
23
+ "README.md"
24
+ ],
25
+ "scripts": {
26
+ "help": "node scripts/help.mjs",
27
+
28
+ "dev": "tsx watch src/index.ts",
29
+ "dev:cli": "tsx src/bin/lunkr-cli.ts",
30
+
31
+ "test": "vitest run",
32
+ "test:watch": "vitest",
33
+ "lint": "eslint src/",
34
+
35
+ "clean": "rm -rf dist/",
36
+ "build": "tsc && tsc-alias",
37
+ "build:release": "node scripts/build-release.js",
38
+
39
+ "deploy:local": "node scripts/deploy-local.mjs",
40
+ "deploy:local:full": "npm run clean && npm test && npm run build && npm run deploy:local",
41
+
42
+ "pack": "npm run clean && npm test && npm run build && npm pack",
43
+ "prepublishOnly": "npm run build:release"
44
+ },
45
+ "dependencies": {
46
+ "@sinclair/typebox": "0.34.48",
47
+ "commander": "^12.0.0",
48
+ "fast-xml-parser": "^5.0.0",
49
+ "https-proxy-agent": "^7.0.6",
50
+ "qrcode-terminal": "^0.12.0",
51
+ "uuid": "^11.0.0",
52
+ "ws": "^8.18.0"
53
+ },
54
+ "devDependencies": {
55
+ "@types/mime-types": "^3.0.1",
56
+ "@types/node": "^25.4.0",
57
+ "@types/qrcode-terminal": "^0.12.2",
58
+ "@types/ws": "^8.18.1",
59
+ "esbuild": "^0.25.0",
60
+ "mime-types": "^3.0.2",
61
+ "tsc-alias": "^1.8.16",
62
+ "tsx": "^4.19.0",
63
+ "typescript": "^5.9.3",
64
+ "vitest": "^3.0.0"
65
+ },
66
+ "keywords": [
67
+ "openclaw",
68
+ "lunkr",
69
+ "coremail",
70
+ "channel",
71
+ "plugin"
72
+ ],
73
+ "openclaw": {
74
+ "extensions": [
75
+ "./dist/index.js"
76
+ ],
77
+ "channel": {
78
+ "id": "lunkr",
79
+ "label": "Lunkr",
80
+ "selectionLabel": "Lunkr/Coremail (论客)",
81
+ "docsPath": "/channels/lunkr",
82
+ "docsLabel": "lunkr",
83
+ "blurb": "Lunkr/Coremail enterprise messaging with rich API support.",
84
+ "aliases": [
85
+ "coremail"
86
+ ],
87
+ "order": 40
88
+ },
89
+ "install": {
90
+ "npmSpec": "@coremail/lunkr-openclaw"
91
+ }
92
+ }
93
+ }
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: lunkr
3
+ description: Send messages and interact with Lunkr (论客) messaging platform
4
+ user-invocable: true
5
+ command-dispatch: tool
6
+ command-tool: lunkr_command
7
+ ---
8
+
9
+ # Lunkr/论客 Skill
10
+
11
+ Send messages and interact with Lunkr (论客) messaging platform.
12
+
13
+ ## Usage
14
+
15
+ ```
16
+ /lunkr <subcommand> [args]
17
+ ```
18
+
19
+ > **Note**: The `/lunkr` command works when typed directly but does not appear in the TUI slash command autocomplete list. This is a limitation of OpenClaw core's `getSlashCommands()` function, which doesn't include skill commands in autocomplete suggestions. Just type `/lunkr` and it will work.
20
+
21
+ ## Subcommands
22
+
23
+ | Command | Alias | Description |
24
+ |---------|-------|-------------|
25
+ | `send <to> <message>` | `s` | Send message to user or group |
26
+ | `search-groups <keyword> [limit]` | `sg` | Search for groups (default: 10) |
27
+ | `search-contacts <keyword> [limit]` | `sc` | Search for contacts (default: 10) |
28
+ | `list-chats [limit]` | `lc` | List recent chats (default: 20) |
29
+ | `help` | | Show usage help |
30
+
31
+ ## Examples
32
+
33
+ Send a message to a user by email:
34
+ ```
35
+ /lunkr send user@example.com Hello, this is a test message
36
+ ```
37
+
38
+ Send a message to a group by ID:
39
+ ```
40
+ /lunkr s #26783249#T Meeting reminder: standup at 10am
41
+ ```
42
+
43
+ Search for groups:
44
+ ```
45
+ /lunkr search-groups project-alpha
46
+ ```
47
+
48
+ List recent chats:
49
+ ```
50
+ /lunkr list-chats 10
51
+ ```
52
+
53
+ ## Agent Usage
54
+
55
+ **IMPORTANT: Always use `lunkr_send_message` tool for sending messages to Lunkr, NOT the generic "message" tool.**
56
+
57
+ The `lunkr_send_message` tool automatically resolves recipient names to UIDs:
58
+ - Pass group name directly: `测试Bot` → tool will search and find the UID
59
+ - Pass user name directly: `张三` → tool will search and find the UID
60
+ - Of course you can also use: `#xxx#U`, `#xxx#T`, `email@example.com`
61
+
62
+ Other available tools:
63
+
64
+ - `lunkr_search_groups` - Search for discussion groups
65
+ - `lunkr_search_contacts` - Search for contacts
66
+ - `lunkr_get_group_info` - Get group details
67
+ - `lunkr_get_user_info` - Get user details
68
+ - `lunkr_list_recent_chats` - List recent conversations
69
+ - `lunkr_download_file` - Download files from messages
70
+ - `lunkr_get_message` - Get specific message details
71
+
72
+ ## Recipient Formats
73
+
74
+ The `to` parameter in `/lunkr-send` accepts:
75
+
76
+ - User ID: `#835#U`
77
+ - Group ID: `#26783249#T`
78
+ - User email: `user@example.com`
79
+ - Group email: `t..xxx@coremail.cn`
80
+ - Group name (will search): `Project Alpha Team`