cc-lark 0.1.1

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 (298) hide show
  1. package/.github/workflows/ci.yml +47 -0
  2. package/.github/workflows/release.yml +47 -0
  3. package/.github/workflows/sync-upstream.yml +127 -0
  4. package/.prettierrc.json +7 -0
  5. package/README.md +214 -0
  6. package/dist/core/api-error.d.ts +193 -0
  7. package/dist/core/api-error.d.ts.map +1 -0
  8. package/dist/core/api-error.js +263 -0
  9. package/dist/core/api-error.js.map +1 -0
  10. package/dist/core/auth-errors.d.ts +13 -0
  11. package/dist/core/auth-errors.d.ts.map +1 -0
  12. package/dist/core/auth-errors.js +14 -0
  13. package/dist/core/auth-errors.js.map +1 -0
  14. package/dist/core/config.d.ts +60 -0
  15. package/dist/core/config.d.ts.map +1 -0
  16. package/dist/core/config.js +115 -0
  17. package/dist/core/config.js.map +1 -0
  18. package/dist/core/device-flow.d.ts +80 -0
  19. package/dist/core/device-flow.d.ts.map +1 -0
  20. package/dist/core/device-flow.js +231 -0
  21. package/dist/core/device-flow.js.map +1 -0
  22. package/dist/core/index.d.ts +16 -0
  23. package/dist/core/index.d.ts.map +1 -0
  24. package/dist/core/index.js +16 -0
  25. package/dist/core/index.js.map +1 -0
  26. package/dist/core/lark-client.d.ts +136 -0
  27. package/dist/core/lark-client.d.ts.map +1 -0
  28. package/dist/core/lark-client.js +315 -0
  29. package/dist/core/lark-client.js.map +1 -0
  30. package/dist/core/token-store.d.ts +67 -0
  31. package/dist/core/token-store.d.ts.map +1 -0
  32. package/dist/core/token-store.js +215 -0
  33. package/dist/core/token-store.js.map +1 -0
  34. package/dist/core/types.d.ts +286 -0
  35. package/dist/core/types.d.ts.map +1 -0
  36. package/dist/core/types.js +11 -0
  37. package/dist/core/types.js.map +1 -0
  38. package/dist/core/uat-client.d.ts +64 -0
  39. package/dist/core/uat-client.d.ts.map +1 -0
  40. package/dist/core/uat-client.js +227 -0
  41. package/dist/core/uat-client.js.map +1 -0
  42. package/dist/core/version.d.ts +26 -0
  43. package/dist/core/version.d.ts.map +1 -0
  44. package/dist/core/version.js +50 -0
  45. package/dist/core/version.js.map +1 -0
  46. package/dist/index.d.ts +12 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +116 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/tools/bitable/app.d.ts +20 -0
  51. package/dist/tools/bitable/app.d.ts.map +1 -0
  52. package/dist/tools/bitable/app.js +301 -0
  53. package/dist/tools/bitable/app.js.map +1 -0
  54. package/dist/tools/bitable/field.d.ts +19 -0
  55. package/dist/tools/bitable/field.d.ts.map +1 -0
  56. package/dist/tools/bitable/field.js +315 -0
  57. package/dist/tools/bitable/field.js.map +1 -0
  58. package/dist/tools/bitable/index.d.ts +21 -0
  59. package/dist/tools/bitable/index.d.ts.map +1 -0
  60. package/dist/tools/bitable/index.js +39 -0
  61. package/dist/tools/bitable/index.js.map +1 -0
  62. package/dist/tools/bitable/record.d.ts +22 -0
  63. package/dist/tools/bitable/record.d.ts.map +1 -0
  64. package/dist/tools/bitable/record.js +434 -0
  65. package/dist/tools/bitable/record.js.map +1 -0
  66. package/dist/tools/bitable/table.d.ts +21 -0
  67. package/dist/tools/bitable/table.d.ts.map +1 -0
  68. package/dist/tools/bitable/table.js +361 -0
  69. package/dist/tools/bitable/table.js.map +1 -0
  70. package/dist/tools/calendar/calendar.d.ts +18 -0
  71. package/dist/tools/calendar/calendar.d.ts.map +1 -0
  72. package/dist/tools/calendar/calendar.js +192 -0
  73. package/dist/tools/calendar/calendar.js.map +1 -0
  74. package/dist/tools/calendar/event.d.ts +20 -0
  75. package/dist/tools/calendar/event.d.ts.map +1 -0
  76. package/dist/tools/calendar/event.js +465 -0
  77. package/dist/tools/calendar/event.js.map +1 -0
  78. package/dist/tools/calendar/index.d.ts +19 -0
  79. package/dist/tools/calendar/index.d.ts.map +1 -0
  80. package/dist/tools/calendar/index.js +37 -0
  81. package/dist/tools/calendar/index.js.map +1 -0
  82. package/dist/tools/chat/chat.d.ts +11 -0
  83. package/dist/tools/chat/chat.d.ts.map +1 -0
  84. package/dist/tools/chat/chat.js +106 -0
  85. package/dist/tools/chat/chat.js.map +1 -0
  86. package/dist/tools/chat/index.d.ts +11 -0
  87. package/dist/tools/chat/index.d.ts.map +1 -0
  88. package/dist/tools/chat/index.js +20 -0
  89. package/dist/tools/chat/index.js.map +1 -0
  90. package/dist/tools/chat/members.d.ts +9 -0
  91. package/dist/tools/chat/members.d.ts.map +1 -0
  92. package/dist/tools/chat/members.js +80 -0
  93. package/dist/tools/chat/members.js.map +1 -0
  94. package/dist/tools/common/get-user.d.ts +11 -0
  95. package/dist/tools/common/get-user.d.ts.map +1 -0
  96. package/dist/tools/common/get-user.js +112 -0
  97. package/dist/tools/common/get-user.js.map +1 -0
  98. package/dist/tools/common/index.d.ts +11 -0
  99. package/dist/tools/common/index.d.ts.map +1 -0
  100. package/dist/tools/common/index.js +20 -0
  101. package/dist/tools/common/index.js.map +1 -0
  102. package/dist/tools/common/search-user.d.ts +9 -0
  103. package/dist/tools/common/search-user.d.ts.map +1 -0
  104. package/dist/tools/common/search-user.js +88 -0
  105. package/dist/tools/common/search-user.js.map +1 -0
  106. package/dist/tools/doc/create.d.ts +17 -0
  107. package/dist/tools/doc/create.d.ts.map +1 -0
  108. package/dist/tools/doc/create.js +159 -0
  109. package/dist/tools/doc/create.js.map +1 -0
  110. package/dist/tools/doc/fetch.d.ts +17 -0
  111. package/dist/tools/doc/fetch.d.ts.map +1 -0
  112. package/dist/tools/doc/fetch.js +123 -0
  113. package/dist/tools/doc/fetch.js.map +1 -0
  114. package/dist/tools/doc/index.d.ts +21 -0
  115. package/dist/tools/doc/index.d.ts.map +1 -0
  116. package/dist/tools/doc/index.js +33 -0
  117. package/dist/tools/doc/index.js.map +1 -0
  118. package/dist/tools/doc/shared.d.ts +69 -0
  119. package/dist/tools/doc/shared.d.ts.map +1 -0
  120. package/dist/tools/doc/shared.js +172 -0
  121. package/dist/tools/doc/shared.js.map +1 -0
  122. package/dist/tools/doc/update.d.ts +25 -0
  123. package/dist/tools/doc/update.d.ts.map +1 -0
  124. package/dist/tools/doc/update.js +208 -0
  125. package/dist/tools/doc/update.js.map +1 -0
  126. package/dist/tools/drive/file.d.ts +13 -0
  127. package/dist/tools/drive/file.d.ts.map +1 -0
  128. package/dist/tools/drive/file.js +212 -0
  129. package/dist/tools/drive/file.js.map +1 -0
  130. package/dist/tools/drive/index.d.ts +12 -0
  131. package/dist/tools/drive/index.d.ts.map +1 -0
  132. package/dist/tools/drive/index.js +25 -0
  133. package/dist/tools/drive/index.js.map +1 -0
  134. package/dist/tools/im/format-messages.d.ts +99 -0
  135. package/dist/tools/im/format-messages.d.ts.map +1 -0
  136. package/dist/tools/im/format-messages.js +277 -0
  137. package/dist/tools/im/format-messages.js.map +1 -0
  138. package/dist/tools/im/helpers.d.ts +53 -0
  139. package/dist/tools/im/helpers.d.ts.map +1 -0
  140. package/dist/tools/im/helpers.js +85 -0
  141. package/dist/tools/im/helpers.js.map +1 -0
  142. package/dist/tools/im/index.d.ts +25 -0
  143. package/dist/tools/im/index.d.ts.map +1 -0
  144. package/dist/tools/im/index.js +44 -0
  145. package/dist/tools/im/index.js.map +1 -0
  146. package/dist/tools/im/message-read.d.ts +19 -0
  147. package/dist/tools/im/message-read.d.ts.map +1 -0
  148. package/dist/tools/im/message-read.js +526 -0
  149. package/dist/tools/im/message-read.js.map +1 -0
  150. package/dist/tools/im/message.d.ts +22 -0
  151. package/dist/tools/im/message.d.ts.map +1 -0
  152. package/dist/tools/im/message.js +233 -0
  153. package/dist/tools/im/message.js.map +1 -0
  154. package/dist/tools/im/resource.d.ts +19 -0
  155. package/dist/tools/im/resource.d.ts.map +1 -0
  156. package/dist/tools/im/resource.js +185 -0
  157. package/dist/tools/im/resource.js.map +1 -0
  158. package/dist/tools/im/time-utils.d.ts +70 -0
  159. package/dist/tools/im/time-utils.d.ts.map +1 -0
  160. package/dist/tools/im/time-utils.js +277 -0
  161. package/dist/tools/im/time-utils.js.map +1 -0
  162. package/dist/tools/index.d.ts +85 -0
  163. package/dist/tools/index.d.ts.map +1 -0
  164. package/dist/tools/index.js +135 -0
  165. package/dist/tools/index.js.map +1 -0
  166. package/dist/tools/oauth.d.ts +15 -0
  167. package/dist/tools/oauth.d.ts.map +1 -0
  168. package/dist/tools/oauth.js +379 -0
  169. package/dist/tools/oauth.js.map +1 -0
  170. package/dist/tools/search/doc-search.d.ts +9 -0
  171. package/dist/tools/search/doc-search.d.ts.map +1 -0
  172. package/dist/tools/search/doc-search.js +219 -0
  173. package/dist/tools/search/doc-search.js.map +1 -0
  174. package/dist/tools/search/index.d.ts +11 -0
  175. package/dist/tools/search/index.d.ts.map +1 -0
  176. package/dist/tools/search/index.js +18 -0
  177. package/dist/tools/search/index.js.map +1 -0
  178. package/dist/tools/sheets/index.d.ts +11 -0
  179. package/dist/tools/sheets/index.d.ts.map +1 -0
  180. package/dist/tools/sheets/index.js +18 -0
  181. package/dist/tools/sheets/index.js.map +1 -0
  182. package/dist/tools/sheets/sheet.d.ts +11 -0
  183. package/dist/tools/sheets/sheet.d.ts.map +1 -0
  184. package/dist/tools/sheets/sheet.js +332 -0
  185. package/dist/tools/sheets/sheet.js.map +1 -0
  186. package/dist/tools/task/index.d.ts +12 -0
  187. package/dist/tools/task/index.d.ts.map +1 -0
  188. package/dist/tools/task/index.js +30 -0
  189. package/dist/tools/task/index.js.map +1 -0
  190. package/dist/tools/task/task.d.ts +13 -0
  191. package/dist/tools/task/task.d.ts.map +1 -0
  192. package/dist/tools/task/task.js +225 -0
  193. package/dist/tools/task/task.js.map +1 -0
  194. package/dist/tools/task/tasklist.d.ts +13 -0
  195. package/dist/tools/task/tasklist.d.ts.map +1 -0
  196. package/dist/tools/task/tasklist.js +206 -0
  197. package/dist/tools/task/tasklist.js.map +1 -0
  198. package/dist/tools/wiki/index.d.ts +11 -0
  199. package/dist/tools/wiki/index.d.ts.map +1 -0
  200. package/dist/tools/wiki/index.js +20 -0
  201. package/dist/tools/wiki/index.js.map +1 -0
  202. package/dist/tools/wiki/node.d.ts +11 -0
  203. package/dist/tools/wiki/node.d.ts.map +1 -0
  204. package/dist/tools/wiki/node.js +112 -0
  205. package/dist/tools/wiki/node.js.map +1 -0
  206. package/dist/tools/wiki/space.d.ts +11 -0
  207. package/dist/tools/wiki/space.d.ts.map +1 -0
  208. package/dist/tools/wiki/space.js +125 -0
  209. package/dist/tools/wiki/space.js.map +1 -0
  210. package/dist/utils/index.d.ts +8 -0
  211. package/dist/utils/index.d.ts.map +1 -0
  212. package/dist/utils/index.js +8 -0
  213. package/dist/utils/index.js.map +1 -0
  214. package/dist/utils/logger.d.ts +36 -0
  215. package/dist/utils/logger.d.ts.map +1 -0
  216. package/dist/utils/logger.js +101 -0
  217. package/dist/utils/logger.js.map +1 -0
  218. package/eslint.config.js +13 -0
  219. package/package.json +54 -0
  220. package/skills/feishu-bitable/SKILL.md +248 -0
  221. package/skills/feishu-bitable/references/examples.md +813 -0
  222. package/skills/feishu-bitable/references/field-properties.md +763 -0
  223. package/skills/feishu-bitable/references/record-values.md +911 -0
  224. package/skills/feishu-calendar/SKILL.md +244 -0
  225. package/skills/feishu-channel-rules/SKILL.md +18 -0
  226. package/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
  227. package/skills/feishu-create-doc/SKILL.md +719 -0
  228. package/skills/feishu-fetch-doc/SKILL.md +93 -0
  229. package/skills/feishu-im-read/SKILL.md +163 -0
  230. package/skills/feishu-task/SKILL.md +293 -0
  231. package/skills/feishu-troubleshoot/SKILL.md +70 -0
  232. package/skills/feishu-update-doc/SKILL.md +285 -0
  233. package/src/core/api-error.ts +342 -0
  234. package/src/core/auth-errors.ts +27 -0
  235. package/src/core/config.ts +134 -0
  236. package/src/core/device-flow.ts +314 -0
  237. package/src/core/index.ts +16 -0
  238. package/src/core/lark-client.ts +391 -0
  239. package/src/core/token-store.ts +249 -0
  240. package/src/core/types.ts +302 -0
  241. package/src/core/uat-client.ts +298 -0
  242. package/src/core/version.ts +53 -0
  243. package/src/index.ts +138 -0
  244. package/src/tools/bitable/app.ts +390 -0
  245. package/src/tools/bitable/field.ts +406 -0
  246. package/src/tools/bitable/index.ts +43 -0
  247. package/src/tools/bitable/record.ts +559 -0
  248. package/src/tools/bitable/table.ts +472 -0
  249. package/src/tools/calendar/calendar.ts +254 -0
  250. package/src/tools/calendar/event.ts +606 -0
  251. package/src/tools/calendar/index.ts +41 -0
  252. package/src/tools/chat/chat.ts +127 -0
  253. package/src/tools/chat/index.ts +24 -0
  254. package/src/tools/chat/members.ts +93 -0
  255. package/src/tools/common/get-user.ts +127 -0
  256. package/src/tools/common/index.ts +24 -0
  257. package/src/tools/common/search-user.ts +99 -0
  258. package/src/tools/doc/create.ts +184 -0
  259. package/src/tools/doc/fetch.ts +149 -0
  260. package/src/tools/doc/index.ts +38 -0
  261. package/src/tools/doc/shared.ts +228 -0
  262. package/src/tools/doc/update.ts +240 -0
  263. package/src/tools/drive/file.ts +265 -0
  264. package/src/tools/drive/index.ts +29 -0
  265. package/src/tools/im/format-messages.ts +391 -0
  266. package/src/tools/im/helpers.ts +109 -0
  267. package/src/tools/im/index.ts +49 -0
  268. package/src/tools/im/message-read.ts +676 -0
  269. package/src/tools/im/message.ts +303 -0
  270. package/src/tools/im/resource.ts +225 -0
  271. package/src/tools/im/time-utils.ts +347 -0
  272. package/src/tools/index.ts +205 -0
  273. package/src/tools/oauth.ts +460 -0
  274. package/src/tools/search/doc-search.ts +250 -0
  275. package/src/tools/search/index.ts +22 -0
  276. package/src/tools/sheets/index.ts +22 -0
  277. package/src/tools/sheets/sheet.ts +382 -0
  278. package/src/tools/task/index.ts +34 -0
  279. package/src/tools/task/task.ts +265 -0
  280. package/src/tools/task/tasklist.ts +262 -0
  281. package/src/tools/wiki/index.ts +24 -0
  282. package/src/tools/wiki/node.ts +131 -0
  283. package/src/tools/wiki/space.ts +152 -0
  284. package/src/utils/index.ts +8 -0
  285. package/src/utils/logger.ts +132 -0
  286. package/tests/core/config.test.ts +238 -0
  287. package/tests/core/device-flow.test.ts +490 -0
  288. package/tests/core/lark-client.test.ts +378 -0
  289. package/tests/core/token-store.test.ts +438 -0
  290. package/tests/index.test.ts +360 -0
  291. package/tests/tools/doc/create.test.ts +224 -0
  292. package/tests/tools/doc/fetch.test.ts +182 -0
  293. package/tests/tools/doc/shared.test.ts +183 -0
  294. package/tests/tools/doc/update.test.ts +330 -0
  295. package/tests/tools/im/format-messages.test.ts +184 -0
  296. package/tests/tools/im/time-utils.test.ts +178 -0
  297. package/tests/utils/logger.test.ts +140 -0
  298. package/tsconfig.json +20 -0
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Shared Lark API error handling utilities.
6
+ *
7
+ * Provides unified error handling for two distinct error paths:
8
+ *
9
+ * 1. **Response-level errors** — The SDK returns a response object with a
10
+ * non-zero `code`. Handled by {@link assertLarkOk}.
11
+ *
12
+ * 2. **Thrown exceptions** — The SDK throws an Axios-style error (HTTP 4xx)
13
+ * whose properties include the Feishu error `code` and `msg`.
14
+ * Handled by {@link formatLarkError}.
15
+ *
16
+ * Adapted from openclaw-lark for MCP Server architecture.
17
+ */
18
+ // ---------------------------------------------------------------------------
19
+ // Well-known Lark error codes
20
+ // ---------------------------------------------------------------------------
21
+ /**
22
+ * Well-known Lark API error codes.
23
+ * @see https://open.feishu.cn/document/ukTMukTMukTM/ugTM5UjL4ETO14COxkTN/code
24
+ */
25
+ export const LARK_ERROR = {
26
+ /** Success */
27
+ SUCCESS: 0,
28
+ /** Permission denied - app scope missing (tenant level) */
29
+ APP_SCOPE_MISSING: 99991672,
30
+ /** User token scope insufficient */
31
+ USER_SCOPE_INSUFFICIENT: 99991679,
32
+ /** Invalid access token */
33
+ INVALID_ACCESS_TOKEN: 99991663,
34
+ /** Access token expired */
35
+ ACCESS_TOKEN_EXPIRED: 99991664,
36
+ /** access_token invalid */
37
+ TOKEN_INVALID: 99991668,
38
+ /** access_token expired */
39
+ TOKEN_EXPIRED: 99991669,
40
+ /** refresh_token invalid */
41
+ REFRESH_TOKEN_INVALID: 20003,
42
+ /** refresh_token expired */
43
+ REFRESH_TOKEN_EXPIRED: 20004,
44
+ /** refresh_token missing */
45
+ REFRESH_TOKEN_MISSING: 20024,
46
+ /** refresh_token revoked */
47
+ REFRESH_TOKEN_REVOKED: 20063,
48
+ /** Message recalled */
49
+ MESSAGE_RECALLED: 230011,
50
+ /** Message deleted */
51
+ MESSAGE_DELETED: 231003,
52
+ };
53
+ // ---------------------------------------------------------------------------
54
+ // Code extraction
55
+ // ---------------------------------------------------------------------------
56
+ /**
57
+ * Coerce a value to a number if possible.
58
+ */
59
+ function coerceCode(value) {
60
+ if (typeof value === 'number' && Number.isFinite(value)) {
61
+ return value;
62
+ }
63
+ if (typeof value === 'string') {
64
+ const parsed = Number(value);
65
+ if (Number.isFinite(parsed))
66
+ return parsed;
67
+ }
68
+ return undefined;
69
+ }
70
+ /**
71
+ * Extract the Lark API code from a thrown error object.
72
+ *
73
+ * Supports three common structures:
74
+ * - `{ code }` — SDK direct mount
75
+ * - `{ data: { code } }` — Response body nested
76
+ * - `{ response: { data: { code } } }` — Axios style
77
+ */
78
+ export function extractLarkApiCode(err) {
79
+ if (!err || typeof err !== 'object')
80
+ return undefined;
81
+ const e = err;
82
+ return coerceCode(e.code) ?? coerceCode(e.data?.code) ?? coerceCode(e.response?.data?.code);
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Public API
86
+ // ---------------------------------------------------------------------------
87
+ /**
88
+ * Assert that a Lark SDK response is successful (code === 0).
89
+ *
90
+ * @param res - Lark SDK response object
91
+ * @throws Error with the message from the response if code is non-zero
92
+ */
93
+ export function assertLarkOk(res) {
94
+ if (!res.code || res.code === 0)
95
+ return;
96
+ throw new Error(res.msg ?? `Feishu API error (code: ${res.code})`);
97
+ }
98
+ /**
99
+ * Extract a meaningful error message from a thrown Lark SDK / Axios error.
100
+ *
101
+ * The Lark SDK throws Axios errors whose object carries Feishu-specific
102
+ * fields (`code`, `msg`) alongside the standard `message`. For all errors
103
+ * we try `err.msg` first (the Feishu detail) and fall back to `err.message`
104
+ * (the generic Axios text).
105
+ */
106
+ export function formatLarkError(err) {
107
+ if (!err || typeof err !== 'object') {
108
+ return String(err);
109
+ }
110
+ const e = err;
111
+ // Path 1: Lark SDK merges Feishu fields onto the thrown error object.
112
+ if (typeof e.code === 'number' && e.msg) {
113
+ return e.msg;
114
+ }
115
+ // Path 2: Standard Axios error — dig into response.data.
116
+ const data = e.response?.data;
117
+ if (data && typeof data.code === 'number' && data.msg) {
118
+ return data.msg;
119
+ }
120
+ // Fallback.
121
+ return e.message ?? String(err);
122
+ }
123
+ /**
124
+ * Check if an error indicates missing app scope/permission.
125
+ */
126
+ export function isPermissionError(err) {
127
+ const code = extractLarkApiCode(err);
128
+ return code === LARK_ERROR.APP_SCOPE_MISSING;
129
+ }
130
+ /**
131
+ * Check if an error indicates an invalid or expired access token.
132
+ */
133
+ export function isTokenError(err) {
134
+ const code = extractLarkApiCode(err);
135
+ return code === LARK_ERROR.INVALID_ACCESS_TOKEN || code === LARK_ERROR.ACCESS_TOKEN_EXPIRED;
136
+ }
137
+ // ---------------------------------------------------------------------------
138
+ // Error code sets
139
+ // ---------------------------------------------------------------------------
140
+ /** Irrecoverable refresh_token error codes - require re-authorization */
141
+ export const REFRESH_TOKEN_IRRECOVERABLE = new Set([
142
+ LARK_ERROR.REFRESH_TOKEN_INVALID,
143
+ LARK_ERROR.REFRESH_TOKEN_EXPIRED,
144
+ LARK_ERROR.REFRESH_TOKEN_MISSING,
145
+ LARK_ERROR.REFRESH_TOKEN_REVOKED,
146
+ ]);
147
+ /** Message terminal error codes (recalled/deleted) - stop further operations */
148
+ export const MESSAGE_TERMINAL_CODES = new Set([
149
+ LARK_ERROR.MESSAGE_RECALLED,
150
+ LARK_ERROR.MESSAGE_DELETED,
151
+ ]);
152
+ /** access_token failure error codes - can retry with refresh */
153
+ export const TOKEN_RETRY_CODES = new Set([
154
+ LARK_ERROR.TOKEN_INVALID,
155
+ LARK_ERROR.TOKEN_EXPIRED,
156
+ ]);
157
+ // ---------------------------------------------------------------------------
158
+ // Error classes
159
+ // ---------------------------------------------------------------------------
160
+ /**
161
+ * Thrown when no valid UAT exists and the user needs to (re-)authorize.
162
+ * Callers should catch this and trigger the OAuth flow.
163
+ */
164
+ export class NeedAuthorizationError extends Error {
165
+ userOpenId;
166
+ constructor(userOpenId) {
167
+ super('need_user_authorization');
168
+ this.name = 'NeedAuthorizationError';
169
+ this.userOpenId = userOpenId;
170
+ }
171
+ }
172
+ /**
173
+ * Thrown when the app lacks the application:application:self_manage permission.
174
+ *
175
+ * The administrator needs to enable this permission in the Lark Developer Console.
176
+ */
177
+ export class AppScopeCheckFailedError extends Error {
178
+ appId;
179
+ constructor(appId) {
180
+ super('App lacks application:application:self_manage permission. ' +
181
+ 'Please ask the administrator to enable this permission in the Developer Console.');
182
+ this.name = 'AppScopeCheckFailedError';
183
+ this.appId = appId;
184
+ }
185
+ }
186
+ /**
187
+ * Thrown when the app is missing required OAPI scopes.
188
+ *
189
+ * The administrator needs to enable permissions in the Lark Developer Console.
190
+ */
191
+ export class AppScopeMissingError extends Error {
192
+ apiName;
193
+ /** Missing scopes that the app doesn't have */
194
+ missingScopes;
195
+ /** All required scopes (including enabled ones), for requesting user authorization after app permission setup */
196
+ allRequiredScopes;
197
+ /** Application ID for generating permission management links */
198
+ appId;
199
+ scopeNeedType;
200
+ /** Token type used when this error was triggered */
201
+ tokenType;
202
+ constructor(info, scopeNeedType, tokenType, allRequiredScopes) {
203
+ if (scopeNeedType === 'one') {
204
+ super(`App missing permission [${info.scopes.join(', ')}] ` +
205
+ '(enable any one of these). Please ask the administrator to enable in Developer Console.');
206
+ }
207
+ else {
208
+ super(`App missing permission [${info.scopes.join(', ')}]. ` +
209
+ 'Please ask the administrator to enable in Developer Console.');
210
+ }
211
+ this.name = 'AppScopeMissingError';
212
+ this.apiName = info.apiName;
213
+ this.missingScopes = info.scopes;
214
+ this.allRequiredScopes = allRequiredScopes;
215
+ this.appId = info.appId;
216
+ this.scopeNeedType = scopeNeedType;
217
+ this.tokenType = tokenType;
218
+ }
219
+ }
220
+ /**
221
+ * Thrown when user has not authorized or scope is insufficient.
222
+ *
223
+ * `requiredScopes` contains valid scopes from APP∩OAPI intersection,
224
+ * can be passed directly to OAuth authorize.
225
+ */
226
+ export class UserAuthRequiredError extends Error {
227
+ userOpenId;
228
+ apiName;
229
+ /** APP∩OAPI intersection scopes, pass to OAuth authorize */
230
+ requiredScopes;
231
+ /** Whether app scope was verified. false means requiredScopes may be inaccurate. */
232
+ appScopeVerified;
233
+ /** Application ID for generating permission management links */
234
+ appId;
235
+ constructor(userOpenId, info) {
236
+ super('need_user_authorization');
237
+ this.name = 'UserAuthRequiredError';
238
+ this.userOpenId = userOpenId;
239
+ this.apiName = info.apiName;
240
+ this.requiredScopes = info.scopes;
241
+ this.appId = info.appId;
242
+ this.appScopeVerified = info.appScopeVerified ?? true;
243
+ }
244
+ }
245
+ /**
246
+ * Thrown when server returns 99991679 - user token scope insufficient.
247
+ *
248
+ * Requires incremental authorization: start a new Device Flow with missing scopes.
249
+ */
250
+ export class UserScopeInsufficientError extends Error {
251
+ userOpenId;
252
+ apiName;
253
+ /** Missing scope list */
254
+ missingScopes;
255
+ constructor(userOpenId, info) {
256
+ super('user_scope_insufficient');
257
+ this.name = 'UserScopeInsufficientError';
258
+ this.userOpenId = userOpenId;
259
+ this.apiName = info.apiName;
260
+ this.missingScopes = info.scopes;
261
+ }
262
+ }
263
+ //# sourceMappingURL=api-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-error.js","sourceRoot":"","sources":["../../src/core/api-error.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Authentication error types for cc-lark MCP Server.
6
+ *
7
+ * Re-exports error types from api-error.ts for convenience.
8
+ * This module provides backward compatibility and a dedicated import path.
9
+ *
10
+ * Adapted from openclaw-lark for MCP Server architecture.
11
+ */
12
+ export { LARK_ERROR, REFRESH_TOKEN_IRRECOVERABLE, MESSAGE_TERMINAL_CODES, TOKEN_RETRY_CODES, ScopeErrorInfo, AuthHint, TryInvokeResult, NeedAuthorizationError, AppScopeCheckFailedError, AppScopeMissingError, UserAuthRequiredError, UserScopeInsufficientError, } from './api-error.js';
13
+ //# sourceMappingURL=auth-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-errors.d.ts","sourceRoot":"","sources":["../../src/core/auth-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,UAAU,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,eAAe,EACf,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Authentication error types for cc-lark MCP Server.
6
+ *
7
+ * Re-exports error types from api-error.ts for convenience.
8
+ * This module provides backward compatibility and a dedicated import path.
9
+ *
10
+ * Adapted from openclaw-lark for MCP Server architecture.
11
+ */
12
+ // Re-export everything from api-error.ts
13
+ export { LARK_ERROR, REFRESH_TOKEN_IRRECOVERABLE, MESSAGE_TERMINAL_CODES, TOKEN_RETRY_CODES, NeedAuthorizationError, AppScopeCheckFailedError, AppScopeMissingError, UserAuthRequiredError, UserScopeInsufficientError, } from './api-error.js';
14
+ //# sourceMappingURL=auth-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-errors.js","sourceRoot":"","sources":["../../src/core/auth-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,yCAAyC;AACzC,OAAO,EACL,UAAU,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,iBAAiB,EAIjB,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Configuration management for the cc-lark MCP Server.
6
+ *
7
+ * Loads configuration from environment variables and provides validation.
8
+ */
9
+ import type { FeishuConfig, ConfigValidationResult, LarkBrand } from './types.js';
10
+ export declare const ENV_VARS: {
11
+ readonly APP_ID: "FEISHU_APP_ID";
12
+ readonly APP_SECRET: "FEISHU_APP_SECRET";
13
+ readonly USER_ACCESS_TOKEN: "FEISHU_USER_ACCESS_TOKEN";
14
+ readonly BRAND: "FEISHU_BRAND";
15
+ readonly ENCRYPT_KEY: "FEISHU_ENCRYPT_KEY";
16
+ readonly VERIFICATION_TOKEN: "FEISHU_VERIFICATION_TOKEN";
17
+ };
18
+ /**
19
+ * Load Feishu configuration from environment variables.
20
+ *
21
+ * Required:
22
+ * - FEISHU_APP_ID: Feishu App ID
23
+ * - FEISHU_APP_SECRET: Feishu App Secret
24
+ *
25
+ * Optional:
26
+ * - FEISHU_USER_ACCESS_TOKEN: User access token for user-authorized operations
27
+ * - FEISHU_BRAND: Platform brand ('feishu' | 'lark' | custom URL)
28
+ * - FEISHU_ENCRYPT_KEY: Encryption key for webhook events
29
+ * - FEISHU_VERIFICATION_TOKEN: Verification token for webhooks
30
+ */
31
+ export declare function loadConfig(): FeishuConfig;
32
+ /**
33
+ * Validate the Feishu configuration.
34
+ *
35
+ * @param config - Configuration to validate
36
+ * @returns Validation result with errors if any
37
+ */
38
+ export declare function validateConfig(config: FeishuConfig): ConfigValidationResult;
39
+ /**
40
+ * Load and validate configuration in one step.
41
+ *
42
+ * @throws Error if configuration is invalid
43
+ * @returns Validated Feishu configuration
44
+ */
45
+ export declare function loadAndValidateConfig(): FeishuConfig;
46
+ /**
47
+ * Check if configuration has user access token.
48
+ *
49
+ * @param config - Configuration to check
50
+ * @returns True if user access token is configured
51
+ */
52
+ export declare function hasUserAccessToken(config: FeishuConfig): boolean;
53
+ /**
54
+ * Get the base URL for the Lark API based on brand.
55
+ *
56
+ * @param brand - Platform brand
57
+ * @returns Base URL for API calls
58
+ */
59
+ export declare function getApiBaseUrl(brand?: LarkBrand): string;
60
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMlF,eAAO,MAAM,QAAQ;;;;;;;CAOX,CAAC;AAMX;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,IAAI,YAAY,CAgBzC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,sBAAsB,CAyB3E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,YAAY,CASpD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,SAAoB,GAAG,MAAM,CAQjE"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Configuration management for the cc-lark MCP Server.
6
+ *
7
+ * Loads configuration from environment variables and provides validation.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // Environment variable names
11
+ // ---------------------------------------------------------------------------
12
+ export const ENV_VARS = {
13
+ APP_ID: 'FEISHU_APP_ID',
14
+ APP_SECRET: 'FEISHU_APP_SECRET',
15
+ USER_ACCESS_TOKEN: 'FEISHU_USER_ACCESS_TOKEN',
16
+ BRAND: 'FEISHU_BRAND',
17
+ ENCRYPT_KEY: 'FEISHU_ENCRYPT_KEY',
18
+ VERIFICATION_TOKEN: 'FEISHU_VERIFICATION_TOKEN',
19
+ };
20
+ // ---------------------------------------------------------------------------
21
+ // Configuration loader
22
+ // ---------------------------------------------------------------------------
23
+ /**
24
+ * Load Feishu configuration from environment variables.
25
+ *
26
+ * Required:
27
+ * - FEISHU_APP_ID: Feishu App ID
28
+ * - FEISHU_APP_SECRET: Feishu App Secret
29
+ *
30
+ * Optional:
31
+ * - FEISHU_USER_ACCESS_TOKEN: User access token for user-authorized operations
32
+ * - FEISHU_BRAND: Platform brand ('feishu' | 'lark' | custom URL)
33
+ * - FEISHU_ENCRYPT_KEY: Encryption key for webhook events
34
+ * - FEISHU_VERIFICATION_TOKEN: Verification token for webhooks
35
+ */
36
+ export function loadConfig() {
37
+ const appId = process.env[ENV_VARS.APP_ID];
38
+ const appSecret = process.env[ENV_VARS.APP_SECRET];
39
+ const userAccessToken = process.env[ENV_VARS.USER_ACCESS_TOKEN];
40
+ const brand = process.env[ENV_VARS.BRAND];
41
+ const encryptKey = process.env[ENV_VARS.ENCRYPT_KEY];
42
+ const verificationToken = process.env[ENV_VARS.VERIFICATION_TOKEN];
43
+ return {
44
+ appId: appId ?? '',
45
+ appSecret: appSecret ?? '',
46
+ userAccessToken,
47
+ brand: brand ?? 'feishu',
48
+ encryptKey,
49
+ verificationToken,
50
+ };
51
+ }
52
+ /**
53
+ * Validate the Feishu configuration.
54
+ *
55
+ * @param config - Configuration to validate
56
+ * @returns Validation result with errors if any
57
+ */
58
+ export function validateConfig(config) {
59
+ const errors = [];
60
+ if (!config.appId) {
61
+ errors.push(`Missing required environment variable: ${ENV_VARS.APP_ID}`);
62
+ }
63
+ if (!config.appSecret) {
64
+ errors.push(`Missing required environment variable: ${ENV_VARS.APP_SECRET}`);
65
+ }
66
+ if (config.brand) {
67
+ const validBrands = ['feishu', 'lark'];
68
+ if (!validBrands.includes(config.brand) && !config.brand.startsWith('https://')) {
69
+ errors.push(`Invalid FEISHU_BRAND value: "${config.brand}". Must be "feishu", "lark", or a custom HTTPS URL`);
70
+ }
71
+ }
72
+ if (errors.length > 0) {
73
+ return { valid: false, errors };
74
+ }
75
+ return { valid: true, errors: [], config };
76
+ }
77
+ /**
78
+ * Load and validate configuration in one step.
79
+ *
80
+ * @throws Error if configuration is invalid
81
+ * @returns Validated Feishu configuration
82
+ */
83
+ export function loadAndValidateConfig() {
84
+ const config = loadConfig();
85
+ const result = validateConfig(config);
86
+ if (!result.valid) {
87
+ throw new Error(`Invalid configuration:\n${result.errors.map(e => ` - ${e}`).join('\n')}`);
88
+ }
89
+ return config;
90
+ }
91
+ /**
92
+ * Check if configuration has user access token.
93
+ *
94
+ * @param config - Configuration to check
95
+ * @returns True if user access token is configured
96
+ */
97
+ export function hasUserAccessToken(config) {
98
+ return typeof config.userAccessToken === 'string' && config.userAccessToken.length > 0;
99
+ }
100
+ /**
101
+ * Get the base URL for the Lark API based on brand.
102
+ *
103
+ * @param brand - Platform brand
104
+ * @returns Base URL for API calls
105
+ */
106
+ export function getApiBaseUrl(brand = 'feishu') {
107
+ if (brand === 'lark') {
108
+ return 'https://open.larksuite.com/open-apis';
109
+ }
110
+ if (brand.startsWith('https://')) {
111
+ return brand;
112
+ }
113
+ return 'https://open.feishu.cn/open-apis';
114
+ }
115
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * OAuth 2.0 Device Authorization Grant (RFC 8628) for Lark/Feishu.
6
+ *
7
+ * Two-step flow:
8
+ * 1. `requestDeviceAuthorization` – obtains device_code + user_code.
9
+ * 2. `pollDeviceToken` – polls the token endpoint until the user authorizes,
10
+ * rejects, or the code expires.
11
+ *
12
+ * All HTTP calls use the built-in `fetch` (Node 18+). The Lark SDK is not
13
+ * used here because these OAuth endpoints are outside the SDK's scope.
14
+ *
15
+ * Adapted from openclaw-lark for MCP Server architecture.
16
+ */
17
+ import type { LarkBrand } from './types.js';
18
+ export interface DeviceAuthResponse {
19
+ deviceCode: string;
20
+ userCode: string;
21
+ verificationUri: string;
22
+ verificationUriComplete: string;
23
+ expiresIn: number;
24
+ interval: number;
25
+ }
26
+ export interface DeviceFlowTokenData {
27
+ accessToken: string;
28
+ refreshToken: string;
29
+ expiresIn: number;
30
+ refreshExpiresIn: number;
31
+ scope: string;
32
+ }
33
+ export type DeviceFlowResult = {
34
+ ok: true;
35
+ token: DeviceFlowTokenData;
36
+ } | {
37
+ ok: false;
38
+ error: DeviceFlowError;
39
+ message: string;
40
+ };
41
+ export type DeviceFlowError = 'authorization_pending' | 'slow_down' | 'access_denied' | 'expired_token';
42
+ /**
43
+ * Resolve the two OAuth endpoint URLs based on the configured brand.
44
+ */
45
+ export declare function resolveOAuthEndpoints(brand: LarkBrand): {
46
+ deviceAuthorization: string;
47
+ token: string;
48
+ };
49
+ /**
50
+ * Request a device authorization code from the Feishu OAuth server.
51
+ *
52
+ * Uses Confidential Client authentication (HTTP Basic with appId:appSecret).
53
+ * The `offline_access` scope is automatically appended so that the token
54
+ * response includes a refresh_token.
55
+ */
56
+ export declare function requestDeviceAuthorization(params: {
57
+ appId: string;
58
+ appSecret: string;
59
+ brand: LarkBrand;
60
+ scope?: string;
61
+ }): Promise<DeviceAuthResponse>;
62
+ /**
63
+ * Poll the token endpoint until the user authorizes, rejects, or the code
64
+ * expires.
65
+ *
66
+ * Handles `authorization_pending` (keep polling), `slow_down` (back off by
67
+ * +5 s), `access_denied` and `expired_token` (terminal errors).
68
+ *
69
+ * Pass an `AbortSignal` to cancel polling from the outside.
70
+ */
71
+ export declare function pollDeviceToken(params: {
72
+ appId: string;
73
+ appSecret: string;
74
+ brand: LarkBrand;
75
+ deviceCode: string;
76
+ interval: number;
77
+ expiresIn: number;
78
+ signal?: AbortSignal;
79
+ }): Promise<DeviceFlowResult>;
80
+ //# sourceMappingURL=device-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/core/device-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAU5C,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,GACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,MAAM,MAAM,eAAe,GAAG,uBAAuB,GAAG,WAAW,GAAG,eAAe,GAAG,eAAe,CAAC;AAyBxG;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG;IACvD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf,CA8BA;AAMD;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA0D9B;AAoBD;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2F5B"}