@coremail/lunkr-openclaw 1.0.0 → 1.0.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
1
  {
2
- "id": "lunkr",
3
- "channels": ["lunkr"],
2
+ "id": "lunkr-openclaw",
3
+ "entry": "./index.js",
4
+ "channels": ["lunkr-openclaw"],
4
5
  "skills": ["skills/lunkr"],
5
6
  "configSchema": {
6
7
  "type": "object",
package/package.json CHANGED
@@ -1,46 +1,20 @@
1
1
  {
2
2
  "name": "@coremail/lunkr-openclaw",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "OpenClaw Lunkr/Coremail channel plugin",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
- "main": "./dist/index.js",
8
- "types": "./dist/index.ts",
7
+ "main": "./index.js",
9
8
  "exports": {
10
9
  ".": {
11
- "import": "./dist/index.js",
12
- "types": "./dist/index.ts"
10
+ "import": "./index.js"
13
11
  }
14
12
  },
15
13
  "bin": {
16
- "lunkr-cli": "./dist/bin/lunkr-cli.js"
14
+ "lunkr-cli": "./bin/lunkr-cli.js"
17
15
  },
18
- "files": [
19
- "dist/**/*.js",
20
- "openclaw.plugin.json",
21
- "skills/**",
22
- "docs/**",
23
- "README.md"
24
- ],
25
16
  "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"
17
+ "start": "node index.js"
44
18
  },
45
19
  "dependencies": {
46
20
  "@sinclair/typebox": "0.34.48",
@@ -51,18 +25,6 @@
51
25
  "uuid": "^11.0.0",
52
26
  "ws": "^8.18.0"
53
27
  },
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
28
  "keywords": [
67
29
  "openclaw",
68
30
  "lunkr",
@@ -72,14 +34,14 @@
72
34
  ],
73
35
  "openclaw": {
74
36
  "extensions": [
75
- "./dist/index.js"
37
+ "./index.js"
76
38
  ],
77
39
  "channel": {
78
- "id": "lunkr",
40
+ "id": "lunkr-openclaw",
79
41
  "label": "Lunkr",
80
42
  "selectionLabel": "Lunkr/Coremail (论客)",
81
- "docsPath": "/channels/lunkr",
82
- "docsLabel": "lunkr",
43
+ "docsPath": "/channels/lunkr-openclaw",
44
+ "docsLabel": "lunkr-openclaw",
83
45
  "blurb": "Lunkr/Coremail enterprise messaging with rich API support.",
84
46
  "aliases": [
85
47
  "coremail"
@@ -90,4 +52,4 @@
90
52
  "npmSpec": "@coremail/lunkr-openclaw"
91
53
  }
92
54
  }
93
- }
55
+ }
@@ -1,254 +0,0 @@
1
- # Lunkr Authentication Flow
2
-
3
- This document describes the complete authentication flow for the Lunkr channel plugin.
4
-
5
- ## Overview
6
-
7
- Lunkr authentication involves two separate systems:
8
-
9
- 1. **Coremail** - The email server that handles user authentication
10
- 2. **Lunkr** - The collaboration platform that uses Coremail for authentication
11
-
12
- The authentication flow must first authenticate with Coremail, then obtain a Lunkr session.
13
-
14
- ## Authentication Flow Diagram
15
-
16
- ```
17
- ┌─────────────────────────────────────────────────────────────────────────┐
18
- │ Login Flow │
19
- └─────────────────────────────────────────────────────────────────────────┘
20
-
21
- User Input Coremail Server Lunkr Server
22
- │ │ │
23
- │ 1. Discover Server │ │
24
- │ ─────────────────────> │ │
25
- │ │ │
26
- │ 2. Get RSA Key │ │
27
- │ <───────────────────── │ │
28
- │ │ │
29
- │ 3. Encrypt Password │ │
30
- │ ─────────────────────> │ │
31
- │ │ │
32
- │ 4. user:login │ │
33
- │ ─────────────────────> │ │
34
- │ │ │
35
- │ 5. Return Code │ │
36
- │ <───────────────────── │ │
37
- │ │ │
38
- │ ╔═════════════════════════════════════════════════╗ │
39
- │ ║ Branch based on return code ║ │
40
- │ ╠═════════════════════════════════════════════════╣ │
41
- │ ║ S_OK / FA_NEED_ACCESS_SECRET → Continue ║ │
42
- │ ║ FA_NEED_DYNAMIC_PWD → OTP Flow ║ │
43
- │ ║ FA_NEED_VERIFY_CODE → Manual Login Required ║ │
44
- │ ╚═════════════════════════════════════════════════╝ │
45
- │ │ │
46
- │ 6. getLunkrSession │ │
47
- │ ──────────────────────────────────────────────────────────> │
48
- │ │ │
49
- │ 7. cim.common:verify │ │
50
- │ <───────────────────────────────────────────────────────── │
51
- │ (returns login_key) │ │
52
- │ │ │
53
- │ 8. Generate X-CM-TOKEN │ │
54
- │ │ │
55
- │ 9. cim.user:login │ │
56
- │ ──────────────────────────────────────────────────────────> │
57
- │ │ │
58
- │ 10. Lunkr Session │ │
59
- │ <───────────────────────────────────────────────────────── │
60
- │ (Cim cookie, Lunkr SID) │ │
61
- ```
62
-
63
- ## Step-by-Step Flow
64
-
65
- ### Step 1: Server Discovery
66
-
67
- First, discover the Coremail server for the user's email domain:
68
-
69
- ```typescript
70
- const serverInfo = await DomainDiscoveryService.discoverAvailableServer(email);
71
- // Returns: { baseUrl, apiPath, apiUrl, uri }
72
- ```
73
-
74
- ### Step 2: Get RSA Key
75
-
76
- Request RSA public key for password encryption:
77
-
78
- ```typescript
79
- const rsaInfo = await client.postJson({
80
- func: 'user:get_rsa',
81
- payload: { uid: email }
82
- });
83
- // Returns: { sid, authType, rsaE, rsaN }
84
- ```
85
-
86
- ### Step 3: Encrypt Password
87
-
88
- Encrypt the password using RSA:
89
-
90
- ```typescript
91
- const encryptedPassword = encryptPasswordRsa(password, rsaInfo.rsaE, rsaInfo.rsaN);
92
- ```
93
-
94
- ### Step 4-5: Login Request
95
-
96
- Send login request with encrypted password and device info:
97
-
98
- ```typescript
99
- const loginPayload = {
100
- uid: email,
101
- password: encryptedPassword,
102
- authType: rsaInfo.authType,
103
- device: {
104
- uuid: deviceUuid,
105
- os: 'macOS',
106
- model: 'Desktop',
107
- friendlyName: deviceName,
108
- },
109
- supportDynamicPwd: true,
110
- supportBind2FA: true,
111
- returnCookie: true,
112
- // ... other fields
113
- };
114
-
115
- const response = await client.postJson({
116
- func: 'user:login',
117
- sid: rsaInfo.sid,
118
- payload: loginPayload
119
- });
120
- ```
121
-
122
- ### Step 6: Handle Return Code
123
-
124
- The login response returns different codes:
125
-
126
- | Code | Meaning | Action |
127
- |------|---------|--------|
128
- | `S_OK` | Success | Proceed to getLunkrSession |
129
- | `FA_NEED_ACCESS_SECRET` | Device auth success | Proceed to getLunkrSession |
130
- | `FA_NEED_DYNAMIC_PWD` | OTP required | Trigger OTP flow |
131
- | `FA_NEED_VERIFY_CODE` | Captcha required | Manual login required |
132
- | `FA_USER_IN_GRAYLIST` | User restricted | Manual login required |
133
-
134
- ### OTP Flow (FA_NEED_DYNAMIC_PWD)
135
-
136
- When OTP is required:
137
-
138
- 1. **Trigger second auth**:
139
- ```typescript
140
- await client.postJson({
141
- func: 'user:triggerSecondAuth',
142
- payload: { type: 'OTP', device, tempSid, trans: 'login' }
143
- });
144
- ```
145
-
146
- 2. **Wait for user** to complete OTP on another device
147
-
148
- 3. **Query validation status**:
149
- ```typescript
150
- const result = await client.postJson({
151
- func: 'user:querySecondAuthValidateStage',
152
- payload: { tempSid, trans: 'login' }
153
- });
154
- // Wait for stage === 'VALIDATED'
155
- ```
156
-
157
- 4. **Re-login** without password (auth already verified)
158
-
159
- 5. **Proceed to getLunkrSession**
160
-
161
- ### Step 6-10: Get Lunkr Session
162
-
163
- After successful Coremail login, obtain a Lunkr session:
164
-
165
- #### 6.1: Call cim.common:verify
166
-
167
- ```typescript
168
- const verifyResp = await httpsPost(
169
- 'https://lunkr.coremail.cn/lunkr/s/json?func=cim.common:verify',
170
- '{}',
171
- { Cookie: `Coremail=${coremailCookie}` }
172
- );
173
- // Returns: { login_key, login_index }
174
- ```
175
-
176
- #### 6.2: Generate X-CM-TOKEN
177
-
178
- ```typescript
179
- const dataToEncrypt = `${coremailSid}:${coremailCookie}`;
180
- const dataB64 = Buffer.from(dataToEncrypt).toString('base64');
181
- const xCmToken = encryptWithLoginKey(dataB64, loginKey);
182
- ```
183
-
184
- #### 6.3: Call cim.user:login
185
-
186
- ```typescript
187
- const loginResp = await httpsPost(
188
- 'https://lunkr.coremail.cn/lunkr/s/json?func=cim.user:login',
189
- {
190
- uid: email,
191
- device: { uuid, os, model, friendlyName },
192
- forceCookieCheck: true,
193
- setCookieKey: true,
194
- login_index: loginIndex
195
- },
196
- { 'X-CM-TOKEN': xCmToken }
197
- );
198
- // Returns: { sid, self_uid }
199
- // Set-Cookie header: Cim=...
200
- ```
201
-
202
- ## Session Data
203
-
204
- ### Coremail Session
205
-
206
- ```typescript
207
- {
208
- sid: string, // Coremail session ID
209
- cookie: string, // Coremail=...
210
- baseUrl: string, // e.g., https://mail.example.com
211
- apiPath: string // e.g., /coremail/s/json
212
- }
213
- ```
214
-
215
- ### Lunkr Session
216
-
217
- ```typescript
218
- {
219
- sid: string, // Lunkr session ID
220
- selfUid: string, // User's Lunkr ID
221
- cookie: string, // Cim=...
222
- baseUrl: string, // https://lunkr.coremail.cn
223
- apiPath: string // /lunkr/s/json
224
- }
225
- ```
226
-
227
- ## Key Difference
228
-
229
- The critical difference is:
230
-
231
- - **Coremail session** is for the email server API
232
- - **Lunkr session** is for the collaboration platform API
233
-
234
- Both OTP flow and normal login flow must call `getLunkrSession()` to convert the Coremail session to a Lunkr session. The bug fixed in this version was that the OTP flow was returning the Coremail session directly instead of calling `getLunkrSession()`.
235
-
236
- ## Error Handling
237
-
238
- | Error | Cause | Solution |
239
- |-------|-------|----------|
240
- | `PasswordError` | Wrong password | Check credentials |
241
- | `FA_NEED_VERIFY_CODE` | Captcha required | Login via webmail first |
242
- | `FA_USER_IN_GRAYLIST` | Account restricted | Contact admin |
243
- | `No Coremail cookie` | Login incomplete | Check server response |
244
- | `cim.common:verify failed` | Session invalid | Re-login required |
245
-
246
- ## Session Validation
247
-
248
- Sessions are validated periodically (every 5 minutes) by calling:
249
-
250
- ```typescript
251
- await client.checkSessionValid(sid);
252
- ```
253
-
254
- If the session is invalid, the user must re-authenticate.
@@ -1,112 +0,0 @@
1
- # 命令速查表
2
-
3
- ## npm scripts
4
-
5
- ### 开发调试
6
-
7
- ```bash
8
- npm run dev # 热重载开发模式
9
- npm run dev:cli # 直接运行 CLI (不编译)
10
-
11
- # 调试单个命令
12
- npx tsx src/bin/lunkr-cli.ts status
13
- npx tsx src/bin/lunkr-cli.ts login
14
- ```
15
-
16
- ### 测试
17
-
18
- ```bash
19
- npm test # 运行测试
20
- npm run test:watch # 测试监视模式
21
- npm run lint # 代码检查
22
- ```
23
-
24
- ### 构建
25
-
26
- ```bash
27
- npm run clean # 清理 dist/
28
- npm run build # 编译 TypeScript
29
- npm run build:release # 生产构建 (esbuild)
30
- ```
31
-
32
- ### 部署
33
-
34
- ```bash
35
- npm run deploy:local # 快速部署 (仅复制)
36
- npm run deploy:local:full # 完整: clean → test → build → deploy
37
- ```
38
-
39
- ### 版本与发布
40
-
41
- ```bash
42
- npm version patch # 提升补丁版本 (1.0.0 → 1.0.1)
43
- npm version minor # 提升小版本 (1.0.0 → 1.1.0)
44
- npm version major # 提升大版本 (1.0.0 → 2.0.0)
45
-
46
- npm run pack # 打包 .tgz
47
- npm publish # 发布到 npm
48
- git push --follow-tags # 推送代码和标签
49
- ```
50
-
51
- ## 环境变量
52
-
53
- | 变量 | 默认值 | 说明 |
54
- |------|--------|------|
55
- | `OPENCLAW_ROOT` | `~/work/ai/openclaw` | OpenClaw 根目录 |
56
- | `OPENCLAW_EXT` | `$OPENCLAW_ROOT/extensions` | 扩展目录 |
57
- | `LUNKR_LANG` | 自动检测 | 语言 (zh-CN, en-US) |
58
-
59
- ## 典型工作流
60
-
61
- ```
62
- ┌─────────────────────────────────────────────────────────┐
63
- │ 开发 │
64
- ├─────────────────────────────────────────────────────────┤
65
- │ npm run test:watch # 开着测试监视 │
66
- │ # 编写代码... │
67
- │ npm run deploy:local # 快速部署测试 │
68
- └─────────────────────────────────────────────────────────┘
69
-
70
- ┌─────────────────────────────────────────────────────────┐
71
- │ 发布前验证 │
72
- ├─────────────────────────────────────────────────────────┤
73
- │ npm run deploy:local:full # 完整流程 │
74
- └─────────────────────────────────────────────────────────┘
75
-
76
- ┌─────────────────────────────────────────────────────────┐
77
- │ 打包/发布 │
78
- ├─────────────────────────────────────────────────────────┤
79
- │ npm version patch # 提升版本号 │
80
- │ git push --follow-tags # 推送代码和标签 │
81
- │ npm run pack # 生成 .tgz (可选) │
82
- │ npm publish # 发布到 npm │
83
- └─────────────────────────────────────────────────────────┘
84
- ```
85
-
86
- ## CLI 命令
87
-
88
- ```bash
89
- # 认证
90
- openclaw lunkr login --email <email> # 登录
91
- openclaw lunkr login --email <email> --password <pwd> # 密码登录
92
- openclaw lunkr logout # 登出
93
- openclaw lunkr status # 状态
94
-
95
- # 消息
96
- openclaw lunkr send -t <uid> -m "hello" # 发送消息
97
- openclaw lunkr send-file -t <uid> -f file.pdf # 发送文件
98
- openclaw lunkr download --file-id <id> # 下载文件
99
-
100
- # 搜索
101
- openclaw lunkr search-contact <keyword> # 搜索联系人
102
- openclaw lunkr search-group <keyword> # 搜索讨论组
103
-
104
- # Bot 讨论
105
- openclaw lunkr create <name> # 创建 Bot 讨论
106
- openclaw lunkr bot-list # 列出 Bot 讨论
107
- openclaw lunkr bot-delete --name <name> # 删除 Bot 讨论
108
-
109
- # 其他
110
- openclaw lunkr list-msg -t <uid> # 列出消息
111
- openclaw lunkr listen # 监听实时消息
112
- ```