@lark-project/openclaw-lark-project 2026.3.131

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 (368) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/README.zh.md +80 -0
  4. package/dist/index.js +172 -0
  5. package/dist/index.js.map +7 -0
  6. package/dist/skills/feishu-bitable/SKILL.md +248 -0
  7. package/dist/skills/feishu-bitable/references/examples.md +813 -0
  8. package/dist/skills/feishu-bitable/references/field-properties.md +763 -0
  9. package/dist/skills/feishu-bitable/references/record-values.md +911 -0
  10. package/dist/skills/feishu-calendar/SKILL.md +244 -0
  11. package/dist/skills/feishu-channel-rules/SKILL.md +18 -0
  12. package/dist/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
  13. package/dist/skills/feishu-create-doc/SKILL.md +719 -0
  14. package/dist/skills/feishu-fetch-doc/SKILL.md +93 -0
  15. package/dist/skills/feishu-im-read/SKILL.md +163 -0
  16. package/dist/skills/feishu-project/SKILL.md +122 -0
  17. package/dist/skills/feishu-task/SKILL.md +293 -0
  18. package/dist/skills/feishu-troubleshoot/SKILL.md +70 -0
  19. package/dist/skills/feishu-update-doc/SKILL.md +285 -0
  20. package/dist/src/card/builder.js +293 -0
  21. package/dist/src/card/builder.js.map +7 -0
  22. package/dist/src/card/cardkit.js +126 -0
  23. package/dist/src/card/cardkit.js.map +7 -0
  24. package/dist/src/card/flush-controller.js +107 -0
  25. package/dist/src/card/flush-controller.js.map +7 -0
  26. package/dist/src/card/markdown-style.js +57 -0
  27. package/dist/src/card/markdown-style.js.map +7 -0
  28. package/dist/src/card/reply-dispatcher-types.js +39 -0
  29. package/dist/src/card/reply-dispatcher-types.js.map +7 -0
  30. package/dist/src/card/reply-dispatcher.js +245 -0
  31. package/dist/src/card/reply-dispatcher.js.map +7 -0
  32. package/dist/src/card/reply-mode.js +29 -0
  33. package/dist/src/card/reply-mode.js.map +7 -0
  34. package/dist/src/card/streaming-card-controller.js +653 -0
  35. package/dist/src/card/streaming-card-controller.js.map +7 -0
  36. package/dist/src/card/unavailable-guard.js +76 -0
  37. package/dist/src/card/unavailable-guard.js.map +7 -0
  38. package/dist/src/channel/abort-detect.js +79 -0
  39. package/dist/src/channel/abort-detect.js.map +7 -0
  40. package/dist/src/channel/chat-queue.js +50 -0
  41. package/dist/src/channel/chat-queue.js.map +7 -0
  42. package/dist/src/channel/config-adapter.js +89 -0
  43. package/dist/src/channel/config-adapter.js.map +7 -0
  44. package/dist/src/channel/directory.js +133 -0
  45. package/dist/src/channel/directory.js.map +7 -0
  46. package/dist/src/channel/event-handlers.js +175 -0
  47. package/dist/src/channel/event-handlers.js.map +7 -0
  48. package/dist/src/channel/monitor.js +108 -0
  49. package/dist/src/channel/monitor.js.map +7 -0
  50. package/dist/src/channel/onboarding-config.js +76 -0
  51. package/dist/src/channel/onboarding-config.js.map +7 -0
  52. package/dist/src/channel/onboarding-migrate.js +55 -0
  53. package/dist/src/channel/onboarding-migrate.js.map +7 -0
  54. package/dist/src/channel/onboarding.js +285 -0
  55. package/dist/src/channel/onboarding.js.map +7 -0
  56. package/dist/src/channel/plugin.js +260 -0
  57. package/dist/src/channel/plugin.js.map +7 -0
  58. package/dist/src/channel/probe.js +14 -0
  59. package/dist/src/channel/probe.js.map +7 -0
  60. package/dist/src/channel/types.js +1 -0
  61. package/dist/src/channel/types.js.map +7 -0
  62. package/dist/src/commands/auth.js +73 -0
  63. package/dist/src/commands/auth.js.map +7 -0
  64. package/dist/src/commands/diagnose.js +658 -0
  65. package/dist/src/commands/diagnose.js.map +7 -0
  66. package/dist/src/commands/doctor.js +327 -0
  67. package/dist/src/commands/doctor.js.map +7 -0
  68. package/dist/src/commands/index.js +124 -0
  69. package/dist/src/commands/index.js.map +7 -0
  70. package/dist/src/core/accounts.js +129 -0
  71. package/dist/src/core/accounts.js.map +7 -0
  72. package/dist/src/core/agent-config.js +60 -0
  73. package/dist/src/core/agent-config.js.map +7 -0
  74. package/dist/src/core/api-error.js +55 -0
  75. package/dist/src/core/api-error.js.map +7 -0
  76. package/dist/src/core/app-owner-fallback.js +17 -0
  77. package/dist/src/core/app-owner-fallback.js.map +7 -0
  78. package/dist/src/core/app-scope-checker.js +95 -0
  79. package/dist/src/core/app-scope-checker.js.map +7 -0
  80. package/dist/src/core/auth-errors.js +120 -0
  81. package/dist/src/core/auth-errors.js.map +7 -0
  82. package/dist/src/core/chat-info-cache.js +102 -0
  83. package/dist/src/core/chat-info-cache.js.map +7 -0
  84. package/dist/src/core/config-schema.js +150 -0
  85. package/dist/src/core/config-schema.js.map +7 -0
  86. package/dist/src/core/device-flow.js +174 -0
  87. package/dist/src/core/device-flow.js.map +7 -0
  88. package/dist/src/core/feishu-fetch.js +12 -0
  89. package/dist/src/core/feishu-fetch.js.map +7 -0
  90. package/dist/src/core/footer-config.js +16 -0
  91. package/dist/src/core/footer-config.js.map +7 -0
  92. package/dist/src/core/lark-client.js +322 -0
  93. package/dist/src/core/lark-client.js.map +7 -0
  94. package/dist/src/core/lark-logger.js +92 -0
  95. package/dist/src/core/lark-logger.js.map +7 -0
  96. package/dist/src/core/lark-ticket.js +18 -0
  97. package/dist/src/core/lark-ticket.js.map +7 -0
  98. package/dist/src/core/message-unavailable.js +119 -0
  99. package/dist/src/core/message-unavailable.js.map +7 -0
  100. package/dist/src/core/owner-policy.js +25 -0
  101. package/dist/src/core/owner-policy.js.map +7 -0
  102. package/dist/src/core/permission-url.js +37 -0
  103. package/dist/src/core/permission-url.js.map +7 -0
  104. package/dist/src/core/project-auth.js +177 -0
  105. package/dist/src/core/project-auth.js.map +7 -0
  106. package/dist/src/core/project-oauth-flow.js +124 -0
  107. package/dist/src/core/project-oauth-flow.js.map +7 -0
  108. package/dist/src/core/project-token-store.js +172 -0
  109. package/dist/src/core/project-token-store.js.map +7 -0
  110. package/dist/src/core/raw-request.js +45 -0
  111. package/dist/src/core/raw-request.js.map +7 -0
  112. package/dist/src/core/scope-manager.js +62 -0
  113. package/dist/src/core/scope-manager.js.map +7 -0
  114. package/dist/src/core/security-check.js +118 -0
  115. package/dist/src/core/security-check.js.map +7 -0
  116. package/dist/src/core/shutdown-hooks.js +37 -0
  117. package/dist/src/core/shutdown-hooks.js.map +7 -0
  118. package/dist/src/core/targets.js +55 -0
  119. package/dist/src/core/targets.js.map +7 -0
  120. package/dist/src/core/token-store.js +215 -0
  121. package/dist/src/core/token-store.js.map +7 -0
  122. package/dist/src/core/tool-client.js +335 -0
  123. package/dist/src/core/tool-client.js.map +7 -0
  124. package/dist/src/core/tool-scopes.js +207 -0
  125. package/dist/src/core/tool-scopes.js.map +7 -0
  126. package/dist/src/core/tools-config.js +57 -0
  127. package/dist/src/core/tools-config.js.map +7 -0
  128. package/dist/src/core/types.js +1 -0
  129. package/dist/src/core/types.js.map +7 -0
  130. package/dist/src/core/uat-client.js +124 -0
  131. package/dist/src/core/uat-client.js.map +7 -0
  132. package/dist/src/core/version.js +27 -0
  133. package/dist/src/core/version.js.map +7 -0
  134. package/dist/src/messaging/converters/audio.js +19 -0
  135. package/dist/src/messaging/converters/audio.js.map +7 -0
  136. package/dist/src/messaging/converters/calendar.js +46 -0
  137. package/dist/src/messaging/converters/calendar.js.map +7 -0
  138. package/dist/src/messaging/converters/content-converter.js +61 -0
  139. package/dist/src/messaging/converters/content-converter.js.map +7 -0
  140. package/dist/src/messaging/converters/file.js +18 -0
  141. package/dist/src/messaging/converters/file.js.map +7 -0
  142. package/dist/src/messaging/converters/folder.js +18 -0
  143. package/dist/src/messaging/converters/folder.js.map +7 -0
  144. package/dist/src/messaging/converters/hongbao.js +14 -0
  145. package/dist/src/messaging/converters/hongbao.js.map +7 -0
  146. package/dist/src/messaging/converters/image.js +16 -0
  147. package/dist/src/messaging/converters/image.js.map +7 -0
  148. package/dist/src/messaging/converters/index.js +48 -0
  149. package/dist/src/messaging/converters/index.js.map +7 -0
  150. package/dist/src/messaging/converters/interactive/card-converter.js +1040 -0
  151. package/dist/src/messaging/converters/interactive/card-converter.js.map +7 -0
  152. package/dist/src/messaging/converters/interactive/card-utils.js +36 -0
  153. package/dist/src/messaging/converters/interactive/card-utils.js.map +7 -0
  154. package/dist/src/messaging/converters/interactive/index.js +19 -0
  155. package/dist/src/messaging/converters/interactive/index.js.map +7 -0
  156. package/dist/src/messaging/converters/interactive/legacy.js +53 -0
  157. package/dist/src/messaging/converters/interactive/legacy.js.map +7 -0
  158. package/dist/src/messaging/converters/interactive/types.js +23 -0
  159. package/dist/src/messaging/converters/interactive/types.js.map +7 -0
  160. package/dist/src/messaging/converters/location.js +17 -0
  161. package/dist/src/messaging/converters/location.js.map +7 -0
  162. package/dist/src/messaging/converters/merge-forward.js +143 -0
  163. package/dist/src/messaging/converters/merge-forward.js.map +7 -0
  164. package/dist/src/messaging/converters/post.js +113 -0
  165. package/dist/src/messaging/converters/post.js.map +7 -0
  166. package/dist/src/messaging/converters/share.js +22 -0
  167. package/dist/src/messaging/converters/share.js.map +7 -0
  168. package/dist/src/messaging/converters/sticker.js +16 -0
  169. package/dist/src/messaging/converters/sticker.js.map +7 -0
  170. package/dist/src/messaging/converters/system.js +25 -0
  171. package/dist/src/messaging/converters/system.js.map +7 -0
  172. package/dist/src/messaging/converters/text.js +12 -0
  173. package/dist/src/messaging/converters/text.js.map +7 -0
  174. package/dist/src/messaging/converters/todo.js +37 -0
  175. package/dist/src/messaging/converters/todo.js.map +7 -0
  176. package/dist/src/messaging/converters/types.js +1 -0
  177. package/dist/src/messaging/converters/types.js.map +7 -0
  178. package/dist/src/messaging/converters/unknown.js +13 -0
  179. package/dist/src/messaging/converters/unknown.js.map +7 -0
  180. package/dist/src/messaging/converters/utils.js +35 -0
  181. package/dist/src/messaging/converters/utils.js.map +7 -0
  182. package/dist/src/messaging/converters/video-chat.js +21 -0
  183. package/dist/src/messaging/converters/video-chat.js.map +7 -0
  184. package/dist/src/messaging/converters/video.js +30 -0
  185. package/dist/src/messaging/converters/video.js.map +7 -0
  186. package/dist/src/messaging/converters/vote.js +24 -0
  187. package/dist/src/messaging/converters/vote.js.map +7 -0
  188. package/dist/src/messaging/inbound/dedup.js +82 -0
  189. package/dist/src/messaging/inbound/dedup.js.map +7 -0
  190. package/dist/src/messaging/inbound/dispatch-builders.js +98 -0
  191. package/dist/src/messaging/inbound/dispatch-builders.js.map +7 -0
  192. package/dist/src/messaging/inbound/dispatch-commands.js +94 -0
  193. package/dist/src/messaging/inbound/dispatch-commands.js.map +7 -0
  194. package/dist/src/messaging/inbound/dispatch-context.js +96 -0
  195. package/dist/src/messaging/inbound/dispatch-context.js.map +7 -0
  196. package/dist/src/messaging/inbound/dispatch.js +150 -0
  197. package/dist/src/messaging/inbound/dispatch.js.map +7 -0
  198. package/dist/src/messaging/inbound/enrich.js +137 -0
  199. package/dist/src/messaging/inbound/enrich.js.map +7 -0
  200. package/dist/src/messaging/inbound/gate-effects.js +28 -0
  201. package/dist/src/messaging/inbound/gate-effects.js.map +7 -0
  202. package/dist/src/messaging/inbound/gate.js +163 -0
  203. package/dist/src/messaging/inbound/gate.js.map +7 -0
  204. package/dist/src/messaging/inbound/handler.js +132 -0
  205. package/dist/src/messaging/inbound/handler.js.map +7 -0
  206. package/dist/src/messaging/inbound/media-resolver.js +70 -0
  207. package/dist/src/messaging/inbound/media-resolver.js.map +7 -0
  208. package/dist/src/messaging/inbound/mention.js +50 -0
  209. package/dist/src/messaging/inbound/mention.js.map +7 -0
  210. package/dist/src/messaging/inbound/parse-io.js +41 -0
  211. package/dist/src/messaging/inbound/parse-io.js.map +7 -0
  212. package/dist/src/messaging/inbound/parse.js +79 -0
  213. package/dist/src/messaging/inbound/parse.js.map +7 -0
  214. package/dist/src/messaging/inbound/permission.js +30 -0
  215. package/dist/src/messaging/inbound/permission.js.map +7 -0
  216. package/dist/src/messaging/inbound/policy.js +83 -0
  217. package/dist/src/messaging/inbound/policy.js.map +7 -0
  218. package/dist/src/messaging/inbound/reaction-handler.js +162 -0
  219. package/dist/src/messaging/inbound/reaction-handler.js.map +7 -0
  220. package/dist/src/messaging/inbound/user-name-cache.js +172 -0
  221. package/dist/src/messaging/inbound/user-name-cache.js.map +7 -0
  222. package/dist/src/messaging/outbound/actions.js +239 -0
  223. package/dist/src/messaging/outbound/actions.js.map +7 -0
  224. package/dist/src/messaging/outbound/chat-manage.js +74 -0
  225. package/dist/src/messaging/outbound/chat-manage.js.map +7 -0
  226. package/dist/src/messaging/outbound/deliver.js +162 -0
  227. package/dist/src/messaging/outbound/deliver.js.map +7 -0
  228. package/dist/src/messaging/outbound/fetch.js +7 -0
  229. package/dist/src/messaging/outbound/fetch.js.map +7 -0
  230. package/dist/src/messaging/outbound/forward.js +31 -0
  231. package/dist/src/messaging/outbound/forward.js.map +7 -0
  232. package/dist/src/messaging/outbound/media-url-utils.js +101 -0
  233. package/dist/src/messaging/outbound/media-url-utils.js.map +7 -0
  234. package/dist/src/messaging/outbound/media.js +463 -0
  235. package/dist/src/messaging/outbound/media.js.map +7 -0
  236. package/dist/src/messaging/outbound/outbound.js +95 -0
  237. package/dist/src/messaging/outbound/outbound.js.map +7 -0
  238. package/dist/src/messaging/outbound/reactions.js +312 -0
  239. package/dist/src/messaging/outbound/reactions.js.map +7 -0
  240. package/dist/src/messaging/outbound/send.js +194 -0
  241. package/dist/src/messaging/outbound/send.js.map +7 -0
  242. package/dist/src/messaging/outbound/typing.js +77 -0
  243. package/dist/src/messaging/outbound/typing.js.map +7 -0
  244. package/dist/src/messaging/shared/message-lookup.js +84 -0
  245. package/dist/src/messaging/shared/message-lookup.js.map +7 -0
  246. package/dist/src/messaging/types.js +1 -0
  247. package/dist/src/messaging/types.js.map +7 -0
  248. package/dist/src/tools/auto-auth.js +714 -0
  249. package/dist/src/tools/auto-auth.js.map +7 -0
  250. package/dist/src/tools/helpers.js +133 -0
  251. package/dist/src/tools/helpers.js.map +7 -0
  252. package/dist/src/tools/mcp/doc/create.js +35 -0
  253. package/dist/src/tools/mcp/doc/create.js.map +7 -0
  254. package/dist/src/tools/mcp/doc/fetch.js +33 -0
  255. package/dist/src/tools/mcp/doc/fetch.js.map +7 -0
  256. package/dist/src/tools/mcp/doc/index.js +32 -0
  257. package/dist/src/tools/mcp/doc/index.js.map +7 -0
  258. package/dist/src/tools/mcp/doc/update.js +61 -0
  259. package/dist/src/tools/mcp/doc/update.js.map +7 -0
  260. package/dist/src/tools/mcp/project/endpoint.js +25 -0
  261. package/dist/src/tools/mcp/project/endpoint.js.map +7 -0
  262. package/dist/src/tools/mcp/project/index.js +27 -0
  263. package/dist/src/tools/mcp/project/index.js.map +7 -0
  264. package/dist/src/tools/mcp/project/tools.js +579 -0
  265. package/dist/src/tools/mcp/project/tools.js.map +7 -0
  266. package/dist/src/tools/mcp/shared.js +170 -0
  267. package/dist/src/tools/mcp/shared.js.map +7 -0
  268. package/dist/src/tools/oapi/bitable/app-table-field.js +244 -0
  269. package/dist/src/tools/oapi/bitable/app-table-field.js.map +7 -0
  270. package/dist/src/tools/oapi/bitable/app-table-record.js +501 -0
  271. package/dist/src/tools/oapi/bitable/app-table-record.js.map +7 -0
  272. package/dist/src/tools/oapi/bitable/app-table-view.js +226 -0
  273. package/dist/src/tools/oapi/bitable/app-table-view.js.map +7 -0
  274. package/dist/src/tools/oapi/bitable/app-table.js +278 -0
  275. package/dist/src/tools/oapi/bitable/app-table.js.map +7 -0
  276. package/dist/src/tools/oapi/bitable/app.js +200 -0
  277. package/dist/src/tools/oapi/bitable/app.js.map +7 -0
  278. package/dist/src/tools/oapi/bitable/index.js +13 -0
  279. package/dist/src/tools/oapi/bitable/index.js.map +7 -0
  280. package/dist/src/tools/oapi/calendar/calendar.js +131 -0
  281. package/dist/src/tools/oapi/calendar/calendar.js.map +7 -0
  282. package/dist/src/tools/oapi/calendar/event-attendee.js +301 -0
  283. package/dist/src/tools/oapi/calendar/event-attendee.js.map +7 -0
  284. package/dist/src/tools/oapi/calendar/event.js +834 -0
  285. package/dist/src/tools/oapi/calendar/event.js.map +7 -0
  286. package/dist/src/tools/oapi/calendar/freebusy.js +111 -0
  287. package/dist/src/tools/oapi/calendar/freebusy.js.map +7 -0
  288. package/dist/src/tools/oapi/calendar/index.js +11 -0
  289. package/dist/src/tools/oapi/calendar/index.js.map +7 -0
  290. package/dist/src/tools/oapi/chat/chat.js +132 -0
  291. package/dist/src/tools/oapi/chat/chat.js.map +7 -0
  292. package/dist/src/tools/oapi/chat/index.js +11 -0
  293. package/dist/src/tools/oapi/chat/index.js.map +7 -0
  294. package/dist/src/tools/oapi/chat/members.js +83 -0
  295. package/dist/src/tools/oapi/chat/members.js.map +7 -0
  296. package/dist/src/tools/oapi/common/get-user.js +95 -0
  297. package/dist/src/tools/oapi/common/get-user.js.map +7 -0
  298. package/dist/src/tools/oapi/common/index.js +7 -0
  299. package/dist/src/tools/oapi/common/index.js.map +7 -0
  300. package/dist/src/tools/oapi/common/search-user.js +67 -0
  301. package/dist/src/tools/oapi/common/search-user.js.map +7 -0
  302. package/dist/src/tools/oapi/drive/doc-comments.js +310 -0
  303. package/dist/src/tools/oapi/drive/doc-comments.js.map +7 -0
  304. package/dist/src/tools/oapi/drive/doc-media.js +314 -0
  305. package/dist/src/tools/oapi/drive/doc-media.js.map +7 -0
  306. package/dist/src/tools/oapi/drive/file.js +548 -0
  307. package/dist/src/tools/oapi/drive/file.js.map +7 -0
  308. package/dist/src/tools/oapi/drive/index.js +29 -0
  309. package/dist/src/tools/oapi/drive/index.js.map +7 -0
  310. package/dist/src/tools/oapi/helpers.js +199 -0
  311. package/dist/src/tools/oapi/helpers.js.map +7 -0
  312. package/dist/src/tools/oapi/im/format-messages.js +128 -0
  313. package/dist/src/tools/oapi/im/format-messages.js.map +7 -0
  314. package/dist/src/tools/oapi/im/index.js +15 -0
  315. package/dist/src/tools/oapi/im/index.js.map +7 -0
  316. package/dist/src/tools/oapi/im/message-read.js +404 -0
  317. package/dist/src/tools/oapi/im/message-read.js.map +7 -0
  318. package/dist/src/tools/oapi/im/message.js +179 -0
  319. package/dist/src/tools/oapi/im/message.js.map +7 -0
  320. package/dist/src/tools/oapi/im/resource.js +126 -0
  321. package/dist/src/tools/oapi/im/resource.js.map +7 -0
  322. package/dist/src/tools/oapi/im/time-utils.js +169 -0
  323. package/dist/src/tools/oapi/im/time-utils.js.map +7 -0
  324. package/dist/src/tools/oapi/im/user-name-uat.js +103 -0
  325. package/dist/src/tools/oapi/im/user-name-uat.js.map +7 -0
  326. package/dist/src/tools/oapi/index.js +56 -0
  327. package/dist/src/tools/oapi/index.js.map +7 -0
  328. package/dist/src/tools/oapi/sdk-types.js +1 -0
  329. package/dist/src/tools/oapi/sdk-types.js.map +7 -0
  330. package/dist/src/tools/oapi/search/doc-search.js +215 -0
  331. package/dist/src/tools/oapi/search/doc-search.js.map +7 -0
  332. package/dist/src/tools/oapi/search/index.js +25 -0
  333. package/dist/src/tools/oapi/search/index.js.map +7 -0
  334. package/dist/src/tools/oapi/sheets/index.js +25 -0
  335. package/dist/src/tools/oapi/sheets/index.js.map +7 -0
  336. package/dist/src/tools/oapi/sheets/sheet.js +652 -0
  337. package/dist/src/tools/oapi/sheets/sheet.js.map +7 -0
  338. package/dist/src/tools/oapi/task/comment.js +151 -0
  339. package/dist/src/tools/oapi/task/comment.js.map +7 -0
  340. package/dist/src/tools/oapi/task/index.js +11 -0
  341. package/dist/src/tools/oapi/task/index.js.map +7 -0
  342. package/dist/src/tools/oapi/task/subtask.js +175 -0
  343. package/dist/src/tools/oapi/task/subtask.js.map +7 -0
  344. package/dist/src/tools/oapi/task/task.js +405 -0
  345. package/dist/src/tools/oapi/task/task.js.map +7 -0
  346. package/dist/src/tools/oapi/task/tasklist.js +366 -0
  347. package/dist/src/tools/oapi/task/tasklist.js.map +7 -0
  348. package/dist/src/tools/oapi/wiki/index.js +27 -0
  349. package/dist/src/tools/oapi/wiki/index.js.map +7 -0
  350. package/dist/src/tools/oapi/wiki/space-node.js +311 -0
  351. package/dist/src/tools/oapi/wiki/space-node.js.map +7 -0
  352. package/dist/src/tools/oapi/wiki/space.js +148 -0
  353. package/dist/src/tools/oapi/wiki/space.js.map +7 -0
  354. package/dist/src/tools/oauth-batch-auth.js +125 -0
  355. package/dist/src/tools/oauth-batch-auth.js.map +7 -0
  356. package/dist/src/tools/oauth-cards.js +269 -0
  357. package/dist/src/tools/oauth-cards.js.map +7 -0
  358. package/dist/src/tools/oauth.js +538 -0
  359. package/dist/src/tools/oauth.js.map +7 -0
  360. package/dist/src/tools/onboarding-auth.js +101 -0
  361. package/dist/src/tools/onboarding-auth.js.map +7 -0
  362. package/dist/src/tools/project-oauth.js +305 -0
  363. package/dist/src/tools/project-oauth.js.map +7 -0
  364. package/dist/src/tools/tat/im/index.js +9 -0
  365. package/dist/src/tools/tat/im/index.js.map +7 -0
  366. package/dist/src/tools/tat/im/resource.js +123 -0
  367. package/dist/src/tools/tat/im/resource.js.map +7 -0
  368. package/package.json +64 -0
