@yandy0725/pi-lark 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/README.md +30 -0
  2. package/README.zh.md +30 -0
  3. package/package.json +36 -0
  4. package/skills/lark-approval/SKILL.md +56 -0
  5. package/skills/lark-approval/references/lark-approval-initiate.md +196 -0
  6. package/skills/lark-approval/references/lark-approval-instance-form-control-parameters.md +606 -0
  7. package/skills/lark-approval/references/lark-approval-instance-value-sourcing.md +108 -0
  8. package/skills/lark-apps/SKILL.md +78 -0
  9. package/skills/lark-apps/references/lark-apps-access-scope-get.md +28 -0
  10. package/skills/lark-apps/references/lark-apps-access-scope-set.md +40 -0
  11. package/skills/lark-apps/references/lark-apps-cloud-dev.md +120 -0
  12. package/skills/lark-apps/references/lark-apps-create.md +40 -0
  13. package/skills/lark-apps/references/lark-apps-db-env-create.md +31 -0
  14. package/skills/lark-apps/references/lark-apps-db-execute.md +40 -0
  15. package/skills/lark-apps/references/lark-apps-db-table-get.md +29 -0
  16. package/skills/lark-apps/references/lark-apps-db-table-list.md +31 -0
  17. package/skills/lark-apps/references/lark-apps-env-pull.md +35 -0
  18. package/skills/lark-apps/references/lark-apps-git-credential.md +37 -0
  19. package/skills/lark-apps/references/lark-apps-html-publish.md +57 -0
  20. package/skills/lark-apps/references/lark-apps-init.md +37 -0
  21. package/skills/lark-apps/references/lark-apps-list.md +37 -0
  22. package/skills/lark-apps/references/lark-apps-local-dev.md +76 -0
  23. package/skills/lark-apps/references/lark-apps-release-create.md +30 -0
  24. package/skills/lark-apps/references/lark-apps-release-get.md +28 -0
  25. package/skills/lark-apps/references/lark-apps-release-list.md +31 -0
  26. package/skills/lark-apps/references/lark-apps-session-messages-list.md +53 -0
  27. package/skills/lark-apps/references/lark-apps-update.md +30 -0
  28. package/skills/lark-attendance/SKILL.md +57 -0
  29. package/skills/lark-base/SKILL.md +157 -0
  30. package/skills/lark-base/references/dashboard-block-data-config.md +350 -0
  31. package/skills/lark-base/references/formula-field-guide.md +737 -0
  32. package/skills/lark-base/references/lark-base-cell-value.md +153 -0
  33. package/skills/lark-base/references/lark-base-dashboard-block-get-data.md +717 -0
  34. package/skills/lark-base/references/lark-base-dashboard.md +238 -0
  35. package/skills/lark-base/references/lark-base-data-analysis-sop.md +210 -0
  36. package/skills/lark-base/references/lark-base-data-query-guide.md +61 -0
  37. package/skills/lark-base/references/lark-base-data-query.md +452 -0
  38. package/skills/lark-base/references/lark-base-field-create.md +103 -0
  39. package/skills/lark-base/references/lark-base-field-json.md +489 -0
  40. package/skills/lark-base/references/lark-base-field-update.md +171 -0
  41. package/skills/lark-base/references/lark-base-form-detail.md +71 -0
  42. package/skills/lark-base/references/lark-base-form-questions-create.md +118 -0
  43. package/skills/lark-base/references/lark-base-form-questions-update.md +92 -0
  44. package/skills/lark-base/references/lark-base-form-submit.md +170 -0
  45. package/skills/lark-base/references/lark-base-record-batch-create.md +57 -0
  46. package/skills/lark-base/references/lark-base-record-batch-update.md +52 -0
  47. package/skills/lark-base/references/lark-base-record-history-list.md +43 -0
  48. package/skills/lark-base/references/lark-base-record-upsert.md +63 -0
  49. package/skills/lark-base/references/lark-base-role-guide.md +65 -0
  50. package/skills/lark-base/references/lark-base-view-set-filter.md +189 -0
  51. package/skills/lark-base/references/lark-base-workflow-guide.md +830 -0
  52. package/skills/lark-base/references/lark-base-workflow-schema.md +1071 -0
  53. package/skills/lark-base/references/lookup-field-guide.md +512 -0
  54. package/skills/lark-base/references/role-config.md +549 -0
  55. package/skills/lark-calendar/SKILL.md +137 -0
  56. package/skills/lark-calendar/references/lark-calendar-agenda.md +78 -0
  57. package/skills/lark-calendar/references/lark-calendar-create.md +106 -0
  58. package/skills/lark-calendar/references/lark-calendar-freebusy.md +124 -0
  59. package/skills/lark-calendar/references/lark-calendar-meeting.md +40 -0
  60. package/skills/lark-calendar/references/lark-calendar-room-find.md +113 -0
  61. package/skills/lark-calendar/references/lark-calendar-rsvp.md +42 -0
  62. package/skills/lark-calendar/references/lark-calendar-schedule-meeting.md +265 -0
  63. package/skills/lark-calendar/references/lark-calendar-search-event.md +29 -0
  64. package/skills/lark-calendar/references/lark-calendar-suggestion.md +125 -0
  65. package/skills/lark-calendar/references/lark-calendar-update.md +105 -0
  66. package/skills/lark-contact/SKILL.md +59 -0
  67. package/skills/lark-contact/references/lark-contact-get-user.md +19 -0
  68. package/skills/lark-contact/references/lark-contact-search-user.md +124 -0
  69. package/skills/lark-doc/SKILL.md +79 -0
  70. package/skills/lark-doc/references/lark-doc-create.md +79 -0
  71. package/skills/lark-doc/references/lark-doc-fetch.md +138 -0
  72. package/skills/lark-doc/references/lark-doc-md.md +76 -0
  73. package/skills/lark-doc/references/lark-doc-media-download.md +50 -0
  74. package/skills/lark-doc/references/lark-doc-media-insert.md +114 -0
  75. package/skills/lark-doc/references/lark-doc-media-preview.md +41 -0
  76. package/skills/lark-doc/references/lark-doc-resource-cover.md +70 -0
  77. package/skills/lark-doc/references/lark-doc-update.md +259 -0
  78. package/skills/lark-doc/references/lark-doc-whiteboard.md +154 -0
  79. package/skills/lark-doc/references/lark-doc-xml.md +181 -0
  80. package/skills/lark-doc/references/style/lark-doc-create-workflow.md +59 -0
  81. package/skills/lark-doc/references/style/lark-doc-style.md +86 -0
  82. package/skills/lark-doc/references/style/lark-doc-update-workflow.md +55 -0
  83. package/skills/lark-drive/SKILL.md +215 -0
  84. package/skills/lark-drive/references/lark-drive-add-comment.md +193 -0
  85. package/skills/lark-drive/references/lark-drive-apply-permission.md +77 -0
  86. package/skills/lark-drive/references/lark-drive-comment-location.md +193 -0
  87. package/skills/lark-drive/references/lark-drive-comments-guide.md +72 -0
  88. package/skills/lark-drive/references/lark-drive-cover.md +79 -0
  89. package/skills/lark-drive/references/lark-drive-create-folder.md +73 -0
  90. package/skills/lark-drive/references/lark-drive-create-shortcut.md +103 -0
  91. package/skills/lark-drive/references/lark-drive-delete.md +79 -0
  92. package/skills/lark-drive/references/lark-drive-download.md +31 -0
  93. package/skills/lark-drive/references/lark-drive-export-download.md +50 -0
  94. package/skills/lark-drive/references/lark-drive-export.md +145 -0
  95. package/skills/lark-drive/references/lark-drive-files-list.md +158 -0
  96. package/skills/lark-drive/references/lark-drive-import.md +170 -0
  97. package/skills/lark-drive/references/lark-drive-inspect.md +50 -0
  98. package/skills/lark-drive/references/lark-drive-member-add.md +66 -0
  99. package/skills/lark-drive/references/lark-drive-move.md +120 -0
  100. package/skills/lark-drive/references/lark-drive-permission-guide.md +41 -0
  101. package/skills/lark-drive/references/lark-drive-preview.md +87 -0
  102. package/skills/lark-drive/references/lark-drive-pull.md +137 -0
  103. package/skills/lark-drive/references/lark-drive-push.md +162 -0
  104. package/skills/lark-drive/references/lark-drive-reactions.md +113 -0
  105. package/skills/lark-drive/references/lark-drive-search.md +269 -0
  106. package/skills/lark-drive/references/lark-drive-secure-label.md +52 -0
  107. package/skills/lark-drive/references/lark-drive-status.md +137 -0
  108. package/skills/lark-drive/references/lark-drive-task-result.md +302 -0
  109. package/skills/lark-drive/references/lark-drive-upload.md +101 -0
  110. package/skills/lark-drive/references/lark-drive-version-delete.md +38 -0
  111. package/skills/lark-drive/references/lark-drive-version-get.md +71 -0
  112. package/skills/lark-drive/references/lark-drive-version-history.md +73 -0
  113. package/skills/lark-drive/references/lark-drive-version-revert.md +35 -0
  114. package/skills/lark-drive/references/lark-drive-workflow-knowledge-organize-analysis.md +249 -0
  115. package/skills/lark-drive/references/lark-drive-workflow-knowledge-organize-discovery.md +253 -0
  116. package/skills/lark-drive/references/lark-drive-workflow-knowledge-organize-execution.md +200 -0
  117. package/skills/lark-drive/references/lark-drive-workflow-knowledge-organize-planning.md +336 -0
  118. package/skills/lark-drive/references/lark-drive-workflow-knowledge-organize-rollback.md +308 -0
  119. package/skills/lark-drive/references/lark-drive-workflow-knowledge-organize.md +226 -0
  120. package/skills/lark-drive/references/lark-drive-workflow-permission-governance-commands.md +168 -0
  121. package/skills/lark-drive/references/lark-drive-workflow-permission-governance-outputs.md +424 -0
  122. package/skills/lark-drive/references/lark-drive-workflow-permission-governance.md +207 -0
  123. package/skills/lark-drive/references/lark-drive-workflow.md +130 -0
  124. package/skills/lark-event/SKILL.md +154 -0
  125. package/skills/lark-event/references/lark-event-im.md +87 -0
  126. package/skills/lark-event/references/lark-event-minutes.md +54 -0
  127. package/skills/lark-event/references/lark-event-task.md +78 -0
  128. package/skills/lark-event/references/lark-event-vc.md +94 -0
  129. package/skills/lark-event/references/lark-event-whiteboard.md +67 -0
  130. package/skills/lark-im/SKILL.md +247 -0
  131. package/skills/lark-im/references/lark-im-card-action-reply.md +175 -0
  132. package/skills/lark-im/references/lark-im-chat-create.md +162 -0
  133. package/skills/lark-im/references/lark-im-chat-identity.md +55 -0
  134. package/skills/lark-im/references/lark-im-chat-list.md +166 -0
  135. package/skills/lark-im/references/lark-im-chat-messages-list.md +157 -0
  136. package/skills/lark-im/references/lark-im-chat-search.md +142 -0
  137. package/skills/lark-im/references/lark-im-chat-update.md +84 -0
  138. package/skills/lark-im/references/lark-im-feed-group-list-item.md +68 -0
  139. package/skills/lark-im/references/lark-im-feed-group-list.md +65 -0
  140. package/skills/lark-im/references/lark-im-feed-group-query-item.md +44 -0
  141. package/skills/lark-im/references/lark-im-feed-groups.md +452 -0
  142. package/skills/lark-im/references/lark-im-feed-shortcut-create.md +97 -0
  143. package/skills/lark-im/references/lark-im-feed-shortcut-list.md +103 -0
  144. package/skills/lark-im/references/lark-im-feed-shortcut-remove.md +48 -0
  145. package/skills/lark-im/references/lark-im-flag-cancel.md +67 -0
  146. package/skills/lark-im/references/lark-im-flag-create.md +67 -0
  147. package/skills/lark-im/references/lark-im-flag-list.md +100 -0
  148. package/skills/lark-im/references/lark-im-message-enrichment.md +54 -0
  149. package/skills/lark-im/references/lark-im-messages-mget.md +99 -0
  150. package/skills/lark-im/references/lark-im-messages-reply.md +267 -0
  151. package/skills/lark-im/references/lark-im-messages-resources-download.md +94 -0
  152. package/skills/lark-im/references/lark-im-messages-search.md +234 -0
  153. package/skills/lark-im/references/lark-im-messages-send.md +267 -0
  154. package/skills/lark-im/references/lark-im-reactions.md +299 -0
  155. package/skills/lark-im/references/lark-im-threads-messages-list.md +115 -0
  156. package/skills/lark-mail/SKILL.md +287 -0
  157. package/skills/lark-mail/assets/templates/job-application--resume.html +33 -0
  158. package/skills/lark-mail/assets/templates/newsletter--weekly-brief.html +50 -0
  159. package/skills/lark-mail/assets/templates/research--market-report.html +256 -0
  160. package/skills/lark-mail/assets/templates/weekly--personal-report.html +43 -0
  161. package/skills/lark-mail/assets/templates/weekly--team-report.html +9 -0
  162. package/skills/lark-mail/references/lark-mail-calendar-invite.md +36 -0
  163. package/skills/lark-mail/references/lark-mail-decline-receipt.md +115 -0
  164. package/skills/lark-mail/references/lark-mail-draft-create.md +127 -0
  165. package/skills/lark-mail/references/lark-mail-draft-edit.md +404 -0
  166. package/skills/lark-mail/references/lark-mail-forward.md +239 -0
  167. package/skills/lark-mail/references/lark-mail-html.md +333 -0
  168. package/skills/lark-mail/references/lark-mail-lint-html.md +243 -0
  169. package/skills/lark-mail/references/lark-mail-message.md +233 -0
  170. package/skills/lark-mail/references/lark-mail-messages.md +108 -0
  171. package/skills/lark-mail/references/lark-mail-recall.md +66 -0
  172. package/skills/lark-mail/references/lark-mail-recipient-search.md +59 -0
  173. package/skills/lark-mail/references/lark-mail-reply-all.md +213 -0
  174. package/skills/lark-mail/references/lark-mail-reply.md +249 -0
  175. package/skills/lark-mail/references/lark-mail-rules.md +31 -0
  176. package/skills/lark-mail/references/lark-mail-send-as.md +44 -0
  177. package/skills/lark-mail/references/lark-mail-send-receipt.md +120 -0
  178. package/skills/lark-mail/references/lark-mail-send-status.md +46 -0
  179. package/skills/lark-mail/references/lark-mail-send.md +222 -0
  180. package/skills/lark-mail/references/lark-mail-share-to-chat.md +87 -0
  181. package/skills/lark-mail/references/lark-mail-signature.md +98 -0
  182. package/skills/lark-mail/references/lark-mail-template-create.md +129 -0
  183. package/skills/lark-mail/references/lark-mail-template-update.md +150 -0
  184. package/skills/lark-mail/references/lark-mail-template.md +54 -0
  185. package/skills/lark-mail/references/lark-mail-thread.md +111 -0
  186. package/skills/lark-mail/references/lark-mail-triage.md +131 -0
  187. package/skills/lark-mail/references/lark-mail-watch.md +94 -0
  188. package/skills/lark-markdown/SKILL.md +69 -0
  189. package/skills/lark-markdown/references/lark-markdown-create.md +94 -0
  190. package/skills/lark-markdown/references/lark-markdown-diff.md +156 -0
  191. package/skills/lark-markdown/references/lark-markdown-fetch.md +79 -0
  192. package/skills/lark-markdown/references/lark-markdown-overwrite.md +85 -0
  193. package/skills/lark-markdown/references/lark-markdown-patch.md +160 -0
  194. package/skills/lark-minutes/SKILL.md +192 -0
  195. package/skills/lark-minutes/references/lark-minutes-detail.md +62 -0
  196. package/skills/lark-minutes/references/lark-minutes-download.md +137 -0
  197. package/skills/lark-minutes/references/lark-minutes-search.md +204 -0
  198. package/skills/lark-minutes/references/lark-minutes-speaker-replace.md +107 -0
  199. package/skills/lark-minutes/references/lark-minutes-summary.md +122 -0
  200. package/skills/lark-minutes/references/lark-minutes-todo.md +138 -0
  201. package/skills/lark-minutes/references/lark-minutes-update.md +41 -0
  202. package/skills/lark-minutes/references/lark-minutes-upload.md +104 -0
  203. package/skills/lark-note/SKILL.md +94 -0
  204. package/skills/lark-note/references/lark-note-detail.md +26 -0
  205. package/skills/lark-note/references/lark-note-transcript.md +23 -0
  206. package/skills/lark-okr/SKILL.md +115 -0
  207. package/skills/lark-okr/references/lark-okr-batch-create.md +106 -0
  208. package/skills/lark-okr/references/lark-okr-contentblock.md +359 -0
  209. package/skills/lark-okr/references/lark-okr-cycle-detail.md +84 -0
  210. package/skills/lark-okr/references/lark-okr-cycle-list.md +90 -0
  211. package/skills/lark-okr/references/lark-okr-entities.md +329 -0
  212. package/skills/lark-okr/references/lark-okr-image-upload.md +116 -0
  213. package/skills/lark-okr/references/lark-okr-indicator-update.md +80 -0
  214. package/skills/lark-okr/references/lark-okr-progress-create.md +81 -0
  215. package/skills/lark-okr/references/lark-okr-progress-delete.md +47 -0
  216. package/skills/lark-okr/references/lark-okr-progress-get.md +62 -0
  217. package/skills/lark-okr/references/lark-okr-progress-list.md +80 -0
  218. package/skills/lark-okr/references/lark-okr-progress-update.md +81 -0
  219. package/skills/lark-okr/references/lark-okr-reorder.md +81 -0
  220. package/skills/lark-okr/references/lark-okr-weight.md +96 -0
  221. package/skills/lark-openapi-explorer/SKILL.md +153 -0
  222. package/skills/lark-shared/SKILL.md +168 -0
  223. package/skills/lark-shared/references/lark-wiki-token-routing.md +42 -0
  224. package/skills/lark-sheets/SKILL.md +165 -0
  225. package/skills/lark-sheets/references/lark-sheets-batch-update.md +191 -0
  226. package/skills/lark-sheets/references/lark-sheets-chart.md +330 -0
  227. package/skills/lark-sheets/references/lark-sheets-conditional-format.md +179 -0
  228. package/skills/lark-sheets/references/lark-sheets-core-operations.md +103 -0
  229. package/skills/lark-sheets/references/lark-sheets-filter-view.md +137 -0
  230. package/skills/lark-sheets/references/lark-sheets-filter.md +130 -0
  231. package/skills/lark-sheets/references/lark-sheets-float-image.md +159 -0
  232. package/skills/lark-sheets/references/lark-sheets-formula-translation.md +267 -0
  233. package/skills/lark-sheets/references/lark-sheets-pivot-table.md +166 -0
  234. package/skills/lark-sheets/references/lark-sheets-range-operations.md +267 -0
  235. package/skills/lark-sheets/references/lark-sheets-read-data.md +235 -0
  236. package/skills/lark-sheets/references/lark-sheets-search-replace.md +111 -0
  237. package/skills/lark-sheets/references/lark-sheets-sheet-structure.md +212 -0
  238. package/skills/lark-sheets/references/lark-sheets-sparkline.md +149 -0
  239. package/skills/lark-sheets/references/lark-sheets-visual-standards.md +205 -0
  240. package/skills/lark-sheets/references/lark-sheets-workbook.md +395 -0
  241. package/skills/lark-sheets/references/lark-sheets-write-cells.md +565 -0
  242. package/skills/lark-sheets/scripts/sheets_df.py +32 -0
  243. package/skills/lark-skill-maker/SKILL.md +85 -0
  244. package/skills/lark-slides/SKILL.md +293 -0
  245. package/skills/lark-slides/assets/templates/administration--all_hands_meeting.xml +1999 -0
  246. package/skills/lark-slides/assets/templates/administration--annual_gala.xml +1160 -0
  247. package/skills/lark-slides/assets/templates/administration--company_intro.xml +1376 -0
  248. package/skills/lark-slides/assets/templates/administration--corporate_culture.xml +1765 -0
  249. package/skills/lark-slides/assets/templates/hr--employee_training.xml +912 -0
  250. package/skills/lark-slides/assets/templates/hr--employee_training_workshop.xml +1504 -0
  251. package/skills/lark-slides/assets/templates/hr--onboarding.xml +933 -0
  252. package/skills/lark-slides/assets/templates/marketing--brand_communication.xml +1367 -0
  253. package/skills/lark-slides/assets/templates/marketing--brand_logo_design.xml +1347 -0
  254. package/skills/lark-slides/assets/templates/marketing--brand_operations_plan.xml +1309 -0
  255. package/skills/lark-slides/assets/templates/marketing--business_plan.xml +1646 -0
  256. package/skills/lark-slides/assets/templates/marketing--marketing_plan.xml +1469 -0
  257. package/skills/lark-slides/assets/templates/marketing--marketing_strategy.xml +1484 -0
  258. package/skills/lark-slides/assets/templates/marketing--product_whitepaper.xml +1455 -0
  259. package/skills/lark-slides/assets/templates/marketing--roadshow_business_plan.xml +1506 -0
  260. package/skills/lark-slides/assets/templates/misc--book_sharing.xml +1338 -0
  261. package/skills/lark-slides/assets/templates/misc--club_event_plan.xml +4885 -0
  262. package/skills/lark-slides/assets/templates/misc--student_career_plan.xml +1854 -0
  263. package/skills/lark-slides/assets/templates/office--dark_general.xml +3763 -0
  264. package/skills/lark-slides/assets/templates/office--dept_annual_report.xml +1192 -0
  265. package/skills/lark-slides/assets/templates/office--light_general.xml +3378 -0
  266. package/skills/lark-slides/assets/templates/office--project_kickoff.xml +3152 -0
  267. package/skills/lark-slides/assets/templates/office--quarterly_review.xml +1253 -0
  268. package/skills/lark-slides/assets/templates/office--work_report.xml +1099 -0
  269. package/skills/lark-slides/assets/templates/office--work_summary.xml +4420 -0
  270. package/skills/lark-slides/assets/templates/office--work_summary_report.xml +1523 -0
  271. package/skills/lark-slides/assets/templates/operations--brand_logo_design.xml +1347 -0
  272. package/skills/lark-slides/assets/templates/operations--brand_operations_plan.xml +1309 -0
  273. package/skills/lark-slides/assets/templates/operations--marketing_plan.xml +1469 -0
  274. package/skills/lark-slides/assets/templates/operations--product_promotion.xml +687 -0
  275. package/skills/lark-slides/assets/templates/personal--experience_sharing.xml +2242 -0
  276. package/skills/lark-slides/assets/templates/personal--personal_resume.xml +2047 -0
  277. package/skills/lark-slides/assets/templates/personal--promotion_defense.xml +1099 -0
  278. package/skills/lark-slides/assets/templates/personal--promotion_report.xml +1039 -0
  279. package/skills/lark-slides/assets/templates/personal--self_intro.xml +696 -0
  280. package/skills/lark-slides/assets/templates/personal--teaching_sharing.xml +3013 -0
  281. package/skills/lark-slides/assets/templates/product--business_case_analysis.xml +1341 -0
  282. package/skills/lark-slides/assets/templates/product--market_analysis.xml +898 -0
  283. package/skills/lark-slides/assets/templates/product--product_analysis.xml +1537 -0
  284. package/skills/lark-slides/assets/templates/product--product_intro.xml +2838 -0
  285. package/skills/lark-slides/assets/templates/product--product_promotion.xml +687 -0
  286. package/skills/lark-slides/assets/templates/product--product_promotion_2.xml +687 -0
  287. package/skills/lark-slides/references/asset-planning.md +124 -0
  288. package/skills/lark-slides/references/examples.md +261 -0
  289. package/skills/lark-slides/references/iconpark-index.json +41901 -0
  290. package/skills/lark-slides/references/iconpark.md +46 -0
  291. package/skills/lark-slides/references/lark-slides-create.md +137 -0
  292. package/skills/lark-slides/references/lark-slides-edit-workflows.md +144 -0
  293. package/skills/lark-slides/references/lark-slides-media-upload.md +128 -0
  294. package/skills/lark-slides/references/lark-slides-replace-pages.md +95 -0
  295. package/skills/lark-slides/references/lark-slides-replace-slide.md +240 -0
  296. package/skills/lark-slides/references/lark-slides-screenshot.md +94 -0
  297. package/skills/lark-slides/references/lark-slides-whiteboard.md +330 -0
  298. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-create.md +220 -0
  299. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-delete.md +123 -0
  300. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-get.md +110 -0
  301. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-replace.md +187 -0
  302. package/skills/lark-slides/references/lark-slides-xml-presentations-get.md +98 -0
  303. package/skills/lark-slides/references/planning-layer.md +219 -0
  304. package/skills/lark-slides/references/slide-templates.md +201 -0
  305. package/skills/lark-slides/references/slides_demo.xml +226 -0
  306. package/skills/lark-slides/references/slides_xml_schema_definition.xml +3049 -0
  307. package/skills/lark-slides/references/template-catalog.md +463 -0
  308. package/skills/lark-slides/references/template-index.json +1853 -0
  309. package/skills/lark-slides/references/troubleshooting.md +63 -0
  310. package/skills/lark-slides/references/validation-checklist.md +110 -0
  311. package/skills/lark-slides/references/visual-planning.md +254 -0
  312. package/skills/lark-slides/references/xml-format-guide.md +369 -0
  313. package/skills/lark-slides/references/xml-schema-quick-ref.md +245 -0
  314. package/skills/lark-slides/scripts/iconpark_tool.py +362 -0
  315. package/skills/lark-slides/scripts/iconpark_tool_test.py +177 -0
  316. package/skills/lark-slides/scripts/template_tool.py +970 -0
  317. package/skills/lark-slides/scripts/template_tool_test.py +177 -0
  318. package/skills/lark-slides/scripts/xml_text_overlap_lint.py +367 -0
  319. package/skills/lark-slides/scripts/xml_text_overlap_lint_test.py +263 -0
  320. package/skills/lark-task/SKILL.md +167 -0
  321. package/skills/lark-task/references/lark-task-assign.md +38 -0
  322. package/skills/lark-task/references/lark-task-comment.md +28 -0
  323. package/skills/lark-task/references/lark-task-complete.md +27 -0
  324. package/skills/lark-task/references/lark-task-create.md +57 -0
  325. package/skills/lark-task/references/lark-task-followers.md +35 -0
  326. package/skills/lark-task/references/lark-task-get-my-tasks.md +61 -0
  327. package/skills/lark-task/references/lark-task-get-related-tasks.md +53 -0
  328. package/skills/lark-task/references/lark-task-reminder.md +36 -0
  329. package/skills/lark-task/references/lark-task-reopen.md +27 -0
  330. package/skills/lark-task/references/lark-task-search.md +41 -0
  331. package/skills/lark-task/references/lark-task-set-ancestor.md +32 -0
  332. package/skills/lark-task/references/lark-task-tasklist-create.md +35 -0
  333. package/skills/lark-task/references/lark-task-tasklist-members.md +36 -0
  334. package/skills/lark-task/references/lark-task-tasklist-search.md +38 -0
  335. package/skills/lark-task/references/lark-task-tasklist-task-add.md +38 -0
  336. package/skills/lark-task/references/lark-task-update.md +37 -0
  337. package/skills/lark-task/references/lark-task-upload-attachment.md +59 -0
  338. package/skills/lark-vc/SKILL.md +202 -0
  339. package/skills/lark-vc/references/lark-vc-detail.md +44 -0
  340. package/skills/lark-vc/references/lark-vc-recording.md +154 -0
  341. package/skills/lark-vc/references/lark-vc-search.md +163 -0
  342. package/skills/lark-vc/references/vc-domain-boundaries.md +188 -0
  343. package/skills/lark-vc-agent/SKILL.md +169 -0
  344. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-events.md +287 -0
  345. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-join.md +141 -0
  346. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-leave.md +105 -0
  347. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-list-active.md +91 -0
  348. package/skills/lark-whiteboard/SKILL.md +47 -0
  349. package/skills/lark-whiteboard/elements/connectors.md +102 -0
  350. package/skills/lark-whiteboard/elements/content.md +40 -0
  351. package/skills/lark-whiteboard/elements/image.md +80 -0
  352. package/skills/lark-whiteboard/elements/layout.md +374 -0
  353. package/skills/lark-whiteboard/elements/schema.md +357 -0
  354. package/skills/lark-whiteboard/elements/style.md +318 -0
  355. package/skills/lark-whiteboard/elements/typography.md +73 -0
  356. package/skills/lark-whiteboard/references/lark-whiteboard-query.md +60 -0
  357. package/skills/lark-whiteboard/references/lark-whiteboard-update.md +122 -0
  358. package/skills/lark-whiteboard/references/lark-whiteboard-workflow.md +94 -0
  359. package/skills/lark-whiteboard/routes/dsl.md +107 -0
  360. package/skills/lark-whiteboard/routes/mermaid.md +27 -0
  361. package/skills/lark-whiteboard/routes/svg-edit.md +85 -0
  362. package/skills/lark-whiteboard/routes/svg.md +54 -0
  363. package/skills/lark-whiteboard/scenes/architecture.md +433 -0
  364. package/skills/lark-whiteboard/scenes/bar-chart.md +187 -0
  365. package/skills/lark-whiteboard/scenes/comparison.md +135 -0
  366. package/skills/lark-whiteboard/scenes/fishbone.md +238 -0
  367. package/skills/lark-whiteboard/scenes/flowchart.md +185 -0
  368. package/skills/lark-whiteboard/scenes/flywheel.md +195 -0
  369. package/skills/lark-whiteboard/scenes/funnel.md +101 -0
  370. package/skills/lark-whiteboard/scenes/line-chart.md +214 -0
  371. package/skills/lark-whiteboard/scenes/mermaid.md +130 -0
  372. package/skills/lark-whiteboard/scenes/milestone.md +139 -0
  373. package/skills/lark-whiteboard/scenes/organization.md +173 -0
  374. package/skills/lark-whiteboard/scenes/photo-showcase.md +126 -0
  375. package/skills/lark-whiteboard/scenes/pyramid.md +99 -0
  376. package/skills/lark-whiteboard/scenes/swimlane.md +371 -0
  377. package/skills/lark-whiteboard/scenes/treemap.md +216 -0
  378. package/skills/lark-wiki/SKILL.md +110 -0
  379. package/skills/lark-wiki/references/lark-wiki-delete-space.md +205 -0
  380. package/skills/lark-wiki/references/lark-wiki-member-add.md +67 -0
  381. package/skills/lark-wiki/references/lark-wiki-member-list.md +76 -0
  382. package/skills/lark-wiki/references/lark-wiki-member-remove.md +61 -0
  383. package/skills/lark-wiki/references/lark-wiki-move.md +183 -0
  384. package/skills/lark-wiki/references/lark-wiki-node-copy.md +72 -0
  385. package/skills/lark-wiki/references/lark-wiki-node-create.md +127 -0
  386. package/skills/lark-wiki/references/lark-wiki-node-delete.md +62 -0
  387. package/skills/lark-wiki/references/lark-wiki-node-get.md +57 -0
  388. package/skills/lark-wiki/references/lark-wiki-node-list.md +88 -0
  389. package/skills/lark-wiki/references/lark-wiki-space-create.md +46 -0
  390. package/skills/lark-wiki/references/lark-wiki-space-list.md +68 -0
  391. package/skills/lark-workflow-meeting-summary/SKILL.md +122 -0
  392. package/skills/lark-workflow-standup-report/SKILL.md +122 -0
