pi-feishu-cli 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 (407) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/src/bot.d.ts +29 -0
  4. package/dist/src/bot.js +75 -0
  5. package/dist/src/cards.d.ts +6 -0
  6. package/dist/src/cards.js +87 -0
  7. package/dist/src/config.d.ts +3 -0
  8. package/dist/src/config.js +28 -0
  9. package/dist/src/daemon.d.ts +2 -0
  10. package/dist/src/daemon.js +151 -0
  11. package/dist/src/extension.d.ts +2 -0
  12. package/dist/src/extension.js +124 -0
  13. package/dist/src/poller.d.ts +33 -0
  14. package/dist/src/poller.js +94 -0
  15. package/dist/src/renderer.d.ts +8 -0
  16. package/dist/src/renderer.js +31 -0
  17. package/dist/src/session-registry.d.ts +15 -0
  18. package/dist/src/session-registry.js +82 -0
  19. package/dist/src/types.d.ts +25 -0
  20. package/dist/src/types.js +1 -0
  21. package/dist/tests/bot.test.d.ts +1 -0
  22. package/dist/tests/bot.test.js +89 -0
  23. package/dist/tests/cards.test.d.ts +1 -0
  24. package/dist/tests/cards.test.js +39 -0
  25. package/dist/tests/config.test.d.ts +1 -0
  26. package/dist/tests/config.test.js +59 -0
  27. package/dist/tests/renderer.test.d.ts +1 -0
  28. package/dist/tests/renderer.test.js +61 -0
  29. package/dist/tests/session-registry.test.d.ts +1 -0
  30. package/dist/tests/session-registry.test.js +92 -0
  31. package/dist/tests/types.test.d.ts +1 -0
  32. package/dist/tests/types.test.js +30 -0
  33. package/package.json +35 -0
  34. package/skills/lark-approval/SKILL.md +56 -0
  35. package/skills/lark-apps/SKILL.md +92 -0
  36. package/skills/lark-apps/references/lark-apps-access-scope-get.md +104 -0
  37. package/skills/lark-apps/references/lark-apps-access-scope-set.md +126 -0
  38. package/skills/lark-apps/references/lark-apps-create.md +112 -0
  39. package/skills/lark-apps/references/lark-apps-html-publish.md +151 -0
  40. package/skills/lark-apps/references/lark-apps-list.md +95 -0
  41. package/skills/lark-apps/references/lark-apps-update.md +86 -0
  42. package/skills/lark-attendance/SKILL.md +57 -0
  43. package/skills/lark-base/SKILL.md +359 -0
  44. package/skills/lark-base/references/dashboard-block-data-config.md +350 -0
  45. package/skills/lark-base/references/examples.md +140 -0
  46. package/skills/lark-base/references/formula-field-guide.md +737 -0
  47. package/skills/lark-base/references/lark-base-advperm-disable.md +83 -0
  48. package/skills/lark-base/references/lark-base-advperm-enable.md +80 -0
  49. package/skills/lark-base/references/lark-base-base-copy.md +74 -0
  50. package/skills/lark-base/references/lark-base-base-create.md +68 -0
  51. package/skills/lark-base/references/lark-base-base-get.md +39 -0
  52. package/skills/lark-base/references/lark-base-cell-value.md +151 -0
  53. package/skills/lark-base/references/lark-base-dashboard-arrange.md +83 -0
  54. package/skills/lark-base/references/lark-base-dashboard-block-create.md +108 -0
  55. package/skills/lark-base/references/lark-base-dashboard-block-delete.md +46 -0
  56. package/skills/lark-base/references/lark-base-dashboard-block-get.md +57 -0
  57. package/skills/lark-base/references/lark-base-dashboard-block-list.md +53 -0
  58. package/skills/lark-base/references/lark-base-dashboard-block-update.md +84 -0
  59. package/skills/lark-base/references/lark-base-dashboard-create.md +73 -0
  60. package/skills/lark-base/references/lark-base-dashboard-delete.md +44 -0
  61. package/skills/lark-base/references/lark-base-dashboard-get.md +59 -0
  62. package/skills/lark-base/references/lark-base-dashboard-list.md +52 -0
  63. package/skills/lark-base/references/lark-base-dashboard-update.md +69 -0
  64. package/skills/lark-base/references/lark-base-dashboard.md +240 -0
  65. package/skills/lark-base/references/lark-base-data-analysis-sop.md +88 -0
  66. package/skills/lark-base/references/lark-base-data-query.md +375 -0
  67. package/skills/lark-base/references/lark-base-field-create.md +104 -0
  68. package/skills/lark-base/references/lark-base-field-delete.md +51 -0
  69. package/skills/lark-base/references/lark-base-field-get.md +42 -0
  70. package/skills/lark-base/references/lark-base-field-list.md +44 -0
  71. package/skills/lark-base/references/lark-base-field-search-options.md +48 -0
  72. package/skills/lark-base/references/lark-base-field-update.md +97 -0
  73. package/skills/lark-base/references/lark-base-field.md +22 -0
  74. package/skills/lark-base/references/lark-base-form-create.md +87 -0
  75. package/skills/lark-base/references/lark-base-form-delete.md +64 -0
  76. package/skills/lark-base/references/lark-base-form-detail.md +198 -0
  77. package/skills/lark-base/references/lark-base-form-get.md +68 -0
  78. package/skills/lark-base/references/lark-base-form-list.md +73 -0
  79. package/skills/lark-base/references/lark-base-form-questions-create.md +118 -0
  80. package/skills/lark-base/references/lark-base-form-questions-delete.md +68 -0
  81. package/skills/lark-base/references/lark-base-form-questions-list.md +84 -0
  82. package/skills/lark-base/references/lark-base-form-questions-update.md +92 -0
  83. package/skills/lark-base/references/lark-base-form-questions.md +23 -0
  84. package/skills/lark-base/references/lark-base-form-submit.md +171 -0
  85. package/skills/lark-base/references/lark-base-form-update.md +82 -0
  86. package/skills/lark-base/references/lark-base-form.md +25 -0
  87. package/skills/lark-base/references/lark-base-history.md +16 -0
  88. package/skills/lark-base/references/lark-base-record-batch-create.md +58 -0
  89. package/skills/lark-base/references/lark-base-record-batch-update.md +53 -0
  90. package/skills/lark-base/references/lark-base-record-delete.md +62 -0
  91. package/skills/lark-base/references/lark-base-record-history-list.md +86 -0
  92. package/skills/lark-base/references/lark-base-record-share-link-create.md +72 -0
  93. package/skills/lark-base/references/lark-base-record-upsert.md +64 -0
  94. package/skills/lark-base/references/lark-base-record.md +31 -0
  95. package/skills/lark-base/references/lark-base-role-create.md +89 -0
  96. package/skills/lark-base/references/lark-base-role-delete.md +83 -0
  97. package/skills/lark-base/references/lark-base-role-get.md +87 -0
  98. package/skills/lark-base/references/lark-base-role-list.md +81 -0
  99. package/skills/lark-base/references/lark-base-role-update.md +94 -0
  100. package/skills/lark-base/references/lark-base-shortcut-field-properties.md +481 -0
  101. package/skills/lark-base/references/lark-base-table-create.md +62 -0
  102. package/skills/lark-base/references/lark-base-table-delete.md +51 -0
  103. package/skills/lark-base/references/lark-base-table-get.md +46 -0
  104. package/skills/lark-base/references/lark-base-table-list.md +43 -0
  105. package/skills/lark-base/references/lark-base-table-update.md +49 -0
  106. package/skills/lark-base/references/lark-base-table.md +20 -0
  107. package/skills/lark-base/references/lark-base-view-create.md +50 -0
  108. package/skills/lark-base/references/lark-base-view-delete.md +48 -0
  109. package/skills/lark-base/references/lark-base-view-get-card.md +38 -0
  110. package/skills/lark-base/references/lark-base-view-get-filter.md +38 -0
  111. package/skills/lark-base/references/lark-base-view-get-group.md +38 -0
  112. package/skills/lark-base/references/lark-base-view-get-sort.md +38 -0
  113. package/skills/lark-base/references/lark-base-view-get-timebar.md +38 -0
  114. package/skills/lark-base/references/lark-base-view-get-visible-fields.md +28 -0
  115. package/skills/lark-base/references/lark-base-view-get.md +38 -0
  116. package/skills/lark-base/references/lark-base-view-list.md +44 -0
  117. package/skills/lark-base/references/lark-base-view-rename.md +44 -0
  118. package/skills/lark-base/references/lark-base-view-set-card.md +55 -0
  119. package/skills/lark-base/references/lark-base-view-set-filter.md +181 -0
  120. package/skills/lark-base/references/lark-base-view-set-group.md +65 -0
  121. package/skills/lark-base/references/lark-base-view-set-sort.md +63 -0
  122. package/skills/lark-base/references/lark-base-view-set-timebar.md +51 -0
  123. package/skills/lark-base/references/lark-base-view-set-visible-fields.md +46 -0
  124. package/skills/lark-base/references/lark-base-view.md +44 -0
  125. package/skills/lark-base/references/lark-base-workflow-create.md +180 -0
  126. package/skills/lark-base/references/lark-base-workflow-disable.md +94 -0
  127. package/skills/lark-base/references/lark-base-workflow-enable.md +94 -0
  128. package/skills/lark-base/references/lark-base-workflow-get.md +147 -0
  129. package/skills/lark-base/references/lark-base-workflow-guide.md +718 -0
  130. package/skills/lark-base/references/lark-base-workflow-list.md +124 -0
  131. package/skills/lark-base/references/lark-base-workflow-schema.md +935 -0
  132. package/skills/lark-base/references/lark-base-workflow-update.md +167 -0
  133. package/skills/lark-base/references/lark-base-workflow.md +23 -0
  134. package/skills/lark-base/references/lark-base-workspace.md +18 -0
  135. package/skills/lark-base/references/lookup-field-guide.md +512 -0
  136. package/skills/lark-base/references/role-config.md +539 -0
  137. package/skills/lark-calendar/SKILL.md +154 -0
  138. package/skills/lark-calendar/references/lark-calendar-agenda.md +78 -0
  139. package/skills/lark-calendar/references/lark-calendar-create.md +109 -0
  140. package/skills/lark-calendar/references/lark-calendar-freebusy.md +124 -0
  141. package/skills/lark-calendar/references/lark-calendar-room-find.md +113 -0
  142. package/skills/lark-calendar/references/lark-calendar-rsvp.md +42 -0
  143. package/skills/lark-calendar/references/lark-calendar-schedule-meeting.md +265 -0
  144. package/skills/lark-calendar/references/lark-calendar-suggestion.md +125 -0
  145. package/skills/lark-calendar/references/lark-calendar-update.md +105 -0
  146. package/skills/lark-contact/SKILL.md +45 -0
  147. package/skills/lark-contact/references/lark-contact-get-user.md +19 -0
  148. package/skills/lark-contact/references/lark-contact-search-user.md +124 -0
  149. package/skills/lark-doc/SKILL.md +65 -0
  150. package/skills/lark-doc/references/lark-doc-create.md +89 -0
  151. package/skills/lark-doc/references/lark-doc-fetch.md +141 -0
  152. package/skills/lark-doc/references/lark-doc-md.md +71 -0
  153. package/skills/lark-doc/references/lark-doc-media-download.md +50 -0
  154. package/skills/lark-doc/references/lark-doc-media-insert.md +114 -0
  155. package/skills/lark-doc/references/lark-doc-media-preview.md +41 -0
  156. package/skills/lark-doc/references/lark-doc-update.md +252 -0
  157. package/skills/lark-doc/references/lark-doc-whiteboard.md +100 -0
  158. package/skills/lark-doc/references/lark-doc-xml.md +169 -0
  159. package/skills/lark-doc/references/style/lark-doc-create-workflow.md +56 -0
  160. package/skills/lark-doc/references/style/lark-doc-style.md +106 -0
  161. package/skills/lark-doc/references/style/lark-doc-update-workflow.md +54 -0
  162. package/skills/lark-drive/SKILL.md +369 -0
  163. package/skills/lark-drive/references/lark-drive-add-comment.md +182 -0
  164. package/skills/lark-drive/references/lark-drive-apply-permission.md +77 -0
  165. package/skills/lark-drive/references/lark-drive-create-folder.md +73 -0
  166. package/skills/lark-drive/references/lark-drive-create-shortcut.md +103 -0
  167. package/skills/lark-drive/references/lark-drive-delete.md +79 -0
  168. package/skills/lark-drive/references/lark-drive-download.md +31 -0
  169. package/skills/lark-drive/references/lark-drive-export-download.md +50 -0
  170. package/skills/lark-drive/references/lark-drive-export.md +119 -0
  171. package/skills/lark-drive/references/lark-drive-import.md +159 -0
  172. package/skills/lark-drive/references/lark-drive-inspect.md +50 -0
  173. package/skills/lark-drive/references/lark-drive-move.md +120 -0
  174. package/skills/lark-drive/references/lark-drive-pull.md +137 -0
  175. package/skills/lark-drive/references/lark-drive-push.md +162 -0
  176. package/skills/lark-drive/references/lark-drive-reactions.md +113 -0
  177. package/skills/lark-drive/references/lark-drive-search.md +266 -0
  178. package/skills/lark-drive/references/lark-drive-status.md +198 -0
  179. package/skills/lark-drive/references/lark-drive-task-result.md +302 -0
  180. package/skills/lark-drive/references/lark-drive-upload.md +67 -0
  181. package/skills/lark-drive/references/lark-drive-version-delete.md +38 -0
  182. package/skills/lark-drive/references/lark-drive-version-get.md +71 -0
  183. package/skills/lark-drive/references/lark-drive-version-history.md +73 -0
  184. package/skills/lark-drive/references/lark-drive-version-revert.md +198 -0
  185. package/skills/lark-event/SKILL.md +145 -0
  186. package/skills/lark-event/references/lark-event-im.md +86 -0
  187. package/skills/lark-im/SKILL.md +162 -0
  188. package/skills/lark-im/references/lark-im-chat-create.md +162 -0
  189. package/skills/lark-im/references/lark-im-chat-identity.md +55 -0
  190. package/skills/lark-im/references/lark-im-chat-list.md +198 -0
  191. package/skills/lark-im/references/lark-im-chat-messages-list.md +148 -0
  192. package/skills/lark-im/references/lark-im-chat-search.md +136 -0
  193. package/skills/lark-im/references/lark-im-chat-update.md +84 -0
  194. package/skills/lark-im/references/lark-im-flag-cancel.md +198 -0
  195. package/skills/lark-im/references/lark-im-flag-create.md +67 -0
  196. package/skills/lark-im/references/lark-im-flag-list.md +100 -0
  197. package/skills/lark-im/references/lark-im-messages-mget.md +95 -0
  198. package/skills/lark-im/references/lark-im-messages-reply.md +228 -0
  199. package/skills/lark-im/references/lark-im-messages-resources-download.md +94 -0
  200. package/skills/lark-im/references/lark-im-messages-search.md +232 -0
  201. package/skills/lark-im/references/lark-im-messages-send.md +229 -0
  202. package/skills/lark-im/references/lark-im-reactions.md +297 -0
  203. package/skills/lark-im/references/lark-im-threads-messages-list.md +111 -0
  204. package/skills/lark-mail/SKILL.md +648 -0
  205. package/skills/lark-mail/references/lark-mail-decline-receipt.md +115 -0
  206. package/skills/lark-mail/references/lark-mail-draft-create.md +123 -0
  207. package/skills/lark-mail/references/lark-mail-draft-edit.md +400 -0
  208. package/skills/lark-mail/references/lark-mail-forward.md +173 -0
  209. package/skills/lark-mail/references/lark-mail-message.md +230 -0
  210. package/skills/lark-mail/references/lark-mail-messages.md +108 -0
  211. package/skills/lark-mail/references/lark-mail-reply-all.md +206 -0
  212. package/skills/lark-mail/references/lark-mail-reply.md +242 -0
  213. package/skills/lark-mail/references/lark-mail-send-receipt.md +198 -0
  214. package/skills/lark-mail/references/lark-mail-send.md +216 -0
  215. package/skills/lark-mail/references/lark-mail-share-to-chat.md +198 -0
  216. package/skills/lark-mail/references/lark-mail-signature.md +98 -0
  217. package/skills/lark-mail/references/lark-mail-template-create.md +129 -0
  218. package/skills/lark-mail/references/lark-mail-template-update.md +198 -0
  219. package/skills/lark-mail/references/lark-mail-thread.md +111 -0
  220. package/skills/lark-mail/references/lark-mail-triage.md +122 -0
  221. package/skills/lark-mail/references/lark-mail-watch.md +94 -0
  222. package/skills/lark-minutes/SKILL.md +139 -0
  223. package/skills/lark-minutes/references/lark-minutes-download.md +137 -0
  224. package/skills/lark-minutes/references/lark-minutes-search.md +206 -0
  225. package/skills/lark-minutes/references/lark-minutes-upload.md +104 -0
  226. package/skills/lark-okr/SKILL.md +133 -0
  227. package/skills/lark-okr/references/lark-okr-contentblock.md +359 -0
  228. package/skills/lark-okr/references/lark-okr-cycle-detail.md +84 -0
  229. package/skills/lark-okr/references/lark-okr-cycle-list.md +90 -0
  230. package/skills/lark-okr/references/lark-okr-entities.md +329 -0
  231. package/skills/lark-okr/references/lark-okr-image-upload.md +116 -0
  232. package/skills/lark-okr/references/lark-okr-progress-create.md +81 -0
  233. package/skills/lark-okr/references/lark-okr-progress-delete.md +47 -0
  234. package/skills/lark-okr/references/lark-okr-progress-get.md +62 -0
  235. package/skills/lark-okr/references/lark-okr-progress-list.md +80 -0
  236. package/skills/lark-okr/references/lark-okr-progress-update.md +81 -0
  237. package/skills/lark-openapi-explorer/SKILL.md +153 -0
  238. package/skills/lark-shared/SKILL.md +144 -0
  239. package/skills/lark-sheets/SKILL.md +343 -0
  240. package/skills/lark-sheets/references/lark-sheets-cell-data.md +197 -0
  241. package/skills/lark-sheets/references/lark-sheets-cell-images.md +59 -0
  242. package/skills/lark-sheets/references/lark-sheets-cell-style-and-merge.md +141 -0
  243. package/skills/lark-sheets/references/lark-sheets-dropdown.md +133 -0
  244. package/skills/lark-sheets/references/lark-sheets-filter-views.md +193 -0
  245. package/skills/lark-sheets/references/lark-sheets-float-images.md +125 -0
  246. package/skills/lark-sheets/references/lark-sheets-formula.md +88 -0
  247. package/skills/lark-sheets/references/lark-sheets-row-column-management.md +151 -0
  248. package/skills/lark-sheets/references/lark-sheets-sheet-management.md +164 -0
  249. package/skills/lark-sheets/references/lark-sheets-spreadsheet-management.md +140 -0
  250. package/skills/lark-skill-maker/SKILL.md +85 -0
  251. package/skills/lark-slides/SKILL.md +296 -0
  252. package/skills/lark-slides/assets/templates/administration--all_hands_meeting.xml +1999 -0
  253. package/skills/lark-slides/assets/templates/administration--annual_gala.xml +1160 -0
  254. package/skills/lark-slides/assets/templates/administration--company_intro.xml +1376 -0
  255. package/skills/lark-slides/assets/templates/administration--corporate_culture.xml +1765 -0
  256. package/skills/lark-slides/assets/templates/hr--employee_training.xml +912 -0
  257. package/skills/lark-slides/assets/templates/hr--employee_training_workshop.xml +1504 -0
  258. package/skills/lark-slides/assets/templates/hr--onboarding.xml +933 -0
  259. package/skills/lark-slides/assets/templates/marketing--brand_communication.xml +1367 -0
  260. package/skills/lark-slides/assets/templates/marketing--brand_logo_design.xml +1347 -0
  261. package/skills/lark-slides/assets/templates/marketing--brand_operations_plan.xml +1309 -0
  262. package/skills/lark-slides/assets/templates/marketing--business_plan.xml +1646 -0
  263. package/skills/lark-slides/assets/templates/marketing--marketing_plan.xml +198 -0
  264. package/skills/lark-slides/assets/templates/marketing--marketing_strategy.xml +1484 -0
  265. package/skills/lark-slides/assets/templates/marketing--product_whitepaper.xml +198 -0
  266. package/skills/lark-slides/assets/templates/marketing--roadshow_business_plan.xml +1506 -0
  267. package/skills/lark-slides/assets/templates/misc--book_sharing.xml +198 -0
  268. package/skills/lark-slides/assets/templates/misc--club_event_plan.xml +4885 -0
  269. package/skills/lark-slides/assets/templates/misc--student_career_plan.xml +1854 -0
  270. package/skills/lark-slides/assets/templates/office--dark_general.xml +3763 -0
  271. package/skills/lark-slides/assets/templates/office--dept_annual_report.xml +1192 -0
  272. package/skills/lark-slides/assets/templates/office--light_general.xml +3378 -0
  273. package/skills/lark-slides/assets/templates/office--project_kickoff.xml +3152 -0
  274. package/skills/lark-slides/assets/templates/office--quarterly_review.xml +1253 -0
  275. package/skills/lark-slides/assets/templates/office--work_report.xml +1099 -0
  276. package/skills/lark-slides/assets/templates/office--work_summary.xml +4420 -0
  277. package/skills/lark-slides/assets/templates/office--work_summary_report.xml +1523 -0
  278. package/skills/lark-slides/assets/templates/operations--brand_logo_design.xml +1347 -0
  279. package/skills/lark-slides/assets/templates/operations--brand_operations_plan.xml +1309 -0
  280. package/skills/lark-slides/assets/templates/operations--marketing_plan.xml +1469 -0
  281. package/skills/lark-slides/assets/templates/operations--product_promotion.xml +687 -0
  282. package/skills/lark-slides/assets/templates/personal--experience_sharing.xml +2242 -0
  283. package/skills/lark-slides/assets/templates/personal--personal_resume.xml +2047 -0
  284. package/skills/lark-slides/assets/templates/personal--promotion_defense.xml +1099 -0
  285. package/skills/lark-slides/assets/templates/personal--promotion_report.xml +1039 -0
  286. package/skills/lark-slides/assets/templates/personal--self_intro.xml +696 -0
  287. package/skills/lark-slides/assets/templates/personal--teaching_sharing.xml +3013 -0
  288. package/skills/lark-slides/assets/templates/product--business_case_analysis.xml +1341 -0
  289. package/skills/lark-slides/assets/templates/product--market_analysis.xml +898 -0
  290. package/skills/lark-slides/assets/templates/product--product_analysis.xml +1537 -0
  291. package/skills/lark-slides/assets/templates/product--product_intro.xml +2838 -0
  292. package/skills/lark-slides/assets/templates/product--product_promotion.xml +687 -0
  293. package/skills/lark-slides/assets/templates/product--product_promotion_2.xml +198 -0
  294. package/skills/lark-slides/references/asset-planning.md +124 -0
  295. package/skills/lark-slides/references/examples.md +261 -0
  296. package/skills/lark-slides/references/lark-slides-create.md +137 -0
  297. package/skills/lark-slides/references/lark-slides-edit-workflows.md +142 -0
  298. package/skills/lark-slides/references/lark-slides-media-upload.md +128 -0
  299. package/skills/lark-slides/references/lark-slides-replace-slide.md +239 -0
  300. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-create.md +220 -0
  301. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-delete.md +123 -0
  302. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-get.md +110 -0
  303. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-replace.md +186 -0
  304. package/skills/lark-slides/references/lark-slides-xml-presentations-get.md +98 -0
  305. package/skills/lark-slides/references/planning-layer.md +219 -0
  306. package/skills/lark-slides/references/slide-templates.md +201 -0
  307. package/skills/lark-slides/references/slides_demo.xml +226 -0
  308. package/skills/lark-slides/references/slides_xml_schema_definition.xml +3004 -0
  309. package/skills/lark-slides/references/template-catalog.md +463 -0
  310. package/skills/lark-slides/references/template-index.json +198 -0
  311. package/skills/lark-slides/references/troubleshooting.md +198 -0
  312. package/skills/lark-slides/references/validation-checklist.md +102 -0
  313. package/skills/lark-slides/references/visual-planning.md +250 -0
  314. package/skills/lark-slides/references/xml-format-guide.md +369 -0
  315. package/skills/lark-slides/references/xml-schema-quick-ref.md +215 -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 +165 -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 +55 -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-subscribe-event.md +86 -0
  333. package/skills/lark-task/references/lark-task-tasklist-create.md +35 -0
  334. package/skills/lark-task/references/lark-task-tasklist-members.md +36 -0
  335. package/skills/lark-task/references/lark-task-tasklist-search.md +38 -0
  336. package/skills/lark-task/references/lark-task-tasklist-task-add.md +38 -0
  337. package/skills/lark-task/references/lark-task-update.md +37 -0
  338. package/skills/lark-task/references/lark-task-upload-attachment.md +59 -0
  339. package/skills/lark-vc/SKILL.md +168 -0
  340. package/skills/lark-vc/references/lark-vc-notes.md +126 -0
  341. package/skills/lark-vc/references/lark-vc-recording.md +153 -0
  342. package/skills/lark-vc/references/lark-vc-search.md +193 -0
  343. package/skills/lark-vc-agent/SKILL.md +121 -0
  344. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-events.md +247 -0
  345. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-join.md +133 -0
  346. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-leave.md +111 -0
  347. package/skills/lark-whiteboard/SKILL.md +144 -0
  348. package/skills/lark-whiteboard/references/connectors.md +102 -0
  349. package/skills/lark-whiteboard/references/content.md +40 -0
  350. package/skills/lark-whiteboard/references/image.md +80 -0
  351. package/skills/lark-whiteboard/references/lark-whiteboard-query.md +49 -0
  352. package/skills/lark-whiteboard/references/lark-whiteboard-update.md +100 -0
  353. package/skills/lark-whiteboard/references/layout.md +374 -0
  354. package/skills/lark-whiteboard/references/schema.md +357 -0
  355. package/skills/lark-whiteboard/references/style.md +318 -0
  356. package/skills/lark-whiteboard/references/typography.md +73 -0
  357. package/skills/lark-whiteboard/routes/dsl.md +107 -0
  358. package/skills/lark-whiteboard/routes/mermaid.md +27 -0
  359. package/skills/lark-whiteboard/routes/svg.md +54 -0
  360. package/skills/lark-whiteboard/scenes/architecture.md +433 -0
  361. package/skills/lark-whiteboard/scenes/bar-chart.md +187 -0
  362. package/skills/lark-whiteboard/scenes/comparison.md +135 -0
  363. package/skills/lark-whiteboard/scenes/fishbone.md +238 -0
  364. package/skills/lark-whiteboard/scenes/flowchart.md +198 -0
  365. package/skills/lark-whiteboard/scenes/flywheel.md +195 -0
  366. package/skills/lark-whiteboard/scenes/funnel.md +198 -0
  367. package/skills/lark-whiteboard/scenes/line-chart.md +214 -0
  368. package/skills/lark-whiteboard/scenes/mermaid.md +130 -0
  369. package/skills/lark-whiteboard/scenes/milestone.md +139 -0
  370. package/skills/lark-whiteboard/scenes/organization.md +173 -0
  371. package/skills/lark-whiteboard/scenes/photo-showcase.md +198 -0
  372. package/skills/lark-whiteboard/scenes/pyramid.md +99 -0
  373. package/skills/lark-whiteboard/scenes/swimlane.md +371 -0
  374. package/skills/lark-whiteboard/scenes/treemap.md +198 -0
  375. package/skills/lark-wiki/SKILL.md +119 -0
  376. package/skills/lark-wiki/references/lark-wiki-delete-space.md +205 -0
  377. package/skills/lark-wiki/references/lark-wiki-member-add.md +66 -0
  378. package/skills/lark-wiki/references/lark-wiki-member-list.md +76 -0
  379. package/skills/lark-wiki/references/lark-wiki-member-remove.md +61 -0
  380. package/skills/lark-wiki/references/lark-wiki-move.md +183 -0
  381. package/skills/lark-wiki/references/lark-wiki-node-copy.md +72 -0
  382. package/skills/lark-wiki/references/lark-wiki-node-create.md +127 -0
  383. package/skills/lark-wiki/references/lark-wiki-node-delete.md +62 -0
  384. package/skills/lark-wiki/references/lark-wiki-node-get.md +56 -0
  385. package/skills/lark-wiki/references/lark-wiki-node-list.md +198 -0
  386. package/skills/lark-wiki/references/lark-wiki-space-create.md +46 -0
  387. package/skills/lark-wiki/references/lark-wiki-space-list.md +198 -0
  388. package/skills/lark-workflow-meeting-summary/SKILL.md +104 -0
  389. package/skills/lark-workflow-standup-report/SKILL.md +120 -0
  390. package/skills/mmx-cli/SKILL.md +440 -0
  391. package/src/bot.ts +109 -0
  392. package/src/cards.ts +105 -0
  393. package/src/config.ts +33 -0
  394. package/src/daemon.ts +217 -0
  395. package/src/extension.ts +132 -0
  396. package/src/poller.ts +135 -0
  397. package/src/renderer.ts +47 -0
  398. package/src/session-registry.ts +90 -0
  399. package/src/types.ts +29 -0
  400. package/tests/bot.test.ts +104 -0
  401. package/tests/cards.test.ts +48 -0
  402. package/tests/config.test.ts +59 -0
  403. package/tests/renderer.test.ts +74 -0
  404. package/tests/session-registry.test.ts +94 -0
  405. package/tests/types.test.ts +35 -0
  406. package/tsconfig.json +16 -0
  407. package/vitest.config.ts +7 -0