@@ -0,0 +1,652 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import {
3
+ json,
4
+ createToolContext,
5
+ assertLarkOk,
6
+ handleInvokeErrorWithAutoAuth
7
+ } from "../helpers";
8
+ import * as fs from "fs/promises";
9
+ import * as path from "path";
10
+ const MAX_READ_ROWS = 200;
11
+ const MAX_WRITE_ROWS = 5e3;
12
+ const MAX_WRITE_COLS = 100;
13
+ const EXPORT_POLL_INTERVAL_MS = 1e3;
14
+ const EXPORT_POLL_MAX_RETRIES = 30;
15
+ function sleep(ms) {
16
+ return new Promise((resolve) => setTimeout(resolve, ms));
17
+ }
18
+ function parseSheetUrl(url) {
19
+ try {
20
+ const u = new URL(url);
21
+ const match = u.pathname.match(/\/(?:sheets|wiki)\/([^/?#]+)/);
22
+ if (!match) return null;
23
+ return {
24
+ token: match[1],
25
+ sheetId: u.searchParams.get("sheet") || void 0
26
+ };
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+ const KNOWN_TOKEN_TYPES = /* @__PURE__ */ new Set([
32
+ "dox",
33
+ "doc",
34
+ "sht",
35
+ "bas",
36
+ "app",
37
+ "sld",
38
+ "bmn",
39
+ "fld",
40
+ "nod",
41
+ "box",
42
+ "jsn",
43
+ "img",
44
+ "isv",
45
+ "wik",
46
+ "wia",
47
+ "wib",
48
+ "wic",
49
+ "wid",
50
+ "wie",
51
+ "dsb"
52
+ ]);
53
+ function getTokenType(token) {
54
+ if (token.length >= 15) {
55
+ const prefix = token[4] + token[9] + token[14];
56
+ if (KNOWN_TOKEN_TYPES.has(prefix)) return prefix;
57
+ }
58
+ if (token.length >= 3) {
59
+ const prefix = token.substring(0, 3);
60
+ if (KNOWN_TOKEN_TYPES.has(prefix)) return prefix;
61
+ }
62
+ return null;
63
+ }
64
+ async function resolveToken(p, client, log) {
65
+ let token;
66
+ let urlSheetId;
67
+ if (p.spreadsheet_token) {
68
+ token = p.spreadsheet_token;
69
+ } else if (p.url) {
70
+ const parsed = parseSheetUrl(p.url);
71
+ if (!parsed) {
72
+ throw new Error(`Failed to parse spreadsheet_token from URL: ${p.url}`);
73
+ }
74
+ token = parsed.token;
75
+ urlSheetId = parsed.sheetId;
76
+ } else {
77
+ throw new Error("url or spreadsheet_token is required");
78
+ }
79
+ const tokenType = getTokenType(token);
80
+ if (tokenType === "wik") {
81
+ log.info(`resolveToken: detected wiki token, resolving obj_token...`);
82
+ const wikiNodeRes = await client.invoke(
83
+ "feishu_sheet.info",
84
+ (sdk, opts) => sdk.wiki.space.getNode(
85
+ {
86
+ params: {
87
+ token,
88
+ obj_type: "wiki"
89
+ }
90
+ },
91
+ opts
92
+ ),
93
+ { as: "user" }
94
+ );
95
+ assertLarkOk(wikiNodeRes);
96
+ const objToken = wikiNodeRes.data?.node?.obj_token;
97
+ if (!objToken) {
98
+ throw new Error(`Failed to resolve spreadsheet token from wiki token: ${token}`);
99
+ }
100
+ log.info(`resolveToken: wiki resolved ${token} -> ${objToken}`);
101
+ token = objToken;
102
+ }
103
+ return { token, urlSheetId };
104
+ }
105
+ async function resolveRange(token, range, sheetId, client, apiName) {
106
+ if (range) return range;
107
+ if (sheetId) return sheetId;
108
+ const sheetsRes = await client.invoke(
109
+ apiName,
110
+ (sdk, opts) => sdk.sheets.spreadsheetSheet.query({ path: { spreadsheet_token: token } }, opts),
111
+ { as: "user" }
112
+ );
113
+ assertLarkOk(sheetsRes);
114
+ const firstSheet = (sheetsRes.data?.sheets ?? [])[0];
115
+ if (!firstSheet?.sheet_id) {
116
+ throw new Error("spreadsheet has no worksheets");
117
+ }
118
+ return firstSheet.sheet_id;
119
+ }
120
+ function colLetter(n) {
121
+ let result = "";
122
+ while (n > 0) {
123
+ n--;
124
+ result = String.fromCharCode(65 + n % 26) + result;
125
+ n = Math.floor(n / 26);
126
+ }
127
+ return result;
128
+ }
129
+ function flattenCellValue(cell) {
130
+ if (!Array.isArray(cell)) return cell;
131
+ if (cell.length > 0 && cell.every((seg) => seg != null && typeof seg === "object" && "text" in seg)) {
132
+ return cell.map((seg) => seg.text).join("");
133
+ }
134
+ return cell;
135
+ }
136
+ function flattenValues(values) {
137
+ if (!values) return values;
138
+ return values.map((row) => row.map(flattenCellValue));
139
+ }
140
+ function truncateRows(values, maxRows) {
141
+ if (!values) return { values, truncated: false, total_rows: 0 };
142
+ const total = values.length;
143
+ if (total <= maxRows) return { values, truncated: false, total_rows: total };
144
+ return { values: values.slice(0, maxRows), truncated: true, total_rows: total };
145
+ }
146
+ const UrlOrToken = [
147
+ Type.Optional(
148
+ Type.String({
149
+ description: "\u7535\u5B50\u8868\u683C URL\uFF0C\u4F8B\u5982 https://xxx.feishu.cn/sheets/TOKEN \u6216 https://xxx.feishu.cn/wiki/TOKEN\uFF08\u4E0E spreadsheet_token \u4E8C\u9009\u4E00\uFF09"
150
+ })
151
+ ),
152
+ Type.Optional(
153
+ Type.String({
154
+ description: "\u7535\u5B50\u8868\u683C token\uFF08\u4E0E url \u4E8C\u9009\u4E00\uFF09"
155
+ })
156
+ )
157
+ ];
158
+ const ValueRenderOption = Type.Optional(
159
+ Type.Union(
160
+ [
161
+ Type.Literal("ToString"),
162
+ Type.Literal("FormattedValue"),
163
+ Type.Literal("Formula"),
164
+ Type.Literal("UnformattedValue")
165
+ ],
166
+ {
167
+ description: "\u503C\u6E32\u67D3\u65B9\u5F0F\uFF1AToString\uFF08\u9ED8\u8BA4\uFF09\u3001FormattedValue\uFF08\u6309\u683C\u5F0F\uFF09\u3001Formula\uFF08\u516C\u5F0F\uFF09\u3001UnformattedValue\uFF08\u539F\u59CB\u503C\uFF09"
168
+ }
169
+ )
170
+ );
171
+ const FeishuSheetSchema = Type.Union([
172
+ // INFO
173
+ Type.Object({
174
+ action: Type.Literal("info"),
175
+ url: UrlOrToken[0],
176
+ spreadsheet_token: UrlOrToken[1]
177
+ }),
178
+ // READ
179
+ Type.Object({
180
+ action: Type.Literal("read"),
181
+ url: UrlOrToken[0],
182
+ spreadsheet_token: UrlOrToken[1],
183
+ range: Type.Optional(
184
+ Type.String({
185
+ description: "\u8BFB\u53D6\u8303\u56F4\uFF08\u53EF\u9009\uFF09\u3002\u683C\u5F0F\uFF1A<sheetId>!A1:D10 \u6216 <sheetId>\uFF08sheetId \u901A\u8FC7 info \u83B7\u53D6\uFF09\u3002\u4E0D\u586B\u5219\u81EA\u52A8\u8BFB\u53D6\u7B2C\u4E00\u4E2A\u5DE5\u4F5C\u8868\u5168\u90E8\u6570\u636E"
186
+ })
187
+ ),
188
+ sheet_id: Type.Optional(
189
+ Type.String({
190
+ description: "\u5DE5\u4F5C\u8868 ID\uFF08\u53EF\u9009\uFF09\u3002\u4EC5\u5F53\u4E0D\u63D0\u4F9B range \u65F6\u751F\u6548\uFF0C\u6307\u5B9A\u8981\u8BFB\u53D6\u7684\u5DE5\u4F5C\u8868\u3002\u4E0D\u586B\u5219\u8BFB\u53D6\u7B2C\u4E00\u4E2A\u5DE5\u4F5C\u8868"
191
+ })
192
+ ),
193
+ value_render_option: ValueRenderOption
194
+ }),
195
+ // WRITE
196
+ Type.Object({
197
+ action: Type.Literal("write"),
198
+ url: UrlOrToken[0],
199
+ spreadsheet_token: UrlOrToken[1],
200
+ range: Type.Optional(
201
+ Type.String({
202
+ description: "\u5199\u5165\u8303\u56F4\uFF08\u53EF\u9009\uFF09\u3002\u683C\u5F0F\uFF1A<sheetId>!A1:D10\uFF08sheetId \u901A\u8FC7 info \u83B7\u53D6\uFF09\u3002\u4E0D\u586B\u5219\u5199\u5165\u7B2C\u4E00\u4E2A\u5DE5\u4F5C\u8868\uFF08\u4ECE A1 \u5F00\u59CB\uFF09"
203
+ })
204
+ ),
205
+ sheet_id: Type.Optional(
206
+ Type.String({
207
+ description: "\u5DE5\u4F5C\u8868 ID\uFF08\u53EF\u9009\uFF09\u3002\u4EC5\u5F53\u4E0D\u63D0\u4F9B range \u65F6\u751F\u6548\u3002\u4E0D\u586B\u5219\u4F7F\u7528\u7B2C\u4E00\u4E2A\u5DE5\u4F5C\u8868"
208
+ })
209
+ ),
210
+ values: Type.Array(Type.Array(Type.Any()), {
211
+ description: '\u4E8C\u7EF4\u6570\u7EC4\uFF0C\u6BCF\u4E2A\u5143\u7D20\u662F\u4E00\u884C\u3002\u4F8B\u5982 [["\u59D3\u540D","\u5E74\u9F84"],["\u5F20\u4E09",25]]'
212
+ })
213
+ }),
214
+ // APPEND
215
+ Type.Object({
216
+ action: Type.Literal("append"),
217
+ url: UrlOrToken[0],
218
+ spreadsheet_token: UrlOrToken[1],
219
+ range: Type.Optional(
220
+ Type.String({
221
+ description: "\u8FFD\u52A0\u8303\u56F4\uFF08\u53EF\u9009\uFF09\u3002\u683C\u5F0F\u540C write\u3002\u4E0D\u586B\u5219\u8FFD\u52A0\u5230\u7B2C\u4E00\u4E2A\u5DE5\u4F5C\u8868\u672B\u5C3E"
222
+ })
223
+ ),
224
+ sheet_id: Type.Optional(
225
+ Type.String({
226
+ description: "\u5DE5\u4F5C\u8868 ID\uFF08\u53EF\u9009\uFF09\u3002\u4EC5\u5F53\u4E0D\u63D0\u4F9B range \u65F6\u751F\u6548"
227
+ })
228
+ ),
229
+ values: Type.Array(Type.Array(Type.Any()), {
230
+ description: "\u8981\u8FFD\u52A0\u7684\u4E8C\u7EF4\u6570\u7EC4\u6570\u636E"
231
+ })
232
+ }),
233
+ // FIND
234
+ Type.Object({
235
+ action: Type.Literal("find"),
236
+ url: UrlOrToken[0],
237
+ spreadsheet_token: UrlOrToken[1],
238
+ sheet_id: Type.String({
239
+ description: "\u5DE5\u4F5C\u8868 ID\uFF08\u5FC5\u586B\uFF0C\u53EF\u901A\u8FC7 info action \u83B7\u53D6\uFF09"
240
+ }),
241
+ find: Type.String({
242
+ description: "\u67E5\u627E\u5185\u5BB9\uFF08\u5B57\u7B26\u4E32\u6216\u6B63\u5219\u8868\u8FBE\u5F0F\uFF09"
243
+ }),
244
+ range: Type.Optional(
245
+ Type.String({
246
+ description: "\u67E5\u627E\u8303\u56F4\u3002\u683C\u5F0F\uFF1AA1:D10\uFF08\u4E0D\u542B sheetId \u524D\u7F00\uFF09\u3002\u4E0D\u586B\u5219\u641C\u7D22\u6574\u4E2A\u5DE5\u4F5C\u8868"
247
+ })
248
+ ),
249
+ match_case: Type.Optional(Type.Boolean({ description: "\u662F\u5426\u533A\u5206\u5927\u5C0F\u5199\uFF08\u9ED8\u8BA4 true\uFF09" })),
250
+ match_entire_cell: Type.Optional(Type.Boolean({ description: "\u662F\u5426\u5B8C\u5168\u5339\u914D\u6574\u4E2A\u5355\u5143\u683C\uFF08\u9ED8\u8BA4 false\uFF09" })),
251
+ search_by_regex: Type.Optional(Type.Boolean({ description: "\u662F\u5426\u4F7F\u7528\u6B63\u5219\u8868\u8FBE\u5F0F\uFF08\u9ED8\u8BA4 false\uFF09" })),
252
+ include_formulas: Type.Optional(Type.Boolean({ description: "\u662F\u5426\u641C\u7D22\u516C\u5F0F\uFF08\u9ED8\u8BA4 false\uFF09" }))
253
+ }),
254
+ // CREATE
255
+ Type.Object({
256
+ action: Type.Literal("create"),
257
+ title: Type.String({
258
+ description: "\u7535\u5B50\u8868\u683C\u6807\u9898"
259
+ }),
260
+ folder_token: Type.Optional(
261
+ Type.String({
262
+ description: "\u6587\u4EF6\u5939 token\uFF08\u53EF\u9009\uFF09\u3002\u4E0D\u586B\u65F6\u521B\u5EFA\u5230\u300C\u6211\u7684\u7A7A\u95F4\u300D\u6839\u76EE\u5F55"
263
+ })
264
+ ),
265
+ headers: Type.Optional(
266
+ Type.Array(Type.String(), {
267
+ description: '\u8868\u5934\u5217\u540D\uFF08\u53EF\u9009\uFF09\u3002\u4F8B\u5982 ["\u59D3\u540D", "\u90E8\u95E8", "\u5165\u804C\u65E5\u671F"]\u3002\u63D0\u4F9B\u540E\u4F1A\u5199\u5165\u7B2C\u4E00\u884C'
268
+ })
269
+ ),
270
+ data: Type.Optional(
271
+ Type.Array(Type.Array(Type.Any()), {
272
+ description: '\u521D\u59CB\u6570\u636E\uFF08\u53EF\u9009\uFF09\u3002\u4E8C\u7EF4\u6570\u7EC4\uFF0C\u5199\u5728\u8868\u5934\u4E4B\u540E\u3002\u4F8B\u5982 [["\u5F20\u4E09", "\u5DE5\u7A0B", "2026-01-01"]]'
273
+ })
274
+ )
275
+ }),
276
+ // EXPORT
277
+ Type.Object({
278
+ action: Type.Literal("export"),
279
+ url: UrlOrToken[0],
280
+ spreadsheet_token: UrlOrToken[1],
281
+ file_extension: Type.Union([Type.Literal("xlsx"), Type.Literal("csv")], {
282
+ description: "\u5BFC\u51FA\u683C\u5F0F\uFF1Axlsx \u6216 csv"
283
+ }),
284
+ output_path: Type.Optional(
285
+ Type.String({
286
+ description: "\u672C\u5730\u4FDD\u5B58\u8DEF\u5F84\uFF08\u542B\u6587\u4EF6\u540D\uFF09\u3002\u4E0D\u586B\u5219\u53EA\u8FD4\u56DE\u6587\u4EF6\u4FE1\u606F"
287
+ })
288
+ ),
289
+ sheet_id: Type.Optional(
290
+ Type.String({
291
+ description: "\u5DE5\u4F5C\u8868 ID\u3002\u5BFC\u51FA CSV \u65F6\u5FC5\u586B\uFF08CSV \u4E00\u6B21\u53EA\u80FD\u5BFC\u51FA\u4E00\u4E2A\u5DE5\u4F5C\u8868\uFF09\uFF0C\u5BFC\u51FA xlsx \u65F6\u53EF\u9009"
292
+ })
293
+ )
294
+ })
295
+ ]);
296
+ function registerFeishuSheetTool(api) {
297
+ if (!api.config) return;
298
+ const cfg = api.config;
299
+ const { toolClient, log } = createToolContext(api, "feishu_sheet");
300
+ api.registerTool(
301
+ {
302
+ name: "feishu_sheet",
303
+ label: "Feishu Spreadsheet",
304
+ description: "\u3010\u4EE5\u7528\u6237\u8EAB\u4EFD\u3011\u98DE\u4E66\u7535\u5B50\u8868\u683C\u5DE5\u5177\u3002\u652F\u6301\u521B\u5EFA\u3001\u8BFB\u5199\u3001\u67E5\u627E\u3001\u5BFC\u51FA\u7535\u5B50\u8868\u683C\u3002\n\n\u7535\u5B50\u8868\u683C\uFF08Sheets\uFF09\u7C7B\u4F3C Excel/Google Sheets\uFF0C\u4E0E\u591A\u7EF4\u8868\u683C\uFF08Bitable/Airtable\uFF09\u662F\u4E0D\u540C\u4EA7\u54C1\u3002\n\n\u6240\u6709 action\uFF08\u9664 create \u5916\uFF09\u5747\u652F\u6301\u4F20\u5165 url \u6216 spreadsheet_token\uFF0C\u5DE5\u5177\u4F1A\u81EA\u52A8\u89E3\u6790\u3002\u652F\u6301\u77E5\u8BC6\u5E93 wiki URL\uFF0C\u81EA\u52A8\u89E3\u6790\u4E3A\u7535\u5B50\u8868\u683C token\u3002\n\nActions:\n- info\uFF1A\u83B7\u53D6\u8868\u683C\u4FE1\u606F + \u5168\u90E8\u5DE5\u4F5C\u8868\u5217\u8868\uFF08\u4E00\u6B21\u8C03\u7528\u66FF\u4EE3 get_info + list_sheets\uFF09\n- read\uFF1A\u8BFB\u53D6\u6570\u636E\u3002\u4E0D\u586B range \u81EA\u52A8\u8BFB\u53D6\u7B2C\u4E00\u4E2A\u5DE5\u4F5C\u8868\u5168\u90E8\u6570\u636E\n- write\uFF1A\u8986\u76D6\u5199\u5165,\u9AD8\u5371,\u8BF7\u8C28\u614E\u4F7F\u7528\u8BE5\u64CD\u4F5C\u3002\u4E0D\u586B range \u81EA\u52A8\u5199\u5165\u7B2C\u4E00\u4E2A\u5DE5\u4F5C\u8868\uFF08\u4ECE A1 \u5F00\u59CB\uFF09\n- append\uFF1A\u5728\u5DF2\u6709\u6570\u636E\u672B\u5C3E\u8FFD\u52A0\u884C\n- find\uFF1A\u5728\u5DE5\u4F5C\u8868\u4E2D\u67E5\u627E\u5355\u5143\u683C\n- create\uFF1A\u521B\u5EFA\u7535\u5B50\u8868\u683C\u3002\u652F\u6301\u5E26 headers + data \u4E00\u6B65\u521B\u5EFA\u542B\u6570\u636E\u7684\u8868\u683C\n- export\uFF1A\u5BFC\u51FA\u4E3A xlsx \u6216 csv\uFF08csv \u5FC5\u987B\u6307\u5B9A sheet_id\uFF09",
305
+ parameters: FeishuSheetSchema,
306
+ async execute(_toolCallId, params) {
307
+ const p = params;
308
+ try {
309
+ const client = toolClient();
310
+ switch (p.action) {
311
+ // -----------------------------------------------------------------
312
+ // INFO — 表格信息 + 全部工作表列表
313
+ // -----------------------------------------------------------------
314
+ case "info": {
315
+ const { token } = await resolveToken(p, client, log);
316
+ log.info(`info: token=${token}`);
317
+ const [spreadsheetRes, sheetsRes] = await Promise.all([
318
+ client.invoke(
319
+ "feishu_sheet.info",
320
+ (sdk, opts) => sdk.sheets.spreadsheet.get({ path: { spreadsheet_token: token } }, opts),
321
+ { as: "user" }
322
+ ),
323
+ client.invoke(
324
+ "feishu_sheet.info",
325
+ (sdk, opts) => sdk.sheets.spreadsheetSheet.query({ path: { spreadsheet_token: token } }, opts),
326
+ { as: "user" }
327
+ )
328
+ ]);
329
+ assertLarkOk(spreadsheetRes);
330
+ assertLarkOk(sheetsRes);
331
+ const spreadsheet = spreadsheetRes.data?.spreadsheet;
332
+ const sheets = (sheetsRes.data?.sheets ?? []).map((s) => ({
333
+ sheet_id: s.sheet_id,
334
+ title: s.title,
335
+ index: s.index,
336
+ row_count: s.grid_properties?.row_count,
337
+ column_count: s.grid_properties?.column_count,
338
+ frozen_row_count: s.grid_properties?.frozen_row_count,
339
+ frozen_column_count: s.grid_properties?.frozen_column_count
340
+ }));
341
+ log.info(`info: title="${spreadsheet?.title}", ${sheets.length} sheets`);
342
+ return json({
343
+ title: spreadsheet?.title,
344
+ spreadsheet_token: token,
345
+ url: `https://www.feishu.cn/sheets/${token}`,
346
+ sheets
347
+ });
348
+ }
349
+ // -----------------------------------------------------------------
350
+ // READ — 读取数据(支持自动探测范围)
351
+ // -----------------------------------------------------------------
352
+ case "read": {
353
+ const { token, urlSheetId } = await resolveToken(p, client, log);
354
+ const range = await resolveRange(token, p.range, p.sheet_id ?? urlSheetId, client, "feishu_sheet.read");
355
+ log.info(`read: token=${token}, range=${range}`);
356
+ const query = {
357
+ // 默认返回计算后的值(而非公式原文),日期转为可读字符串
358
+ valueRenderOption: p.value_render_option ?? "ToString",
359
+ dateTimeRenderOption: "FormattedString"
360
+ };
361
+ const res = await client.invokeByPath(
362
+ "feishu_sheet.read",
363
+ `/open-apis/sheets/v2/spreadsheets/${token}/values/${encodeURIComponent(range)}`,
364
+ { method: "GET", query, as: "user" }
365
+ );
366
+ if (res.code && res.code !== 0) {
367
+ return json({ error: res.msg || `API error code: ${res.code}` });
368
+ }
369
+ const valueRange = res.data?.valueRange;
370
+ const { values, truncated, total_rows } = truncateRows(flattenValues(valueRange?.values), MAX_READ_ROWS);
371
+ log.info(`read: ${total_rows} rows${truncated ? ` (truncated to ${MAX_READ_ROWS})` : ""}`);
372
+ return json({
373
+ range: valueRange?.range,
374
+ values,
375
+ ...truncated ? {
376
+ truncated: true,
377
+ total_rows,
378
+ hint: `Data exceeds ${MAX_READ_ROWS} rows, truncated. Please narrow the range and read again.`
379
+ } : {}
380
+ });
381
+ }
382
+ // -----------------------------------------------------------------
383
+ // WRITE — 覆盖写入(支持自动 range)
384
+ // -----------------------------------------------------------------
385
+ case "write": {
386
+ const { token, urlSheetId } = await resolveToken(p, client, log);
387
+ if (p.values && p.values.length > MAX_WRITE_ROWS) {
388
+ return json({ error: `write row count ${p.values.length} exceeds limit ${MAX_WRITE_ROWS}` });
389
+ }
390
+ if (p.values && p.values.some((row) => Array.isArray(row) && row.length > MAX_WRITE_COLS)) {
391
+ return json({ error: `write column count exceeds limit ${MAX_WRITE_COLS}` });
392
+ }
393
+ const range = await resolveRange(token, p.range, p.sheet_id ?? urlSheetId, client, "feishu_sheet.write");
394
+ log.info(`write: token=${token}, range=${range}, rows=${p.values?.length}`);
395
+ const res = await client.invokeByPath("feishu_sheet.write", `/open-apis/sheets/v2/spreadsheets/${token}/values`, {
396
+ method: "PUT",
397
+ body: { valueRange: { range, values: p.values } },
398
+ as: "user"
399
+ });
400
+ if (res.code && res.code !== 0) {
401
+ return json({ error: res.msg || `API error code: ${res.code}` });
402
+ }
403
+ log.info(`write: updated ${res.data?.updatedCells ?? 0} cells`);
404
+ return json({
405
+ updated_range: res.data?.updatedRange,
406
+ updated_rows: res.data?.updatedRows,
407
+ updated_columns: res.data?.updatedColumns,
408
+ updated_cells: res.data?.updatedCells,
409
+ revision: res.data?.revision
410
+ });
411
+ }
412
+ // -----------------------------------------------------------------
413
+ // APPEND — 追加行
414
+ // -----------------------------------------------------------------
415
+ case "append": {
416
+ const { token, urlSheetId } = await resolveToken(p, client, log);
417
+ if (p.values && p.values.length > MAX_WRITE_ROWS) {
418
+ return json({ error: `append row count ${p.values.length} exceeds limit ${MAX_WRITE_ROWS}` });
419
+ }
420
+ const range = await resolveRange(token, p.range, p.sheet_id ?? urlSheetId, client, "feishu_sheet.append");
421
+ log.info(`append: token=${token}, range=${range}, rows=${p.values?.length}`);
422
+ const res = await client.invokeByPath("feishu_sheet.append", `/open-apis/sheets/v2/spreadsheets/${token}/values_append`, {
423
+ method: "POST",
424
+ body: { valueRange: { range, values: p.values } },
425
+ as: "user"
426
+ });
427
+ if (res.code && res.code !== 0) {
428
+ return json({ error: res.msg || `API error code: ${res.code}` });
429
+ }
430
+ const updates = res.data?.updates;
431
+ log.info(`append: updated ${updates?.updatedCells ?? 0} cells`);
432
+ return json({
433
+ table_range: res.data?.tableRange,
434
+ updated_range: updates?.updatedRange,
435
+ updated_rows: updates?.updatedRows,
436
+ updated_columns: updates?.updatedColumns,
437
+ updated_cells: updates?.updatedCells,
438
+ revision: updates?.revision
439
+ });
440
+ }
441
+ // -----------------------------------------------------------------
442
+ // FIND — 查找单元格
443
+ // -----------------------------------------------------------------
444
+ case "find": {
445
+ const { token } = await resolveToken(p, client, log);
446
+ log.info(`find: token=${token}, sheet_id=${p.sheet_id}, find="${p.find}"`);
447
+ const findCondition = {
448
+ range: p.range ? `${p.sheet_id}!${p.range}` : p.sheet_id
449
+ };
450
+ if (p.match_case !== void 0) findCondition.match_case = !p.match_case;
451
+ if (p.match_entire_cell !== void 0) findCondition.match_entire_cell = p.match_entire_cell;
452
+ if (p.search_by_regex !== void 0) findCondition.search_by_regex = p.search_by_regex;
453
+ if (p.include_formulas !== void 0) findCondition.include_formulas = p.include_formulas;
454
+ const res = await client.invoke(
455
+ "feishu_sheet.find",
456
+ (sdk, opts) => sdk.sheets.spreadsheetSheet.find(
457
+ {
458
+ path: {
459
+ spreadsheet_token: token,
460
+ sheet_id: p.sheet_id
461
+ },
462
+ data: {
463
+ find_condition: findCondition,
464
+ find: p.find
465
+ }
466
+ },
467
+ opts
468
+ ),
469
+ { as: "user" }
470
+ );
471
+ assertLarkOk(res);
472
+ const findResult = res.data?.find_result;
473
+ log.info(`find: matched ${findResult?.matched_cells?.length ?? 0} cells`);
474
+ return json({
475
+ matched_cells: findResult?.matched_cells,
476
+ matched_formula_cells: findResult?.matched_formula_cells,
477
+ rows_count: findResult?.rows_count
478
+ });
479
+ }
480
+ // -----------------------------------------------------------------
481
+ // CREATE — 创建电子表格(支持带初始数据)
482
+ // -----------------------------------------------------------------
483
+ case "create": {
484
+ log.info(
485
+ `create: title="${p.title}", folder=${p.folder_token ?? "(root)"}, headers=${!!p.headers}, data=${p.data?.length ?? 0} rows`
486
+ );
487
+ const createRes = await client.invoke(
488
+ "feishu_sheet.create",
489
+ (sdk, opts) => sdk.sheets.spreadsheet.create(
490
+ {
491
+ data: {
492
+ title: p.title,
493
+ folder_token: p.folder_token
494
+ }
495
+ },
496
+ opts
497
+ ),
498
+ { as: "user" }
499
+ );
500
+ assertLarkOk(createRes);
501
+ const spreadsheet = createRes.data?.spreadsheet;
502
+ const token = spreadsheet?.spreadsheet_token;
503
+ if (!token) {
504
+ return json({ error: "failed to create spreadsheet: no token returned" });
505
+ }
506
+ const url = `https://www.feishu.cn/sheets/${token}`;
507
+ log.info(`create: token=${token}`);
508
+ if (p.headers || p.data) {
509
+ const allRows = [];
510
+ if (p.headers) allRows.push(p.headers);
511
+ if (p.data) allRows.push(...p.data);
512
+ if (allRows.length > 0) {
513
+ const sheetsRes = await client.invoke(
514
+ "feishu_sheet.create",
515
+ (sdk, opts) => sdk.sheets.spreadsheetSheet.query({ path: { spreadsheet_token: token } }, opts),
516
+ { as: "user" }
517
+ );
518
+ assertLarkOk(sheetsRes);
519
+ const firstSheet = (sheetsRes.data?.sheets ?? [])[0];
520
+ if (firstSheet?.sheet_id) {
521
+ const sheetId = firstSheet.sheet_id;
522
+ const numRows = allRows.length;
523
+ const numCols = Math.max(...allRows.map((r) => r.length));
524
+ const range = `${sheetId}!A1:${colLetter(numCols)}${numRows}`;
525
+ log.info(`create: writing ${numRows} rows to ${range}`);
526
+ const writeRes = await client.invokeByPath(
527
+ "feishu_sheet.create",
528
+ `/open-apis/sheets/v2/spreadsheets/${token}/values`,
529
+ {
530
+ method: "PUT",
531
+ body: { valueRange: { range, values: allRows } },
532
+ as: "user"
533
+ }
534
+ );
535
+ if (writeRes.code && writeRes.code !== 0) {
536
+ log.info(`create: initial data write failed: ${writeRes.msg}`);
537
+ return json({
538
+ spreadsheet_token: token,
539
+ url,
540
+ warning: `spreadsheet created but failed to write initial data: ${writeRes.msg}`
541
+ });
542
+ }
543
+ }
544
+ }
545
+ }
546
+ return json({
547
+ spreadsheet_token: token,
548
+ title: p.title,
549
+ url
550
+ });
551
+ }
552
+ // -----------------------------------------------------------------
553
+ // EXPORT — 导出为 xlsx/csv
554
+ // -----------------------------------------------------------------
555
+ case "export": {
556
+ const { token } = await resolveToken(p, client, log);
557
+ if (p.file_extension === "csv" && !p.sheet_id) {
558
+ return json({
559
+ error: "sheet_id is required for CSV export (CSV can only export one worksheet at a time). Use info action to get the worksheet list."
560
+ });
561
+ }
562
+ log.info(`export: token=${token}, format=${p.file_extension}, output=${p.output_path ?? "(info only)"}`);
563
+ const createRes = await client.invoke(
564
+ "feishu_sheet.export",
565
+ (sdk, opts) => sdk.drive.exportTask.create(
566
+ {
567
+ data: {
568
+ file_extension: p.file_extension,
569
+ token,
570
+ type: "sheet",
571
+ sub_id: p.sheet_id
572
+ }
573
+ },
574
+ opts
575
+ ),
576
+ { as: "user" }
577
+ );
578
+ assertLarkOk(createRes);
579
+ const ticket = createRes.data?.ticket;
580
+ if (!ticket) {
581
+ return json({ error: "failed to create export task: no ticket returned" });
582
+ }
583
+ log.info(`export: ticket=${ticket}`);
584
+ let fileToken;
585
+ let fileName;
586
+ let fileSize;
587
+ for (let i = 0; i < EXPORT_POLL_MAX_RETRIES; i++) {
588
+ await sleep(EXPORT_POLL_INTERVAL_MS);
589
+ const pollRes = await client.invoke(
590
+ "feishu_sheet.export",
591
+ (sdk, opts) => sdk.drive.exportTask.get({ path: { ticket }, params: { token } }, opts),
592
+ { as: "user" }
593
+ );
594
+ assertLarkOk(pollRes);
595
+ const result = pollRes.data?.result;
596
+ const jobStatus = result?.job_status;
597
+ if (jobStatus === 0) {
598
+ fileToken = result?.file_token;
599
+ fileName = result?.file_name;
600
+ fileSize = result?.file_size;
601
+ log.info(`export: done, file_token=${fileToken}, size=${fileSize}`);
602
+ break;
603
+ }
604
+ if (jobStatus !== void 0 && jobStatus >= 3) {
605
+ return json({ error: result?.job_error_msg || `export failed (status=${jobStatus})` });
606
+ }
607
+ log.info(`export: polling ${i + 1}/${EXPORT_POLL_MAX_RETRIES}, status=${jobStatus}`);
608
+ }
609
+ if (!fileToken) {
610
+ return json({ error: "export timeout: task did not complete within 30 seconds" });
611
+ }
612
+ if (p.output_path) {
613
+ const dlRes = await client.invoke(
614
+ "feishu_sheet.export",
615
+ (sdk, opts) => sdk.drive.exportTask.download({ path: { file_token: fileToken } }, opts),
616
+ { as: "user" }
617
+ );
618
+ const stream = dlRes.getReadableStream();
619
+ const chunks = [];
620
+ for await (const chunk of stream) {
621
+ chunks.push(chunk);
622
+ }
623
+ await fs.mkdir(path.dirname(p.output_path), { recursive: true });
624
+ await fs.writeFile(p.output_path, Buffer.concat(chunks));
625
+ log.info(`export: saved to ${p.output_path}`);
626
+ return json({
627
+ file_path: p.output_path,
628
+ file_name: fileName,
629
+ file_size: fileSize
630
+ });
631
+ }
632
+ return json({
633
+ file_token: fileToken,
634
+ file_name: fileName,
635
+ file_size: fileSize,
636
+ hint: "File exported. Provide output_path parameter to download locally."
637
+ });
638
+ }
639
+ }
640
+ } catch (err) {
641
+ return await handleInvokeErrorWithAutoAuth(err, cfg);
642
+ }
643
+ }
644
+ },
645
+ { name: "feishu_sheet" }
646
+ );
647
+ api.logger.info?.("feishu_sheet: Registered feishu_sheet tool");
648
+ }
649
+ export {
650
+ registerFeishuSheetTool
651
+ };
652
+ //# sourceMappingURL=sheet.js.map