@@ -0,0 +1,362 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2026 Lark Technologies Pte. Ltd.
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ import re
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+
14
+ SKILL_ROOT = Path(__file__).resolve().parent.parent
15
+ REFERENCES_DIR = SKILL_ROOT / "references"
16
+ DEFAULT_INDEX_PATH = REFERENCES_DIR / "iconpark-index.json"
17
+ DEFAULT_LIMIT = 8
18
+ CURATED_ICON_BOOSTS = {
19
+ "设置": {"iconpark/Base/setting.svg"},
20
+ "配置": {"iconpark/Base/setting.svg", "iconpark/Base/config.svg"},
21
+ "目标": {"iconpark/Base/aiming.svg", "iconpark/Sports/target-one.svg"},
22
+ "增长": {"iconpark/Charts/positive-dynamics.svg"},
23
+ "趋势": {"iconpark/Charts/chart-line.svg", "iconpark/Charts/positive-dynamics.svg"},
24
+ "占比": {"iconpark/Charts/chart-proportion.svg"},
25
+ "数据": {"iconpark/Charts/data-screen.svg"},
26
+ "看板": {"iconpark/Charts/data-screen.svg"},
27
+ "成功": {"iconpark/Character/check-one.svg"},
28
+ "完成": {"iconpark/Character/check-one.svg"},
29
+ "失败": {"iconpark/Character/close-one.svg"},
30
+ "风险": {"iconpark/Character/close-one.svg"},
31
+ "团队": {"iconpark/Peoples/peoples.svg"},
32
+ "用户": {"iconpark/Peoples/peoples.svg", "iconpark/Peoples/user.svg"},
33
+ "安全": {"iconpark/Safe/protect.svg"},
34
+ "防护": {"iconpark/Safe/protect.svg"},
35
+ "全球": {"iconpark/Travel/world.svg"},
36
+ "市场": {"iconpark/Travel/world.svg"},
37
+ "邮件": {"iconpark/Office/envelope-one.svg"},
38
+ "联系": {"iconpark/Office/envelope-one.svg"},
39
+ "会议": {"iconpark/Office/schedule.svg"},
40
+ "日程": {"iconpark/Office/schedule.svg"},
41
+ "飞书": {"iconpark/Brand/bydesign.svg"},
42
+ }
43
+ CURATED_BOOST_SCORE = 40
44
+
45
+
46
+ class IconParkToolError(Exception):
47
+ pass
48
+
49
+
50
+ def fail(message: str) -> None:
51
+ raise IconParkToolError(message)
52
+
53
+
54
+ def normalize_whitespace(value: str) -> str:
55
+ return re.sub(r"\s+", " ", value).strip()
56
+
57
+
58
+ def normalize_token(value: str) -> str:
59
+ return normalize_whitespace(value.lower().replace("_", "-"))
60
+
61
+
62
+ def append_unique(target: list[str], token: str) -> None:
63
+ normalized = normalize_token(token)
64
+ if normalized and normalized not in target:
65
+ target.append(normalized)
66
+
67
+
68
+ def tokenize_query(value: str) -> list[str]:
69
+ normalized = normalize_token(value)
70
+ if not normalized:
71
+ return []
72
+
73
+ tokens: list[str] = []
74
+ for item in re.split(r"[\s,/|,。;;::()()【】\[\]《》<>]+", normalized):
75
+ append_unique(tokens, item)
76
+
77
+ for phrase in re.findall(r"[\u3400-\u9fff]+", normalized):
78
+ if len(phrase) < 2:
79
+ continue
80
+ max_size = min(6, len(phrase))
81
+ for size in range(max_size, 1, -1):
82
+ for start in range(0, len(phrase) - size + 1):
83
+ append_unique(tokens, phrase[start : start + size])
84
+
85
+ synonym_tokens = {
86
+ "目标": ["aim", "target", "goal"],
87
+ "聚焦": ["focus", "target"],
88
+ "增长": ["growth", "trend", "positive"],
89
+ "趋势": ["trend", "chart", "line"],
90
+ "数据": ["data", "analytics", "chart"],
91
+ "指标": ["metric", "data"],
92
+ "看板": ["dashboard", "screen", "data"],
93
+ "成功": ["success", "check", "done"],
94
+ "完成": ["done", "success", "check"],
95
+ "失败": ["fail", "close", "risk"],
96
+ "风险": ["risk", "fail", "protect"],
97
+ "安全": ["safe", "security", "protect"],
98
+ "配置": ["config", "setting", "system"],
99
+ "设置": ["setting", "config"],
100
+ "团队": ["team", "people", "users"],
101
+ "用户": ["user", "people"],
102
+ "全球": ["global", "world", "earth"],
103
+ "市场": ["market", "world", "business"],
104
+ "邮件": ["mail", "message"],
105
+ "mail": ["message", "envelope", "envelope-one"],
106
+ "计划": ["plan", "schedule"],
107
+ "时间": ["time", "schedule"],
108
+ "学习": ["learning", "education", "book"],
109
+ "培训": ["training", "education"],
110
+ "自动化": ["automation", "ai"],
111
+ "ai": ["ai", "automation", "magic"],
112
+ }
113
+ for token in list(tokens):
114
+ for keyword, aliases in synonym_tokens.items():
115
+ if is_ascii_token(keyword):
116
+ matches = token == keyword
117
+ else:
118
+ matches = keyword in token
119
+ if matches:
120
+ for alias in aliases:
121
+ append_unique(tokens, alias)
122
+
123
+ return tokens
124
+
125
+
126
+ def is_ascii_token(value: str) -> bool:
127
+ return bool(re.fullmatch(r"[a-z0-9-]+", value))
128
+
129
+
130
+ def allows_substring_match(value: str) -> bool:
131
+ return not is_ascii_token(value) or len(value) >= 3
132
+
133
+
134
+ def field_tokens(*values: str) -> set[str]:
135
+ tokens: set[str] = set()
136
+ for value in values:
137
+ normalized = normalize_token(value)
138
+ if not normalized:
139
+ continue
140
+ tokens.add(normalized)
141
+ for part in re.split(r"[-\s]+", normalized):
142
+ if part:
143
+ tokens.add(part)
144
+ return tokens
145
+
146
+
147
+ def load_index(path: str | Path = DEFAULT_INDEX_PATH) -> dict[str, Any]:
148
+ index_path = Path(path)
149
+ if not index_path.exists():
150
+ fail(f"iconpark index not found: {index_path}")
151
+ try:
152
+ index_data = json.loads(index_path.read_text(encoding="utf-8"))
153
+ except json.JSONDecodeError as error:
154
+ fail(f"invalid iconpark index JSON: {error}")
155
+ if not isinstance(index_data.get("icons"), list):
156
+ fail("iconpark index must contain an icons array")
157
+ return index_data
158
+
159
+
160
+ def icon_search_text(entry: dict[str, Any]) -> str:
161
+ parts = [
162
+ entry.get("iconType", ""),
163
+ entry.get("category", ""),
164
+ entry.get("name", ""),
165
+ " ".join(entry.get("tags") or []),
166
+ ]
167
+ return normalize_token(" ".join(parts))
168
+
169
+
170
+ def score_icon(entry: dict[str, Any], query: str, tokens: list[str]) -> int:
171
+ raw_icon_type = entry.get("iconType", "")
172
+ icon_type = normalize_token(raw_icon_type)
173
+ category = normalize_token(entry.get("category", ""))
174
+ name = normalize_token(entry.get("name", ""))
175
+ tags = [normalize_token(tag) for tag in entry.get("tags") or []]
176
+ name_tokens = field_tokens(name)
177
+ category_tokens = field_tokens(category)
178
+ tag_tokens = field_tokens(*tags)
179
+ icon_type_tokens = field_tokens(icon_type)
180
+ search_text = icon_search_text(entry)
181
+ normalized_query = normalize_token(query)
182
+
183
+ score = 0
184
+ boosted_keywords: set[str] = set()
185
+ if normalized_query:
186
+ if normalized_query == icon_type or normalized_query == name:
187
+ score += 200
188
+ elif normalized_query in tag_tokens:
189
+ score += 120
190
+ elif normalized_query in icon_type_tokens:
191
+ score += 60
192
+ elif allows_substring_match(normalized_query) and normalized_query in search_text:
193
+ score += 30
194
+
195
+ for token in tokens:
196
+ for keyword, boosted_icon_types in CURATED_ICON_BOOSTS.items():
197
+ if keyword in boosted_keywords:
198
+ continue
199
+ if keyword in token and raw_icon_type in boosted_icon_types:
200
+ score += CURATED_BOOST_SCORE
201
+ boosted_keywords.add(keyword)
202
+ if token == name:
203
+ score += 80
204
+ elif token in name_tokens:
205
+ score += 55
206
+ elif allows_substring_match(token) and token in name:
207
+ score += 45
208
+ if token == category:
209
+ score += 35
210
+ elif token in category_tokens:
211
+ score += 25
212
+ elif allows_substring_match(token) and token in category:
213
+ score += 15
214
+ for tag in tags:
215
+ if token == tag:
216
+ score += 60
217
+ elif token in field_tokens(tag):
218
+ score += 45
219
+ elif allows_substring_match(token) and token in tag:
220
+ score += 20
221
+ if token in icon_type_tokens:
222
+ score += 20
223
+ elif allows_substring_match(token) and token in icon_type:
224
+ score += 15
225
+
226
+ return score
227
+
228
+
229
+ def parse_limit(value: Any) -> int:
230
+ if value is None or value is False:
231
+ return DEFAULT_LIMIT
232
+ if value is True:
233
+ fail("limit requires an integer value")
234
+ try:
235
+ return int(value)
236
+ except (TypeError, ValueError):
237
+ fail(f"limit must be an integer: {value}")
238
+
239
+
240
+ def public_icon(entry: dict[str, Any], score: int | None = None) -> dict[str, Any]:
241
+ result = {
242
+ "iconType": entry["iconType"],
243
+ "category": entry["category"],
244
+ "name": entry["name"],
245
+ "tags": entry.get("tags") or [],
246
+ }
247
+ if score is not None:
248
+ result["score"] = score
249
+ return result
250
+
251
+
252
+ def search_icons(index_data: dict[str, Any], options: dict[str, Any]) -> list[dict[str, Any]]:
253
+ query = str(options.get("query") or "")
254
+ if not normalize_whitespace(query):
255
+ fail("query is required")
256
+ limit = parse_limit(options.get("limit"))
257
+ category_filter = normalize_token(str(options.get("category") or ""))
258
+ tokens = tokenize_query(query)
259
+
260
+ ranked: list[dict[str, Any]] = []
261
+ for entry in index_data["icons"]:
262
+ if category_filter and normalize_token(entry.get("category", "")) != category_filter:
263
+ continue
264
+ score = score_icon(entry, query, tokens)
265
+ if query and score == 0:
266
+ continue
267
+ ranked.append(public_icon(entry, score))
268
+
269
+ ranked.sort(key=lambda item: (-int(item["score"]), item["category"], item["name"]))
270
+ return ranked[: max(limit, 0)]
271
+
272
+
273
+ def resolve_icon(index_data: dict[str, Any], name_or_type: str | None) -> dict[str, Any]:
274
+ if not name_or_type:
275
+ fail("name is required")
276
+ target = normalize_token(name_or_type)
277
+ matches = []
278
+ for entry in index_data["icons"]:
279
+ candidates = {
280
+ normalize_token(entry["iconType"]),
281
+ normalize_token(entry["name"]),
282
+ normalize_token(f'{entry["category"]}/{entry["name"]}.svg'),
283
+ }
284
+ if target in candidates:
285
+ matches.append(entry)
286
+ if not matches:
287
+ fail(f"icon not found: {name_or_type}")
288
+ if len(matches) > 1:
289
+ names = ", ".join(entry["iconType"] for entry in matches)
290
+ fail(f"ambiguous icon name: {name_or_type}; matches: {names}")
291
+ return public_icon(matches[0])
292
+
293
+
294
+ def list_categories(index_data: dict[str, Any]) -> list[dict[str, Any]]:
295
+ counts: dict[str, int] = {}
296
+ for entry in index_data["icons"]:
297
+ counts[entry["category"]] = counts.get(entry["category"], 0) + 1
298
+ return [{"category": category, "count": counts[category]} for category in sorted(counts)]
299
+
300
+
301
+ def parse_cli_args(argv: list[str]) -> tuple[str | None, dict[str, Any]]:
302
+ if not argv:
303
+ return None, {}
304
+ command, *rest = argv
305
+ options: dict[str, Any] = {}
306
+ index = 0
307
+ while index < len(rest):
308
+ token = rest[index]
309
+ if not token.startswith("--"):
310
+ fail(f"unexpected argument: {token}")
311
+ key = token[2:]
312
+ next_token = rest[index + 1] if index + 1 < len(rest) else None
313
+ if next_token is None or next_token.startswith("--"):
314
+ options[key] = True
315
+ index += 1
316
+ continue
317
+ options[key] = next_token
318
+ index += 2
319
+ return command, options
320
+
321
+
322
+ def print_usage() -> None:
323
+ usage = [
324
+ "Usage:",
325
+ " python3 iconpark_tool.py search --query <text> [--category <Category>] [--limit 8]",
326
+ " python3 iconpark_tool.py resolve --name <name|iconType>",
327
+ " python3 iconpark_tool.py list-categories",
328
+ ]
329
+ print("\n".join(usage), file=sys.stderr)
330
+
331
+
332
+ def write_json(value: Any) -> None:
333
+ print(json.dumps(value, ensure_ascii=False, indent=2))
334
+
335
+
336
+ def run_cli(argv: list[str] | None = None) -> None:
337
+ command, options = parse_cli_args(argv or sys.argv[1:])
338
+ if not command or command in {"--help", "help"}:
339
+ print_usage()
340
+ raise SystemExit(0)
341
+
342
+ index_data = load_index()
343
+ if command == "search":
344
+ write_json(search_icons(index_data, options))
345
+ return
346
+ if command == "resolve":
347
+ write_json(resolve_icon(index_data, options.get("name")))
348
+ return
349
+ if command == "list-categories":
350
+ write_json(list_categories(index_data))
351
+ return
352
+
353
+ print_usage()
354
+ fail(f"unknown command: {command}")
355
+
356
+
357
+ if __name__ == "__main__":
358
+ try:
359
+ run_cli()
360
+ except IconParkToolError as error:
361
+ print(f"iconpark-tool error: {error}", file=sys.stderr)
362
+ raise SystemExit(1) from error
@@ -0,0 +1,177 @@
1
+ # Copyright (c) 2026 Lark Technologies Pte. Ltd.
2
+ # SPDX-License-Identifier: MIT
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import subprocess
7
+ import sys
8
+ import unittest
9
+ from pathlib import Path
10
+
11
+ import iconpark_tool
12
+
13
+
14
+ SCRIPT_PATH = Path(__file__).resolve().with_name("iconpark_tool.py")
15
+
16
+
17
+ class IconParkToolTest(unittest.TestCase):
18
+ @classmethod
19
+ def setUpClass(cls) -> None:
20
+ cls.index_data = iconpark_tool.load_index()
21
+
22
+ def test_search_icons_finds_growth_trend(self) -> None:
23
+ results = iconpark_tool.search_icons(self.index_data, {"query": "增长趋势", "limit": 5})
24
+ self.assertTrue(results)
25
+ self.assertTrue(
26
+ any(entry["iconType"] == "iconpark/Charts/positive-dynamics.svg" for entry in results)
27
+ )
28
+
29
+ def test_search_icons_supports_english_query(self) -> None:
30
+ results = iconpark_tool.search_icons(self.index_data, {"query": "security protect", "limit": 3})
31
+ self.assertTrue(results)
32
+ self.assertEqual(results[0]["iconType"], "iconpark/Safe/protect.svg")
33
+
34
+ def test_search_icons_supports_category_filter(self) -> None:
35
+ results = iconpark_tool.search_icons(
36
+ self.index_data,
37
+ {"query": "data", "category": "Charts", "limit": 10},
38
+ )
39
+ self.assertTrue(results)
40
+ self.assertTrue(all(entry["category"] == "Charts" for entry in results))
41
+
42
+ def test_search_icons_does_not_expand_ai_inside_words(self) -> None:
43
+ mail_results = iconpark_tool.search_icons(self.index_data, {"query": "mail", "limit": 5})
44
+ self.assertEqual(mail_results[0]["iconType"], "iconpark/Office/envelope-one.svg")
45
+ self.assertNotEqual(mail_results[0]["iconType"], "iconpark/Others/magic.svg")
46
+
47
+ fail_results = iconpark_tool.search_icons(self.index_data, {"query": "fail", "limit": 5})
48
+ self.assertNotEqual(fail_results[0]["iconType"], "iconpark/Others/magic.svg")
49
+
50
+ def test_search_icons_supports_template_icon_queries(self) -> None:
51
+ cases = [
52
+ ("arrow", "iconpark/Arrows/arrow-right.svg"),
53
+ ("right", "iconpark/Arrows/right.svg"),
54
+ ("PPT", "iconpark/Music/ppt.svg"),
55
+ ("table", "iconpark/Office/table.svg"),
56
+ ("会议", "iconpark/Office/schedule.svg"),
57
+ ("飞书", "iconpark/Brand/bydesign.svg"),
58
+ ]
59
+ for query, icon_type in cases:
60
+ with self.subTest(query=query):
61
+ results = iconpark_tool.search_icons(self.index_data, {"query": query, "limit": 10})
62
+ self.assertTrue(
63
+ any(entry["iconType"] == icon_type for entry in results),
64
+ f"{icon_type} not found in {results}",
65
+ )
66
+
67
+ def test_search_icons_defaults_to_wider_candidate_set(self) -> None:
68
+ results = iconpark_tool.search_icons(self.index_data, {"query": "data"})
69
+ self.assertEqual(len(results), 8)
70
+
71
+ def test_search_icons_boosts_common_slide_terms(self) -> None:
72
+ results = iconpark_tool.search_icons(self.index_data, {"query": "会议", "limit": 3})
73
+ self.assertTrue(
74
+ any(entry["iconType"] == "iconpark/Office/schedule.svg" for entry in results),
75
+ f"iconpark/Office/schedule.svg not found in {results}",
76
+ )
77
+
78
+ def test_search_icons_keeps_high_value_top_results(self) -> None:
79
+ cases = [
80
+ ("安全", "iconpark/Safe/protect.svg"),
81
+ ("邮件", "iconpark/Office/mail-open.svg"),
82
+ ("会议", "iconpark/Office/schedule.svg"),
83
+ ("增长趋势", "iconpark/Charts/chart-line.svg"),
84
+ ("飞书", "iconpark/Brand/bydesign.svg"),
85
+ ]
86
+ for query, icon_type in cases:
87
+ with self.subTest(query=query):
88
+ results = iconpark_tool.search_icons(self.index_data, {"query": query, "limit": 3})
89
+ self.assertTrue(results)
90
+ self.assertEqual(results[0]["iconType"], icon_type)
91
+
92
+ def test_search_icons_requires_query(self) -> None:
93
+ with self.assertRaises(iconpark_tool.IconParkToolError):
94
+ iconpark_tool.search_icons(self.index_data, {"limit": 5})
95
+
96
+ def test_search_icons_rejects_invalid_limit(self) -> None:
97
+ with self.assertRaises(iconpark_tool.IconParkToolError):
98
+ iconpark_tool.search_icons(self.index_data, {"query": "data", "limit": "abc"})
99
+
100
+ def test_resolve_icon_accepts_name_and_icon_type(self) -> None:
101
+ by_name = iconpark_tool.resolve_icon(self.index_data, "chart-line")
102
+ by_type = iconpark_tool.resolve_icon(self.index_data, "iconpark/Charts/chart-line.svg")
103
+ self.assertEqual(by_name["iconType"], "iconpark/Charts/chart-line.svg")
104
+ self.assertEqual(by_name, by_type)
105
+
106
+ def test_resolve_icon_accepts_template_icon_type(self) -> None:
107
+ result = iconpark_tool.resolve_icon(self.index_data, "iconpark/Arrows/arrow-right.svg")
108
+ self.assertEqual(result["iconType"], "iconpark/Arrows/arrow-right.svg")
109
+
110
+ def test_resolve_icon_rejects_unknown_name(self) -> None:
111
+ with self.assertRaises(iconpark_tool.IconParkToolError):
112
+ iconpark_tool.resolve_icon(self.index_data, "not-a-real-icon")
113
+
114
+ def test_list_categories_counts_index(self) -> None:
115
+ categories = iconpark_tool.list_categories(self.index_data)
116
+ self.assertTrue(any(entry["category"] == "Charts" and entry["count"] > 0 for entry in categories))
117
+
118
+
119
+ class IconParkToolCLITest(unittest.TestCase):
120
+ def run_tool(self, *args: str) -> subprocess.CompletedProcess[str]:
121
+ return subprocess.run(
122
+ [sys.executable, str(SCRIPT_PATH), *args],
123
+ capture_output=True,
124
+ check=False,
125
+ text=True,
126
+ )
127
+
128
+ def test_cli_search_writes_json_to_stdout(self) -> None:
129
+ result = self.run_tool("search", "--query", "增长趋势", "--limit", "5")
130
+ self.assertEqual(result.returncode, 0, result.stderr)
131
+ self.assertEqual(result.stderr, "")
132
+
133
+ output = json.loads(result.stdout)
134
+ self.assertTrue(output)
135
+ self.assertTrue(
136
+ any(entry["iconType"] == "iconpark/Charts/positive-dynamics.svg" for entry in output)
137
+ )
138
+
139
+ def test_cli_resolve_writes_json_to_stdout(self) -> None:
140
+ result = self.run_tool("resolve", "--name", "chart-line")
141
+ self.assertEqual(result.returncode, 0, result.stderr)
142
+ self.assertEqual(result.stderr, "")
143
+
144
+ output = json.loads(result.stdout)
145
+ self.assertEqual(output["iconType"], "iconpark/Charts/chart-line.svg")
146
+
147
+ def test_cli_list_categories_writes_json_to_stdout(self) -> None:
148
+ result = self.run_tool("list-categories")
149
+ self.assertEqual(result.returncode, 0, result.stderr)
150
+ self.assertEqual(result.stderr, "")
151
+
152
+ output = json.loads(result.stdout)
153
+ self.assertTrue(any(entry["category"] == "Charts" and entry["count"] > 0 for entry in output))
154
+
155
+ def test_cli_help_writes_usage_to_stderr(self) -> None:
156
+ result = self.run_tool("--help")
157
+ self.assertEqual(result.returncode, 0, result.stderr)
158
+ self.assertEqual(result.stdout, "")
159
+ self.assertIn("Usage:", result.stderr)
160
+ self.assertIn("python3 iconpark_tool.py search", result.stderr)
161
+
162
+ def test_cli_invalid_argument_writes_error_to_stderr(self) -> None:
163
+ result = self.run_tool("search", "增长趋势")
164
+ self.assertEqual(result.returncode, 1)
165
+ self.assertEqual(result.stdout, "")
166
+ self.assertIn("iconpark-tool error: unexpected argument: 增长趋势", result.stderr)
167
+
168
+ def test_cli_unknown_command_writes_usage_and_error_to_stderr(self) -> None:
169
+ result = self.run_tool("unknown")
170
+ self.assertEqual(result.returncode, 1)
171
+ self.assertEqual(result.stdout, "")
172
+ self.assertIn("Usage:", result.stderr)
173
+ self.assertIn("iconpark-tool error: unknown command: unknown", result.stderr)
174
+
175
+
176
+ if __name__ == "__main__":
177
+ unittest.main()