@@ -0,0 +1,737 @@
1
+ # Base Formula Writing Guide
2
+
3
+ ## Mandatory Read Acknowledgement
4
+
5
+ When creating or updating a formula field with `lark-cli base +field-create/+field-update --json ...` and `type` is `formula`, you should read this guide first and only then add `--i-have-read-guide` to the command.
6
+
7
+ Do **not** proactively add `--i-have-read-guide` before reading this guide. Without it, the CLI will fail fast and direct you back to this guide.
8
+
9
+ When using `+field-update`, also pass `--yes`: field update is a high-risk `PUT` operation because changing a field definition can affect the whole column.
10
+
11
+ ## Default strategy
12
+
13
+ **All cross-table references, aggregations, and computed fields should use Formula fields by default.** Do NOT use Lookup fields unless the user explicitly requests it. Formula is a strict superset of Lookup — anything Lookup can do, Formula can do with a single expression.
14
+
15
+ ## Usage
16
+
17
+ When creating a formula field, the Agent should:
18
+
19
+ 1. Get all table names: `lark-cli base +table-list --base-token <base>` — returns `items[].table_name`
20
+ 2. Get table structure: `lark-cli base +table-get --base-token <base> --table-id <table>` — returns `fields[]`
21
+ 3. If the formula references other tables, also get those tables' structures
22
+ 4. Write the formula expression following this guide
23
+ 5. Construct the Formula field JSON and submit it to create or update the field
24
+
25
+ **Key constraints**:
26
+
27
+ - The JSON must include `"type": "formula"` — this field is required
28
+ - Table names and field names in the formula must **exactly match** those returned by `+table-list` / `+table-get`
29
+ - The `expression` value is a string containing the formula expression; double quotes inside the expression must be properly escaped in JSON (e.g. `\"text\"`)
30
+
31
+ ---
32
+
33
+ ## Section 1: Core Concepts — Scalar vs List
34
+
35
+ This is the foundation of formula logic. You must determine this before writing any formula.
36
+
37
+ | Syntax | Meaning | Return type | Example |
38
+ | --------------------- | -------------------------------------------- | ---------------------- | -------------------------------------------- |
39
+ | `[Field]` | Value of this field in the current row | Scalar (single value) | `[Name]` → `"Alice"` |
40
+ | `[TableName].[Field]` | All values of this field in the target table | List (multiple values) | `[Employees].[Name]` → `["Alice","Bob",...]` |
41
+ | `[TableName]` | The target table (entire table) | Table reference | Used as data range for FILTER/COUNTIF etc. |
42
+
43
+ **Rules**:
44
+
45
+ - Scalars can be used directly in operations: `[Price] * [Quantity]`
46
+ - Lists cannot be used as scalars — they must be processed first: use `SUM()` for sum, `ARRAYJOIN(",")` for joining, `FIRST()`/`LAST()`/`NTH()` for single value extraction
47
+ - Link field access `[LinkField].[TargetField]` returns a list (values of the target field for all linked records)
48
+ - **LISTCOMBINE flattening rule**: When a FILTER's result column is itself a multi-value field (`select` with `multiple=true`, `link`, etc.), it produces a 2D array and **must** be flattened with `.LISTCOMBINE()`; for single-value fields (`number`, `text`, etc.) it can be omitted, but adding it is never wrong:
49
+
50
+ ```
51
+ [Table].FILTER(CurrentValue.[Field] = [Value]).[Tags].LISTCOMBINE() ← required for multi-value columns
52
+ [Table].FILTER(CurrentValue.[Field] = [Value]).[NumberCol].LISTCOMBINE() ← optional for single-value columns
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Section 2: Data Types and Type Conversion
58
+
59
+ ### Field storage types
60
+
61
+ | Type | Description | Supported operations |
62
+ |------|-------------|----------------------|
63
+ | `number` | Stored as numeric value | Math operations, comparisons, auto-converts to string for concatenation |
64
+ | `text` | Stored as string | String operations; can participate in math if content is numeric, otherwise errors |
65
+ | `datetime` | Date object | Date functions, add/subtract with numbers; auto-converts to default format string when using `&` — use TEXT to format first for controlled output |
66
+ | `select` (`multiple=true`) | Data list | List functions, CONTAIN checks |
67
+ | `link` | Links to other table records | Chained access `[LinkField].[Field]`, result is a list |
68
+ | `checkbox` | TRUE/FALSE | Logical operations; auto-converts to number when compared with numbers |
69
+
70
+ ### Implicit type conversion
71
+
72
+ | Scenario | Conversion rule |
73
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------- |
74
+ | Number + Float | → Float |
75
+ | Date + Number | → Date (adds/subtracts days). Use `+`/`-` for whole days, use `DURATION()` for hour/minute/second precision |
76
+ | Date - Date | → Duration |
77
+ | Boolean compared with Number | Boolean auto-converts to number (TRUE=1, FALSE=0) |
78
+ | `&` concatenation | Both sides auto-convert to string |
79
+
80
+ ### Type consistency in comparisons
81
+
82
+ When using comparison operators (`>`, `>=`, `<`, `<=`, `=`, `!=`), **both sides should be the same type** to avoid semantic errors or unexpected results.
83
+
84
+ **Principle**: When types differ, explicitly convert one side rather than relying on implicit conversion:
85
+
86
+ - `number` vs `text` → use `VALUE()` to convert text to number
87
+ - `datetime` vs `text` → use `TEXT()` to convert date to text
88
+ - `datetime` vs `datetime` equality → dates include time components, so direct `=` comparison may fail due to different hours/minutes/seconds. For day-level equality, convert to text first: `TEXT([DateA], "YYYY/MM/DD") = TEXT([DateB], "YYYY/MM/DD")`
89
+ - `select` and `user` fields can be compared with both same-type values and text
90
+ - `text` fields in numeric aggregation (SUM/AVERAGE/MIN/MAX etc.) → convert to number with `VALUE()` first. For FILTER results, use `.MAP(VALUE(CurrentValue)).SUM()`
91
+
92
+ ---
93
+
94
+ ## Section 3: CurrentValue
95
+
96
+ **CurrentValue is the iteration variable in FILTER/MAP/COUNTIF/SUMIF functions, representing the "current item" being processed in the data range.**
97
+
98
+ ### CurrentValue meaning in different contexts
99
+
100
+ | Data range type | CurrentValue represents | Access pattern | Example |
101
+ | ---------------------------- | ----------------------- | --------------------------- | --------------------------------------------------------- |
102
+ | Entire table `[TableName]` | A row in the table | `CurrentValue.[FieldName]` | `[Orders].FILTER(CurrentValue.[Amount] > 100).[Customer]` |
103
+ | Column `[TableName].[Field]` | A single field value | Use `CurrentValue` directly | `[Orders].[Amount].FILTER(CurrentValue > 100)` |
104
+ | `select` (`multiple=true`) field `[Tags]` | One option | Use `CurrentValue` directly | `[Tags].FILTER(CurrentValue = "Important")` |
105
+ | LIST-generated list | One element | Use `CurrentValue` directly | `LIST(1,2,3).MAP(CurrentValue * 2)` |
106
+
107
+ ### Key rules
108
+
109
+ 1. **When data range is a table**, use `CurrentValue.[FieldName]` to access row fields
110
+ 2. **When data range is a column/list**, use `CurrentValue` directly for the element value — **cannot** use `CurrentValue.[FieldName]`
111
+ 3. CurrentValue can **only** appear inside the condition/mapping parameters of FILTER/MAP/COUNTIF/SUMIF functions
112
+ 4. To reference the current table's field value in a condition, write `[FieldName]` directly — it refers to the formula row's value, not a property of CurrentValue
113
+
114
+ ### Anti-patterns
115
+
116
+ | Wrong | Reason | Correct |
117
+ | ---------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------ |
118
+ | `[Table].[Col].FILTER(CurrentValue.[Col] > 0)` | Data range is a column; CurrentValue is a scalar, cannot use `.` to access fields | `[Table].[Col].FILTER(CurrentValue > 0)` |
119
+ | `[Table].FILTER(CurrentValue > 100)` | Data range is a table; CurrentValue is a row, cannot compare directly | `[Table].FILTER(CurrentValue.[Amount] > 100).[Amount]` |
120
+ | `CurrentValue + 1` (at top level) | CurrentValue can only be used inside iteration functions | Use inside MAP/FILTER etc. |
121
+
122
+ ---
123
+
124
+ ## Section 4: Operators
125
+
126
+ Base formulas **only allow** the following operators. `like`, `in`, `<>`, `**`, `^` etc. are prohibited.
127
+
128
+ | Category | Operators | Description |
129
+ | ------------- | -------------------------- | -------------------------------------------------------------------------- |
130
+ | Arithmetic | `+` `-` `*` `/` `%` | Add, subtract, multiply, divide, modulo (`%` is equivalent to `MOD()`) |
131
+ | Comparison | `>` `>=` `<` `<=` `=` `!=` | Greater than, greater or equal, less than, less or equal, equal, not equal |
132
+ | Logical | `&&` `\|\|` | AND, OR |
133
+ | Concatenation | `&` | Text concatenation; non-text values auto-convert to string |
134
+
135
+ **Important**:
136
+
137
+ - Equality uses `=` (single equals), not `==`
138
+ - Not-equal uses `!=`, not `<>`
139
+ - String concatenation uses `&`, not `+`
140
+ - Both `&&`/`||` and AND()/OR() functions are supported
141
+
142
+ ---
143
+
144
+ ## Section 5: Link Fields and Cross-Table References
145
+
146
+ ### Link field description
147
+
148
+ When a field type is described as `FieldName: Link [target table: X, foreign key: Y]`, it links to target table X using field Y as the join key.
149
+
150
+ ### Chained cross-table access
151
+
152
+ ```
153
+ [LinkField].[TargetField]
154
+ ```
155
+
156
+ Retrieves the target field values for all linked records as a list. Supports continued chaining: `[LinkA].[LinkB].[Field]`.
157
+
158
+ ### Equivalent expanded form
159
+
160
+ - Multi-value link: `[TargetTableX].FILTER([LinkField].CONTAIN(CurrentValue.[Y])).[TargetField].LISTCOMBINE()`
161
+ - Single-value link: `[TargetTableX].FILTER(CurrentValue.[Y] = [LinkField]).[TargetField].LISTCOMBINE()`
162
+
163
+ (`.LISTCOMBINE()` is required when `[TargetField]` is a multi-value field; optional for single-value fields)
164
+
165
+ ### Notes
166
+
167
+ - Link fields typically return **lists** (possibly empty)
168
+ - To output a single value, use aggregation (SUM/MAX), joining (ARRAYJOIN), or extraction (FIRST/LAST/NTH)
169
+ - Do not nest FILTER inside FILTER for cross-table queries — prefer link field chained access
170
+
171
+ ---
172
+
173
+ ## Section 6: Function Call Conventions
174
+
175
+ ### Two calling styles
176
+
177
+ | Style | Format | Description |
178
+ | ---------- | ------------------ | ----------------------------------- |
179
+ | Functional | `FUNC(arg1, arg2)` | Works for all functions |
180
+ | Chained | `arg1.FUNC(arg2)` | Moves the first argument before `.` |
181
+
182
+ **Rules**:
183
+
184
+ - Zero-argument functions cannot be chained: `NOW()`, `TODAY()`, `PI()`, `TRUE()`, `FALSE()`
185
+ - SORTBY can **only** be chained: `[Table].SORTBY([Table].[SortCol]).[OutputCol]`. The sort column always uses the original table's column name (`[TableName].[Field]` format); the engine aligns rows internally, even when the data range is a FILTER result
186
+ - FILTER is recommended to be chained: `[Table].FILTER(condition).[OutputCol]`
187
+
188
+ ### FILTER / SORTBY result column rules
189
+
190
+ - **When data range is a table** `[TableName]`, FILTER / SORTBY returns a table reference. The chain **must** end with `.[Field]` to specify the result column, otherwise the formula fails:
191
+
192
+ ```
193
+ Correct: [Sales].FILTER(CurrentValue.[Amount] > 100).[Customer]
194
+ Correct: [Sales].FILTER(condition).SORTBY([Sales].[SortCol]).[Customer] ← result column at end of chain
195
+ Wrong: [Sales].FILTER(CurrentValue.[Amount] > 100) ← missing result column
196
+ ```
197
+
198
+ - **When data range is a column** `[TableName].[Field]` or a list, FILTER returns the filtered list directly — **no** result column needed:
199
+
200
+ ```
201
+ Correct: [Sales].[Amount].FILTER(CurrentValue > 100)
202
+ ```
203
+
204
+ After the result column, it's recommended to flatten with `.LISTCOMBINE()` first (especially when the result column is a multi-value field), then chain aggregation functions:
205
+
206
+ ```
207
+ [Sales].FILTER(CurrentValue.[Amount] > 100).[Amount].LISTCOMBINE().SUM()
208
+ ```
209
+
210
+ ---
211
+
212
+ ## Section 7: Hard Constraints
213
+
214
+ 1. **Nesting prohibition**: FILTER / SUMIF / COUNTIF / MAP **must not be nested** inside each other's condition/mapping expressions. None of these functions can appear inside the condition or mapping parameter of another.
215
+ - Prohibited: `[Table1].FILTER(CurrentValue.[Col] = [Table2].FILTER(...).[Col])` ← FILTER inside FILTER condition
216
+ - Prohibited: `[Table].MAP([Table2].MAP(...))` ← MAP inside MAP mapping
217
+ - **Allowed**: `[Table].FILTER(cond1).[Col].FILTER(cond2)` ← chained call; the first FILTER's output is the second's data range, not nesting
218
+
219
+ 2. **Function whitelist**: Only use functions listed in Section 8. No unlisted functions.
220
+
221
+ 3. **Exact name matching**: Table names and field names in formulas must **exactly match** those returned by `+table-get` — no renaming or adding spaces.
222
+
223
+ 4. **Operator whitelist**: Only use operators listed in Section 4.
224
+
225
+ 5. **Strings use double quotes**: Strings must be wrapped in double quotes `"`, single quotes are not supported.
226
+
227
+ 6. **Do not use LOOKUP**: FILTER is a superset of LOOKUP. All LOOKUP formulas can be rewritten with FILTER. Use FILTER exclusively to reduce complexity.
228
+
229
+ ---
230
+
231
+ ## Section 8: Complete Function Reference
232
+
233
+ ### 8.1 Logic functions
234
+
235
+ | Function | Signature | Return type | Description |
236
+ | ------------- | ------------------------------------------------------------------ | -------------------- | -------------------------------------------------------------------------------------------- |
237
+ | IF | `IF(condition, true_val, [false_val])` | Matches branch type | Returns true_val when TRUE, false_val otherwise; omitting false_val returns false (not null) |
238
+ | IFS | `IFS(cond1, val1, cond2, val2, ...)` | Matches branch type | Multi-condition branching; returns value for the first TRUE condition |
239
+ | SWITCH | `SWITCH(expr, match1, result1, [match2, result2, ...], [default])` | Matches branch type | Matches expression value and returns corresponding result |
240
+ | IFERROR | `IFERROR(expr, fallback)` | Matches branch type | Returns fallback when expression errors |
241
+ | IFBLANK | `IFBLANK(expr, fallback)` | Matches branch type | Returns fallback when expression is blank (blank = NULL/empty string/empty list) |
242
+ | AND | `AND(cond1, cond2, ...)` | Boolean | TRUE when all conditions are TRUE |
243
+ | OR | `OR(cond1, cond2, ...)` | Boolean | TRUE when any condition is TRUE |
244
+ | NOT | `NOT(condition)` | Boolean | Logical negation |
245
+ | ISBLANK | `ISBLANK(value)` | Boolean | Tests if blank (NULL/empty string/empty list are blank; 0 and FALSE are not) |
246
+ | ISNULL | `ISNULL(value)` | Boolean | Tests if NULL (only NULL is true; empty string is not) |
247
+ | ISERROR | `ISERROR(expr)` | Boolean | Tests if expression errors |
248
+ | ISNUMBER | `ISNUMBER(value)` | Boolean | Tests if value is a number |
249
+ | CONTAIN | `CONTAIN(search_range, value, ...)` | Boolean | Tests if a list or `select` (`multiple=true`) contains the value; **does NOT do text substring matching** |
250
+ | CONTAINSALL | `CONTAINSALL(search_range, value, ...)` | Boolean | Tests if a list or `select` (`multiple=true`) contains all specified values |
251
+ | CONTAINSONLY | `CONTAINSONLY(search_range, value, ...)` | Boolean | Tests if a list or `select` (`multiple=true`) contains only the specified values |
252
+ | TRUE | `TRUE()` | Boolean | Returns TRUE |
253
+ | FALSE | `FALSE()` | Boolean | Returns FALSE |
254
+ | RECORD_ID | `RECORD_ID()` | Text | Returns the current row's record ID |
255
+ | RANDOMBETWEEN | `RANDOMBETWEEN(min_int, max_int, [keep_updating])` | Number | Random integer in the specified range |
256
+ | RANDOMITEM | `RANDOMITEM(list, [keep_updating])` | Matches element type | Randomly picks one element from a list |
257
+
258
+ ### 8.2 Numeric functions
259
+
260
+ | Function | Signature | Return type | Description |
261
+ | --- | --- | --- | --- |
262
+ | SUM | `SUM(val1, val2, ...)` | Number | Sum; accepts multiple values or a list |
263
+ | AVERAGE | `AVERAGE(val1, val2, ...)` | Number | Average |
264
+ | MAX | `MAX(val1, val2, ...)` | Number | Maximum |
265
+ | MIN | `MIN(val1, val2, ...)` | Number | Minimum |
266
+ | MEDIAN | `MEDIAN(val1, val2, ...)` | Number | Median |
267
+ | COUNTA | `COUNTA(val1, val2, ...)` | Number | Count of non-blank values |
268
+ | COUNTIF | `COUNTIF(data_range, condition)` | Number | Count matching items. Data range can be a **table** (CurrentValue is a row, use `CurrentValue.[Field]`) or a **column** (CurrentValue is a scalar value) |
269
+ | SUMIF | `SUMIF(data_range, condition)` | Number | Sum matching values. Data range **must be a numeric column** (e.g. `[Table].[NumField]`); CurrentValue is each value in that column (scalar), cannot use `CurrentValue.[Field]` to access other fields. For cross-field conditions, use FILTER+SUM instead |
270
+ | ROUND | `ROUND(number, digits)` | Number | Round. digits: 1=one decimal, 0=integer, -1=tens place |
271
+ | ROUNDUP | `ROUNDUP(number, digits)` | Number | Round away from zero. Same digits semantics as ROUND |
272
+ | ROUNDDOWN | `ROUNDDOWN(number, digits)` | Number | Round toward zero. Same digits semantics as ROUND |
273
+ | FLOOR | `FLOOR(number, [base])` | Number | Round down to nearest multiple of base (default 1) |
274
+ | CEILING | `CEILING(number, [base])` | Number | Round up to nearest multiple of base (default 1) |
275
+ | ABS | `ABS(number)` | Number | Absolute value |
276
+ | INT | `INT(number)` | Integer | Truncate to integer |
277
+ | MOD | `MOD(dividend, divisor)` | Number | Modulo |
278
+ | POWER | `POWER(base, exponent)` | Number | Exponentiation |
279
+ | QUOTIENT | `QUOTIENT(dividend, divisor)` | Number | Integer division |
280
+ | VALUE | `VALUE(text)` | Number | Convert text to number |
281
+ | ISODD | `ISODD(number)` | Boolean | Tests if number is odd |
282
+ | RANK | `RANK(value, search_range, [ascending])` | Number | Rank of value in range; default descending |
283
+ | SEQUENCE | `SEQUENCE(start, end, [step])` | List | Generate number sequence |
284
+ | PI | `PI()` | Number | Pi constant |
285
+ | SIN/COS/TAN/ASIN/ACOS/ATAN/ATAN2/SINH/COSH/TANH/ASINH/ACOSH/ATANH | `func(radians_or_value)` | Number | Trigonometric and hyperbolic functions; arguments in radians |
286
+
287
+ ### 8.3 Text functions
288
+
289
+ | Function | Signature | Return type | Description |
290
+ | --------------- | ---------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------- |
291
+ | CONCATENATE | `CONCATENATE(text1, text2, ...)` | Text | Concatenate multiple texts; supports lists as input |
292
+ | LEN | `LEN(text)` | Number | Character count |
293
+ | LEFT | `LEFT(text, [count])` | Text | Extract from left; default 1 |
294
+ | RIGHT | `RIGHT(text, [count])` | Text | Extract from right; default 1 |
295
+ | MID | `MID(text, start, count)` | Text | Extract from middle |
296
+ | FIND | `FIND(search_val, search_range, [start])` | Number | Find substring position (case-sensitive); returns -1 if not found |
297
+ | REPLACE | `REPLACE(text, start, count, new_text)` | Text | Replace by position |
298
+ | SUBSTITUTE | `SUBSTITUTE(text, old_text, new_text, [occurrence])` | Text | Replace by content; can specify which occurrence |
299
+ | UPPER | `UPPER(text)` | Text | Convert to uppercase |
300
+ | LOWER | `LOWER(text)` | Text | Convert to lowercase |
301
+ | TRIM | `TRIM(text)` | Text | Remove leading/trailing spaces |
302
+ | TEXT | `TEXT(value, format)` | Text | Format output. Date formats: `"YYYY-MM-DD"`, `"YYYY/MM/DD hh:mm:ss"`; number formats: `"00"`, `"000.00"` |
303
+ | CONTAINTEXT | `CONTAINTEXT(text, search_text)` | Boolean | Tests if text contains substring (text substring matching) |
304
+ | SPLIT | `SPLIT(text, delimiter)` | List | Split text by delimiter |
305
+ | TODATE | `TODATE(value)` | Date | Convert date string to date type |
306
+ | CHAR | `CHAR(number)` | Text | ASCII code to character |
307
+ | FORMAT | `FORMAT(template, [val1, val2, ...])` | Text | Template string formatting; use `{1}`, `{2}` as placeholders |
308
+ | HYPERLINK | `HYPERLINK(url, [display_text])` | Hyperlink | Create a hyperlink |
309
+ | ENCODEURL | `ENCODEURL(text)` | Text | URL encode |
310
+ | REGEXMATCH | `REGEXMATCH(text, regex)` | Boolean | Regex match test |
311
+ | REGEXEXTRACT | `REGEXEXTRACT(text, regex)` | List | Extract first match's capture groups |
312
+ | REGEXEXTRACTALL | `REGEXEXTRACTALL(text, regex)` | 2D List | Extract all matches |
313
+ | REGEXREPLACE | `REGEXREPLACE(text, regex, replacement)` | Text | Regex replace |
314
+
315
+ ### 8.4 Date functions
316
+
317
+ | Function | Signature | Return type | Description |
318
+ | ----------- | ----------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------- |
319
+ | NOW | `NOW()` | Date | Current date and time |
320
+ | TODAY | `TODAY()` | Date | Current date (midnight) |
321
+ | DATE | `DATE(year, month, day)` | Date | Construct a date |
322
+ | YEAR | `YEAR(date)` | Number | Extract year |
323
+ | MONTH | `MONTH(date)` | Number | Extract month |
324
+ | DAY | `DAY(date)` | Number | Extract day |
325
+ | HOUR | `HOUR(date)` | Number | Extract hour |
326
+ | MINUTE | `MINUTE(date)` | Number | Extract minute |
327
+ | SECOND | `SECOND(date)` | Number | Extract second |
328
+ | WEEKDAY | `WEEKDAY(date, [type])` | Number | Day of week |
329
+ | WEEKNUM | `WEEKNUM(date, [type])` | Number | Week number |
330
+ | DAYS | `DAYS(end_date, start_date)` | Number | Days between two dates (end - start), includes decimals. **Note parameter order: end date comes first** |
331
+ | DATEDIF | `DATEDIF(start_date, end_date, [unit])` | Number | Whole days/months/years between dates. Unit: `"D"`(default)/`"M"`/`"Y"`. **Start must be before end** |
332
+ | DURATION | `DURATION(days, [hours], [minutes], [seconds])` | Duration | Create a duration for date arithmetic |
333
+ | EDATE | `EDATE(date, months)` | Date | Date N months later |
334
+ | EOMONTH | `EOMONTH(date, [months])` | Date | End of month N months later; months default 0 |
335
+ | WORKDAY | `WORKDAY(start_date, days, [holidays])` | Date | Date N workdays later (skips weekends and holidays) |
336
+ | NETWORKDAYS | `NETWORKDAYS(start_date, end_date, [holidays])` | Number | Workdays between dates (inclusive) |
337
+
338
+ ### 8.5 List functions
339
+
340
+ | Function | Signature | Return type | Description |
341
+ | --- | --- | --- | --- |
342
+ | LIST | `LIST(val1, val2, ...)` | List | Create a list |
343
+ | FIRST | `FIRST(list)` | Scalar | First element |
344
+ | LAST | `LAST(list)` | Scalar | Last element |
345
+ | NTH | `NTH(list, index)` | Scalar | Nth element (1-based) |
346
+ | FILTER | `[Table].FILTER(condition).[ResultCol]` or `[Table].[Col].FILTER(condition)` | List | Filter by condition. When data range is a table, result column is **required**; when it's a column/list, it's not needed. Use CurrentValue in conditions. Add `.LISTCOMBINE()` when result column is multi-value |
347
+ | MAP | `data_range.MAP(mapping_expr)` | List | Apply mapping to each element. Use CurrentValue in mapping |
348
+ | SORT | `SORT(list, [ascending])` | List | Sort; default ascending (TRUE) |
349
+ | SORTBY | `[Table].SORTBY([Table].[SortCol], [ascending]).[OutputCol]` | List | Sort by column then extract output column. **Chain-only, must include output column** |
350
+ | UNIQUE | `UNIQUE(list)` | List | Deduplicate |
351
+ | ARRAYJOIN | `ARRAYJOIN(list, [delimiter])` | Text | Join list elements as text; default comma-separated |
352
+ | LISTCOMBINE | `LISTCOMBINE(val1, [val2, ...])` or `list.LISTCOMBINE()` | List | Two uses: (1) merge values/lists into one list; (2) chained call to flatten 2D array (commonly used when FILTER result column is a multi-value field) |
353
+ | DISTANCE | `DISTANCE(location1, location2)` | Number | Distance between two geographic locations (km) |
354
+
355
+ ---
356
+
357
+ ## Section 9: Commonly Confused Functions
358
+
359
+ ### CONTAIN vs CONTAINTEXT
360
+
361
+ | | CONTAIN | CONTAINTEXT |
362
+ | ----------- | -------------------------------------------------------------- | ---------------------------------------------------------- |
363
+ | Purpose | Tests if a **list / `select` (`multiple=true`)** contains a value | Tests if **text** contains a substring |
364
+ | Example | `[Tags].CONTAIN("Urgent")` | `[Notes].CONTAINTEXT("completed")` |
365
+ | Wrong usage | `CONTAIN([Notes], "completed")` — cannot do substring matching | `CONTAINTEXT([Tags], "Urgent")` — Tags is a list, not text |
366
+
367
+ ### ISBLANK vs ISNULL
368
+
369
+ | | ISBLANK | ISNULL |
370
+ | ----------------- | ------- | ------ |
371
+ | NULL | TRUE | TRUE |
372
+ | `""` empty string | TRUE | FALSE |
373
+ | Empty list `[]` | TRUE | FALSE |
374
+ | `0` | FALSE | FALSE |
375
+ | `FALSE` | FALSE | FALSE |
376
+
377
+ ### DAYS vs DATEDIF
378
+
379
+ | | DAYS | DATEDIF |
380
+ | --------------- | ------------------------------------------------------------ | ----------------------------------------- |
381
+ | Parameter order | `DAYS(end, start)` — end first | `DATEDIF(start, end, unit)` — start first |
382
+ | Precision | Includes decimals (hours/minutes/seconds as fractional days) | Integer only (whole days/months/years) |
383
+ | Negative values | Returns negative when start is after end | **Errors** when start is after end |
384
+
385
+ ### SUM vs SUMIF
386
+
387
+ | | SUM | SUMIF |
388
+ | --------- | ---------------------------------------------- | -------------------------------------------------------------- |
389
+ | Purpose | Sum all values | Sum values **matching a condition** |
390
+ | Arguments | `SUM(val1, val2, ...)` or `SUM([Table].[Col])` | `SUMIF(data_range, condition)` with CurrentValue in condition |
391
+ | Example | `SUM([Orders].[Amount])` — sum all | `SUMIF([Orders].[Amount], CurrentValue > 100)` — sum only >100 |
392
+
393
+ ### FILTER+aggregation vs COUNTIF/SUMIF
394
+
395
+ | | FILTER+aggregation | COUNTIF/SUMIF |
396
+ | ----------- | ----------------------------------------------------- | ------------------------------------------------------------------------------ |
397
+ | Nature | Filter then aggregate (two steps) | One-step (syntactic sugar) |
398
+ | Equivalence | `[Table].FILTER(cond).[Col].LISTCOMBINE().SUM()` | `SUMIF([Table].[Col], cond)` (only when condition involves only column values) |
399
+ | When to use | Conditions span multiple fields, or multi-step needed | Conditions only involve column values (e.g. `CurrentValue > 100`) |
400
+
401
+ ---
402
+
403
+ ## Section 10: Decision Trees
404
+
405
+ ### Cross-table queries: which approach?
406
+
407
+ ```
408
+ Need data from another table?
409
+ ├─ Current table has a link field to the target table?
410
+ │ ├─ Yes → Use chained access: [LinkField].[TargetField]
411
+ │ │ Need aggregation? → .SUM() / .ARRAYJOIN(",") / .FIRST()
412
+ │ └─ No → Need to match by field value?
413
+ │ ├─ Field matching or complex filtering → [TargetTable].FILTER(CurrentValue.[MatchField] = [Value]).[OutputCol]
414
+ │ └─ Only counting or summing → COUNTIF([TargetTable], condition) / FILTER+SUM
415
+ ```
416
+
417
+ ### Conditional logic: IF vs IFS vs SWITCH?
418
+
419
+ ```
420
+ Need conditional logic?
421
+ ├─ Single condition → IF(condition, true_val, false_val)
422
+ ├─ Multiple mutually exclusive conditions (if-elseif-else) → IFS(cond1, val1, cond2, val2, ...)
423
+ ├─ Matching a value against fixed options → SWITCH(expr, option1, result1, option2, result2, ..., default)
424
+ └─ Need error handling?
425
+ ├─ Catch errors → IFERROR(expr, fallback)
426
+ └─ Catch blanks → IFBLANK(expr, fallback)
427
+ ```
428
+
429
+ ### Aggregation: which function?
430
+
431
+ ```
432
+ Need to aggregate data?
433
+ ├─ Sum/average/max/min for entire column → SUM/AVERAGE/MAX/MIN([Table].[Col])
434
+ ├─ Count non-blank → COUNTA([Table].[Col])
435
+ ├─ Conditional count → COUNTIF([Table], CurrentValue.[Field] = [Value])
436
+ ├─ Conditional sum (column-only condition) → SUMIF([Table].[Col], CurrentValue > threshold)
437
+ ├─ Conditional sum (cross-field condition) → [Table].FILTER(CurrentValue.[Field]=value).[NumCol].LISTCOMBINE().SUM()
438
+ ├─ Count unique → [Table].[Col].UNIQUE().COUNTA()
439
+ └─ Ranking → RANK([Value], [Table].[Col])
440
+ ```
441
+
442
+ ---
443
+
444
+ ## Section 11: Common Formula Patterns
445
+
446
+ ### Pattern 1: Cross-table conditional count
447
+
448
+ Count rows in target table matching a condition:
449
+
450
+ ```
451
+ [TargetTable].COUNTIF(CurrentValue.[MatchField] = [CurrentTableField])
452
+ ```
453
+
454
+ ### Pattern 2: Cross-table conditional sum
455
+
456
+ Filter target table by current row's value, then sum:
457
+
458
+ ```
459
+ [TargetTable].FILTER(CurrentValue.[MatchField] = [CurrentTableField]).[NumCol].LISTCOMBINE().SUM()
460
+ ```
461
+
462
+ SUMIF works when data range is a column and conditions only involve column values:
463
+
464
+ ```
465
+ SUMIF([TargetTable].[NumCol], CurrentValue > 100)
466
+ ```
467
+
468
+ Note: COUNTIF can use a table as data range (only counting, no specific column needed), but SUMIF's data range **must be a numeric column** (needs values to sum), so `CurrentValue` is each value in that column (scalar) — cannot use `CurrentValue.[OtherField]` to access other fields. For cross-field conditions, use FILTER with a table as data range.
469
+
470
+ ### Pattern 3: Cross-table lookup
471
+
472
+ ```
473
+ [TargetTable].FILTER(CurrentValue.[MatchCol] = [CurrentTableField]).[ReturnCol]
474
+ ```
475
+
476
+ ### Pattern 4: Link field values + aggregation
477
+
478
+ ```
479
+ SUM([LinkField].[NumField])
480
+ [LinkField].[TextField].UNIQUE().ARRAYJOIN(",")
481
+ ```
482
+
483
+ ### Pattern 5: Conditional text concatenation
484
+
485
+ ```
486
+ IF([Condition], "prefix" & [Field] & "suffix", "default text")
487
+ ```
488
+
489
+ ### Pattern 6: Date difference
490
+
491
+ ```
492
+ DATEDIF([StartDate], [EndDate], "D") & " days"
493
+ DAYS([EndDate], [StartDate])
494
+ ```
495
+
496
+ ### Pattern 7: List element mapping
497
+
498
+ ```
499
+ [SelectField(which multiple=true)].MAP(CurrentValue & " tag")
500
+ SPLIT([TextField], ",").MAP(TRIM(CurrentValue))
501
+ ```
502
+
503
+ ### Pattern 8: Cross-table with sorting
504
+
505
+ ```
506
+ [TargetTable].SORTBY([TargetTable].[SortCol], FALSE).[OutputCol]
507
+ [TargetTable].FILTER(CurrentValue.[Field] = [Value]).SORTBY([TargetTable].[SortCol]).[OutputCol]
508
+ ```
509
+
510
+ ---
511
+
512
+ ## Section 12: Anti-Pattern Collection
513
+
514
+ ### Mistake 1: Extra argument in MAP
515
+
516
+ ```
517
+ Wrong: [Table].[Col].MAP([Table2].[Col], CurrentValue + 1)
518
+ Correct: [Table].[Col].MAP(CurrentValue + 1)
519
+ ```
520
+
521
+ Reason: MAP takes only two arguments (data range + mapping expression), no "lookup range".
522
+
523
+ ### Mistake 2: Inverted FILTER syntax
524
+
525
+ ```
526
+ Wrong: condition.[Table].FILTER()
527
+ Correct: [Table].FILTER(condition).[ResultCol] (result column required when data range is a table)
528
+ ```
529
+
530
+ Reason: FILTER's data range comes first, condition is passed as the argument.
531
+
532
+ ### Mistake 3: Using CurrentValue.[Field] on a column range
533
+
534
+ ```
535
+ Wrong: SUMIF([Sales].[Revenue], CurrentValue.[Salesperson] = [Name])
536
+ Correct: [Sales].FILTER(CurrentValue.[Salesperson] = [Name]).[Revenue].LISTCOMBINE().SUM()
537
+ ```
538
+
539
+ Reason: `SUMIF([Sales].[Revenue], ...)` uses "Revenue" column as data range. CurrentValue is each revenue value (scalar), not a row — cannot use `.` to access other fields. Use FILTER with the table as data range for cross-field conditions.
540
+
541
+ ### Mistake 4: Missing result column after FILTER
542
+
543
+ ```
544
+ Wrong: [Sales].FILTER(CurrentValue.[Amount] > 100)
545
+ Correct: [Sales].FILTER(CurrentValue.[Amount] > 100).[Customer]
546
+ ```
547
+
548
+ Reason: FILTER on a table returns a table reference; must specify result column with `.[Field]` at the end.
549
+
550
+ ### Mistake 5: Nested FILTER
551
+
552
+ ```
553
+ Wrong: [Table1].FILTER(CurrentValue.[ID] = [Table2].FILTER(CurrentValue.[Status]="Done").[ID])
554
+ Correct: [Table1].FILTER(CurrentValue.[ID] = [CurrentRowField]).[OutputCol]
555
+ ```
556
+
557
+ Reason: FILTER/MAP/SUMIF/COUNTIF cannot be nested inside each other's conditions. Split into multiple steps or use link fields.
558
+
559
+ ### Mistake 6: SORTBY without output column
560
+
561
+ ```
562
+ Wrong: [Table].SORTBY([Table].[Col])
563
+ Correct: [Table].SORTBY([Table].[Col]).[OutputCol]
564
+ ```
565
+
566
+ Reason: SORTBY must have an output column at the end; otherwise the result cannot be represented as an array.
567
+
568
+ ### Mistake 7: SORTBY sort column without table name
569
+
570
+ ```
571
+ Wrong: [Table].SORTBY([Col]).[OutputCol]
572
+ Correct: [Table].SORTBY([Table].[Col]).[OutputCol]
573
+ ```
574
+
575
+ Reason: SORTBY's sort column must use `[TableName].[FieldName]` format.
576
+
577
+ ### Mistake 8: Using CONTAIN for text substring matching
578
+
579
+ ```
580
+ Wrong: CONTAIN([Notes], "urgent")
581
+ Correct: CONTAINTEXT([Notes], "urgent")
582
+ ```
583
+
584
+ Reason: CONTAIN checks if a list or `select` (`multiple=true`) contains a whole value, not substring matching. Use CONTAINTEXT for text substrings.
585
+
586
+ ### Mistake 9: Date concatenation without formatting
587
+
588
+ ```
589
+ Not recommended: "Deadline: " & [DateField] ← output format is uncontrolled
590
+ Recommended: "Deadline: " & TEXT([DateField], "YYYY-MM-DD")
591
+ ```
592
+
593
+ Reason: Concatenating a date with `&` won't error, but uses the default format. Use TEXT to specify the format explicitly.
594
+
595
+ ### Mistake 10: Reversed DAYS parameter order
596
+
597
+ ```
598
+ Wrong: DAYS([StartDate], [EndDate]) → returns negative
599
+ Correct: DAYS([EndDate], [StartDate]) → returns positive
600
+ ```
601
+
602
+ Reason: DAYS parameter order is end date first, start date second.
603
+
604
+ ### Mistake 11: Chaining zero-argument functions
605
+
606
+ ```
607
+ Wrong: TODAY.DAYS([Date])
608
+ Correct: TODAY().DAYS([Date])
609
+ ```
610
+
611
+ Reason: NOW, TODAY, PI and other zero-argument functions must include parentheses.
612
+
613
+ ---
614
+
615
+ ## Section 13: Complete Examples
616
+
617
+ ### Example 1: Employee sales summary
618
+
619
+ **Table structure** (from `+table-get`):
620
+
621
+ - Employees: EmployeeID (Text), Name (Text), Department (Text)
622
+ - Sales: ContractID (Number), SalespersonID (Text), Quantity (Number), Total (Number)
623
+
624
+ **Current table**: Employees
625
+
626
+ **Requirement**: For each employee, output "Sold XX orders" if they have sales records, otherwise "No sales records".
627
+
628
+ **Formula**:
629
+
630
+ ```
631
+ IF(
632
+ [Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) >= 1,
633
+ "Sold " & [Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) & " orders",
634
+ "No sales records"
635
+ )
636
+ ```
637
+
638
+ **Field JSON**:
639
+
640
+ ```json
641
+ {
642
+ "type": "formula",
643
+ "name": "Sales Summary",
644
+ "expression": "IF([Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) >= 1, \"Sold \" & [Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) & \" orders\", \"No sales records\")"
645
+ }
646
+ ```
647
+
648
+ **Explanation**: `[Sales].COUNTIF(...)` uses the entire Sales table as data range. CurrentValue represents each row in Sales, accessing `CurrentValue.[SalespersonID]` for that row's salesperson. `[EmployeeID]` refers to the current row in the Employees table (where the formula lives).
649
+
650
+ ### Example 2: Chained cross-table access via link fields
651
+
652
+ **Table structure**:
653
+
654
+ - Orders: ID (`auto_number`), OrderItems (`link` [target: OrderItems, foreign key: ID])
655
+ - OrderItems: ID (`auto_number`), Product (`link` [target: Products, foreign key: ID])
656
+ - Products: ID (`auto_number`), ProductName (`text`)
657
+
658
+ **Current table**: Orders
659
+
660
+ **Requirement**: Deduplicate and comma-join all product names from linked order items.
661
+
662
+ **Formula**:
663
+
664
+ ```
665
+ [OrderItems].[Product].[ProductName].UNIQUE().ARRAYJOIN(",")
666
+ ```
667
+
668
+ **Field JSON**:
669
+
670
+ ```json
671
+ {
672
+ "type": "formula",
673
+ "name": "Product List",
674
+ "expression": "[OrderItems].[Product].[ProductName].UNIQUE().ARRAYJOIN(\",\")"
675
+ }
676
+ ```
677
+
678
+ **Explanation**: `[OrderItems]` gets linked order item records, `.[Product]` expands to each item's linked product, `.[ProductName]` gets all product names, `.UNIQUE()` deduplicates, `.ARRAYJOIN(",")` joins with commas.
679
+
680
+ ### Example 3: Cross-table filter + sort
681
+
682
+ **Table structure**:
683
+
684
+ - Projects: ProjectName (Text), Status (Text), Owner (Text)
685
+ - Tasks: TaskName (Text), Project (Text), Priority (Number), DueDate (Date)
686
+
687
+ **Current table**: Projects
688
+
689
+ **Requirement**: Find the highest-priority (lowest number) task name for the current project.
690
+
691
+ **Formula**:
692
+
693
+ ```
694
+ FIRST(
695
+ [Tasks].FILTER(CurrentValue.[Project] = [ProjectName]).SORTBY([Tasks].[Priority], TRUE).[TaskName]
696
+ )
697
+ ```
698
+
699
+ **Field JSON**:
700
+
701
+ ```json
702
+ {
703
+ "type": "formula",
704
+ "name": "Top Priority Task",
705
+ "expression": "FIRST([Tasks].FILTER(CurrentValue.[Project] = [ProjectName]).SORTBY([Tasks].[Priority], TRUE).[TaskName])"
706
+ }
707
+ ```
708
+
709
+ **Explanation**: `[Tasks].FILTER(CurrentValue.[Project] = [ProjectName])` filters tasks belonging to the current project. `.SORTBY([Tasks].[Priority], TRUE)` sorts by priority ascending. `.[TaskName]` extracts task names. `FIRST(...)` gets the first one (highest priority).
710
+
711
+ ---
712
+
713
+ ## Section 14: Translating User Requirements to Formulas
714
+
715
+ When the user describes their formula need in natural language, follow these rules to convert it into a precise expression:
716
+
717
+ 1. **Numbers must use precise values**: "less than 80%" → field value less than `0.8`. "above 1000" → `>= 1000`.
718
+ 2. **Interval boundaries**: "above/below/within" = closed (inclusive); "less than/more than/outside" = open (exclusive).
719
+ 3. **Branching logic** must be organized as an ordered list with a fallback branch. Each branch has a condition and output.
720
+ - Example: "return risk level for 1-3" → `IFS([Value] = 1, "low", [Value] = 2, "medium", [Value] = 3, "high")` with an `IFERROR` or trailing empty-string fallback.
721
+ 4. **Multi-level branches must be flattened** to a single level. Nested if-else chains → flat IFS.
722
+ 5. **Branch conditions must be mutually exclusive**. If the user's conditions overlap, rewrite to eliminate ambiguity.
723
+ 6. **Reorder branches by logical priority** if the user's order is illogical (e.g., check specific conditions before catch-all).
724
+
725
+ ---
726
+
727
+ ## Section 15: Constraint Summary
728
+
729
+ - Request body must include `"type": "formula"` — this field is required
730
+ - Only use functions and operators listed in this document
731
+ - FILTER/SUMIF/COUNTIF/MAP must not be nested inside each other's conditions (chained calls are not nesting)
732
+ - Do not use LOOKUP — use FILTER exclusively
733
+ - Table and field names must exactly match `+table-get` output
734
+ - Strings must use double quotes `"`
735
+ - Format dates with TEXT before concatenating, to control output format
736
+ - SORTBY can only be chained and must include an output column
737
+ - Link fields return lists — aggregate or extract single values before output