weaver-work-cli 0.1.40 → 0.1.44

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 (401) hide show
  1. package/README.md +17 -0
  2. package/dist/chunks/{archive-JHTONRST.js → archive-P6TBQGKL.js} +13 -5
  3. package/dist/chunks/{archive-oa-FCHLCPHC.js → archive-oa-7TQ2NXOH.js} +12 -5
  4. package/dist/chunks/{asset-RLIHC7DB.js → asset-3ELRG37G.js} +11 -4
  5. package/dist/chunks/{asset-idle-KVOFTLCP.js → asset-idle-WIGMUFMD.js} +7 -3
  6. package/dist/chunks/{attachment-content-RZYDB3MB.js → attachment-content-E3276UOV.js} +5 -4
  7. package/dist/chunks/{blog-42OZTJNP.js → blog-C5NMZAAC.js} +11 -4
  8. package/dist/chunks/{caizhilian-KRK547K5.js → caizhilian-5XSM2DFP.js} +13 -6
  9. package/dist/chunks/{calendar-RTWAMKHD.js → calendar-FI2WNSBO.js} +71 -26
  10. package/dist/chunks/{chunk-CXRQWOZ5.js → chunk-3YBDYOC4.js} +3 -3
  11. package/dist/chunks/{chunk-OOUTBLZ4.js → chunk-56EZERK4.js} +1 -1
  12. package/dist/chunks/chunk-6N4JPNFL.js +76 -0
  13. package/dist/chunks/{chunk-ZUX3P6BQ.js → chunk-727FH2NI.js} +1 -1
  14. package/dist/chunks/chunk-7BDPM5ST.js +11 -0
  15. package/dist/chunks/{chunk-LN447PY2.js → chunk-BCVYBYYT.js} +432 -2247
  16. package/dist/chunks/{chunk-7E6MUOEK.js → chunk-CWYGFU5B.js} +2 -2
  17. package/dist/chunks/{chunk-NOODWMCL.js → chunk-D4ADSZ7H.js} +1 -1
  18. package/dist/chunks/{chunk-WFFNM65B.js → chunk-ETNJSKMM.js} +281 -29
  19. package/dist/chunks/{chunk-CAQNBBQA.js → chunk-F4E4EM35.js} +3 -3
  20. package/dist/chunks/{chunk-4CTESSKI.js → chunk-FAZTGX7S.js} +6 -6
  21. package/dist/chunks/chunk-FRZKBMSW.js +2562 -0
  22. package/dist/chunks/{chunk-BYBSCN4X.js → chunk-G7PQWD4L.js} +6 -3
  23. package/dist/chunks/{chunk-NJKREDA3.js → chunk-GAMZLAG2.js} +1 -1
  24. package/dist/chunks/{chunk-FLS4DPGP.js → chunk-GM6J7Q4B.js} +28 -15
  25. package/dist/chunks/{chunk-NETCCARD.js → chunk-GRDRG6HP.js} +3 -3
  26. package/dist/chunks/chunk-HIT4Y6OI.js +1238 -0
  27. package/dist/chunks/{chunk-EZALDOQH.js → chunk-HP7JIYMT.js} +5 -2
  28. package/dist/chunks/{chunk-IZSSVYAG.js → chunk-IAZ3UPY6.js} +3 -3
  29. package/dist/chunks/{chunk-ZEDWSH32.js → chunk-IC62NFM5.js} +1 -1
  30. package/dist/chunks/{chunk-P26ZWSKU.js → chunk-KIHNAS25.js} +5 -2
  31. package/dist/chunks/{chunk-57IECMWX.js → chunk-N4M2DDFE.js} +29 -15
  32. package/dist/chunks/{chunk-JWRZM2H2.js → chunk-OF4S23UB.js} +4 -4
  33. package/dist/chunks/{chunk-VNBU55SL.js → chunk-PC7VKEB5.js} +80 -2458
  34. package/dist/chunks/{chunk-G2JSIUWF.js → chunk-PUQS5MWL.js} +91 -2
  35. package/dist/chunks/{chunk-E7OK5WD5.js → chunk-Q4OYAQYH.js} +5 -5
  36. package/dist/chunks/{chunk-7BRU4EFH.js → chunk-QVSWRLLU.js} +35 -6
  37. package/dist/chunks/{chunk-T6EGVBKU.js → chunk-TA7FXXJD.js} +6 -3
  38. package/dist/chunks/{chunk-GPMFD4RD.js → chunk-TXUG266F.js} +1 -1
  39. package/dist/chunks/{chunk-4TEDNCON.js → chunk-UFIT2UU3.js} +354 -56
  40. package/dist/chunks/{chunk-LUSPKZKY.js → chunk-UG5G54VL.js} +1 -0
  41. package/dist/chunks/{chunk-NIAJ5ZCG.js → chunk-UL5XUQ25.js} +5 -2
  42. package/dist/chunks/{chunk-FMPJJYYI.js → chunk-WRXSAVKO.js} +1 -1
  43. package/dist/chunks/{chunk-7U577Q7U.js → chunk-WSF4NNMR.js} +3 -3
  44. package/dist/chunks/chunk-XHK4MDR5.js +2497 -0
  45. package/dist/chunks/{chunk-LFMSDBZN.js → chunk-XNIK66I4.js} +326 -161
  46. package/dist/chunks/{chunk-3SO6QL6U.js → chunk-YWX377BY.js} +5 -2
  47. package/dist/chunks/{chunk-BYATLLEF.js → chunk-Z3GDFVJR.js} +1 -1
  48. package/dist/chunks/{chunk-I566ZYNF.js → chunk-Z7VYWPZV.js} +1 -1
  49. package/dist/chunks/{conflict-VR55AOOO.js → conflict-ARLSZJ6V.js} +4 -3
  50. package/dist/chunks/{continuation-2CKSBLA6.js → continuation-3S37AUSH.js} +4 -3
  51. package/dist/chunks/{continuation-RN6PZN2M.js → continuation-3XLYYTKV.js} +4 -3
  52. package/dist/chunks/{continuation-HZIZRZBX.js → continuation-HFW2YT5S.js} +4 -3
  53. package/dist/chunks/{continuation-NLECEJPX.js → continuation-KI7DRRZN.js} +4 -3
  54. package/dist/chunks/{contract-HI4FNPYE.js → contract-DNIIW5VJ.js} +13 -5
  55. package/dist/chunks/{cowork-HJLI353D.js → cowork-GMLRGVIW.js} +31 -14
  56. package/dist/chunks/create-flow-J22BO65E.js +56 -0
  57. package/dist/chunks/{ebuilder-form-HTGI63UU.js → ebuilder-form-ANV2FHYV.js} +12 -7
  58. package/dist/chunks/{ehr-GYXIYH3A.js → ehr-GSTGAIY3.js} +695 -1255
  59. package/dist/chunks/{employee-SAK2QYXX.js → employee-22BGJ3QS.js} +3 -3
  60. package/dist/chunks/{env-DW3G4HUO.js → env-BX3VRFS7.js} +4 -3
  61. package/dist/chunks/{esb-I5INCEFE.js → esb-ATAIASX2.js} +12 -7
  62. package/dist/chunks/{factory-TKXGXS6L.js → factory-PETTFME6.js} +3 -2
  63. package/dist/chunks/{fna-K2MHTQ24.js → fna-YEKBSFSX.js} +14 -8
  64. package/dist/chunks/{group-chat-VYBNMJLG.js → group-chat-BFVXAYFX.js} +7 -4
  65. package/dist/chunks/{host-D5SERMAJ.js → host-HRBXEPDQ.js} +5 -5
  66. package/dist/chunks/{host-JM4YVHFM.js → host-LR55CTHP.js} +5 -5
  67. package/dist/chunks/{host-L3VLITMT.js → host-SUOY6VYQ.js} +5 -5
  68. package/dist/chunks/{host-ZUQTJYYK.js → host-SZGV4UNT.js} +5 -5
  69. package/dist/chunks/{host-256GVCAH.js → host-WIKN2EJ5.js} +5 -5
  70. package/dist/chunks/{hrm-VLRBKTZB.js → hrm-NRDO4W5G.js} +11 -7
  71. package/dist/chunks/{im-QK3VTLXK.js → im-IQ2HN23S.js} +11 -10
  72. package/dist/chunks/{invoice-T5JTA32H.js → invoice-MNRW76PP.js} +636 -1768
  73. package/dist/chunks/{jiuchuanhui-P2FNEQVZ.js → jiuchuanhui-DTRBAX4N.js} +14 -6
  74. package/dist/chunks/{lazy-dispatch-XRRI46M6.js → lazy-dispatch-ZVWAI25B.js} +7 -6
  75. package/dist/chunks/{mail-3Y7MJ6PS.js → mail-ZVAUXOJA.js} +16 -14
  76. package/dist/chunks/{meeting-M7LTXGJE.js → meeting-FEVPZ67S.js} +21 -13
  77. package/dist/chunks/{okr-OBC6S67L.js → okr-SDH3E5RA.js} +12 -5
  78. package/dist/chunks/{operations-5QL3AECO.js → operations-62N6EP3C.js} +4 -3
  79. package/dist/chunks/{plan-5H6I53SK.js → plan-E35JFDI7.js} +12 -5
  80. package/dist/chunks/{project-L75QZV4S.js → project-73QXBAB2.js} +49 -25
  81. package/dist/chunks/reception-UWZVACBN.js +1899 -0
  82. package/dist/chunks/recruit-stage-4MAOCKFY.js +4770 -0
  83. package/dist/chunks/registry-IM5G23LS.js +24 -0
  84. package/dist/chunks/{registry-UGRBCBHO.js → registry-JDUS4E7D.js} +7 -6
  85. package/dist/chunks/{registry-RXPN6BBT.js → registry-KNKSCJNT.js} +7 -6
  86. package/dist/chunks/{registry-NYPYMZXG.js → registry-PO7SI256.js} +4 -4
  87. package/dist/chunks/{registry-QGHFNUWS.js → registry-PVUZQDDQ.js} +3 -3
  88. package/dist/chunks/{room-recommend-A3UDC3CA.js → room-recommend-H7KLXA5R.js} +6 -5
  89. package/dist/chunks/{schedule-5GCACCK7.js → schedule-ESZIBAUO.js} +6 -5
  90. package/dist/chunks/{workflow-M5ZJ7DWF.js → workflow-CWJFJLQU.js} +15 -10
  91. package/dist/cmd/action.js +6 -0
  92. package/dist/cmd/identity/index.js +45 -0
  93. package/dist/cmd/index.js +2 -0
  94. package/dist/core/continuation-ttl.js +18 -0
  95. package/dist/core/error-codes.js +85 -0
  96. package/dist/core/logger.js +11 -0
  97. package/dist/index.js +41 -30
  98. package/dist/internal/e10/auth/commands.js +164 -8
  99. package/dist/internal/e10/auth/error-log.js +182 -0
  100. package/dist/internal/e10/auth/messages.js +6 -0
  101. package/dist/internal/e10/auth/session.js +34 -3
  102. package/dist/internal/e10/auth/xiaoe.js +286 -44
  103. package/dist/internal/e10/auth-recovery.js +72 -14
  104. package/dist/internal/e10/context.js +72 -13
  105. package/dist/internal/e10/index.js +1 -1
  106. package/dist/internal/e10/network-error.js +93 -0
  107. package/dist/internal/e10/request-runtime.js +6 -0
  108. package/dist/internal/skills/install.js +9 -1
  109. package/dist/shortcuts/archive/continuation.js +2 -1
  110. package/dist/shortcuts/archive/index.js +3 -0
  111. package/dist/shortcuts/archive/operations/confirm.js +2 -1
  112. package/dist/shortcuts/archive-oa/continuation.js +2 -1
  113. package/dist/shortcuts/archive-oa/index.js +2 -0
  114. package/dist/shortcuts/archive-oa/operations/confirm.js +2 -1
  115. package/dist/shortcuts/asset/continuation.js +2 -1
  116. package/dist/shortcuts/asset/index.js +2 -0
  117. package/dist/shortcuts/asset-idle/index.js +2 -0
  118. package/dist/shortcuts/blog/continuation.js +2 -1
  119. package/dist/shortcuts/blog/index.js +2 -0
  120. package/dist/shortcuts/caizhilian/continuation.js +2 -1
  121. package/dist/shortcuts/caizhilian/index.js +2 -0
  122. package/dist/shortcuts/caizhilian/operations/confirm.js +3 -2
  123. package/dist/shortcuts/calendar/continuation.js +2 -1
  124. package/dist/shortcuts/calendar/index.js +2 -0
  125. package/dist/shortcuts/calendar/operations/read.js +31 -22
  126. package/dist/shortcuts/calendar/operations/write.js +46 -2
  127. package/dist/shortcuts/contract/continuation.js +2 -1
  128. package/dist/shortcuts/contract/index.js +2 -0
  129. package/dist/shortcuts/contract/operations/write.js +2 -1
  130. package/dist/shortcuts/cowork/continuation.js +2 -1
  131. package/dist/shortcuts/cowork/index.js +2 -0
  132. package/dist/shortcuts/cowork/operations/discuss-write.js +5 -1
  133. package/dist/shortcuts/cowork/operations/item-write.js +1 -7
  134. package/dist/shortcuts/cowork/operations/member-write.js +3 -1
  135. package/dist/shortcuts/cowork/operations/permission-write.js +5 -1
  136. package/dist/shortcuts/cowork/operations/shared.js +7 -0
  137. package/dist/shortcuts/ebuilder-form/continuation.js +2 -1
  138. package/dist/shortcuts/ebuilder-form/index.js +2 -0
  139. package/dist/shortcuts/ebuilder-form/operations/write.js +3 -2
  140. package/dist/shortcuts/ehr/continuation.js +2 -1
  141. package/dist/shortcuts/ehr/index.js +2 -0
  142. package/dist/shortcuts/ehr/operations/attend-write.js +44 -2
  143. package/dist/shortcuts/ehr/operations/hr-contact.js +7 -4
  144. package/dist/shortcuts/ehr/operations/hr-report.js +13 -7
  145. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +317 -63
  146. package/dist/shortcuts/ehr/operations/recruit-position.js +134 -2
  147. package/dist/shortcuts/ehr/operations/recruit-write.js +263 -18
  148. package/dist/shortcuts/ehr/operations/recruit.js +10 -4
  149. package/dist/shortcuts/ehr/operations/shared.js +47 -0
  150. package/dist/shortcuts/esb/continuation.js +2 -1
  151. package/dist/shortcuts/esb/index.js +2 -0
  152. package/dist/shortcuts/esb/operations/trigger.js +2 -1
  153. package/dist/shortcuts/fna/continuation.js +2 -1
  154. package/dist/shortcuts/fna/index.js +2 -0
  155. package/dist/shortcuts/fna/operations/invoice-writeoff.js +1 -1
  156. package/dist/shortcuts/fna/operations/loan.js +1 -1
  157. package/dist/shortcuts/hrm/index.js +2 -0
  158. package/dist/shortcuts/hrm/operations/org.js +118 -0
  159. package/dist/shortcuts/im/continuation.js +2 -1
  160. package/dist/shortcuts/index.js +10 -0
  161. package/dist/shortcuts/invoice/continuation.js +2 -1
  162. package/dist/shortcuts/invoice/index.js +14 -15
  163. package/dist/shortcuts/invoice/invoice-record.js +93 -0
  164. package/dist/shortcuts/invoice/manifest.js +190 -393
  165. package/dist/shortcuts/invoice/operations/add.js +2 -1
  166. package/dist/shortcuts/invoice/operations/delete.js +2 -1
  167. package/dist/shortcuts/invoice/operations/import.js +2 -1
  168. package/dist/shortcuts/invoice/operations/issuing-contract-detail.js +86 -0
  169. package/dist/shortcuts/invoice/operations/issuing-contracts.js +210 -0
  170. package/dist/shortcuts/invoice/operations/registry.js +17 -17
  171. package/dist/shortcuts/invoice/operations/reim-auto.js +4 -569
  172. package/dist/shortcuts/invoice/operations/reim.js +52 -341
  173. package/dist/shortcuts/invoice/operations/shared.js +21 -4
  174. package/dist/shortcuts/invoice/operations/update.js +2 -1
  175. package/dist/shortcuts/invoice/projection.js +10 -62
  176. package/dist/shortcuts/jiuchuanhui/continuation.js +2 -1
  177. package/dist/shortcuts/jiuchuanhui/index.js +2 -0
  178. package/dist/shortcuts/jiuchuanhui/operations/datajson.js +2 -1
  179. package/dist/shortcuts/jiuchuanhui/operations/esb.js +2 -1
  180. package/dist/shortcuts/mail/continuation.js +2 -1
  181. package/dist/shortcuts/mail/index.js +2 -0
  182. package/dist/shortcuts/mail/operations/mail-blacklist.js +1 -1
  183. package/dist/shortcuts/mail/operations/mail-contacts.js +1 -1
  184. package/dist/shortcuts/mail/operations/mail-send.js +1 -1
  185. package/dist/shortcuts/mail/operations/mail-sign.js +1 -1
  186. package/dist/shortcuts/mail/operations/mail-template.js +1 -1
  187. package/dist/shortcuts/meeting/continuation.js +2 -1
  188. package/dist/shortcuts/meeting/index.js +2 -0
  189. package/dist/shortcuts/meeting/operations/change.js +1 -1
  190. package/dist/shortcuts/meeting/operations/create.js +1 -1
  191. package/dist/shortcuts/meeting/operations/eb/catalog.js +4 -1
  192. package/dist/shortcuts/meeting/operations/eb/create-flow.js +101 -35
  193. package/dist/shortcuts/meeting/operations/eb/decision.js +1 -1
  194. package/dist/shortcuts/meeting/operations/eb/factory.js +34 -1
  195. package/dist/shortcuts/meeting/operations/eb/group-chat.js +25 -3
  196. package/dist/shortcuts/meeting/operations/eb/person-cache.js +96 -0
  197. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +33 -11
  198. package/dist/shortcuts/meeting/operations/lifecycle.js +1 -1
  199. package/dist/shortcuts/meeting/operations/receipts.js +1 -1
  200. package/dist/shortcuts/meeting/operations/signs.js +1 -1
  201. package/dist/shortcuts/okr/continuation.js +2 -1
  202. package/dist/shortcuts/okr/index.js +2 -0
  203. package/dist/shortcuts/okr/operations/write.js +1 -1
  204. package/dist/shortcuts/plan/continuation.js +2 -1
  205. package/dist/shortcuts/plan/index.js +2 -0
  206. package/dist/shortcuts/plan/operations/write.js +1 -1
  207. package/dist/shortcuts/project/continuation.js +2 -1
  208. package/dist/shortcuts/project/index.js +2 -0
  209. package/dist/shortcuts/project/operations/read.js +6 -25
  210. package/dist/shortcuts/project/operations/shared.js +22 -0
  211. package/dist/shortcuts/project/operations/write.js +28 -2
  212. package/dist/shortcuts/reception/constants.js +53 -0
  213. package/dist/shortcuts/reception/errors.js +54 -0
  214. package/dist/shortcuts/reception/host.js +125 -0
  215. package/dist/shortcuts/reception/index.js +198 -0
  216. package/dist/shortcuts/reception/manifest.js +177 -0
  217. package/dist/shortcuts/reception/operations/ask.js +71 -0
  218. package/dist/shortcuts/reception/operations/browsertool.js +58 -0
  219. package/dist/shortcuts/reception/operations/compose.js +129 -0
  220. package/dist/shortcuts/reception/operations/customparams.js +74 -0
  221. package/dist/shortcuts/reception/operations/doc.js +238 -0
  222. package/dist/shortcuts/reception/operations/docrender.js +36 -0
  223. package/dist/shortcuts/reception/operations/panels.js +179 -0
  224. package/dist/shortcuts/reception/operations/registry.js +26 -0
  225. package/dist/shortcuts/reception/operations/render-assets.js +184 -0
  226. package/dist/shortcuts/reception/operations/render.js +123 -0
  227. package/dist/shortcuts/reception/operations/runs.js +38 -0
  228. package/dist/shortcuts/reception/operations/schedule.js +127 -0
  229. package/dist/shortcuts/reception/operations/shared.js +196 -0
  230. package/dist/shortcuts/reception/operations/snapshot.js +68 -0
  231. package/dist/shortcuts/reception/operations/types.js +1 -0
  232. package/dist/shortcuts/reception/operations.js +33 -0
  233. package/dist/shortcuts/reception/upload.js +218 -0
  234. package/dist/shortcuts/recruit-stage/context.js +231 -0
  235. package/dist/shortcuts/recruit-stage/continuation.js +74 -0
  236. package/dist/shortcuts/recruit-stage/errors.js +65 -0
  237. package/dist/shortcuts/recruit-stage/host.js +109 -0
  238. package/dist/shortcuts/recruit-stage/index.js +115 -0
  239. package/dist/shortcuts/recruit-stage/manifest.js +29 -0
  240. package/dist/shortcuts/recruit-stage/operations/interview-arrange.js +722 -0
  241. package/dist/shortcuts/recruit-stage/operations/interview-feedback.js +269 -0
  242. package/dist/shortcuts/recruit-stage/operations/jd-create.js +719 -0
  243. package/dist/shortcuts/recruit-stage/operations/list.js +431 -0
  244. package/dist/shortcuts/recruit-stage/operations/registry.js +38 -0
  245. package/dist/shortcuts/recruit-stage/operations/resume-import.js +1354 -0
  246. package/dist/shortcuts/recruit-stage/operations/search.js +158 -0
  247. package/dist/shortcuts/recruit-stage/operations/types.js +25 -0
  248. package/dist/shortcuts/recruit-stage/school-tiers.json +318 -0
  249. package/dist/shortcuts/recruit-stage/shared.js +608 -0
  250. package/dist/shortcuts/workflow/continuation.js +2 -1
  251. package/dist/shortcuts/workflow/index.js +2 -0
  252. package/dist/shortcuts/workflow/operations/form.js +32 -8
  253. package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +4 -2
  254. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +13 -6
  255. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +17 -24
  256. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +14 -9
  257. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +50 -8
  258. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +2 -1
  259. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +17 -11
  260. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +7 -39
  261. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +3 -2
  262. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +51 -15
  263. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +16 -1
  264. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +151 -63
  265. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.js +56 -0
  266. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +39 -14
  267. package/dist/shortcuts/workflow/operations/write.js +1 -1
  268. package/docs/_catalog.md +3 -0
  269. package/docs/agent-invoice.md +1 -1
  270. package/docs/archive-oa.md +1 -1
  271. package/docs/caizhilian.md +1 -1
  272. package/docs/calendar.md +1 -1
  273. package/docs/contract.md +1 -1
  274. package/docs/e10-auth.md +23 -1
  275. package/docs/ehr.md +2 -2
  276. package/docs/esb.md +1 -1
  277. package/docs/im.md +1 -1
  278. package/docs/invoice.md +8 -12
  279. package/docs/okr.md +1 -1
  280. package/docs/operation-manual.md +8 -0
  281. package/docs/reception.md +119 -0
  282. package/package.json +1 -1
  283. package/scripts/clean.mjs +43 -2
  284. package/scripts/install-skill-to-xiaoe.mjs +105 -0
  285. package/scripts/package-skill.mjs +4 -2
  286. package/skill-template/business-info.json +42 -2
  287. package/skill-template/domains/caizhilian.md +1 -1
  288. package/skill-template/domains/reception-flow.md +18 -0
  289. package/skill-template/domains/recruit-stage.md +29 -0
  290. package/skill-template/domains/yepiaotong.md +4 -7
  291. package/skills/weaver-e10-archive-oa/references/source-manifest.json +14 -14
  292. package/skills/weaver-e10-blog/references/blog-publish.md +1 -1
  293. package/skills/weaver-e10-blog/references/source-manifest.json +7 -7
  294. package/skills/weaver-e10-caizhilian/references/source-manifest.json +21 -21
  295. package/skills/weaver-e10-caizhilian/references/write-protocol.md +2 -2
  296. package/skills/weaver-e10-calendar/SKILL.md +2 -1
  297. package/skills/weaver-e10-calendar/references/calendar-write.md +55 -1
  298. package/skills/weaver-e10-cowork/SKILL.md +1 -1
  299. package/skills/weaver-e10-cowork/references/cowork-write.md +3 -1
  300. package/skills/weaver-e10-ebuilder-form/SKILL.md +1 -1
  301. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -1
  302. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -1
  303. package/skills/weaver-e10-esb/SKILL.md +2 -2
  304. package/skills/weaver-e10-esb/references/source-manifest.json +22 -22
  305. package/skills/weaver-e10-esb/references/trigger.md +2 -2
  306. package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +1 -1
  307. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +1 -1
  308. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +1 -1
  309. package/skills/weaver-e10-jinchengda/references/source-manifest.json +29 -29
  310. package/skills/weaver-e10-jucailin/SKILL.md +1 -1
  311. package/skills/weaver-e10-jucailin/references/attend-write.md +10 -2
  312. package/skills/weaver-e10-jucailin/references/hr-contact.md +8 -0
  313. package/skills/weaver-e10-jucailin/references/hr-report.md +8 -0
  314. package/skills/weaver-e10-jucailin/references/recruit-create.md +14 -5
  315. package/skills/weaver-e10-jucailin/references/recruit-read.md +1 -1
  316. package/skills/weaver-e10-jucailin/references/recruit-write.md +5 -4
  317. package/skills/weaver-e10-mail/SKILL.md +1 -1
  318. package/skills/weaver-e10-meeting/SKILL.md +39 -7
  319. package/skills/weaver-e10-meeting/references/meeting-change.md +1 -1
  320. package/skills/weaver-e10-meeting/references/meeting-create.md +1 -1
  321. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +1 -1
  322. package/skills/weaver-e10-meeting/references/meeting-verification.md +1 -1
  323. package/skills/weaver-e10-okr/references/okr-align.md +1 -1
  324. package/skills/weaver-e10-okr/references/okr-keyresult.md +1 -1
  325. package/skills/weaver-e10-okr/references/okr-write.md +1 -1
  326. package/skills/weaver-e10-okr/references/source-manifest.json +8 -8
  327. package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
  328. package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
  329. package/skills/weaver-e10-qiyecheng/references/loan-management.md +1 -1
  330. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +18 -18
  331. package/skills/weaver-e10-reception-flow/SKILL.md +173 -0
  332. package/skills/weaver-e10-reception-flow/assets//350/241/214/347/250/213/345/215/225/346/250/241/346/235/277-/346/263/233/345/276/256.docx +0 -0
  333. package/skills/weaver-e10-reception-flow/data/fields-snapshot.json +213 -0
  334. package/skills/weaver-e10-reception-flow/references/browsertool.md +68 -0
  335. package/skills/weaver-e10-reception-flow/references/env-pitfalls.md +51 -0
  336. package/skills/weaver-e10-reception-flow/references/fields-snapshot.md +227 -0
  337. package/skills/weaver-e10-reception-flow/references/guide.md +179 -0
  338. package/skills/weaver-e10-reception-flow/scripts/locate.sh +14 -0
  339. package/skills/weaver-e10-reception-flow/scripts/render.py +724 -0
  340. package/skills/weaver-e10-recruit-stage/SKILL.md +230 -0
  341. package/skills/weaver-e10-recruit-stage/agents/openai.yaml +119 -0
  342. package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +188 -0
  343. package/skills/weaver-e10-recruit-stage/lib/xiaoe-session.mjs +66 -0
  344. package/skills/weaver-e10-recruit-stage/references/position-templates.md +202 -0
  345. package/skills/weaver-e10-recruit-stage/references/recruit-arrange-interview.md +322 -0
  346. package/skills/weaver-e10-recruit-stage/references/recruit-capability-check.md +127 -0
  347. package/skills/weaver-e10-recruit-stage/references/recruit-check-install.md +65 -0
  348. package/skills/weaver-e10-recruit-stage/references/recruit-detail-process.md +63 -0
  349. package/skills/weaver-e10-recruit-stage/references/recruit-edit-interview-feedback.md +142 -0
  350. package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +95 -0
  351. package/skills/weaver-e10-recruit-stage/references/recruit-jd-template.md +56 -0
  352. package/skills/weaver-e10-recruit-stage/references/recruit-list-candidate.md +101 -0
  353. package/skills/weaver-e10-recruit-stage/references/recruit-list-interview.md +148 -0
  354. package/skills/weaver-e10-recruit-stage/references/recruit-match-candidates.md +77 -0
  355. package/skills/weaver-e10-recruit-stage/references/recruit-output-links.md +59 -0
  356. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-creator.md +69 -0
  357. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-metadata.md +241 -0
  358. package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +451 -0
  359. package/skills/weaver-e10-recruit-stage/references/recruit-resume-parse.md +128 -0
  360. package/skills/weaver-e10-recruit-stage/references/recruit-search-candidate.md +146 -0
  361. package/skills/weaver-e10-recruit-stage/references/recruit-urge-feedback.md +69 -0
  362. package/skills/weaver-e10-shared/SKILL.md +1 -1
  363. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -2
  364. package/skills/weaver-e10-shijingran/SKILL.md +7 -6
  365. package/skills/weaver-e10-shijingran/references/operations.md +3 -1
  366. package/skills/weaver-e10-shijingran/references/source-manifest.json +30 -28
  367. package/skills/weaver-e10-shijingran/references/write-operations.md +2 -0
  368. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +2 -0
  369. package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
  370. package/skills/weaver-e10-workflow/SKILL.md +4 -2
  371. package/skills/weaver-e10-workflow/aigroup/default.json +11 -9
  372. package/skills/weaver-e10-workflow/references/source-manifest.json +32 -32
  373. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +23 -13
  374. package/skills/weaver-e10-workflow/tools/todo-summary.cjs +62 -20
  375. package/skills/weaver-e10-yepiaotong/SKILL.md +28 -36
  376. package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +6 -3
  377. package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +13 -10
  378. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +2 -0
  379. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +194 -155
  380. package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +28 -32
  381. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +5 -1
  382. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +8 -10
  383. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +211 -616
  384. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +149 -117
  385. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +17 -20
  386. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +20 -39
  387. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +55 -22
  388. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -17
  389. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +88 -92
  390. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +144 -354
  391. package/skills/weaver-e10-yimiaoban/SKILL.md +1 -1
  392. package/skills/weaver-e10-yimiaoban/references/msg-write.md +1 -1
  393. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +1 -1
  394. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +7 -7
  395. package/dist/chunks/chunk-SPRHHSVC.js +0 -465
  396. package/dist/chunks/registry-KMHCPAAD.js +0 -22
  397. package/dist/shortcuts/invoice/markdown.js +0 -172
  398. package/dist/shortcuts/invoice/operations/issuing-qys.js +0 -424
  399. package/skills/weaver-e10-meeting.zip +0 -0
  400. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +0 -131
  401. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +0 -179
@@ -2,42 +2,33 @@ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
4
  meetingEbGroupChatOperations
5
- } from "./chunk-57IECMWX.js";
5
+ } from "./chunk-N4M2DDFE.js";
6
+ import {
7
+ meetingEbCreateFlowOperations
8
+ } from "./chunk-FRZKBMSW.js";
6
9
  import {
7
- dayOf,
8
10
  ebRoomRecommendOperation,
9
- filterUsages,
10
- invalidateDayUsages,
11
- loadDayUsages,
12
- loadRooms,
13
11
  recommendRooms,
14
12
  rememberFrequentRoom
15
- } from "./chunk-FLS4DPGP.js";
13
+ } from "./chunk-GM6J7Q4B.js";
16
14
  import {
17
15
  meetingEbScheduleOperations
18
- } from "./chunk-4CTESSKI.js";
19
- import {
20
- cacheScopeSuffix,
21
- readCache,
22
- writeCache
23
- } from "./chunk-I566ZYNF.js";
16
+ } from "./chunk-FAZTGX7S.js";
24
17
  import {
25
18
  ebMeetingWritePreflight,
26
- fetchEbAppSettings,
27
- findCommonFreeSlots,
28
19
  meetingEbConflictOperations
29
- } from "./chunk-JWRZM2H2.js";
20
+ } from "./chunk-OF4S23UB.js";
30
21
  import {
31
22
  PENDING_MARK,
32
23
  listMeetingAttachments,
33
24
  meetingAttachmentContentOperations,
34
25
  renderDocx
35
- } from "./chunk-7E6MUOEK.js";
26
+ } from "./chunk-CWYGFU5B.js";
36
27
  import {
37
28
  meetingEnvOperations,
38
29
  meetingStateDir,
39
30
  resolveMeetingEnvMode
40
- } from "./chunk-NJKREDA3.js";
31
+ } from "./chunk-GAMZLAG2.js";
41
32
  import {
42
33
  EB_BASE,
43
34
  EB_ENDPOINTS,
@@ -69,7 +60,10 @@ import {
69
60
  toIdString,
70
61
  verifyLease,
71
62
  writeBody
72
- } from "./chunk-7BRU4EFH.js";
63
+ } from "./chunk-QVSWRLLU.js";
64
+ import {
65
+ CONTINUATION_TTL_SECONDS
66
+ } from "./chunk-7BDPM5ST.js";
73
67
 
74
68
  // src/shortcuts/meeting/operations/meetings.ts
75
69
  function overlapsDate(beginDatetime, endDatetime, date) {
@@ -438,7 +432,6 @@ var meetingConflictOperations = [
438
432
 
439
433
  // src/shortcuts/meeting/operations/change.ts
440
434
  import { createHash } from "node:crypto";
441
- var CONTINUATION_TTL_SECONDS = 600;
442
435
  var LIST_PATH = "/api/meeting/search/getMeetingList";
443
436
  function fingerprint2(value) {
444
437
  return createHash("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
@@ -678,7 +671,6 @@ var meetingChangeOperations = [
678
671
 
679
672
  // src/shortcuts/meeting/operations/create.ts
680
673
  import { createHash as createHash2 } from "node:crypto";
681
- var CONTINUATION_TTL_SECONDS2 = 600;
682
674
  function fingerprint3(value) {
683
675
  return createHash2("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
684
676
  }
@@ -912,13 +904,13 @@ var meetingCreatePrepare = {
912
904
  payload: body,
913
905
  fingerprint: fingerprint3(body)
914
906
  },
915
- CONTINUATION_TTL_SECONDS2 * 1e3
907
+ CONTINUATION_TTL_SECONDS * 1e3
916
908
  );
917
909
  return meetingSuccess("meeting.create.prepare", {
918
910
  status: "AWAITING_CONFIRMATION",
919
911
  preview: body,
920
912
  continuation: token,
921
- expiresInSeconds: CONTINUATION_TTL_SECONDS2
913
+ expiresInSeconds: CONTINUATION_TTL_SECONDS
922
914
  }, { warnings });
923
915
  }
924
916
  };
@@ -1008,7 +1000,6 @@ var meetingCreateOperations = [
1008
1000
 
1009
1001
  // src/shortcuts/meeting/operations/lifecycle.ts
1010
1002
  import { createHash as createHash3 } from "node:crypto";
1011
- var CONTINUATION_TTL_SECONDS3 = 600;
1012
1003
  function fingerprint4(value) {
1013
1004
  return createHash3("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
1014
1005
  }
@@ -1062,13 +1053,13 @@ function lifecyclePair(spec) {
1062
1053
  payload: { id },
1063
1054
  fingerprint: fingerprint4({ id })
1064
1055
  },
1065
- CONTINUATION_TTL_SECONDS3 * 1e3
1056
+ CONTINUATION_TTL_SECONDS * 1e3
1066
1057
  );
1067
1058
  return meetingSuccess(prepareName, {
1068
1059
  status: "AWAITING_CONFIRMATION",
1069
1060
  preview: { action: spec.action, id, body: spec.bodyOf(id), note: spec.note },
1070
1061
  continuation: token,
1071
- expiresInSeconds: CONTINUATION_TTL_SECONDS3
1062
+ expiresInSeconds: CONTINUATION_TTL_SECONDS
1072
1063
  });
1073
1064
  }
1074
1065
  };
@@ -1147,7 +1138,6 @@ var meetingLifecycleOperations = [
1147
1138
 
1148
1139
  // src/shortcuts/meeting/operations/receipts.ts
1149
1140
  import { createHash as createHash4 } from "node:crypto";
1150
- var CONTINUATION_TTL_SECONDS4 = 600;
1151
1141
  function fingerprint5(value) {
1152
1142
  return createHash4("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
1153
1143
  }
@@ -1285,13 +1275,13 @@ var meetingReceiptUpdatePrepare = {
1285
1275
  payload,
1286
1276
  fingerprint: fingerprint5(normalized)
1287
1277
  },
1288
- CONTINUATION_TTL_SECONDS4 * 1e3
1278
+ CONTINUATION_TTL_SECONDS * 1e3
1289
1279
  );
1290
1280
  return meetingSuccess("meeting.receipt.update.prepare", {
1291
1281
  status: "AWAITING_CONFIRMATION",
1292
1282
  preview: payload,
1293
1283
  continuation: token,
1294
- expiresInSeconds: CONTINUATION_TTL_SECONDS4
1284
+ expiresInSeconds: CONTINUATION_TTL_SECONDS
1295
1285
  });
1296
1286
  }
1297
1287
  };
@@ -1360,7 +1350,6 @@ var meetingReceiptOperations = [
1360
1350
 
1361
1351
  // src/shortcuts/meeting/operations/signs.ts
1362
1352
  import { createHash as createHash5 } from "node:crypto";
1363
- var CONTINUATION_TTL_SECONDS5 = 600;
1364
1353
  function fingerprint6(value) {
1365
1354
  return createHash5("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
1366
1355
  }
@@ -1514,7 +1503,7 @@ function signWritePair(spec) {
1514
1503
  payload,
1515
1504
  fingerprint: fingerprint6(payload)
1516
1505
  },
1517
- CONTINUATION_TTL_SECONDS5 * 1e3
1506
+ CONTINUATION_TTL_SECONDS * 1e3
1518
1507
  );
1519
1508
  const record = target.record;
1520
1509
  const alreadySigned = record.signtime !== void 0 && record.signtime !== null && record.signtime !== "";
@@ -1545,7 +1534,7 @@ function signWritePair(spec) {
1545
1534
  note: spec.note
1546
1535
  },
1547
1536
  continuation: token,
1548
- expiresInSeconds: CONTINUATION_TTL_SECONDS5
1537
+ expiresInSeconds: CONTINUATION_TTL_SECONDS
1549
1538
  });
1550
1539
  }
1551
1540
  };
@@ -2235,7 +2224,7 @@ var meetingAttachmentAttach = {
2235
2224
  if (mode === "append" && existingIds.length === 0) {
2236
2225
  existingIds.push(...beforeIds);
2237
2226
  }
2238
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
2227
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
2239
2228
  const list = getMeetingOperation2("meeting.eb.meeting.list");
2240
2229
  let fileId = incomingFileId;
2241
2230
  let name = String(args.name ?? "").trim();
@@ -2323,7 +2312,7 @@ function textOf(value) {
2323
2312
  return value === void 0 || value === null ? "" : String(value);
2324
2313
  }
2325
2314
  async function readMinute(env, id) {
2326
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
2315
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
2327
2316
  const detail = getMeetingOperation2("meeting.eb.minute.detail");
2328
2317
  const result = await detail.handler({ id }, env);
2329
2318
  const row = result?.data?.data;
@@ -2402,7 +2391,7 @@ var meetingMinuteWriteContent = {
2402
2391
  } else {
2403
2392
  statusReason = "\u4EC5\u6E05\u7A7A\u5185\u5BB9\uFF0C\u672A\u6539\u72B6\u6001";
2404
2393
  }
2405
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
2394
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
2406
2395
  const prepare = getMeetingOperation2("meeting.eb.minute.update.prepare");
2407
2396
  const apply = getMeetingOperation2("meeting.eb.minute.update.apply");
2408
2397
  const prepared = await prepare.handler({ id, mt_id: mtId, ...patch }, env);
@@ -2533,8 +2522,8 @@ function parseLocalTime(value) {
2533
2522
  return Number.isNaN(parsed.getTime()) ? null : parsed;
2534
2523
  }
2535
2524
  function formatStamp(d) {
2536
- const pad3 = (n) => String(n).padStart(2, "0");
2537
- return `${d.getFullYear()}-${pad3(d.getMonth() + 1)}-${pad3(d.getDate())} ${pad3(d.getHours())}:${pad3(d.getMinutes())}:${pad3(d.getSeconds())}`;
2525
+ const pad2 = (n) => String(n).padStart(2, "0");
2526
+ return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
2538
2527
  }
2539
2528
  function computeChatWindow(meeting, now = /* @__PURE__ */ new Date()) {
2540
2529
  const begin = parseLocalTime(meeting.begin_datetime);
@@ -2662,16 +2651,16 @@ function buildDigest(messages, nameByUid, keepSystem, maxChars) {
2662
2651
  return { transcript, kept: lines.length, dropped, truncated };
2663
2652
  }
2664
2653
  async function saveTranscript(ctx, mtId, transcript) {
2665
- const { mkdir: mkdir5, writeFile: writeFile5 } = await import("node:fs/promises");
2654
+ const { mkdir: mkdir4, writeFile: writeFile4 } = await import("node:fs/promises");
2666
2655
  const { join: join3 } = await import("node:path");
2667
2656
  const { stateDir } = await import("./state-Y2XBP6YE.js");
2668
2657
  const dir = join3(stateDir(ctx), "transcripts");
2669
- await mkdir5(dir, { recursive: true });
2670
- const pad3 = (n) => String(n).padStart(2, "0");
2658
+ await mkdir4(dir, { recursive: true });
2659
+ const pad2 = (n) => String(n).padStart(2, "0");
2671
2660
  const now = /* @__PURE__ */ new Date();
2672
- const stamp2 = `${now.getFullYear()}${pad3(now.getMonth() + 1)}${pad3(now.getDate())}-${pad3(now.getHours())}${pad3(now.getMinutes())}${pad3(now.getSeconds())}`;
2661
+ const stamp2 = `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}-${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`;
2673
2662
  const filePath = join3(dir, `${mtId}-${stamp2}.txt`);
2674
- await writeFile5(filePath, transcript, "utf8");
2663
+ await writeFile4(filePath, transcript, "utf8");
2675
2664
  return filePath;
2676
2665
  }
2677
2666
  var meetingMinuteFromGroupChat = {
@@ -2761,7 +2750,7 @@ var meetingMinuteFromGroupChat = {
2761
2750
  const mtId = textOf2(args.mt_id).trim();
2762
2751
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
2763
2752
  const pipeline = ["text", "minutes", "document"].includes(args.pipeline) ? args.pipeline : "text";
2764
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
2753
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
2765
2754
  const ctx = env.ctx;
2766
2755
  let stepStart = Date.now();
2767
2756
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
@@ -2785,9 +2774,9 @@ var meetingMinuteFromGroupChat = {
2785
2774
  }
2786
2775
  mark("readMeeting", stepStart);
2787
2776
  const pullStart = Date.now();
2788
- const { createImHost } = await import("./host-JM4YVHFM.js");
2789
- const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
2790
- const { getImOperation } = await import("./registry-QGHFNUWS.js");
2777
+ const { createImHost } = await import("./host-LR55CTHP.js");
2778
+ const { createImContinuationSigner } = await import("./continuation-3S37AUSH.js");
2779
+ const { getImOperation } = await import("./registry-PVUZQDDQ.js");
2791
2780
  const imEnv = { ctx, host: createImHost(ctx), continuation: createImContinuationSigner(ctx) };
2792
2781
  const syncOp = getImOperation("im.msg.sync.group");
2793
2782
  const chatWindow = computeChatWindow(meeting);
@@ -2853,9 +2842,9 @@ var meetingMinuteFromGroupChat = {
2853
2842
  const extraSections = [];
2854
2843
  for (const file of extraFiles) {
2855
2844
  try {
2856
- const { readFile: readFile5 } = await import("node:fs/promises");
2857
- const buffer = await readFile5(file);
2858
- const { extractText } = await import("./attachment-content-RZYDB3MB.js");
2845
+ const { readFile: readFile4 } = await import("node:fs/promises");
2846
+ const buffer = await readFile4(file);
2847
+ const { extractText } = await import("./attachment-content-E3276UOV.js");
2859
2848
  const extracted = extractText(buffer, file, "");
2860
2849
  if (extracted.text.trim()) {
2861
2850
  extraSections.push(`\u3010\u6750\u6599\uFF1A${file.split(/[\\/]/).pop() ?? file}\u3011
@@ -2984,9 +2973,9 @@ ${groupTranscript}` : ""
2984
2973
  if (!employeeId) {
2985
2974
  warnings.push("\u672A\u53D6\u5230 ESB \u89E6\u53D1\u4EBA id\uFF08employeeId\uFF09\uFF0C\u5DF2\u8DF3\u8FC7\u540E\u7EED ESB \u8C03\u7528");
2986
2975
  } else {
2987
- const { createEsbHost } = await import("./host-256GVCAH.js");
2988
- const { createEsbContinuationSigner } = await import("./continuation-NLECEJPX.js");
2989
- const { getEsbOperation } = await import("./registry-RXPN6BBT.js");
2976
+ const { createEsbHost } = await import("./host-WIKN2EJ5.js");
2977
+ const { createEsbContinuationSigner } = await import("./continuation-KI7DRRZN.js");
2978
+ const { getEsbOperation } = await import("./registry-KNKSCJNT.js");
2990
2979
  const esbEnv = { ctx, host: createEsbHost(ctx), continuation: createEsbContinuationSigner(ctx) };
2991
2980
  const prepareOp = getEsbOperation("esb.trigger.prepare");
2992
2981
  const applyOp = getEsbOperation("esb.trigger.apply");
@@ -3174,7 +3163,7 @@ var meetingDecisionNotifyGroup = {
3174
3163
  const warnings = [];
3175
3164
  const mtId = textOf3(args.mt_id).trim();
3176
3165
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
3177
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
3166
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
3178
3167
  const ctx = env.ctx;
3179
3168
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
3180
3169
  { mt_id: mtId, pageNo: 1, pageSize: 1 },
@@ -3238,7 +3227,7 @@ var meetingDecisionNotifyGroup = {
3238
3227
  charCount: formatted.text.length,
3239
3228
  text: formatted.text
3240
3229
  };
3241
- const { createImHost } = await import("./host-JM4YVHFM.js");
3230
+ const { createImHost } = await import("./host-LR55CTHP.js");
3242
3231
  const imHost = createImHost(ctx);
3243
3232
  let displayText = formatted.text;
3244
3233
  let wireText = formatted.text;
@@ -3246,7 +3235,7 @@ var meetingDecisionNotifyGroup = {
3246
3235
  const mentioned = [];
3247
3236
  if (args.mention !== false) {
3248
3237
  try {
3249
- const { getImOperation } = await import("./registry-QGHFNUWS.js");
3238
+ const { getImOperation } = await import("./registry-PVUZQDDQ.js");
3250
3239
  const membersResult = await getImOperation("im.group.users").handler(
3251
3240
  { groupId },
3252
3241
  { ctx, host: imHost }
@@ -3380,14 +3369,14 @@ function defaultDueDate(begin, days) {
3380
3369
  const base = new Date(normalized.replace(/-/g, "/"));
3381
3370
  const start = Number.isNaN(base.getTime()) ? /* @__PURE__ */ new Date() : base;
3382
3371
  const due = new Date(start.getTime() + Math.max(days, 1) * 24 * 36e5);
3383
- const pad3 = (n) => String(n).padStart(2, "0");
3384
- return `${due.getFullYear()}-${pad3(due.getMonth() + 1)}-${pad3(due.getDate())} 18:00`;
3372
+ const pad2 = (n) => String(n).padStart(2, "0");
3373
+ return `${due.getFullYear()}-${pad2(due.getMonth() + 1)}-${pad2(due.getDate())} 18:00`;
3385
3374
  }
3386
3375
  async function waitForTaskIncrease(fetchTotal, baseline, timeoutMs = 15e3, intervalMs = 2e3) {
3387
3376
  const start = Date.now();
3388
3377
  let total = baseline;
3389
3378
  while (Date.now() - start < timeoutMs) {
3390
- await new Promise((resolve6) => setTimeout(resolve6, intervalMs));
3379
+ await new Promise((resolve5) => setTimeout(resolve5, intervalMs));
3391
3380
  total = await fetchTotal();
3392
3381
  if (total > baseline) return { total, waitedMs: Date.now() - start, increased: true };
3393
3382
  }
@@ -3476,7 +3465,7 @@ var meetingPipelineRun = {
3476
3465
  const needsConfirm = level === "tasks" || level === "notify";
3477
3466
  const confirmed = args.confirm === true;
3478
3467
  const executedLevel = needsConfirm && !confirmed ? "document" : level;
3479
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
3468
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
3480
3469
  const ctx = env.ctx;
3481
3470
  let stepStart = Date.now();
3482
3471
  const reuseMinuteId = textOf4(args.minuteId).trim();
@@ -3545,8 +3534,8 @@ var meetingPipelineRun = {
3545
3534
  ]);
3546
3535
  }
3547
3536
  stepStart = Date.now();
3548
- const { createHrmHost } = await import("./host-D5SERMAJ.js");
3549
- const { getHrmOperation } = await import("./registry-NYPYMZXG.js");
3537
+ const { createHrmHost } = await import("./host-HRBXEPDQ.js");
3538
+ const { getHrmOperation } = await import("./registry-PO7SI256.js");
3550
3539
  const hrmEnv = { ctx, host: createHrmHost(ctx) };
3551
3540
  const queryOp = getHrmOperation("hrm.employee.query");
3552
3541
  const resolved = [];
@@ -3583,8 +3572,8 @@ var meetingPipelineRun = {
3583
3572
  })();
3584
3573
  const beginAt = textOf4(meetingInfo.end_datetime).trim() || textOf4(meetingInfo.begin_datetime).trim() || (() => {
3585
3574
  const now = /* @__PURE__ */ new Date();
3586
- const pad3 = (n) => String(n).padStart(2, "0");
3587
- return `${now.getFullYear()}-${pad3(now.getMonth() + 1)}-${pad3(now.getDate())} ${pad3(now.getHours())}:${pad3(now.getMinutes())}`;
3575
+ const pad2 = (n) => String(n).padStart(2, "0");
3576
+ return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())} ${pad2(now.getHours())}:${pad2(now.getMinutes())}`;
3588
3577
  })();
3589
3578
  const dueDays = typeof args.taskDueDays === "number" && args.taskDueDays > 0 ? args.taskDueDays : 7;
3590
3579
  const dueAt = defaultDueDate(beginAt, dueDays);
@@ -3848,7 +3837,7 @@ function formatTimeRange(start, end) {
3848
3837
  }
3849
3838
  async function loadAgendaFromTopics(env, mtId) {
3850
3839
  try {
3851
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
3840
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
3852
3841
  const operation = getMeetingOperation2("meeting.eb.topic.list");
3853
3842
  const result = await operation.handler({ mt_id: mtId, pageNo: 1, pageSize: 200 }, env);
3854
3843
  const rows = result.data?.rows ?? [];
@@ -3928,7 +3917,7 @@ function flattenFieldValue(raw) {
3928
3917
  }
3929
3918
  async function resolveIssuerOrganization(env, creatorId) {
3930
3919
  try {
3931
- const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
3920
+ const { hrmEmployeeOperations } = await import("./employee-22BGJ3QS.js");
3932
3921
  const batch = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.batch");
3933
3922
  if (!batch) return null;
3934
3923
  const result = await batch.handler({ ids: [creatorId] }, env);
@@ -3950,7 +3939,7 @@ async function resolveSessionUserName(env) {
3950
3939
  const session = await env.host.getSession();
3951
3940
  const userId = String(session?.userId ?? "").trim();
3952
3941
  if (!userId) return "";
3953
- const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
3942
+ const { hrmEmployeeOperations } = await import("./employee-22BGJ3QS.js");
3954
3943
  const batch = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.batch");
3955
3944
  if (!batch) return "";
3956
3945
  const result = await batch.handler({ ids: [userId] }, env);
@@ -3986,7 +3975,7 @@ async function supplementRowFromDetail(row, mtId, env) {
3986
3975
  const missing = DETAIL_FALLBACK_KEYS.filter((key) => isBlank(row[key]));
3987
3976
  if (missing.length === 0) return { row, filled: [] };
3988
3977
  try {
3989
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
3978
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
3990
3979
  const detailOperation = getMeetingOperation2("meeting.eb.meeting.detail");
3991
3980
  const result = await detailOperation.handler({ id: mtId }, env);
3992
3981
  const flat = result?.data?.data ?? result?.data ?? {};
@@ -4160,7 +4149,7 @@ var meetingInvitationRender = {
4160
4149
  };
4161
4150
  dataSource = "payload";
4162
4151
  } else {
4163
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
4152
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
4164
4153
  const listOperation = getMeetingOperation2("meeting.eb.meeting.list");
4165
4154
  try {
4166
4155
  const listed = await listOperation.handler({ mt_id: mtId, pageNo: 1, pageSize: 1 }, env);
@@ -4562,7 +4551,7 @@ function buildCodewords(bytes, version, ecc) {
4562
4551
  for (const byte of bytes) appendBits(byte, 8);
4563
4552
  appendBits(0, Math.min(4, capacityBits - bits.length));
4564
4553
  appendBits(0, (8 - bits.length % 8) % 8);
4565
- for (let pad3 = 236; bits.length < capacityBits; pad3 ^= 236 ^ 17) appendBits(pad3, 8);
4554
+ for (let pad2 = 236; bits.length < capacityBits; pad2 ^= 236 ^ 17) appendBits(pad2, 8);
4566
4555
  const dataCodewords = new Array(bits.length / 8).fill(0);
4567
4556
  bits.forEach((bit, i) => {
4568
4557
  dataCodewords[i >>> 3] |= bit << 7 - (i & 7);
@@ -4748,8 +4737,8 @@ function renderQrSvg(matrix, options = {}) {
4748
4737
  var ECC_LEVELS = ["L", "M", "Q", "H"];
4749
4738
  function stamp() {
4750
4739
  const now = /* @__PURE__ */ new Date();
4751
- const pad3 = (n) => String(n).padStart(2, "0");
4752
- return `${now.getFullYear()}${pad3(now.getMonth() + 1)}${pad3(now.getDate())}-${pad3(now.getHours())}${pad3(now.getMinutes())}${pad3(now.getSeconds())}`;
4740
+ const pad2 = (n) => String(n).padStart(2, "0");
4741
+ return `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}-${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`;
4753
4742
  }
4754
4743
  function safeName(input) {
4755
4744
  return input.replace(/[\\/:*?"<>|\s]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
@@ -4914,7 +4903,7 @@ var meetingSummaryGet = {
4914
4903
  const mtId = textOf5(args.mt_id).trim();
4915
4904
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
4916
4905
  const ctx = env.ctx;
4917
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
4906
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
4918
4907
  const warnings = [];
4919
4908
  const timings = {};
4920
4909
  const include = Array.isArray(args.include) && args.include.length > 0 ? args.include.filter((item) => ALL_SECTIONS.includes(item)) : ALL_SECTIONS;
@@ -5050,9 +5039,9 @@ var meetingSummaryGet = {
5050
5039
  warnings.push("\u8BE5\u4F1A\u8BAE\u6CA1\u6709\u5173\u8054\u7FA4\u804A\uFF08imchat_groupid \u4E3A\u7A7A\uFF09\uFF0Cchat \u6BB5\u4E3A null");
5051
5040
  } else {
5052
5041
  try {
5053
- const { createImHost } = await import("./host-JM4YVHFM.js");
5054
- const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
5055
- const { getImOperation } = await import("./registry-QGHFNUWS.js");
5042
+ const { createImHost } = await import("./host-LR55CTHP.js");
5043
+ const { createImContinuationSigner } = await import("./continuation-3S37AUSH.js");
5044
+ const { getImOperation } = await import("./registry-PVUZQDDQ.js");
5056
5045
  const imEnv = {
5057
5046
  ctx,
5058
5047
  // 测试环境靠 env.imHost 注入假实现,否则会真的打到线上群聊
@@ -5176,9 +5165,9 @@ var meetingFormFields = {
5176
5165
  hint: "\u6CA1\u89E3\u6790\u5230\u8BE5\u8868\u7684 objId\uFF08\u53EF\u80FD\u5F53\u524D\u73AF\u5883\u6CA1\u6709\u8FD9\u5F20\u8868\uFF0C\u6216\u8D26\u53F7\u65E0\u6743\u9650\uFF09"
5177
5166
  }, { warnings: resolved.warnings });
5178
5167
  }
5179
- const { createEbuilderFormHost } = await import("./host-ZUQTJYYK.js");
5180
- const { createEbuilderFormContinuationSigner } = await import("./continuation-RN6PZN2M.js");
5181
- const { executeEbuilderFormOperation } = await import("./operations-5QL3AECO.js");
5168
+ const { createEbuilderFormHost } = await import("./host-SZGV4UNT.js");
5169
+ const { createEbuilderFormContinuationSigner } = await import("./continuation-3XLYYTKV.js");
5170
+ const { executeEbuilderFormOperation } = await import("./operations-62N6EP3C.js");
5182
5171
  const formEnv = {
5183
5172
  ctx: env.ctx,
5184
5173
  host: createEbuilderFormHost(env.ctx),
@@ -5224,19 +5213,18 @@ var meetingFormFields = {
5224
5213
  var meetingFormFieldOperations = [meetingFormFields];
5225
5214
 
5226
5215
  // src/shortcuts/meeting/operations/eb/decision.ts
5227
- var CONTINUATION_TTL_SECONDS6 = 600;
5228
5216
  var DATE_PATTERN = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}$";
5229
5217
  function formatSecondNow() {
5230
5218
  const now = /* @__PURE__ */ new Date();
5231
- const pad3 = (value) => String(value).padStart(2, "0");
5232
- return `${now.getFullYear()}-${pad3(now.getMonth() + 1)}-${pad3(now.getDate())} ${pad3(now.getHours())}:${pad3(now.getMinutes())}:${pad3(now.getSeconds())}`;
5219
+ const pad2 = (value) => String(value).padStart(2, "0");
5220
+ return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())} ${pad2(now.getHours())}:${pad2(now.getMinutes())}:${pad2(now.getSeconds())}`;
5233
5221
  }
5234
5222
  var DECISION_DONE = "2";
5235
5223
  var MT_STATUS_OVER = "8";
5236
5224
  var CANCELLED_MARK_DELAY_MS = 800;
5237
5225
  async function isCancelledMeeting(env, mtId) {
5238
5226
  try {
5239
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
5227
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
5240
5228
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
5241
5229
  // withCount:false —— 这里只要一行状态,不必额外请求 count(少一次往返,也便于测试替身)
5242
5230
  { mt_id: mtId, pageNo: 1, pageSize: 1, withCount: false },
@@ -5354,7 +5342,7 @@ var decisionPublishPrepare = {
5354
5342
  payload,
5355
5343
  fingerprint: fingerprint(payload)
5356
5344
  },
5357
- CONTINUATION_TTL_SECONDS6 * 1e3
5345
+ CONTINUATION_TTL_SECONDS * 1e3
5358
5346
  );
5359
5347
  return meetingSuccess("meeting.eb.decision.publish.prepare", {
5360
5348
  status: "AWAITING_CONFIRMATION",
@@ -5376,7 +5364,7 @@ var decisionPublishPrepare = {
5376
5364
  decisionCount: (create.details.detail1 ?? []).length
5377
5365
  },
5378
5366
  continuation: token,
5379
- expiresInSeconds: CONTINUATION_TTL_SECONDS6
5367
+ expiresInSeconds: CONTINUATION_TTL_SECONDS
5380
5368
  }, {
5381
5369
  meta: {
5382
5370
  notes: [
@@ -5455,8 +5443,8 @@ var decisionPublishApply = {
5455
5443
  );
5456
5444
  }
5457
5445
  if (cancelled) {
5458
- await new Promise((resolve6) => {
5459
- setTimeout(resolve6, CANCELLED_MARK_DELAY_MS);
5446
+ await new Promise((resolve5) => {
5447
+ setTimeout(resolve5, CANCELLED_MARK_DELAY_MS);
5460
5448
  });
5461
5449
  warnings.push(
5462
5450
  `\u8BE5\u4F1A\u8BAE\u6B64\u524D\u88AB\u53D6\u6D88\u8FC7\uFF1A\u5DF2\u5728\u300C\u5199\u51B3\u8BAE\u300D\u4E0E\u300C\u6807\u8BB0\u5DF2\u51B3\u8BAE\u300D\u4E4B\u95F4\u7559 ${CANCELLED_MARK_DELAY_MS}ms \u95F4\u9694\uFF0C\u907F\u514D ESB \u628A\u540C\u4E00\u6279\u660E\u7EC6\u751F\u6210\u4E24\u8F6E\u4EFB\u52A1\uFF08\u771F\u673A\u9A8C\u8BC1\u8FC7\u7684\u5751\uFF09`
@@ -5562,7 +5550,7 @@ var signMarkPrepare = {
5562
5550
  payload,
5563
5551
  fingerprint: fingerprint(payload)
5564
5552
  },
5565
- CONTINUATION_TTL_SECONDS6 * 1e3
5553
+ CONTINUATION_TTL_SECONDS * 1e3
5566
5554
  );
5567
5555
  return meetingSuccess("meeting.eb.sign.mark.prepare", {
5568
5556
  status: "AWAITING_CONFIRMATION",
@@ -5575,7 +5563,7 @@ var signMarkPrepare = {
5575
5563
  after: update.mainTable
5576
5564
  },
5577
5565
  continuation: token,
5578
- expiresInSeconds: CONTINUATION_TTL_SECONDS6
5566
+ expiresInSeconds: CONTINUATION_TTL_SECONDS
5579
5567
  }, {
5580
5568
  warnings,
5581
5569
  meta: {
@@ -6049,9 +6037,9 @@ async function runCrmSearchFlow(env, input) {
6049
6037
  if (!employeeId) {
6050
6038
  throw meetingValidationError("crm_employee_required", "\u53D6\u4E0D\u5230\u5F53\u524D\u767B\u5F55\u7528\u6237 id\uFF0C\u65E0\u6CD5\u89E6\u53D1 ESB \u5BA2\u6237\u67E5\u8BE2");
6051
6039
  }
6052
- const { createEsbHost } = await import("./host-256GVCAH.js");
6053
- const { createEsbContinuationSigner } = await import("./continuation-NLECEJPX.js");
6054
- const { getEsbOperation } = await import("./registry-RXPN6BBT.js");
6040
+ const { createEsbHost } = await import("./host-WIKN2EJ5.js");
6041
+ const { createEsbContinuationSigner } = await import("./continuation-KI7DRRZN.js");
6042
+ const { getEsbOperation } = await import("./registry-KNKSCJNT.js");
6055
6043
  const esbEnv = {
6056
6044
  ctx: env.ctx,
6057
6045
  host: createEsbHost(env.ctx),
@@ -6174,2372 +6162,6 @@ var ebCrmSearch = {
6174
6162
  };
6175
6163
  var meetingEbCrmOperations = [ebCrmSearch];
6176
6164
 
6177
- // src/shortcuts/meeting/operations/eb/create-flow.ts
6178
- import { existsSync as existsSync3 } from "node:fs";
6179
- import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
6180
- import { homedir } from "node:os";
6181
- import { resolve as resolve5 } from "node:path";
6182
-
6183
- // src/shortcuts/meeting/operations/eb/flow-memory.ts
6184
- var FLOW_PICK_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
6185
- function flowPickKey(scope) {
6186
- return `flow-pick-${scope}`;
6187
- }
6188
- async function readFlowPick(env) {
6189
- const scope = await cacheScopeSuffix(env);
6190
- const hit = await readCache(env, flowPickKey(scope), { ttlMs: FLOW_PICK_TTL_MS });
6191
- if (!hit?.data?.workflowId) return null;
6192
- try {
6193
- const session = await env.host.getSession();
6194
- const userId = String(session?.userId ?? "");
6195
- if (hit.data.userId && userId && hit.data.userId !== userId) return null;
6196
- } catch {
6197
- }
6198
- return hit.data;
6199
- }
6200
- async function rememberFlowPick(env, workflowId, name) {
6201
- const id = String(workflowId ?? "").trim();
6202
- if (id === "") return;
6203
- let userId = "";
6204
- try {
6205
- const session = await env.host.getSession();
6206
- userId = String(session?.userId ?? "");
6207
- } catch {
6208
- }
6209
- const scope = await cacheScopeSuffix(env);
6210
- await writeCache(env, flowPickKey(scope), {
6211
- workflowId: id,
6212
- ...name ? { name: String(name) } : {},
6213
- ...userId ? { userId } : {},
6214
- savedAt: Date.now()
6215
- });
6216
- }
6217
- function pickRememberedFlow(launchable, remembered) {
6218
- if (!remembered?.workflowId) return null;
6219
- return launchable.find((probe) => probe.workflowId === remembered.workflowId) ?? null;
6220
- }
6221
-
6222
- // src/shortcuts/meeting/operations/eb/create-flow.ts
6223
- var FIELD_ALIASES = {
6224
- mt_name: ["\u4F1A\u8BAE\u540D\u79F0", "\u4F1A\u8BAE\u4E3B\u9898", "\u4E3B\u9898"],
6225
- begin_datetime: ["\u5F00\u59CB\u65F6\u95F4", "\u4F1A\u8BAE\u5F00\u59CB\u65F6\u95F4"],
6226
- end_datetime: ["\u7ED3\u675F\u65F6\u95F4", "\u4F1A\u8BAE\u7ED3\u675F\u65F6\u95F4"],
6227
- mt_desc: ["\u4F1A\u8BAE\u5185\u5BB9", "\u4F1A\u8BAE\u8BF4\u660E", "\u4F1A\u8BAE\u63CF\u8FF0"],
6228
- address: ["\u4F1A\u8BAE\u5730\u70B9", "\u4F1A\u8BAE\u5BA4"],
6229
- customize_address: ["\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9", "\u81EA\u5B9A\u4E49\u5730\u70B9"],
6230
- hrm_members: ["\u53C2\u4F1A\u4EBA\u5458", "\u53C2\u4F1A\u4EBA"],
6231
- total_member: ["\u53C2\u4F1A\u4EBA\u6570", "\u4EBA\u6570"],
6232
- /** 参会客户(CustomerComponent 客户浏览按钮):值是客户 id 列表,不是客户名称文本。 */
6233
- crm_members: ["\u53C2\u4F1A\u5BA2\u6237", "\u5BA2\u6237"],
6234
- crm_member_count: ["\u5E94\u5230\u5BA2\u6237\u6570", "\u5BA2\u6237\u6570"],
6235
- caller: ["\u53EC\u96C6\u4EBA", "\u53D1\u8D77\u4EBA"],
6236
- contacter: ["\u8054\u7CFB\u4EBA"],
6237
- mt_type: ["\u4F1A\u8BAE\u7C7B\u578B"],
6238
- other_remark: ["\u5907\u6CE8", "\u5176\u4ED6\u8BF4\u660E"]
6239
- };
6240
- var PERSON_FIELD_LABELS = { caller: "\u53EC\u96C6\u4EBA", contacter: "\u8054\u7CFB\u4EBA" };
6241
- function workflowEnv(env) {
6242
- return env;
6243
- }
6244
- async function loadCreateForm(env, workflowId) {
6245
- const { createWorkflowHost } = await import("./host-L3VLITMT.js");
6246
- const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
6247
- const { getWorkflowOperation } = await import("./registry-UGRBCBHO.js");
6248
- const wfEnv = {
6249
- ...workflowEnv(env),
6250
- host: createWorkflowHost(env.ctx),
6251
- continuation: createWorkflowContinuationSigner(env.ctx)
6252
- };
6253
- const operation = getWorkflowOperation("workflow.createForm");
6254
- const result = await operation.handler({ workflow: [workflowId] }, wfEnv);
6255
- const data = result?.data ?? {};
6256
- if (data.status !== "FORM_READY") {
6257
- throw meetingValidationError(
6258
- "flow_form_unavailable",
6259
- `\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u8F7D\u5165\u5931\u8D25\uFF08status=${String(data.status)}\uFF09\uFF1A${String(data.clarificationQuestion ?? data.note ?? "").slice(0, 200)}`,
6260
- { workflowId }
6261
- );
6262
- }
6263
- const wf = data.workflow ?? {};
6264
- return {
6265
- fields: data.fields ?? [],
6266
- continuation: data.continuation,
6267
- requestName: data.requestName,
6268
- contextId: data.contextId,
6269
- workflowName: String(wf.name ?? wf.workflowName ?? "").trim() || void 0
6270
- };
6271
- }
6272
- async function resolveEmployeeNames(env, ids) {
6273
- const map = /* @__PURE__ */ new Map();
6274
- const unique = [...new Set(ids.map((id) => String(id).trim()).filter((id) => id !== ""))];
6275
- if (unique.length === 0) return map;
6276
- try {
6277
- const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
6278
- const batch = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.batch");
6279
- if (!batch) return map;
6280
- const result = await batch.handler({ ids: unique }, env);
6281
- const rows = result?.data?.rows ?? result?.data?.userList ?? [];
6282
- for (const row of rows) {
6283
- const id = String(row.id ?? "").trim();
6284
- const name = String(row.name ?? "").trim();
6285
- if (id && name) map.set(id, name);
6286
- }
6287
- } catch {
6288
- }
6289
- return map;
6290
- }
6291
- async function resolvePersonTokens(env, tokens) {
6292
- const map = /* @__PURE__ */ new Map();
6293
- const unique = [...new Set(tokens.map((token) => String(token).trim()).filter((token) => token !== ""))];
6294
- if (unique.length === 0) return map;
6295
- const idLike = unique.filter((token) => /^\d{8,}$/.test(token));
6296
- const nameLike = unique.filter((token) => !/^\d{8,}$/.test(token));
6297
- if (idLike.length > 0) {
6298
- const names = await resolveEmployeeNames(env, idLike);
6299
- for (const id of idLike) map.set(id, { id, name: names.get(id) ?? id });
6300
- }
6301
- if (nameLike.length > 0) {
6302
- try {
6303
- const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
6304
- const query = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.query");
6305
- for (const name of nameLike) {
6306
- if (!query) break;
6307
- const found = await query.handler({ keyword: name, pageSize: 10 }, env).catch(() => null);
6308
- const rows = found?.data?.rows ?? [];
6309
- const exact = rows.find((row) => String(row.name ?? "").trim() === name);
6310
- const hit = exact ?? (rows.length === 1 ? rows[0] : void 0);
6311
- const id = String(hit?.id ?? "").trim();
6312
- if (id === "") continue;
6313
- map.set(name, { id, name: String(hit?.name ?? name) });
6314
- }
6315
- } catch {
6316
- }
6317
- }
6318
- return map;
6319
- }
6320
- async function resolveSelfPerson(env) {
6321
- let session = null;
6322
- try {
6323
- session = await env.host?.getSession?.();
6324
- } catch {
6325
- return null;
6326
- }
6327
- const id = String(session?.userId ?? "").trim();
6328
- if (id === "" || id === "unknown") return null;
6329
- const names = await resolveEmployeeNames(env, [id]);
6330
- const name = String(names.get(id) ?? "").trim();
6331
- if (name === "") return null;
6332
- return { id, name };
6333
- }
6334
- function applySelfPersonDefaults(args, self) {
6335
- const filled = [];
6336
- const missing = ["caller", "contacter"].filter((field) => String(args[field] ?? "").trim() === "");
6337
- if (missing.length === 0) return { filled, warning: "" };
6338
- if (!self) {
6339
- return {
6340
- filled,
6341
- warning: missing.length === 2 ? "\u26A0\uFE0F \u6CA1\u80FD\u786E\u8BA4\u5F53\u524D\u767B\u5F55\u7528\u6237\u5BF9\u5E94\u7684\u5458\u5DE5 \u2014\u2014\u300C\u53EC\u96C6\u4EBA\u300D\u300C\u8054\u7CFB\u4EBA\u300D\u4F1A\u7559\u7A7A\uFF0C\u8BF7\u663E\u5F0F\u4F20 caller / contacter\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002" : ""
6342
- };
6343
- }
6344
- for (const field of missing) {
6345
- args[field] = self.id;
6346
- filled.push({ field, id: self.id, name: self.name });
6347
- }
6348
- return { filled, warning: "" };
6349
- }
6350
- function parseRoomRef(input) {
6351
- const text = String(input ?? "").trim();
6352
- if (!text) return {};
6353
- const withId = /^(.*?)[((]\s*(\d{4,})\s*[))]$/.exec(text);
6354
- if (withId) {
6355
- const name = withId[1].trim();
6356
- const id = withId[2];
6357
- return name ? { id, name } : { id };
6358
- }
6359
- if (/^\d+$/.test(text)) return { id: text };
6360
- return { name: text };
6361
- }
6362
- async function resolveAddressRoom(env, input) {
6363
- const text = String(input ?? "").trim();
6364
- if (!text) return null;
6365
- const ref = parseRoomRef(text);
6366
- const { loadRooms: loadRooms2 } = await import("./room-recommend-A3UDC3CA.js");
6367
- let rooms = [];
6368
- try {
6369
- rooms = (await loadRooms2(env, {})).rooms;
6370
- } catch {
6371
- return { id: ref.id ?? "", name: ref.name ?? text, status: "unknown", lookupFailed: true };
6372
- }
6373
- const hit = (ref.id ? rooms.find((room) => room.id === ref.id) : void 0) ?? (ref.name ? rooms.find((room) => room.name === ref.name) : void 0);
6374
- if (hit) return { id: hit.id, name: hit.name, status: hit.status, statusText: hit.statusText };
6375
- if (ref.id) return { id: ref.id, name: ref.name ?? "", status: "unknown" };
6376
- return null;
6377
- }
6378
- async function resolveRoomValue(env, input) {
6379
- const text = String(input ?? "").trim();
6380
- if (!text) return null;
6381
- const resolved = await resolveAddressRoom(env, text).catch(() => null);
6382
- if (resolved?.id && !resolved.lookupFailed) {
6383
- return { id: resolved.id, name: resolved.name || resolved.id };
6384
- }
6385
- const ref = parseRoomRef(text);
6386
- if (ref.id) {
6387
- try {
6388
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
6389
- const detail = await getMeetingOperation2("meeting.eb.room.detail").handler({ id: ref.id }, env);
6390
- const main = detail?.data?.mainTable ?? detail?.data?.data?.mainTable ?? {};
6391
- const name = String(main.room_name ?? "").trim() || ref.name || "";
6392
- if (name) return { id: ref.id, name };
6393
- } catch {
6394
- }
6395
- return { id: ref.id, name: ref.name || ref.id };
6396
- }
6397
- return null;
6398
- }
6399
- async function shapeBrowserValues(env, values) {
6400
- const notes = [];
6401
- const shaped = { ...values };
6402
- const readable = {};
6403
- if (shaped.address !== void 0 && shaped.address !== "") {
6404
- const room = await resolveRoomValue(env, String(shaped.address));
6405
- if (room) {
6406
- shaped.address = room;
6407
- readable.address = room.name;
6408
- notes.push(`\u4F1A\u8BAE\u5730\u70B9\u6309\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${room.name}(${room.id})`);
6409
- } else {
6410
- readable.address = String(shaped.address);
6411
- }
6412
- }
6413
- const personFields = ["hrm_members", "caller", "contacter"];
6414
- const idPool = [];
6415
- for (const key of personFields) {
6416
- const raw = shaped[key];
6417
- if (raw === void 0 || raw === "") continue;
6418
- const ids = String(raw).split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6419
- idPool.push(...ids);
6420
- }
6421
- if (idPool.length > 0) {
6422
- const people = await resolvePersonTokens(env, idPool);
6423
- const toObject = (token) => people.get(token) ?? { id: token, name: token };
6424
- const toName = (token) => people.get(token)?.name ?? token;
6425
- if (shaped.hrm_members !== void 0 && shaped.hrm_members !== "") {
6426
- const ids = String(shaped.hrm_members).split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6427
- shaped.hrm_members = ids.map(toObject);
6428
- readable.hrm_members = ids.map(toName).join("\u3001");
6429
- notes.push(`\u53C2\u4F1A\u4EBA\u5458\u6309\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${ids.length} \u4EBA`);
6430
- }
6431
- if (shaped.caller !== void 0 && shaped.caller !== "") {
6432
- const id = String(shaped.caller).trim();
6433
- shaped.caller = toObject(id);
6434
- readable.caller = toName(id);
6435
- }
6436
- if (shaped.contacter !== void 0 && shaped.contacter !== "") {
6437
- const id = String(shaped.contacter).trim();
6438
- shaped.contacter = toObject(id);
6439
- readable.contacter = toName(id);
6440
- }
6441
- const unresolved = [...new Set(idPool)].filter((token) => !people.has(token));
6442
- if (unresolved.length > 0) {
6443
- notes.push(
6444
- `\u26A0\uFE0F \u6709 ${unresolved.length} \u4E2A\u4EBA\u5458\u6CA1\u89E3\u6790\u5230\u5458\u5DE5\uFF1A${unresolved.join("\u3001")} \u2014\u2014 \u8868\u5355\u91CC\u7684\u300C\u53C2\u4F1A\u4EBA\u5458/\u53EC\u96C6\u4EBA/\u8054\u7CFB\u4EBA\u300D\u53EF\u80FD\u663E\u793A\u4E0D\u51FA\u6765\u3002\u8BF7\u6539\u4F20\u5458\u5DE5 id\uFF0C\u6216\u786E\u8BA4\u59D3\u540D\u4E0E\u82B1\u540D\u518C\u5B8C\u5168\u4E00\u81F4\u3002`
6445
- );
6446
- }
6447
- }
6448
- if (shaped.crm_members !== void 0 && shaped.crm_members !== "") {
6449
- const rows = [];
6450
- const push = (idRaw, nameRaw) => {
6451
- const id = String(idRaw ?? "").trim();
6452
- const name = String(nameRaw ?? "").trim();
6453
- if (id === "" && name === "") return;
6454
- rows.push({ id, name });
6455
- };
6456
- const pushToken = (tokenRaw) => {
6457
- const token = String(tokenRaw ?? "").trim();
6458
- if (token === "") return;
6459
- const matched = token.match(/^(.*?)[((]\s*([0-9A-Za-z_-]+)\s*[))]$/);
6460
- if (matched) {
6461
- push(matched[2], matched[1]);
6462
- return;
6463
- }
6464
- if (/^\d{8,}$/.test(token)) {
6465
- push(token, "");
6466
- return;
6467
- }
6468
- push("", token);
6469
- };
6470
- const raw = shaped.crm_members;
6471
- if (Array.isArray(raw)) {
6472
- for (const item of raw) {
6473
- if (item && typeof item === "object") {
6474
- const obj = item;
6475
- push(obj.id ?? obj.sjID ?? obj.customerId, obj.name ?? obj.mc);
6476
- } else {
6477
- for (const token of String(item).split(/[,;,;]+/).map((one) => one.trim()).filter((one) => one !== "")) {
6478
- pushToken(token);
6479
- }
6480
- }
6481
- }
6482
- } else if (typeof raw === "object") {
6483
- const obj = raw;
6484
- push(obj.id ?? obj.sjID ?? obj.customerId, obj.name ?? obj.mc);
6485
- } else {
6486
- for (const token of String(raw).split(/[,;,;]+/).map((item) => item.trim()).filter((item) => item !== "")) {
6487
- pushToken(token);
6488
- }
6489
- }
6490
- if (rows.length > 0) {
6491
- const nameOnly = rows.filter((row) => row.id === "" && row.name !== "");
6492
- if (nameOnly.length > 0) {
6493
- try {
6494
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
6495
- const search = getMeetingOperation2("meeting.eb.crm.search");
6496
- for (const row of nameOnly) {
6497
- const found = await search.handler({ keyword: row.name, limit: 5 }, env).catch(() => null);
6498
- const items = found?.data?.items ?? [];
6499
- const hit = items.find((item) => String(item?.name ?? "").trim() === row.name) ?? items[0];
6500
- const id = String(hit?.customerId ?? "").trim();
6501
- if (id === "") continue;
6502
- row.id = id;
6503
- const fullName = String(hit?.name ?? "").trim();
6504
- if (fullName !== "") row.name = fullName;
6505
- }
6506
- } catch {
6507
- }
6508
- }
6509
- const unresolved = rows.filter((row) => row.id === "");
6510
- if (unresolved.length > 0) {
6511
- throw meetingValidationError(
6512
- "crm_not_found",
6513
- `\u53C2\u4F1A\u5BA2\u6237\u6709 ${unresolved.length} \u4E2A\u5728 CRM \u91CC\u67E5\u4E0D\u5230\uFF1A${unresolved.map((row) => row.name).join("\u3001")}\u3002\u8BF7\u786E\u8BA4\u5BA2\u6237\u540D\u79F0\uFF0C\u6216\u5148\u5230\u5BA2\u6237\u8868\u5EFA\u6863\uFF1B\u4E5F\u53EF\u4EE5\u6539\u7528\u300C\u5BA2\u6237\u540D(\u5BA2\u6237id)\u300D\u6216 \`[{id,name}]\` \u4F20 crm_members\u3002`
6514
- );
6515
- }
6516
- shaped.crm_members = rows;
6517
- readable.crm_members = rows.map((row) => row.name || row.id).join("\u3001");
6518
- notes.push(`\u53C2\u4F1A\u5BA2\u6237\u6309\u5BA2\u6237\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${rows.length} \u4E2A\u5BA2\u6237`);
6519
- const missingNames = rows.filter((row) => row.name === "");
6520
- if (missingNames.length > 0) {
6521
- throw meetingValidationError(
6522
- "crm_name_required",
6523
- `\u53C2\u4F1A\u5BA2\u6237\u6709 ${missingNames.length} \u4E2A\u53EA\u7ED9\u4E86 id\u3001\u6CA1\u6709\u5BA2\u6237\u540D\u79F0\uFF1A${missingNames.map((row) => row.id).join("\u3001")}\u3002\u5BA2\u6237\u6D4F\u89C8\u6309\u94AE\u5FC5\u987B\u5E26\u540D\u79F0\u624D\u80FD\u5199\u5165\uFF08\u53EA\u7ED9 id \u4F1A\u88AB\u670D\u52A1\u7AEF\u9759\u9ED8\u5B58\u6210\u7A7A\u503C\uFF09\u3002\u8BF7\u5148\u7528 \`meeting.eb.crm.search\` \u6309\u5BA2\u6237\u540D\u67E5\u5230 \`{ customerId, name }\`\uFF0C\u518D\u4EE5 \`[{id,name}]\` \u6216\u300C\u5BA2\u6237\u540D(\u5BA2\u6237id)\u300D\u7684\u5F62\u5F0F\u4F20 \`crm_members\`\u3002`
6524
- );
6525
- }
6526
- } else {
6527
- delete shaped.crm_members;
6528
- }
6529
- }
6530
- for (const [key, raw] of Object.entries(values)) {
6531
- if (readable[key] !== void 0) continue;
6532
- if (raw === void 0 || raw === null || raw === "") continue;
6533
- if (typeof raw === "object") continue;
6534
- readable[key] = String(raw);
6535
- }
6536
- return { values: shaped, notes, readable };
6537
- }
6538
- function normalizeFieldName(name) {
6539
- return String(name ?? "").replace(/[((][^(())]*[))]/g, "").replace(/[\s\u3000]+/g, "").trim();
6540
- }
6541
- var CRM_DETAIL_COLUMNS = {
6542
- xm: ["\u59D3\u540D", "\u5BA2\u6237\u59D3\u540D", "\u53C2\u4F1A\u4EBA", "\u53C2\u4F1A\u4EBA\u59D3\u540D"],
6543
- xb: ["\u6027\u522B"],
6544
- zw: ["\u804C\u4F4D", "\u804C\u52A1"],
6545
- sjhm: ["\u624B\u673A\u53F7\u7801", "\u624B\u673A\u53F7", "\u624B\u673A", "\u7535\u8BDD", "\u8054\u7CFB\u7535\u8BDD"],
6546
- bz: ["\u5907\u6CE8", "\u8BF4\u660E"]
6547
- };
6548
- function resolveCrmDetailTarget(fields) {
6549
- const groups = /* @__PURE__ */ new Map();
6550
- for (const field of fields) {
6551
- const sid = String(field.subFormId ?? "").trim();
6552
- if (!sid) continue;
6553
- const list = groups.get(sid);
6554
- if (list) list.push(field);
6555
- else groups.set(sid, [field]);
6556
- }
6557
- let best = null;
6558
- for (const [subFormId, list] of groups) {
6559
- const columns = {};
6560
- const labels = {};
6561
- for (const [semantic, aliases] of Object.entries(CRM_DETAIL_COLUMNS)) {
6562
- const hit = list.find((field) => aliases.includes(normalizeFieldName(field.name)));
6563
- if (!hit) continue;
6564
- columns[semantic] = hit.id;
6565
- labels[semantic] = hit.name;
6566
- }
6567
- if (!columns.xm) continue;
6568
- const score = Object.keys(columns).length + (columns.sjhm ? 1 : 0) + (columns.zw ? 1 : 0);
6569
- if (!best || score > best.score) best = { subFormId, columns, labels, score };
6570
- }
6571
- return best ? { subFormId: best.subFormId, columns: best.columns, labels: best.labels } : null;
6572
- }
6573
- function detectCrmMentionInText(...texts) {
6574
- for (const text of texts) {
6575
- if (typeof text !== "string") continue;
6576
- const value = text.trim();
6577
- if (value === "") continue;
6578
- const hit = /(?:参会|拜访|来访)?客户\s*(?:名称)?\s*(?:是|为|[::])\s*([^\s,,。;;、))]{2,40})/.exec(value);
6579
- if (hit?.[1]) return hit[1].trim();
6580
- }
6581
- return null;
6582
- }
6583
- function normalizeCrmDetailRows(raw) {
6584
- if (raw === void 0 || raw === null || raw === "") return [];
6585
- const list = Array.isArray(raw) ? raw : [raw];
6586
- const keyAlias = {
6587
- xm: "xm",
6588
- name: "xm",
6589
- customername: "xm",
6590
- \u59D3\u540D: "xm",
6591
- \u5BA2\u6237\u59D3\u540D: "xm",
6592
- xb: "xb",
6593
- gender: "xb",
6594
- sex: "xb",
6595
- \u6027\u522B: "xb",
6596
- zw: "zw",
6597
- title: "zw",
6598
- position: "zw",
6599
- job: "zw",
6600
- \u804C\u4F4D: "zw",
6601
- \u804C\u52A1: "zw",
6602
- sjhm: "sjhm",
6603
- mobile: "sjhm",
6604
- phone: "sjhm",
6605
- tel: "sjhm",
6606
- \u624B\u673A\u53F7\u7801: "sjhm",
6607
- \u624B\u673A\u53F7: "sjhm",
6608
- \u7535\u8BDD: "sjhm",
6609
- \u8054\u7CFB\u7535\u8BDD: "sjhm",
6610
- bz: "bz",
6611
- remark: "bz",
6612
- note: "bz",
6613
- \u5907\u6CE8: "bz",
6614
- \u8BF4\u660E: "bz"
6615
- };
6616
- const rows = [];
6617
- for (const item of list) {
6618
- if (item === void 0 || item === null || typeof item !== "object") continue;
6619
- const row = {};
6620
- for (const [key, value] of Object.entries(item)) {
6621
- const semantic = keyAlias[String(key).trim().toLowerCase()] ?? keyAlias[String(key).trim()];
6622
- if (!semantic) continue;
6623
- if (value === void 0 || value === null) continue;
6624
- const text = String(value).trim();
6625
- if (text === "") continue;
6626
- row[semantic] = text;
6627
- }
6628
- if (!row.xm && !row.sjhm) continue;
6629
- rows.push(row);
6630
- }
6631
- return rows;
6632
- }
6633
- function crmMemberEntriesFromArgs(raw) {
6634
- const list = Array.isArray(raw) ? raw : raw === void 0 || raw === null || raw === "" ? [] : [raw];
6635
- const out = [];
6636
- const push = (idRaw, nameRaw, contactsRaw) => {
6637
- const id = String(idRaw ?? "").trim();
6638
- const name = String(nameRaw ?? "").trim();
6639
- if (id === "" && name === "") return;
6640
- const contacts = (Array.isArray(contactsRaw) ? contactsRaw : []).map((item) => {
6641
- const row = item ?? {};
6642
- return {
6643
- name: String(row.name ?? row.xm ?? "").trim(),
6644
- mobile: String(row.mobile ?? row.sjhm ?? row.phone ?? "").trim(),
6645
- ...String(row.dept ?? row.bm ?? "").trim() === "" ? {} : { dept: String(row.dept ?? row.bm).trim() }
6646
- };
6647
- }).filter((one) => one.name !== "" || one.mobile !== "");
6648
- out.push({ id: id === "" ? name : id, name, contacts });
6649
- };
6650
- for (const item of list) {
6651
- if (item && typeof item === "object") {
6652
- const obj = item;
6653
- push(obj.customerId ?? obj.sjID ?? obj.id, obj.name ?? obj.mc, obj.contacts ?? obj.lxr);
6654
- } else {
6655
- const token = String(item).trim();
6656
- if (token === "") continue;
6657
- const matched = token.match(/^(.*?)[((]\s*([0-9A-Za-z_-]+)\s*[))]$/);
6658
- if (matched) push(matched[2], matched[1], void 0);
6659
- else push(token, "", void 0);
6660
- }
6661
- }
6662
- return out;
6663
- }
6664
- function crmContactsToDetailRows(entries) {
6665
- const rows = [];
6666
- const seen = /* @__PURE__ */ new Set();
6667
- for (const entry of entries) {
6668
- for (const contact of entry.contacts) {
6669
- const xm = contact.name.trim();
6670
- const sjhm = contact.mobile.trim();
6671
- if (xm === "" && sjhm === "") continue;
6672
- const key = `${xm}|${sjhm}`;
6673
- if (seen.has(key)) continue;
6674
- seen.add(key);
6675
- const row = { xm: xm === "" ? sjhm : xm };
6676
- if (sjhm !== "") row.sjhm = sjhm;
6677
- if (contact.dept && contact.dept.trim() !== "") row.bz = `\u90E8\u95E8\uFF1A${contact.dept.trim()}`;
6678
- rows.push(row);
6679
- }
6680
- }
6681
- return rows;
6682
- }
6683
- async function resolveAutoCrmDetailRows(env, raw) {
6684
- const entries = crmMemberEntriesFromArgs(raw);
6685
- const missing = [];
6686
- if (entries.length > 0) {
6687
- try {
6688
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
6689
- const search = getMeetingOperation2("meeting.eb.crm.search");
6690
- for (const entry of entries) {
6691
- if (entry.contacts.length > 0) continue;
6692
- const keyword = (entry.name || entry.id).trim();
6693
- if (keyword === "") {
6694
- missing.push(entry.id);
6695
- continue;
6696
- }
6697
- const shortBase = keyword.split("--")[0].trim();
6698
- const stripped = shortBase.replace(/[((][^))]*[))]/gu, "").replace(/(股份有限公司|有限责任公司|集团有限公司|有限公司|集团|公司)$/u, "").trim();
6699
- const candidates = [...new Set([keyword, shortBase, stripped, shortBase.slice(0, 4)].filter((one) => one !== ""))];
6700
- let live = [];
6701
- for (const candidate of candidates) {
6702
- const found = await search.handler({ keyword: candidate, limit: 50 }, env).catch(() => null);
6703
- const items = found?.data?.items ?? [];
6704
- const hit = entry.id !== "" ? items.find((item) => String(item?.customerId ?? "") === entry.id) : void 0;
6705
- const contacts = hit?.contacts ?? [];
6706
- if (contacts.length > live.length) live = contacts;
6707
- }
6708
- if (live.length === 0) {
6709
- missing.push(entry.name || entry.id);
6710
- continue;
6711
- }
6712
- entry.contacts = live;
6713
- }
6714
- } catch {
6715
- }
6716
- }
6717
- return {
6718
- rows: crmContactsToDetailRows(entries),
6719
- customers: entries.map((entry) => entry.name || entry.id).filter((one) => one !== ""),
6720
- missing
6721
- };
6722
- }
6723
- function mapFields(fields, values, preferred = {}) {
6724
- const byName = new Map(fields.map((field) => [field.name.trim(), field]));
6725
- const byId = new Map(fields.map((field) => [field.id, field]));
6726
- const byNormalized = /* @__PURE__ */ new Map();
6727
- for (const field of fields) {
6728
- const key = normalizeFieldName(field.name);
6729
- if (key && !byNormalized.has(key)) byNormalized.set(key, field);
6730
- }
6731
- const main = {};
6732
- const mapped = {};
6733
- const unmapped = [];
6734
- const resolved = {};
6735
- const findField = (aliases) => {
6736
- for (const name of aliases) {
6737
- const field = byName.get(name);
6738
- if (field) return field;
6739
- }
6740
- for (const name of aliases) {
6741
- const field = byNormalized.get(normalizeFieldName(name));
6742
- if (field) return field;
6743
- }
6744
- for (const name of aliases) {
6745
- const needle = normalizeFieldName(name);
6746
- if (needle.length < 2) continue;
6747
- for (const [key, field] of byNormalized) {
6748
- if (key.includes(needle)) return field;
6749
- }
6750
- }
6751
- return void 0;
6752
- };
6753
- for (const [key, raw] of Object.entries(values)) {
6754
- if (raw === void 0 || raw === null || raw === "") continue;
6755
- const aliases = FIELD_ALIASES[key] ?? [key];
6756
- const prefId = preferred[key];
6757
- const hit = (prefId ? byId.get(prefId) : void 0) ?? findField(aliases);
6758
- if (!hit) {
6759
- unmapped.push(key);
6760
- continue;
6761
- }
6762
- main[hit.id] = raw;
6763
- mapped[key] = `${hit.name}(${hit.id})`;
6764
- resolved[key] = hit.id;
6765
- }
6766
- return { main, mapped, unmapped, resolved };
6767
- }
6768
- var PREVIEW_PERSON_FIELD_RE = /^(召集人|联系人|参会人员|会议创建人|主讲人|负责人|费用承担人)$/;
6769
- async function decoratePreviewPersonNames(env, main, fields, known = /* @__PURE__ */ new Map()) {
6770
- const targets = fields.filter((field) => PREVIEW_PERSON_FIELD_RE.test(String(field?.name ?? "").trim()));
6771
- if (targets.length === 0) return main;
6772
- const ID_ONLY_RE = /^\d{8,}$/;
6773
- const missingNameId = (value) => {
6774
- if (typeof value === "string") return ID_ONLY_RE.test(value.trim()) ? value.trim() : null;
6775
- if (value && typeof value === "object" && !Array.isArray(value)) {
6776
- const obj = value;
6777
- const id = String(obj.id ?? "").trim();
6778
- const name = String(obj.name ?? "").trim();
6779
- if (id !== "" && (name === "" || name === id)) return id;
6780
- }
6781
- return null;
6782
- };
6783
- const ids = /* @__PURE__ */ new Set();
6784
- for (const field of targets) {
6785
- const value = main[field.id];
6786
- const one = missingNameId(value);
6787
- if (one) ids.add(one);
6788
- else if (Array.isArray(value)) for (const item of value) {
6789
- const hit = missingNameId(item);
6790
- if (hit) ids.add(hit);
6791
- }
6792
- }
6793
- if (ids.size === 0) return main;
6794
- let names = new Map(known);
6795
- const unknown = [...ids].filter((id) => !names.has(id));
6796
- if (unknown.length > 0) {
6797
- try {
6798
- const resolved = await resolveEmployeeNames(env, unknown);
6799
- for (const [id, name] of resolved) names.set(id, name);
6800
- } catch {
6801
- }
6802
- }
6803
- if (names.size === 0) return main;
6804
- const rename = (value) => {
6805
- const one = missingNameId(value);
6806
- if (one) return names.get(one) ?? value;
6807
- if (value && typeof value === "object" && !Array.isArray(value)) {
6808
- const obj = value;
6809
- const id = String(obj.id ?? "").trim();
6810
- const name = names.get(id);
6811
- if (name) return { ...obj, name };
6812
- }
6813
- return value;
6814
- };
6815
- const decorated = { ...main };
6816
- for (const field of targets) {
6817
- const value = decorated[field.id];
6818
- decorated[field.id] = Array.isArray(value) ? value.map(rename) : rename(value);
6819
- }
6820
- return decorated;
6821
- }
6822
- function renderFormPreview(fields, main) {
6823
- const fmt = (value) => {
6824
- if (value === void 0 || value === null) return "\u2014";
6825
- if (Array.isArray(value)) {
6826
- const parts = value.map((one) => fmt(one)).filter((one) => one !== "\u2014");
6827
- return parts.length > 0 ? parts.join("\u3001") : "\u2014";
6828
- }
6829
- if (typeof value === "object") {
6830
- const obj = value;
6831
- const name = String(obj.name ?? obj.mc ?? "").trim();
6832
- if (name !== "") return name.replace(/\|/gu, "/");
6833
- const id = String(obj.id ?? obj.customerId ?? obj.sjID ?? "").trim();
6834
- return id === "" ? "\u2014" : id;
6835
- }
6836
- const text = String(value).trim();
6837
- return text === "" ? "\u2014" : text.replace(/\|/gu, "/").replace(/\r?\n/gu, " ");
6838
- };
6839
- const lines = ["| \u5B57\u6BB5 | \u503C |", "| --- | --- |"];
6840
- const known = /* @__PURE__ */ new Set();
6841
- for (const field of fields) {
6842
- known.add(field.id);
6843
- if (!(field.id in main)) continue;
6844
- lines.push(`| ${String(field.name).replace(/\|/gu, "/")} | ${fmt(main[field.id])} |`);
6845
- }
6846
- for (const [id, value] of Object.entries(main)) {
6847
- if (known.has(id)) continue;
6848
- lines.push(`| ${id} | ${fmt(value)} |`);
6849
- }
6850
- return lines.join("\n");
6851
- }
6852
- function flowFieldCacheDir(env) {
6853
- const configured = env?.ctx?.config?.path?.();
6854
- const root = configured ? resolve5(String(configured), "..") : process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve5(homedir(), ".weaver-work-cli");
6855
- return resolve5(root, "meeting", "cache");
6856
- }
6857
- function flowFieldCacheFile(env, workflowId) {
6858
- return resolve5(flowFieldCacheDir(env), `flow-fields-${workflowId}.json`);
6859
- }
6860
- async function readFlowFieldMap(env, workflowId) {
6861
- try {
6862
- const file = flowFieldCacheFile(env, workflowId);
6863
- if (!existsSync3(file)) return {};
6864
- const parsed = JSON.parse(await readFile4(file, "utf8"));
6865
- return parsed && typeof parsed.mapping === "object" && parsed.mapping ? parsed.mapping : {};
6866
- } catch {
6867
- return {};
6868
- }
6869
- }
6870
- async function writeFlowFieldMap(env, workflowId, workflowName, mapping) {
6871
- if (Object.keys(mapping).length === 0) return;
6872
- try {
6873
- const file = flowFieldCacheFile(env, workflowId);
6874
- await mkdir4(resolve5(file, ".."), { recursive: true });
6875
- const cache = {
6876
- workflowId,
6877
- ...workflowName ? { workflowName } : {},
6878
- savedAt: (/* @__PURE__ */ new Date()).toISOString(),
6879
- mapping
6880
- };
6881
- await writeFile4(file, JSON.stringify(cache, null, 2), "utf8");
6882
- } catch {
6883
- }
6884
- }
6885
- function normalizeWorkflowIds(raw) {
6886
- if (raw === void 0 || raw === null) return [];
6887
- const list = Array.isArray(raw) ? raw : [raw];
6888
- const ids = [];
6889
- for (const item of list) {
6890
- for (const piece of String(item ?? "").split(/[,;,;\s]+/)) {
6891
- const term = piece.trim();
6892
- if (!term) continue;
6893
- const matched = term.match(/[((](\d{6,})[))]$/);
6894
- const id = matched ? matched[1] : term;
6895
- if (!ids.includes(id)) ids.push(id);
6896
- }
6897
- }
6898
- return ids;
6899
- }
6900
- var FIXED_FLOW_IDS = ["1326190634427154474", "1325677244111462606"];
6901
- var FIXED_FLOW_PROFILES = [
6902
- {
6903
- host: "www.e-cology.com.cn",
6904
- tenantKey: "t7akvdnf84",
6905
- label: "\u6CDB\u5FAE\u751F\u4EA7\uFF08\u6CDB\u5FAE\u7F51\u7EDC\uFF09",
6906
- ids: [...FIXED_FLOW_IDS]
6907
- }
6908
- ];
6909
- function fixedFlowFlagOn() {
6910
- const flag = String(process.env.WEAVER_MEETING_FIXED_FLOW ?? "1").trim().toLowerCase();
6911
- return !(flag === "0" || flag === "false" || flag === "off");
6912
- }
6913
- function fixedFlowOverride() {
6914
- const override = String(process.env.WEAVER_MEETING_FIXED_FLOW_IDS ?? "").trim();
6915
- if (!override) return [];
6916
- return override.split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6917
- }
6918
- async function fixedFlowIdsForEnv(env) {
6919
- if (!fixedFlowFlagOn()) return { ids: [] };
6920
- const override = fixedFlowOverride();
6921
- if (override.length > 0) return { ids: override, label: "\u73AF\u5883\u53D8\u91CF\u6307\u5B9A" };
6922
- let baseUrl = "";
6923
- let tenantKey = "";
6924
- try {
6925
- const session = await env?.host?.getSession?.();
6926
- baseUrl = String(session?.baseUrl ?? "");
6927
- tenantKey = String(session?.tenantKey ?? session?.tenantId ?? "");
6928
- } catch {
6929
- }
6930
- if (!baseUrl) return { ids: [...FIXED_FLOW_IDS], label: "\u9ED8\u8BA4\u56FA\u5316\u914D\u7F6E\uFF08\u672A\u53D6\u5230\u767B\u5F55\u73AF\u5883\uFF09" };
6931
- const host = baseUrl.replace(/^https?:\/\//i, "").replace(/\/.*$/, "").toLowerCase();
6932
- const hit = FIXED_FLOW_PROFILES.find((profile) => profile.host === host && (!profile.tenantKey || !tenantKey || profile.tenantKey === tenantKey));
6933
- return hit ? { ids: [...hit.ids], label: hit.label } : { ids: [] };
6934
- }
6935
- function shouldAutoPickFlow(args) {
6936
- if (args.flowChoice === "auto") return true;
6937
- return String(process.env.WEAVER_MEETING_FLOW_CHOICE ?? "").trim().toLowerCase() === "auto";
6938
- }
6939
- async function resolveWorkflowId(env, args) {
6940
- const explicitList = normalizeWorkflowIds(args.workflowId);
6941
- if (explicitList.length > 0) {
6942
- return {
6943
- workflowId: explicitList.length === 1 ? explicitList[0] : "",
6944
- candidates: explicitList,
6945
- source: "argument"
6946
- };
6947
- }
6948
- const fixed = await fixedFlowIdsForEnv(env);
6949
- if (fixed.ids.length > 0) {
6950
- return {
6951
- workflowId: fixed.ids.length === 1 ? fixed.ids[0] : "",
6952
- candidates: fixed.ids,
6953
- source: "fixed",
6954
- ...fixed.label ? { label: fixed.label } : {}
6955
- };
6956
- }
6957
- const settings = await fetchEbAppSettings(env, "meeting.eb.meeting.create.flow.prepare");
6958
- const candidates = String(settings.mtNewWf ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6959
- if (candidates.length === 0) {
6960
- throw meetingValidationError(
6961
- "flow_not_configured",
6962
- "\u5E94\u7528\u8BBE\u7F6E\u91CC\u6CA1\u6709\u914D\u7F6E\u300C\u65B0\u5EFA\u4F1A\u8BAE\u5DE5\u4F5C\u6D41\u300D\uFF08mt_new_wf \u4E3A\u7A7A\uFF09\uFF0C\u4E5F\u6CA1\u6709\u542F\u7528\u56FA\u5316\u6D41\u7A0B\uFF0C\u65E0\u6CD5\u8D70\u6D41\u7A0B\u5EFA\u4F1A\uFF1B\u8BF7\u7BA1\u7406\u5458\u5728\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\u91CC\u914D\u7F6E\uFF0C\u6216\u7528 WEAVER_MEETING_FIXED_FLOW_IDS \u6307\u5B9A\u9ED8\u8BA4\u6D41\u7A0B"
6963
- );
6964
- }
6965
- return { workflowId: candidates.length === 1 ? candidates[0] : "", candidates, source: "settings" };
6966
- }
6967
- function pad2(value) {
6968
- return String(value).padStart(2, "0");
6969
- }
6970
- function tomorrowIso() {
6971
- const date = new Date(Date.now() + 24 * 60 * 60 * 1e3);
6972
- return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
6973
- }
6974
- function formatMinute(date) {
6975
- return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`;
6976
- }
6977
- async function probeWorkflowCandidates(env, ids) {
6978
- const probed = await Promise.all(ids.map(async (id) => {
6979
- try {
6980
- const probeForm = await loadCreateForm(env, id);
6981
- return {
6982
- id,
6983
- probeForm,
6984
- probe: {
6985
- workflowId: id,
6986
- ...probeForm.workflowName ? { name: probeForm.workflowName } : {},
6987
- launchable: true
6988
- }
6989
- };
6990
- } catch (error) {
6991
- return {
6992
- id,
6993
- probeForm: null,
6994
- probe: {
6995
- workflowId: id,
6996
- launchable: false,
6997
- reason: String(error?.message ?? error).slice(0, 160)
6998
- }
6999
- };
7000
- }
7001
- }));
7002
- const probes = [];
7003
- const loadedForms = /* @__PURE__ */ new Map();
7004
- for (const item of probed) {
7005
- if (item.probeForm) loadedForms.set(item.id, item.probeForm);
7006
- probes.push(item.probe);
7007
- }
7008
- return { probes, loadedForms };
7009
- }
7010
- var ebMeetingCreateFlowPrepare = {
7011
- name: "meeting.eb.meeting.create.flow.prepare",
7012
- resource: "eb",
7013
- method: "meeting.eb.meeting.create.flow.prepare",
7014
- action: "meeting.eb.meeting.create.flow.prepare",
7015
- summary: '\u6D41\u7A0B\u5EFA\u4F1A\uFF08\u51C6\u5907\uFF09\uFF1A\u7528\u56FA\u5316\u6D41\u7A0B\u5019\u9009\u9010\u4E2A\u63A2\u6D4B\u53D1\u8D77\u6743\u9650 \u2014\u2014 \u4EC5 1 \u4E2A\u53EF\u53D1\u8D77\u5C31\u81EA\u52A8\u7528\u5B83\u3001\u591A\u4E2A\u90FD\u53EF\u53D1\u8D77\u5219\u8FD4\u56DE\u9009\u9879\u8BA9\u7528\u6237\u9009\u3001\u90FD\u4E0D\u53EF\u53D1\u8D77\u62A5\u300C\u6CA1\u6709\u53D1\u8D77\u6743\u9650\u300D\uFF1B\u4E0D\u4F20 begin_datetime \u65F6\u81EA\u52A8\u63A8\u8350\u300C\u4EBA+\u4F1A\u8BAE\u5BA4\u90FD\u7A7A\u95F2\u300D\u7684\u65F6\u6BB5\u3002\u53EA\u51FA\u9884\u89C8\u4E0E\u786E\u8BA4\u7968\u636E\uFF0C\u4E0D\u63D0\u4EA4\u3002\u26A0\uFE0F \u7528\u6237\u63D0\u5230\u5BA2\u6237\u540D\uFF08\u300C\u5BA2\u6237\u662F X\u300D\uFF09\u65F6**\u5FC5\u987B\u5148** meeting.eb.crm.search {"keyword":"X"} \u62FF customerId\uFF0C\u518D\u4F20 crm_members:[{id,name}]\uFF1B\u53EA\u628A\u5BA2\u6237\u540D\u5199\u8FDB\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\uFF0C\u8868\u5355\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5C31\u662F\u7A7A\u7684',
7016
- capability: "eb.meeting",
7017
- risk: "read-before-write",
7018
- requiresConfirmation: true,
7019
- inputSchema: schemaOf(
7020
- {
7021
- mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
7022
- begin_datetime: {
7023
- ...SCHEMA_DATETIME_MINUTE,
7024
- description: "\u5F00\u59CB\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\u3002**\u53EF\u4EE5\u4E0D\u4F20**\uFF1A\u4E0D\u4F20\u4F1A\u6309\u53C2\u4F1A\u4EBA\u4E0E\u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u60C5\u51B5\u63A8\u8350 3 \u4E2A\u65F6\u6BB5\u8BA9\u4F60\u9009\uFF1B\u53EA\u4F20\u5F00\u59CB\u65F6\u95F4\u3001\u4E0D\u4F20\u7ED3\u675F\u65F6\u95F4\u65F6\uFF0C\u6309 durationMinutes\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09\u81EA\u52A8\u7B97\u7ED3\u675F\u65F6\u95F4"
7025
- },
7026
- end_datetime: {
7027
- ...SCHEMA_DATETIME_MINUTE,
7028
- description: "\u7ED3\u675F\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\uFF1B\u4E0D\u4F20\u5219\u6309 durationMinutes \u4ECE\u5F00\u59CB\u65F6\u95F4\u63A8\u7B97\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09"
7029
- },
7030
- mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
7031
- address: { type: "string", description: "\u4F1A\u8BAE\u5BA4\uFF08\u540D\u79F0\u6216 id\uFF0C\u6309\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u8981\u6C42\uFF09" },
7032
- customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
7033
- hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u5458\uFF08\u9017\u53F7\u5206\u9694\u5458\u5DE5 id \u6216\u59D3\u540D\uFF0C\u6309\u6D41\u7A0B\u8868\u5355\u8981\u6C42\uFF09" },
7034
- total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
7035
- crm_members: {
7036
- oneOf: [{ type: "string" }, { type: "array", items: { oneOf: [{ type: "string" }, { type: "object" }] } }],
7037
- description: "\u53C2\u4F1A\u5BA2\u6237\uFF1A**\u5FC5\u987B\u5E26\u5BA2\u6237\u540D\u79F0**\uFF0C\u5199\u6CD5 `[{id,name}]` \u6216\u300C\u5BA2\u6237\u540D(\u5BA2\u6237id)\u300D\u6216\u9017\u53F7\u5206\u9694\u7684\u8FD9\u4E24\u79CD\u3002\u5BA2\u6237\u5148\u4ECE `meeting.eb.crm.search` \u6309\u5BA2\u6237\u540D\u67E5\u51FA\uFF08\u5165\u53C2 custom_name\uFF0C\u51FA\u53C2 items[].customerId / name\uFF09\uFF0C\u8BE5\u67E5\u8BE2**\u4E00\u6B21\u53EA\u56DE\u9996\u4E2A\u5339\u914D** \u21D2 exact=false \u65F6\u5FC5\u987B\u5148\u8BA9\u7528\u6237\u786E\u8BA4\u5BA2\u6237\u540D\u518D\u5199\u8FD9\u4E2A\u5B57\u6BB5\u3002\u26D4 \u53EA\u7ED9 id \u4E0D\u7ED9\u540D\u79F0\u4F1A\u88AB\u62D2\u7EDD\uFF08\u5BA2\u6237\u6D4F\u89C8\u6309\u94AE\u6309\u540D\u79F0\u843D\u503C\uFF0C\u53EA\u7ED9 id \u4F1A\u9759\u9ED8\u5B58\u6210\u7A7A\uFF09"
7038
- },
7039
- crm_member_count: { type: "number", description: "\u5E94\u5230\u5BA2\u6237\u6570\uFF1B\u4E0D\u4F20\u5219\u6309 crm_members \u6761\u6570\u81EA\u52A8\u7B97" },
7040
- crm_member_details: {
7041
- type: "array",
7042
- description: '\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\uFF08\u5BBF\u4E3B\u8868\u5355\u91CC\u7684\u660E\u7EC6\u8868\uFF0C\u5217 \u59D3\u540D/\u6027\u522B/\u804C\u4F4D/\u624B\u673A\u53F7\u7801/\u5907\u6CE8\uFF09\uFF1A\u6BCF\u884C `{"xm":"\u5F20\u4E09","xb":"\u7537","zw":"\u7ECF\u7406","sjhm":"138...","bz":""}`\uFF0C\u4E5F\u63A5\u53D7\u4E2D\u6587\u952E\uFF08\u59D3\u540D/\u6027\u522B/\u804C\u4F4D/\u624B\u673A\u53F7\u7801/\u5907\u6CE8\uFF09\u3002\u5217\u5B57\u6BB5 id \u7531 CLI \u4ECE\u8868\u5355\u91CC\u6309\u5217\u540D\u53CD\u67E5\uFF0C\u4E0D\u7528\u4F20\u3002\u26A0\uFE0F \u8BE5\u660E\u7EC6\u8868\u5FC5\u987B\u5728\u53D1\u8D77\u8282\u70B9\u5E03\u5C40\u91CC\uFF08\u5426\u5219 CLI \u4F1A\u63D0\u793A"\u8868\u5355\u91CC\u6CA1\u6709\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6"\u5E76\u5FFD\u7565\u8FD9\u4E9B\u884C\uFF09\u26D4 \u9ED8\u8BA4\u4E0D\u751F\u6548\uFF1A\u5BA2\u6237\u8054\u7CFB\u4EBA\u7531 CLI \u6309 CRM \u5168\u91CF\u81EA\u52A8\u5E26\u5165\uFF0C\u8FD9\u91CC\u53EA\u5728 crm_detail_mode:"only" \u65F6\u624D\u7528\u6765"\u53EA\u5199\u8FD9\u51E0\u4F4D"',
7043
- items: { type: "object" }
7044
- },
7045
- crm_detail_mode: {
7046
- type: "string",
7047
- description: '\u660E\u7EC6\u884C\u53E3\u5F84\uFF1A\u4E0D\u4F20\uFF08\u9ED8\u8BA4\uFF09= \u6309 CRM \u628A\u8BE5\u5BA2\u6237**\u5168\u90E8**\u8054\u7CFB\u4EBA\u81EA\u52A8\u5199\u5165\u300C\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\u300D\uFF08\u4E00\u4EBA\u4E00\u884C\uFF0C\u4E0D\u7528\u95EE\u7528\u6237\u9009\u54EA\u4F4D\uFF09\uFF1B\u4F20 "only" = \u53EA\u5199 crm_member_details \u91CC\u70B9\u540D\u7684\u8FD9\u51E0\u4F4D'
7048
- },
7049
- caller: { type: "string", description: "\u53EC\u96C6\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u53EC\u96C6\u4EBA\u624D\u4F20" },
7050
- contacter: { type: "string", description: "\u8054\u7CFB\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u8054\u7CFB\u4EBA\u624D\u4F20" },
7051
- mt_type: {
7052
- type: "string",
7053
- description: "\u4F1A\u8BAE\u7C7B\u578B\uFF1A\u53EF\u4F20\u7C7B\u578B\u540D\u79F0\u6216 id\uFF08\u5148\u7528 `meeting.eb.type.list` \u67E5\u6709\u54EA\u4E9B\uFF09\u3002**\u5F88\u591A\u79DF\u6237\u7684\u6D41\u7A0B\u8868\u5355\u628A\u300C\u4F1A\u8BAE\u7C7B\u578B\u300D\u8BBE\u4E3A\u5FC5\u586B**\uFF0C\u4E0D\u4F20\u4F1A\u88AB `workflow.createRequest` \u6253\u56DE\u7F3A\u5B57\u6BB5"
7054
- },
7055
- other_remark: { type: "string", description: "\u5907\u6CE8" },
7056
- workflowId: {
7057
- oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
7058
- description: "\u6307\u5B9A\u5EFA\u4F1A\u6D41\u7A0B id\uFF1A\u5355\u4E2A id\u3001id \u6570\u7EC4\u6216\u9017\u53F7\u5206\u9694\u90FD\u53EF\u4EE5\uFF0C\u4E5F\u63A5\u53D7\u300C\u6D41\u7A0B\u540D(123456)\u300D\u5199\u6CD5\u3002**\u4F20\u591A\u4E2A\u65F6 CLI \u540C\u6837\u4E0D\u4F1A\u66FF\u4F60\u9009**\u2014\u2014\u4F1A\u9010\u4E2A\u63A2\u6D4B\u53EF\u53D1\u8D77\u6027\uFF0C\u591A\u4E2A\u53EF\u7528\u5219\u8FD4\u56DE NEEDS_SELECTION \u8BA9\u7528\u6237\u6311\uFF1B\u4E0D\u4F20\u5219\u7528\u5E94\u7528\u8BBE\u7F6E mt_new_wf \u914D\u7F6E\u7684\u6D41\u7A0B\uFF08\u914D\u4E86\u591A\u4E2A\u65F6\u540C\u6837\u8BA9\u7528\u6237\u9009\uFF09"
7059
- },
7060
- autoRoom: { type: "boolean", description: "\u9ED8\u8BA4 false\uFF1A\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\u65F6\u8FD4\u56DE\u5019\u9009\u8BA9\u7528\u6237\u9009\uFF1B\u4F20 true \u624D\u81EA\u52A8\u91C7\u7528\u63A8\u8350" },
7061
- allowNoRoom: { type: "boolean", description: "\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\u7B49\uFF09\u65F6\u4F20 true\uFF0C\u907F\u514D\u88AB\u201C\u8BF7\u9009\u62E9\u4F1A\u8BAE\u5BA4\u201D\u62E6\u4F4F" },
7062
- timeConfirmed: {
7063
- type: "boolean",
7064
- description: '\u26D4 **\u65F6\u95F4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0**\u3002\u53EA\u6709\u4EE5\u4E0B\u4E24\u79CD\u60C5\u51B5\u624D\u4F20 true\uFF1A\u2460 \u7528\u6237\u539F\u8BDD\u91CC\u660E\u786E\u7ED9\u51FA\u4E86\u65F6\u95F4\uFF08\u5982"\u660E\u5929 9 \u70B9\u5230 10 \u70B9"\uFF09\uFF1B\u2461 \u7528\u6237\u5728\u65F6\u6BB5\u9009\u9879\u91CC\u70B9\u9009\u540E\uFF0C\u628A `options[].value` **\u6574\u4F53**\u539F\u6837\u56DE\u4F20\uFF08value \u81EA\u5E26\u8BE5\u6807\u8BB0\uFF09\u3002\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF1A\u5373\u4F7F\u4F60\u4F20\u4E86 begin_datetime\uFF0CCLI \u4E5F**\u4E0D\u4F1A**\u5F53\u6210\u5DF2\u5B9A\uFF0C\u800C\u662F\u8FD4\u56DE\u65F6\u6BB5\u9009\u9879\u8BA9\u7528\u6237\u70B9\u9009\u3002\u26D4 \u7528\u6237\u53EA\u8BF4"\u660E\u5929/\u4E0A\u5348/\u4E0B\u5348"\u8FD9\u7C7B\u6A21\u7CCA\u8BF4\u6CD5\u65F6\uFF0C**\u5FC5\u987B\u4E0D\u4F20**\uFF0C\u8BA9 CLI \u7ED9\u5019\u9009'
7065
- },
7066
- roomConfirmed: {
7067
- type: "boolean",
7068
- description: '\u26D4 **\u4F1A\u8BAE\u5BA4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0**\u3002\u53EA\u6709\u4EE5\u4E0B\u4E24\u79CD\u60C5\u51B5\u624D\u4F20 true\uFF1A\u2460 \u7528\u6237\u539F\u8BDD\u660E\u786E\u6307\u5B9A\u4E86\u67D0\u95F4\u4F1A\u8BAE\u5BA4\uFF1B\u2461 \u7528\u6237\u5728\u623F\u95F4\u9009\u9879\u91CC\u70B9\u9009\u540E\u628A `options[].value` \u6574\u4F53\u539F\u6837\u56DE\u4F20\u3002\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF1A\u5373\u4F7F\u4F20\u4E86 address\uFF0CCLI \u4E5F\u4F1A\u628A"\u4F60\u6307\u5B9A\u7684\u8FD9\u95F4"\u548C\u63A8\u8350\u5019\u9009\u4E00\u8D77\u5217\u51FA\u6765\u8BA9\u7528\u6237\u70B9\u9009\u3002\u26D4 \u4E0D\u8981\u81EA\u5DF1\u4ECE room.list / room.recommend \u91CC\u6311\u4E00\u95F4\u585E\u8FDB address \u2014\u2014 \u90A3\u662F\u66FF\u7528\u6237\u62CD\u677F'
7069
- },
7070
- extraFields: {
7071
- type: "object",
7072
- description: '\u6309**\u6D41\u7A0B\u8868\u5355\u91CC\u7684\u5B57\u6BB5\u540D**\u586B\u989D\u5916\u5B57\u6BB5\uFF0C\u5F62\u5982 {"\u53C2\u4F1A\u5BA2\u6237": "xx\u516C\u53F8", "\u8054\u7CFB\u65B9\u5F0F": "138xxxx"}\uFF1A\u7528\u4E8E\u79DF\u6237\u5728\u6D41\u7A0B\u8868\u5355\u4E0A\u81EA\u5EFA\u3001CLI \u5185\u7F6E\u522B\u540D\u91CC\u6CA1\u6709\u7684\u5B57\u6BB5\u3002\u952E\u5FC5\u987B\u4E0E\u8BE5\u6D41\u7A0B\u8868\u5355\u7684\u5B57\u6BB5\u540D\u5B8C\u5168\u4E00\u81F4\uFF08prepare \u7684 warnings \u4F1A\u5217\u51FA\u8868\u5355\u73B0\u6709\u5168\u90E8\u5B57\u6BB5\u540D\uFF09\uFF1B\u5339\u914D\u4E0D\u5230\u7684\u4F1A\u8FDB unmapped \u63D0\u793A\uFF0C\u4E0D\u4F1A\u778E\u586B\u3002\u26D4 **\u4F1A\u8BAE\u5730\u70B9 / \u53C2\u4F1A\u4EBA\u5458 / \u53EC\u96C6\u4EBA / \u8054\u7CFB\u4EBA / \u4F1A\u8BAE\u7C7B\u578B \u4E0D\u8981\u585E\u8FD9\u91CC** \u2014\u2014 \u5B83\u4EEC\u6709\u4E13\u7528\u5165\u53C2\uFF08address / hrm_members / caller / contacter / mt_type\uFF09\uFF0CCLI \u4F1A\u628A\u503C\u8865\u6210\u6D4F\u89C8\u6309\u94AE\u8981\u7684 `{id,name}` \u5BF9\u8C61\uFF1B\u585E\u8FDB extraFields \u4F1A\u6309\u7EAF\u6587\u672C\u63D0\u4EA4\uFF0C\u670D\u52A1\u7AEF\u4F1A\u6253\u56DE\u300C\u8BF7\u6309\u540D\u79F0\u9009\u62E9\u300D'
7073
- },
7074
- dateFrom: {
7075
- type: "string",
7076
- description: "\u6CA1\u7ED9\u5177\u4F53\u65F6\u95F4\u65F6\u6309\u54EA\u4E00\u5929\u63A8\u8350\u65F6\u6BB5\uFF08yyyy-MM-dd\uFF1B\u4E0D\u4F20\u9ED8\u8BA4\u660E\u5929\uFF09\u3002\u26A0\uFE0F \u7528\u6237\u8BF4\u4E86\u300C\u4E0A\u5348/\u4E0B\u5348/\u665A\u4E0A\u300D\u5C31\u5FC5\u987B\u540C\u65F6\u4F20 time_slot \u2014\u2014 \u53EA\u4F20 dateFrom \u4F1A\u5F39\u65F6\u6BB5\u9009\u62E9\u5668\u8BA9\u7528\u6237\u518D\u9009\u4E00\u6B21"
7077
- },
7078
- time_slot: {
7079
- type: "string",
7080
- enum: ["\u4E0A\u5348", "\u65E9\u4E0A", "\u4E0B\u5348", "\u665A\u4E0A"],
7081
- description: '\u7528\u6237\u53EA\u8BF4\u4E86\u300C\u4E0A\u5348/\u4E0B\u5348/\u665A\u4E0A\u300D\u65F6\u4F20\u8FD9\u4E2A\uFF08\u914D\u5408 dateFrom\uFF09\uFF1A\u4E0A\u5348/\u65E9\u4E0A=09:00\u201312:00\u3001\u4E0B\u5348=13:00\u201318:00\u3001\u665A\u4E0A=18:00\u201321:00\uFF0CCLI \u76F4\u63A5\u5B9A\u4E0B\u6765\u3001\u4E0D\u518D\u8FD4\u56DE\u65F6\u6BB5\u5019\u9009\u3002\u26D4 \u4E0D\u8981\u53EA\u4F20 dateFrom \u5C31\u671F\u5F85"\u8BA9\u7528\u6237\u9009\u65F6\u6BB5"\u2014\u2014\u7528\u6237\u5DF2\u7ECF\u8BF4\u4E86\u65F6\u6BB5\u5C31\u522B\u518D\u95EE'
7082
- },
7083
- durationMinutes: {
7084
- type: "number",
7085
- description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09\uFF1A\u53EA\u7ED9\u4E86\u5F00\u59CB\u65F6\u95F4\u65F6\u7528\u6765\u7B97\u7ED3\u675F\u65F6\u95F4\uFF1B\u63A8\u8350\u65F6\u6BB5\u65F6\u4E5F\u6309\u8FD9\u4E2A\u65F6\u957F\u627E"
7086
- },
7087
- workStartHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u65E9\u5C0F\u65F6\uFF08\u9ED8\u8BA4 9\uFF09" },
7088
- workEndHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u665A\u5C0F\u65F6\uFF08\u9ED8\u8BA4 18\uFF09" },
7089
- fieldValues: {
7090
- type: "object",
7091
- additionalProperties: true,
7092
- description: '\u6309**\u8868\u5355\u5B57\u6BB5 datakey\uFF08fieldId\uFF09**\u76F4\u63A5\u7ED9\u503C\uFF0C\u5F62\u5982 {"1325677252711735881": "\u7814\u8BA8\u4F1A"}\u3002\u4F18\u5148\u7EA7\u6700\u9AD8\uFF08\u540C\u540D\u5B57\u6BB5\u4EE5\u5B83\u4E3A\u51C6\uFF09\uFF1A\u9002\u5408\u5B57\u6BB5\u540D\u5E26\u63D0\u793A\u8BED\u3001\u6216\u79DF\u6237\u81EA\u5EFA\u5B57\u6BB5\u8FD9\u7C7B\u6309\u4E2D\u6587\u540D\u731C\u4E0D\u5230\u7684\u60C5\u51B5\u3002datakey \u4ECE prepare \u8FD4\u56DE\u7684 preview.mapped\uFF08\u5F62\u5982 "\u4F1A\u8BAE\u540D\u79F0(1325677252711735881)"\uFF09\u91CC\u53D6\uFF1B\u6BCF\u4E2A\u6D41\u7A0B\u7684 datakey \u56FA\u5B9A\u4E0D\u53D8\uFF0C\u53EF\u957F\u671F\u786C\u7F16\u7801\u3002'
7093
- },
7094
- flowChoice: {
7095
- type: "string",
7096
- enum: ["auto", "ask"],
7097
- description: '\u591A\u4E2A\u5EFA\u4F1A\u6D41\u7A0B**\u90FD\u6709\u53D1\u8D77\u6743\u9650**\u65F6\u600E\u4E48\u529E\uFF1A\u9ED8\u8BA4\uFF08\u4E0D\u4F20 / ask\uFF09= \u8FD4\u56DE\u9009\u9879\u8BA9\u7528\u6237\u6311\uFF1Bauto = \u81EA\u52A8\u53D6\u4F18\u5148\u7EA7\u6700\u9AD8\u7684\u90A3\u4E2A\uFF08\u7701\u4E00\u8F6E\uFF0C\u4F46\u9009\u9519\u6D41\u7A0B\u4F1A\u6F0F\u5B57\u6BB5\uFF0C\u614E\u7528\uFF09\u3002\u6709**\u6D41\u7A0B\u8BB0\u5FC6**\uFF08\u8BE5\u8D26\u53F7\u4E0A\u6B21\u6210\u529F\u7528\u8FC7\u7684\u6D41\u7A0B\uFF09\u4E14\u672C\u6B21\u4ECD\u53EF\u53D1\u8D77\u65F6\uFF0C\u9ED8\u8BA4\u76F4\u63A5\u6CBF\u7528\u4E0A\u6B21\u9009\u62E9\u5E76\u7559\u75D5\uFF0C\u4E0D\u518D\u5F39\u9009\u9879\uFF1B\u8981\u5F3A\u5236\u56DE\u5230"\u6BCF\u6B21\u90FD\u95EE"\u624D\u4F20 ask\u3002\u53EA\u6709 1 \u4E2A\u6709\u6743\u9650\u65F6\u4E0D\u53D7\u6B64\u53C2\u6570\u5F71\u54CD\uFF0CCLI \u76F4\u63A5\u53D1\u8D77'
7098
- }
7099
- },
7100
- { required: ["mt_name"] }
7101
- ),
7102
- handler: async (args, env) => {
7103
- let workflowId = "";
7104
- let flowPickNote = null;
7105
- const decisions = {};
7106
- const enrich = args.enrich !== false;
7107
- let beginText = String(args.begin_datetime ?? "").trim();
7108
- let endText = String(args.end_datetime ?? "").trim();
7109
- const TIME_SLOT_RANGES = {
7110
- \u4E0A\u5348: ["09:00", "12:00"],
7111
- \u65E9\u4E0A: ["09:00", "12:00"],
7112
- \u4E0B\u5348: ["13:00", "18:00"],
7113
- \u665A\u4E0A: ["18:00", "21:00"]
7114
- };
7115
- let slotConfirmed = false;
7116
- const slotArg = String(args.time_slot ?? "").trim();
7117
- if (slotArg !== "" && !/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(beginText)) {
7118
- const range = TIME_SLOT_RANGES[slotArg];
7119
- const day2 = String(args.dateFrom ?? "").trim().slice(0, 10) || beginText.slice(0, 10) || tomorrowIso();
7120
- if (range && /^\d{4}-\d{2}-\d{2}$/.test(day2)) {
7121
- beginText = `${day2} ${range[0]}`;
7122
- endText = `${day2} ${range[1]}`;
7123
- slotConfirmed = true;
7124
- }
7125
- }
7126
- if (!slotConfirmed && !/\d{1,2}:\d{2}/.test(beginText)) {
7127
- const workStart = Number(args.workStartHour);
7128
- const workEnd = Number(args.workEndHour);
7129
- if (Number.isFinite(workStart) && Number.isFinite(workEnd) && workEnd > workStart) {
7130
- const slotName = workEnd <= 12 && workStart < 12 ? "\u4E0A\u5348" : workStart >= 13 && workEnd <= 18 ? "\u4E0B\u5348" : workStart >= 18 ? "\u665A\u4E0A" : "";
7131
- const range = slotName ? TIME_SLOT_RANGES[slotName] : void 0;
7132
- const day2 = String(args.dateFrom ?? "").trim().slice(0, 10) || beginText.slice(0, 10) || tomorrowIso();
7133
- if (range && /^\d{4}-\d{2}-\d{2}$/.test(day2)) {
7134
- beginText = `${day2} ${range[0]}`;
7135
- endText = `${day2} ${range[1]}`;
7136
- slotConfirmed = true;
7137
- }
7138
- }
7139
- }
7140
- const slotHit = beginText.match(/(\d{4}-\d{2}-\d{2})?\s*(上午|早上|下午|晚上)/u);
7141
- if (slotHit) {
7142
- const range = TIME_SLOT_RANGES[slotHit[2]];
7143
- const day2 = slotHit[1] || beginText.slice(0, 10) || String(args.dateFrom ?? "").trim().slice(0, 10) || tomorrowIso();
7144
- const rest = beginText.replace(slotHit[0], "");
7145
- if (range && /^\d{4}-\d{2}-\d{2}$/.test(day2) && !/\d{1,2}:\d{2}/.test(rest)) {
7146
- beginText = `${day2} ${range[0]}`;
7147
- endText = `${day2} ${range[1]}`;
7148
- slotConfirmed = true;
7149
- }
7150
- }
7151
- const rawMembers = String(args.hrm_members ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
7152
- let membersDefaulted = false;
7153
- if (rawMembers.length === 0) {
7154
- const self = await resolveSelfPerson(env);
7155
- if (self) {
7156
- rawMembers.push(self.id);
7157
- membersDefaulted = true;
7158
- args.hrm_members = rawMembers.join(",");
7159
- }
7160
- }
7161
- const nameLike = rawMembers.filter((item) => !/^\d+$/.test(item));
7162
- const nameToId = nameLike.length > 0 ? await import("./schedule-5GCACCK7.js").then((m) => m.resolveMemberIdsByName(env, nameLike)).catch(() => /* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
7163
- const memberIds = rawMembers.map((item) => nameToId.get(item) ?? item);
7164
- const timeConfirmed = args.timeConfirmed === true || slotConfirmed;
7165
- const callerWorkflowId = String(args.workflowId ?? "").trim();
7166
- const earlyWorkflowNote = callerWorkflowId === "" ? "" : `\u26D4 \u4F60\u4F20\u4E86 workflowId=${callerWorkflowId}\uFF0C\u4F46**\u6D41\u7A0B\u8FD8\u6CA1\u5230\u786E\u8BA4\u6B65\u9AA4**\uFF08\u987A\u5E8F\u662F \u540D\u79F0\u2192\u65F6\u95F4\u2192\u53C2\u4F1A\u4EBA\u2192\u5730\u70B9\u2192\u6D41\u7A0B\uFF09\u3002\u672C\u6B21\u53EA\u5904\u7406\u65F6\u95F4/\u5730\u70B9\uFF1B\u26D4 \u4E0D\u8981\u5728\u56DE\u590D\u91CC\u8BF4"\u6309 X \u6D41\u7A0B\u53D1\u8D77"\u2014\u2014\u56DB\u8981\u7D20\u5B9A\u5B8C\u540E CLI \u4F1A\u8FD4\u56DE\u6D41\u7A0B\u9009\u9879\u8BA9\u7528\u6237\u70B9\u3002`;
7167
- const beginHasTime = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(beginText);
7168
- const endHasTime = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(endText);
7169
- if (beginHasTime && !endHasTime) {
7170
- const duration = Number(args.durationMinutes) > 0 ? Math.round(Number(args.durationMinutes)) : 60;
7171
- const startMs = Date.parse(beginText.slice(0, 16).replace(" ", "T"));
7172
- if (Number.isFinite(startMs)) endText = formatMinute(new Date(startMs + duration * 6e4));
7173
- }
7174
- if (!beginHasTime || !timeConfirmed) {
7175
- const day2 = /^\d{4}-\d{2}-\d{2}/.test(beginText) ? beginText.slice(0, 10) : String(args.dateFrom ?? "").trim().slice(0, 10) || tomorrowIso();
7176
- const duration = Number(args.durationMinutes) > 0 ? Math.round(Number(args.durationMinutes)) : 60;
7177
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
7178
- const suggested = await getMeetingOperation2("meeting.eb.meeting.create.suggest").handler(
7179
- {
7180
- dateFrom: day2,
7181
- durationMinutes: duration,
7182
- hrm_members: memberIds.join(","),
7183
- maxSlots: 3,
7184
- topN: 3,
7185
- ...Number(args.total_member) > 0 ? { memberCount: Number(args.total_member) } : {},
7186
- ...args.workStartHour !== void 0 ? { workStartHour: Number(args.workStartHour) } : {},
7187
- ...args.workEndHour !== void 0 ? { workEndHour: Number(args.workEndHour) } : {}
7188
- },
7189
- env
7190
- ).catch((error) => ({ data: { slots: [] }, slotError: String(error?.message ?? error).slice(0, 160) }));
7191
- const slotOptions2 = suggested?.data?.slots ?? [];
7192
- const slotWarnings = [
7193
- ...suggested?.warnings ?? [],
7194
- ...suggested?.slotError ? [`\u65F6\u6BB5\u63A8\u8350\u672A\u8DD1\u6210\u529F\uFF1A${suggested.slotError}`] : [],
7195
- ...memberIds.length === 0 ? ['\u26A0\uFE0F \u6CA1\u6709\u53C2\u4F1A\u4EBA\u5458\uFF0C\u65E0\u6CD5\u6838\u9A8C"\u4EBA\u662F\u5426\u7A7A\u95F2" \u2014\u2014 \u4E0B\u9762\u53EA\u662F**\u4F1A\u8BAE\u5BA4\u6709\u7A7A**\u7684\u65F6\u6BB5\uFF0C\u8BF7\u5982\u5B9E\u8BF4\u660E\u3002'] : []
7196
- ];
7197
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7198
- status: "NEEDS_SELECTION",
7199
- selectionType: "slot",
7200
- ui: { component: "choice", multiple: false, recommendedKey: "T1" },
7201
- message: slotOptions2.length > 0 ? `${beginHasTime ? `\u4F60\u4F20\u5165\u7684\u65F6\u95F4 ${beginText}~${endText} **\u672A\u7ECF\u7528\u6237\u786E\u8BA4**\uFF08\u6CA1\u5E26 timeConfirmed\uFF09` : "\u6CA1\u6709\u7ED9\u51FA\u5177\u4F53\u65F6\u95F4"}\uFF0C\u5DF2\u6309\u53C2\u4F1A\u4EBA\u4E0E\u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u60C5\u51B5\u63A8\u8350 ${slotOptions2.length} \u4E2A\u65F6\u6BB5\uFF08${day2}\uFF0C\u65F6\u957F ${duration} \u5206\u949F\uFF09\u2014\u2014 \u26D4 \u5FC5\u987B\u8BA9\u7528\u6237\u5728\u9009\u9879\u91CC\u70B9\u9009\uFF0C**\u4E0D\u8981**\u628A\u4EFB\u4F55\u4E00\u4E2A\u5019\u9009\u5199\u6210"\u5DF2\u5B9A"\u6216\u653E\u8FDB\u786E\u8BA4\u6458\u8981` : `${beginHasTime ? `\u4F60\u4F20\u5165\u7684\u65F6\u95F4 ${beginText}~${endText} \u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF08\u6CA1\u5E26 timeConfirmed\uFF09` : "\u6CA1\u6709\u7ED9\u51FA\u5177\u4F53\u65F6\u95F4"}\uFF0C\u4E14 ${day2} \u6CA1\u80FD\u627E\u5230\u300C\u53C2\u4F1A\u4EBA\u7A7A\u95F2 + \u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u300D\u7684\u65F6\u6BB5\uFF0C\u8BF7\u8BA9\u7528\u6237\u6362\u4E2A\u65E5\u671F\u6216\u6307\u5B9A\u65F6\u95F4`,
7202
- options: slotOptions2.map((slot, index) => ({
7203
- key: `T${index + 1}`,
7204
- label: String(slot.label ?? ""),
7205
- // ⛔ 时间不在 slot 顶层,而在 slot.value 里(suggest 的返回结构)—— 取错会让调用方
7206
- // 拿不到 begin/end,只能再问用户一次时间(2026-10-30 冒烟实测踩到)。
7207
- // `timeConfirmed: true` 在这里是**关键**:用户点选后 value 原样回传,下一轮才被认作"已确认";
7208
- // agent 自己编的时间不带这个标记,就永远停在选项这一步。
7209
- value: {
7210
- begin_datetime: String(slot.value?.begin ?? slot.begin ?? "").trim(),
7211
- end_datetime: String(slot.value?.end ?? slot.end ?? "").trim(),
7212
- address: slot.value?.address ?? null,
7213
- timeConfirmed: true
7214
- },
7215
- reason: String(slot.reason ?? ""),
7216
- rooms: slot.rooms ?? []
7217
- })),
7218
- day: day2,
7219
- durationMinutes: duration,
7220
- memberIds,
7221
- // ⛔ 这里**不能**出现 workflowId:流程确认在四要素之后(2026-10-30 顺序调整)。
7222
- // 返回 workflowId 会让 agent 误以为"流程已定",于是在回复里先讲流程、再问时间。
7223
- workflowPending: true,
7224
- hint: "\u9009\u5B9A\u540E\u628A value **\u6574\u4F53**\u539F\u6837\u5E26\u56DE\u91CD\u65B0\u8C03\u7528\uFF08\u542B timeConfirmed: true\uFF09\uFF1Baddress \u5DF2\u81EA\u52A8\u5E26\u4E0A\u8BE5\u65F6\u6BB5\u53EF\u7528\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u4ECD\u9700\u8BA9\u7528\u6237\u5355\u72EC\u786E\u8BA4\u6216\u7528 roomConfirmed: true"
7225
- }, {
7226
- warnings: [
7227
- `${beginHasTime ? `\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\uFF1A\u4F60\u4F20\u5165\u7684\u65F6\u95F4 ${beginText}~${endText} \u6CA1\u6709\u7528\u6237\u786E\u8BA4\u6807\u8BB0\uFF08timeConfirmed\uFF09\uFF0C\u5DF2\u6539\u4E3A\u7ED9\u5019\u9009\u3002` : "\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\uFF1A\u65F6\u95F4\u672A\u786E\u5B9A\uFF08\u7F3A begin_datetime\uFF09\u3002"}\u5DF2\u6309 ${day2} \u63A8\u8350\u65F6\u6BB5\uFF0C\u8BF7\u7528\u9009\u9879\u8BA9\u7528\u6237\u6311\u4E00\u4E2A\u3002`,
7228
- ...slotWarnings,
7229
- ...earlyWorkflowNote ? [earlyWorkflowNote] : []
7230
- ]
7231
- });
7232
- }
7233
- let addressInput = args.address;
7234
- const hadAddressInput = String(args.address ?? "").trim() !== "";
7235
- const day = beginText.slice(0, 10);
7236
- const durationMinutes = beginText && endText ? Math.max(15, Math.round((Date.parse(endText.replace(" ", "T")) - Date.parse(beginText.replace(" ", "T"))) / 6e4) || 60) : 60;
7237
- const timings = {};
7238
- const startedAt = Date.now();
7239
- const enrichFailures = [];
7240
- const noteFailure = (label) => (error) => {
7241
- enrichFailures.push(`${label}\u672A\u5B8C\u6210\uFF1A${String(error?.message ?? error).slice(0, 120)}`);
7242
- return null;
7243
- };
7244
- const needSelfPerson = String(args.caller ?? "").trim() === "" || String(args.contacter ?? "").trim() === "";
7245
- const autoPerson = applySelfPersonDefaults(
7246
- args,
7247
- needSelfPerson ? await resolveSelfPerson(env) : null
7248
- );
7249
- const autoFilledPerson = autoPerson.filled;
7250
- const selfPersonWarning = autoPerson.warning;
7251
- const declaredTotal = Number(args.total_member) > 0 ? Number(args.total_member) : null;
7252
- const callerToken = String(args.caller ?? "").trim();
7253
- const callerInMembers = callerToken !== "" && (rawMembers.includes(callerToken) || memberIds.includes(callerToken));
7254
- const roomMemberCount = declaredTotal ?? (memberIds.length > 0 ? memberIds.length + (callerInMembers ? 0 : 1) : void 0);
7255
- const hasCustomer = Array.isArray(args.crm_members) ? args.crm_members.length > 0 : String(args.crm_members ?? "").trim() !== "";
7256
- const dayUsagesTask = enrich && beginText && endText ? loadDayUsages(env, day) : Promise.resolve(null);
7257
- const roomTask = enrich && beginText && endText ? (async () => {
7258
- const usageData = await dayUsagesTask;
7259
- return recommendRooms(env, {
7260
- beginDatetime: beginText,
7261
- endDatetime: endText,
7262
- ...roomMemberCount ? { memberCount: roomMemberCount } : {},
7263
- // 带客户时优先接待类会议室(2026-11-02 用户口径:加了客户就推接待类)
7264
- ...hasCustomer ? { hasCustomer: true } : {},
7265
- // 2026-11-03 用户批准松绑:不再每次强制重拉台账(省 ~1s + 2 请求)。
7266
- // 兜底在 recommendRooms 内部:24h 缓存凑不出候选时自动强制重拉一次再算;
7267
- // 代价是刚导入的会议室在缓存期可能按名称查不到(按 id 指定不受影响)。
7268
- topN: 3,
7269
- // 占用走全天缓存(usageData 为 null 时 recommendRooms 内部自己查,行为不变)
7270
- ...usageData ? { dayUsages: usageData.rows } : {}
7271
- });
7272
- })().catch(noteFailure("\u4F1A\u8BAE\u5BA4\u63A8\u8350")) : Promise.resolve(null);
7273
- const addressId = String(addressInput ?? "").trim();
7274
- const roomConfirmed = args.roomConfirmed === true;
7275
- const roomConflictTask = enrich && beginText && endText && addressId !== "" ? (async () => {
7276
- const room = await resolveAddressRoom(env, addressId);
7277
- if (!room) return { unresolved: true, input: addressId };
7278
- if (!room.id || room.lookupFailed || room.status !== "0") return { room };
7279
- const usageData = await dayUsagesTask.catch(() => null);
7280
- if (usageData) {
7281
- const conflicts = filterUsages(usageData.rows, { roomId: room.id, begin: beginText, end: endText }).map((usage) => ({ mtId: usage.mtId, begin: usage.start, end: usage.end }));
7282
- return {
7283
- room,
7284
- hasConflict: conflicts.length > 0,
7285
- conflicts,
7286
- verdict: conflicts.length > 0 ? "warn" : "ok",
7287
- requests: usageData.requests,
7288
- usageFromCache: usageData.fromCache
7289
- };
7290
- }
7291
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
7292
- const result = await getMeetingOperation2("meeting.eb.conflict.room").handler(
7293
- { beginDatetime: beginText, endDatetime: endText, address: room.id },
7294
- env
7295
- );
7296
- return { room, ...result?.data ?? {} };
7297
- })().catch(noteFailure("\u4F1A\u8BAE\u5BA4**\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
7298
- const conflictTask = enrich && beginText && endText && memberIds.length > 0 ? (async () => {
7299
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
7300
- return getMeetingOperation2("meeting.eb.conflict.member").handler(
7301
- { beginDatetime: beginText, endDatetime: endText, hrmMembers: memberIds.join(",") },
7302
- env
7303
- );
7304
- })().catch(noteFailure("\u53C2\u4F1A\u4EBA**\u4F1A\u8BAE\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
7305
- const availabilityTask = enrich && beginText && endText && memberIds.length > 0 ? findCommonFreeSlots(env, {
7306
- rangeStart: `${day} 00:00`,
7307
- rangeEnd: `${day} 23:59`,
7308
- durationMinutes,
7309
- members: memberIds,
7310
- maxSlots: 3,
7311
- maxDays: 1,
7312
- includeSchedule: true
7313
- }).catch(noteFailure("\u53C2\u4F1A\u4EBA**\u65E5\u7A0B\u7A7A\u95F2**\u68C0\u6D4B")) : Promise.resolve(null);
7314
- const [roomRec, memberConflict, free, roomConflict] = await Promise.all([
7315
- roomTask,
7316
- conflictTask,
7317
- availabilityTask,
7318
- roomConflictTask
7319
- ]);
7320
- timings.parallelMs = Date.now() - startedAt;
7321
- const memberConflicts = memberConflict?.data?.conflicts ?? [];
7322
- if (memberConflicts.length > 0) decisions.memberConflicts = memberConflicts;
7323
- const freeSlots = free?.slots ?? [];
7324
- if (free) {
7325
- decisions.scheduleItems = free.scheduleItems;
7326
- decisions.availabilityCost = free.cost;
7327
- if (freeSlots.length > 0) {
7328
- decisions.suggestedSlots = freeSlots;
7329
- decisions.slotOptions = freeSlots.map((slot, index) => ({
7330
- key: `T${index + 1}`,
7331
- label: `${slot.begin.slice(11)}~${slot.end.slice(11)}\uFF08${day}\uFF09 \xB7 \u5168\u90E8\u53C2\u4F1A\u4EBA\u7A7A\u95F2`,
7332
- value: { begin: slot.begin, end: slot.end },
7333
- reason: "\u8BE5\u65F6\u6BB5\u6240\u6709\u53C2\u4F1A\u4EBA\u90FD\u6CA1\u6709\u4F1A\u8BAE\u4E0E\u65E5\u7A0B\u5360\u7528\uFF08\u5DF2\u540C\u65F6\u6838\u5BF9\u4F1A\u8BAE\u56DE\u6267\u4E0E\u65E5\u7A0B\uFF09"
7334
- }));
7335
- } else if (free.blockingSummary) {
7336
- decisions.dayBlocked = { day, summary: free.blockingSummary };
7337
- }
7338
- }
7339
- const conflictBrief = {
7340
- memberConflicts,
7341
- suggestedSlots: freeSlots,
7342
- ...enrichFailures.length > 0 ? { enrichFailures } : {}
7343
- };
7344
- const failureWarnings = enrichFailures.map(
7345
- (failure) => `\u26A0\uFE0F ${failure} \u2014\u2014 **\u8FD9\u4E0D\u4EE3\u8868\u6CA1\u6709\u51B2\u7A81**\uFF0C\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\u8BE5\u9879\u672A\u6838\u9A8C\uFF0C\u4E0D\u8981\u58F0\u79F0"\u65F6\u95F4\u5DF2\u786E\u8BA4\u7A7A\u95F2"`
7346
- );
7347
- const roomOptions = (roomRec?.candidates ?? []).map((candidate, index) => ({
7348
- key: `R${index + 1}`,
7349
- label: `${candidate.name}${candidate.capacity.max > 0 ? `\uFF08\u53EF\u5BB9 ${candidate.capacity.max} \u4EBA\uFF09` : ""}${index === 0 ? " \xB7 \u63A8\u8350" : ""}`,
7350
- // roomConfirmed: true = 用户点选该选项即代表"确认用这间",原样回传后下一轮才被认。
7351
- value: { id: candidate.id, name: candidate.name, roomConfirmed: true },
7352
- reason: candidate.reasons.join("\uFF1B")
7353
- }));
7354
- const roomConflictData = roomConflict;
7355
- const resolvedAddress = roomConflictData?.room ?? null;
7356
- const resolvedAddressId = resolvedAddress?.id || addressId;
7357
- const addressDisplay = resolvedAddress?.name || addressId;
7358
- if (roomConflictData?.unresolved === true) {
7359
- decisions.roomNotFound = { input: addressId, candidates: roomOptions.length };
7360
- if (roomOptions.length > 0) decisions.roomOptions = roomOptions;
7361
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7362
- status: "NEEDS_SELECTION",
7363
- selectionType: "room",
7364
- ui: { component: "choice", multiple: false, recommendedKey: "R1" },
7365
- message: `\u6CA1\u627E\u5230\u540D\u4E3A\u300C${addressId}\u300D\u7684\u4F1A\u8BAE\u5BA4\uFF08\u4F1A\u8BAE\u5BA4\u53F0\u8D26\u91CC\u6CA1\u6709\u8FD9\u4E2A\u540D\u5B57\uFF09\uFF0C\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002` + (roomOptions.length > 0 ? `\u8BF7\u4ECE\u4E0B\u9762 ${roomOptions.length} \u4E2A\u5728\u8BE5\u65F6\u6BB5\u7A7A\u95F2\u7684\u4F1A\u8BAE\u5BA4\u91CC\u9009\u4E00\u95F4\uFF0C\u6216\u6838\u5BF9\u4E00\u4E0B\u4F1A\u8BAE\u5BA4\u540D\u79F0` : "\u8BE5\u65F6\u6BB5\u4E5F\u6CA1\u6709\u53EF\u7528\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u6539\u4F1A\u8BAE\u65F6\u95F4\u6216\u6539\u7EBF\u4E0A\u4F1A\u8BAE\uFF08allowNoRoom: true\uFF09"),
7366
- workflowPending: true,
7367
- options: roomOptions,
7368
- recommended: roomOptions[0]?.value ?? null,
7369
- roomNotFound: decisions.roomNotFound,
7370
- hint: "\u9009\u5B9A\u540E\u628A value **\u6574\u4F53**\u539F\u6837\u5E26\u56DE\uFF08\u542B roomConfirmed: true\uFF09\uFF1B\u6838\u5BF9\u540D\u79F0\u53EF\u7528 `meeting.eb.room.list` \u770B\u5168\u91CF\u6E05\u5355"
7371
- }, {
7372
- warnings: [
7373
- `\u4F1A\u8BAE\u5BA4\u300C${addressId}\u300D\u5728\u53F0\u8D26\u91CC\u4E0D\u5B58\u5728\uFF0C\u5DF2\u62E6\u4E0B\u672A\u63D0\u4EA4\u3002`,
7374
- '\u26D4 \u4E0D\u8981\u628A\u5B83\u5F53\u6210"\u7528\u6237\u6307\u5B9A\u7684\u623F\u95F4"\u5199\u8FDB\u786E\u8BA4\u6458\u8981 \u2014\u2014 \u8FD9\u95F4\u623F\u6839\u672C\u6CA1\u6709\u88AB\u89E3\u6790\u51FA\u6765\u3002'
7375
- ]
7376
- });
7377
- }
7378
- if (resolvedAddress && resolvedAddress.status === "1") {
7379
- decisions.roomSealed = { id: resolvedAddress.id, name: resolvedAddress.name };
7380
- if (roomOptions.length > 0) decisions.roomOptions = roomOptions;
7381
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7382
- status: "NEEDS_SELECTION",
7383
- selectionType: "room",
7384
- ui: { component: "choice", multiple: false, recommendedKey: "R1" },
7385
- message: `\u4F1A\u8BAE\u5BA4\u300C${resolvedAddress.name}\u300D\u5F53\u524D\u662F**\u5C01\u5B58**\u72B6\u6001\uFF08\u4E0D\u53EF\u9884\u7EA6\uFF09\uFF0C\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002` + (roomOptions.length > 0 ? "\u8BF7\u6539\u7528\u4E0B\u9762\u7A7A\u95F2\u7684\u4F1A\u8BAE\u5BA4" : "\u8BE5\u65F6\u6BB5\u6CA1\u6709\u5176\u5B83\u53EF\u7528\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u6539\u4F1A\u8BAE\u65F6\u95F4"),
7386
- workflowPending: true,
7387
- options: roomOptions,
7388
- recommended: roomOptions[0]?.value ?? null,
7389
- roomSealed: decisions.roomSealed
7390
- }, {
7391
- warnings: [`\u4F1A\u8BAE\u5BA4\u300C${resolvedAddress.name}\u300D\uFF08${resolvedAddress.id}\uFF09\u5DF2\u5C01\u5B58\uFF0C\u4E0D\u53EF\u9884\u7EA6\uFF0C\u5DF2\u62E6\u4E0B\u672A\u63D0\u4EA4\u3002`]
7392
- });
7393
- }
7394
- if (addressInput && roomConfirmed && roomConflictData?.hasConflict === true) {
7395
- const busy = Array.isArray(roomConflictData.conflicts) ? roomConflictData.conflicts : [];
7396
- decisions.roomConflict = {
7397
- address: resolvedAddressId,
7398
- addressName: addressDisplay,
7399
- hasConflict: true,
7400
- conflicts: busy,
7401
- verdict: roomConflictData.verdict ?? "conflict"
7402
- };
7403
- if (roomOptions.length > 0) decisions.roomOptions = roomOptions;
7404
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7405
- status: "NEEDS_SELECTION",
7406
- selectionType: "room_conflict",
7407
- ui: { component: "choice", multiple: false, recommendedKey: "R1" },
7408
- message: `\u4F60\u6307\u5B9A\u7684\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D\u5728 ${beginText}~${endText} \u5DF2\u88AB\u5360\u7528\uFF08${busy.length} \u6761\u5360\u7528\u8BB0\u5F55\uFF09\uFF0C\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002\u8BF7\u6539\u7528\u4E0B\u9762\u7A7A\u95F2\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u6216\u8C03\u6574\u4F1A\u8BAE\u65F6\u95F4`,
7409
- workflowPending: true,
7410
- options: roomOptions,
7411
- recommended: roomOptions[0]?.value ?? null,
7412
- conflicts: busy,
7413
- roomConflict: decisions.roomConflict,
7414
- hint: "\u9009\u5B9A\u540E\u628A value.id \u4F5C\u4E3A address \u91CD\u65B0\u8C03\u7528\uFF1B\u8981\u6539\u65F6\u95F4\u5C31\u540C\u65F6\u4F20\u65B0\u7684 begin_datetime/end_datetime"
7415
- }, {
7416
- warnings: [
7417
- `\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D\uFF08${resolvedAddressId}\uFF09\u5728\u8BE5\u65F6\u6BB5\u5DF2\u6709 ${busy.length} \u6761\u5360\u7528\uFF0C\u5DF2\u62E6\u4E0B\u672A\u63D0\u4EA4\u3002`,
7418
- roomOptions.length > 0 ? `\u5DF2\u6309\u4EBA\u6570/\u5E38\u7528/\u7A7A\u95F2\u7ED9\u51FA ${roomOptions.length} \u4E2A\u66FF\u4EE3\u4F1A\u8BAE\u5BA4\uFF08R1 \u4E3A\u9996\u9009\uFF09\u3002` : "\u8BE5\u65F6\u6BB5\u6CA1\u6709\u53EF\u66FF\u4EE3\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\uFF0C\u5EFA\u8BAE\u8C03\u6574\u4F1A\u8BAE\u65F6\u95F4\u6216\u6539\u7EBF\u4E0A\u4F1A\u8BAE\uFF08allowNoRoom: true\uFF09\u3002"
7419
- ]
7420
- });
7421
- }
7422
- if (roomRec) {
7423
- decisions.roomOptions = roomOptions;
7424
- decisions.autoRoom = {
7425
- picked: roomRec.best ? { id: roomRec.best.id, name: roomRec.best.name, score: roomRec.best.score, reasons: roomRec.best.reasons } : null,
7426
- candidates: roomRec.candidates,
7427
- meta: roomRec.meta
7428
- };
7429
- const autoRoom = args.autoRoom === true;
7430
- const needRoomPick = !addressInput || !roomConfirmed;
7431
- let pickOptions = roomOptions;
7432
- if (addressInput && !roomConfirmed) {
7433
- const hit = roomOptions.find((item) => String(item.value?.id) === resolvedAddressId);
7434
- const specified = hit ? { ...hit, label: `${hit.label}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`, value: { ...hit.value, roomConfirmed: true } } : {
7435
- key: "R0",
7436
- label: `${addressDisplay}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`,
7437
- value: { ...resolvedAddressId ? { id: resolvedAddressId } : {}, name: addressDisplay, roomConfirmed: true },
7438
- reason: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u672A\u63D0\u4EA4\u3001\u672A\u786E\u8BA4"
7439
- };
7440
- pickOptions = [specified, ...roomOptions.filter((item) => String(item.value?.id) !== resolvedAddressId)].map((item, index) => ({ ...item, key: `R${index + 1}` }));
7441
- }
7442
- if (needRoomPick && !autoRoom && pickOptions.length > 0 && args.allowNoRoom !== true) {
7443
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7444
- status: "NEEDS_SELECTION",
7445
- selectionType: "room",
7446
- ui: { component: "choice", multiple: false, recommendedKey: "R1" },
7447
- message: addressInput ? `\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D**\u672A\u7ECF\u7528\u6237\u786E\u8BA4**\uFF08\u6CA1\u5E26 roomConfirmed\uFF09\uFF0C\u5DF2\u628A\u5B83\u548C\u5176\u5B83\u5019\u9009\u4E00\u8D77\u5217\u51FA\u6765 \u2014\u2014 \u26D4 \u5FC5\u987B\u8BA9\u7528\u6237\u5728\u9009\u9879\u91CC\u70B9\u9009\uFF0C\u4E0D\u8981\u76F4\u63A5\u63D0\u4EA4` : `\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u4ECE ${pickOptions.length} \u4E2A\u5019\u9009\u91CC\u9009\u62E9\uFF08\u5DF2\u6309\u4EBA\u6570/\u5E38\u7528/\u65F6\u6BB5\u5360\u7528\u6392\u5E8F\uFF09`,
7448
- // 固化自动选的流程要带出来:调用方下一轮带 address 重调时不用再猜用的是哪条流程。
7449
- workflowPending: true,
7450
- options: pickOptions,
7451
- recommended: pickOptions[0]?.value ?? null,
7452
- hint: "\u9009\u5B9A\u540E\u628A value **\u6574\u4F53**\u539F\u6837\u5E26\u56DE\uFF08\u542B roomConfirmed: true\uFF09\uFF1B\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\u8BF7\u4F20 allowNoRoom: true",
7453
- ...conflictBrief
7454
- }, {
7455
- warnings: [
7456
- addressInput ? `\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D\u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF1A\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\u3002` : "\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF1A\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\uFF0C\u4E5F\u6CA1\u6709\u66FF\u7528\u6237\u6311\u623F\u95F4\u3002",
7457
- "\u5982\u9700\u76F4\u63A5\u5EFA\u4F1A\u5E76\u6CBF\u7528\u63A8\u8350\uFF0C\u53EF\u4F20 autoRoom: true\uFF1B\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\u5219\u4F20 allowNoRoom: true\u3002",
7458
- ...earlyWorkflowNote ? [earlyWorkflowNote] : [],
7459
- ...memberConflicts.length > 0 ? [`\u26A0\uFE0F \u6CE8\u610F\uFF1A\u53C2\u4F1A\u4EBA\u5728\u8BE5\u65F6\u6BB5\u5DF2\u6709 ${memberConflicts.length} \u573A\u4F1A\u8BAE\u51B2\u7A81 \u2014\u2014 \u9009\u623F\u524D\u5148\u628A\u8FD9\u6761\u544A\u8BC9\u7528\u6237\uFF0C\u522B\u8BA9\u4ED6\u9009\u5B8C\u624D\u53D1\u73B0\u3002`] : [],
7460
- ...freeSlots.length > 0 ? [`\u5F53\u5929\u5168\u90E8\u53C2\u4F1A\u4EBA\u90FD\u7A7A\u95F2\u7684\u65F6\u6BB5\uFF1A${freeSlots.map((s) => `${s.begin.slice(11)}~${s.end.slice(11)}`).join("\u3001")}`] : [],
7461
- ...failureWarnings
7462
- ]
7463
- });
7464
- }
7465
- if (addressInput) {
7466
- } else if (autoRoom && roomRec.best) {
7467
- addressInput = roomRec.best.id;
7468
- }
7469
- }
7470
- if (enrich && !addressInput && args.allowNoRoom !== true) {
7471
- decisions.roomUnavailable = {
7472
- reason: roomRec ? `\u8BE5\u65F6\u6BB5\u6CA1\u6709\u6EE1\u8DB3\u6761\u4EF6\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\uFF08\u5171 ${roomRec.meta?.roomsTotal ?? 0} \u95F4\uFF0C\u53EF\u7528 ${roomRec.meta?.roomsUsable ?? 0} \u95F4\uFF0C\u88AB\u5360\u7528 ${roomRec.meta?.roomsBusy ?? 0} \u95F4\uFF09` : "\u4F1A\u8BAE\u5BA4\u63A8\u8350\u6CA1\u6709\u8FD4\u56DE\u7ED3\u679C\uFF08\u4F1A\u8BAE\u5BA4\u5217\u8868\u63A5\u53E3\u8BFB\u4E0D\u5230\uFF0C\u6216\u63A8\u8350\u8FC7\u7A0B\u51FA\u9519\uFF09",
7473
- meta: roomRec?.meta ?? null
7474
- };
7475
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7476
- status: "NEEDS_SELECTION",
7477
- selectionType: "room_unavailable",
7478
- ui: { component: "choice", multiple: false, recommendedKey: "C2" },
7479
- message: "\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF0C\u4E14\u6309\u4EBA\u6570/\u65F6\u6BB5\u6CA1\u80FD\u63A8\u8350\u51FA\u53EF\u7528\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\u3002\u8BF7\u8BA9\u7528\u6237\u4ECE\u4E0B\u9762\u4E09\u6761\u91CC\u9009\u4E00\u6761\uFF0C**\u4E0D\u8981**\u76F4\u63A5\u63D0\u4EA4\u4E00\u4E2A\u6CA1\u6709\u5730\u70B9\u7684\u4F1A\u8BAE",
7480
- workflowPending: true,
7481
- options: [
7482
- { key: "C1", label: "\u6211\u6307\u5B9A\u5177\u4F53\u4F1A\u8BAE\u5BA4\uFF08\u8868\u5355\u91CC\u70B9\u9009\uFF0C\u6216\u544A\u8BC9\u6211\u4F1A\u8BAE\u5BA4\u540D\u79F0/id\uFF09", value: { action: "specify" } },
7483
- { key: "C2", label: "\u6539\u7528\u7EBF\u4E0A\u4F1A\u8BAE\uFF08\u817E\u8BAF\u4F1A\u8BAE/\u89C6\u9891\uFF09", value: { action: "no_room" } },
7484
- { key: "C3", label: '\u5148\u6309"\u5730\u70B9\u5F85\u5B9A"\u63D0\u4EA4', value: { action: "allow_no_room" } }
7485
- ],
7486
- roomUnavailable: decisions.roomUnavailable,
7487
- ...conflictBrief
7488
- }, {
7489
- warnings: [
7490
- `\u4F1A\u8BAE\u5BA4\u63A8\u8350\u65E0\u7ED3\u679C\uFF1A${String(decisions.roomUnavailable.reason)}\u3002\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002`,
7491
- "\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\uFF09\u5C31\u5E26 allowNoRoom: true \u91CD\u65B0\u8C03\u7528\uFF1B\u8981\u6307\u5B9A\u623F\u95F4\u5C31\u5E26 address\u3002",
7492
- ...memberConflicts.length > 0 ? [`\u26A0\uFE0F \u53E6\u5916\uFF1A\u53C2\u4F1A\u4EBA\u5728\u8BE5\u65F6\u6BB5\u5DF2\u6709 ${memberConflicts.length} \u573A\u4F1A\u8BAE\u51B2\u7A81 \u2014\u2014 \u6362\u65F6\u95F4\u53EF\u80FD\u6BD4\u6362\u623F\u95F4\u66F4\u5212\u7B97\u3002`] : [],
7493
- ...freeSlots.length > 0 ? [`\u5F53\u5929\u5168\u90E8\u53C2\u4F1A\u4EBA\u90FD\u7A7A\u95F2\u7684\u65F6\u6BB5\uFF1A${freeSlots.map((s) => `${s.begin.slice(11)}~${s.end.slice(11)}`).join("\u3001")}`] : [],
7494
- ...failureWarnings
7495
- ]
7496
- });
7497
- }
7498
- if (enrich && addressInput && !roomConfirmed && roomOptions.length === 0 && args.allowNoRoom !== true) {
7499
- const specified = {
7500
- key: "R1",
7501
- label: `${addressDisplay}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`,
7502
- value: { ...resolvedAddressId ? { id: resolvedAddressId } : {}, name: addressDisplay, roomConfirmed: true },
7503
- reason: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u672A\u63D0\u4EA4\u3001\u672A\u786E\u8BA4"
7504
- };
7505
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7506
- status: "NEEDS_SELECTION",
7507
- selectionType: "room",
7508
- ui: { component: "choice", multiple: false, recommendedKey: "R1" },
7509
- message: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF0C\u4E14\u672C\u6B21\u6CA1\u80FD\u63A8\u8350\u51FA\u5176\u5B83\u5019\u9009 \u2014\u2014 \u8BF7\u8BA9\u7528\u6237\u786E\u8BA4\u8FD9\u4E00\u95F4\uFF0C\u6216\u6362\u4E00\u95F4 / \u6539\u65F6\u6BB5",
7510
- workflowPending: true,
7511
- options: [specified],
7512
- recommended: specified.value,
7513
- hint: "\u7528\u6237\u786E\u8BA4\u7528\u8FD9\u95F4\u5C31\u628A value \u539F\u6837\u5E26\u56DE\uFF08\u542B roomConfirmed: true\uFF09"
7514
- }, {
7515
- warnings: ["\u4F1A\u8BAE\u5BA4\u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF0C\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\u3002", ...failureWarnings]
7516
- });
7517
- }
7518
- const resolved = await resolveWorkflowId(env, args);
7519
- const confirmedAddressId = resolvedAddressId;
7520
- const confirmedAddressLabel = addressId === "" ? "" : resolvedAddress?.name || String(roomOptions.find((item) => String(item.value?.id ?? "") === confirmedAddressId)?.value?.name ?? "") || addressId;
7521
- const confirmedWhen = `${beginText}~${String(endText).slice(11) || endText}`;
7522
- let candidates = resolved.candidates;
7523
- workflowId = resolved.workflowId;
7524
- let sourceLabel = resolved.source === "argument" ? "\u8C03\u7528\u65B9\u4F20\u5165" : resolved.source === "fixed" ? `\u56FA\u5316\u914D\u7F6E\uFF08${resolved.label ?? "\u9ED8\u8BA4"}\uFF09` : "\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E";
7525
- let probes = [];
7526
- let loadedForms = /* @__PURE__ */ new Map();
7527
- const autoPick = shouldAutoPickFlow(args);
7528
- if (!workflowId && candidates.length > 1) {
7529
- let probed = await probeWorkflowCandidates(env, candidates);
7530
- probes = probed.probes;
7531
- loadedForms = probed.loadedForms;
7532
- let launchable = probes.filter((probe) => probe.launchable);
7533
- if (launchable.length === 0 && resolved.source === "fixed") {
7534
- const settings = await fetchEbAppSettings(env, "meeting.eb.meeting.create.flow.prepare");
7535
- const fallbackIds = String(settings.mtNewWf ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
7536
- if (fallbackIds.length > 0) {
7537
- probed = await probeWorkflowCandidates(env, fallbackIds);
7538
- probes = probed.probes;
7539
- loadedForms = probed.loadedForms;
7540
- candidates = fallbackIds;
7541
- sourceLabel = "\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E";
7542
- launchable = probes.filter((probe) => probe.launchable);
7543
- }
7544
- }
7545
- if (launchable.length === 0) {
7546
- throw meetingValidationError(
7547
- "flow_not_launchable",
7548
- `\u5F53\u524D\u8D26\u53F7**\u6CA1\u6709\u53D1\u8D77\u5EFA\u4F1A\u6D41\u7A0B\u7684\u6743\u9650**\uFF1A${sourceLabel}\u7684 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\u90FD\u53D1\u8D77\u4E0D\u4E86\uFF08\u65E0\u53D1\u8D77\u6743\u9650\u6216\u6D41\u7A0B\u5DF2\u505C\u7528\uFF09\u2014\u2014${probes.map((probe) => `${probe.workflowId}\uFF08${probe.reason ?? "\u4E0D\u53EF\u53D1\u8D77"}\uFF09`).join("\uFF1B")}\u3002\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\uFF1A\u9700\u8981\u627E\u7BA1\u7406\u5458\u5F00\u901A\u8BE5\u6D41\u7A0B\u7684\u53D1\u8D77\u6743\u9650\uFF0C\u6216\u8BF7\u6709\u6743\u9650\u7684\u540C\u4E8B\u4EE3\u4E3A\u53D1\u8D77\uFF1B**\u4E0D\u8981**\u6539\u7528\u76F4\u8FDE\u5EFA\u4F1A\u7ED5\u8FC7\u6D41\u7A0B\u7BA1\u63A7\u3002`,
7549
- { probes }
7550
- );
7551
- }
7552
- if (launchable.length > 1 && !autoPick) {
7553
- const remembered = args.flowChoice === "ask" ? null : await readFlowPick(env).catch(() => null);
7554
- const rememberedHit = pickRememberedFlow(launchable, remembered);
7555
- if (rememberedHit) {
7556
- workflowId = rememberedHit.workflowId;
7557
- const others = launchable.filter((probe) => probe.workflowId !== rememberedHit.workflowId).map((probe) => probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId);
7558
- flowPickNote = `${sourceLabel}\uFF1A\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77 ${launchable.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5DF2\u6CBF\u7528\u4F60\u4E0A\u6B21\u9009\u7684\u300C${rememberedHit.name ?? rememberedHit.workflowId}\u300D\uFF08${rememberedHit.workflowId}\uFF09\u53D1\u8D77 \u2014\u2014 \u8981\u6362\u7684\u8BDD\u8BF4\u4E00\u58F0${others.length > 0 ? `\uFF08\u5176\u4ED6\u53EF\u7528\uFF1A${others.join("\u3001")}\uFF09` : ""}\u3002`;
7559
- } else {
7560
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
7561
- status: "NEEDS_SELECTION",
7562
- // ⚠️ 以前漏了这个字段(agent 拿到 undefined 无法判断是哪类选择,2026-10-30 真机发现)。
7563
- selectionType: "flow",
7564
- // 明确告诉调用方"这是一道选择题,请用选项控件呈现",不要降级成文本列表
7565
- // (2026-10-30 用户反馈:agent 把会议室候选写成文本 + "需要你指定一间",没给选项卡)。
7566
- ui: { component: "choice", multiple: false, recommendedKey: "W1" },
7567
- // 四要素已经确认到这一步了:摘要一起给出去,用户只需点一下流程,就能直接提交。
7568
- confirmed: {
7569
- mt_name: String(args.mt_name ?? ""),
7570
- begin_datetime: beginText,
7571
- end_datetime: endText,
7572
- address: confirmedAddressId || null,
7573
- addressName: confirmedAddressLabel || null,
7574
- hrm_members: memberIds
7575
- },
7576
- message: `\u4F1A\u8BAE\u8981\u7D20\u5DF2\u786E\u8BA4\uFF08${String(args.mt_name ?? "")} \xB7 ${confirmedWhen}${confirmedAddressLabel ? ` \xB7 ${confirmedAddressLabel}` : " \xB7 \u65E0\u4F1A\u8BAE\u5BA4"}\uFF09\uFF1B\u5F53\u524D\u8D26\u53F7\u5BF9 ${sourceLabel}\u7684 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B**\u90FD\u6709\u53D1\u8D77\u6743\u9650**\uFF0C\u8BF7\u8BA9\u7528\u6237\u6700\u540E\u9009\u4E00\u4E0B\u300C\u7528\u54EA\u6761\u6D41\u7A0B\u53D1\u8D77\u300D\u2014\u2014 **\u4E0D\u8981\u9ED8\u8BA4\u53D6\u7B2C\u4E00\u4E2A**\uFF08\u5404\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u53EF\u80FD\u5B8C\u5168\u4E0D\u540C\uFF0C\u9009\u9519\u4F1A\u6F0F\u5B57\u6BB5\uFF1B2026-10-29 \u771F\u5B9E\u4E8B\u6545\uFF1A\u53D6\u7B2C\u4E00\u4E2A\u5BFC\u81F4\u5B57\u6BB5\u5168\u586B\u4E0D\u8FDB\u53E6\u4E00\u6761\u6D41\u7A0B\uFF0C\u7528\u6237\u4EE5\u4E3A"\u7CFB\u7EDF\u53EA\u652F\u6301\u4E00\u6761\u6D41\u7A0B"\uFF09\u3002\u26A0\uFE0F \u53EA\u6709\u5176\u4E2D 1 \u4E2A\u6709\u6743\u9650\u65F6 CLI \u4F1A\u76F4\u63A5\u53D1\u8D77\uFF0C\u4E0D\u4F1A\u8D70\u5230\u8FD9\u4E00\u6B65`,
7577
- options: launchable.map((probe, index) => ({
7578
- key: `W${index + 1}`,
7579
- label: probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId,
7580
- // ⛔ 把已确认的四要素一起带回去:用户点选流程后**原样回传 value** 就能直接出确认摘要,
7581
- // 不用再走一遍时间/房间闸门(否则"先定四要素再选流程"会多出一轮无效往返)。
7582
- value: {
7583
- workflowId: probe.workflowId,
7584
- begin_datetime: beginText,
7585
- end_datetime: endText,
7586
- timeConfirmed: true,
7587
- ...confirmedAddressId ? { address: confirmedAddressId, roomConfirmed: true } : {}
7588
- },
7589
- reason: "\u5F53\u524D\u8D26\u53F7\u6709\u53D1\u8D77\u6743\u9650",
7590
- // 把该流程的字段名如实带出来:不同流程字段差异很大(有的有设备需求/涉密项目,有的没有),
7591
- // 用户要靠这个才能选对(2026-10-29 用户反馈:选错方式后字段全填不进去)。
7592
- fields: (loadedForms.get(probe.workflowId)?.fields ?? []).map((f) => f.name).filter(Boolean)
7593
- })),
7594
- probes
7595
- }, {
7596
- warnings: [
7597
- `${sourceLabel}\uFF1A\u5171 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5176\u4E2D ${launchable.length} \u4E2A\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77\uFF1B**\u5FC5\u987B\u628A\u8FD9\u51E0\u4E2A\u6D41\u7A0B\u505A\u6210\u9009\u9879\u8BA9\u7528\u6237\u6311\u4E00\u4E2A\uFF0C\u7981\u6B62\u81EA\u5DF1\u66FF\u7528\u6237\u9009**\uFF1B\u9009\u5B9A\u540E\u5E26\u5355\u4E2A workflowId \u91CD\u65B0 prepare\u3002`,
7598
- ...probes.filter((probe) => !probe.launchable).map((probe) => `\u6D41\u7A0B ${probe.workflowId} \u5F53\u524D\u8D26\u53F7\u65E0\u6CD5\u53D1\u8D77\uFF08${probe.reason ?? "\u65E0\u6743\u9650"}\uFF09\uFF0C\u5DF2\u6392\u9664`)
7599
- ]
7600
- });
7601
- }
7602
- }
7603
- if (workflowId === "") workflowId = launchable[0].workflowId;
7604
- if (launchable.length === 1 && candidates.length > 1 && flowPickNote === null) {
7605
- const only = launchable[0];
7606
- flowPickNote = `${sourceLabel}\uFF1A\u5171 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5F53\u524D\u8D26\u53F7\u53EA\u6709\u300C${only.name ?? only.workflowId}\u300D\uFF08${only.workflowId}\uFF09\u6709\u53D1\u8D77\u6743\u9650\uFF0C\u5DF2\u76F4\u63A5\u7528\u5B83\u53D1\u8D77`;
7607
- }
7608
- if (launchable.length > 1 && flowPickNote === null) {
7609
- const picked2 = launchable[0];
7610
- const others = launchable.slice(1).map((probe) => probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId);
7611
- flowPickNote = `${sourceLabel}\uFF1A\u5171 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77 ${launchable.length} \u4E2A\uFF0C\u5DF2\u6309\u4F18\u5148\u7EA7\u81EA\u52A8\u9009\u7528\u300C${picked2.name ?? picked2.workflowId}\u300D\uFF08${picked2.workflowId}\uFF09\uFF1B\u5176\u4ED6\u53EF\u7528\u6D41\u7A0B\uFF1A${others.join("\u3001")} \u2014\u2014 \u8981\u7528\u5B83\u4EEC\u8BF7\u663E\u5F0F\u4F20 workflowId\u3002`;
7612
- }
7613
- }
7614
- let form = loadedForms.get(workflowId);
7615
- if (!form) {
7616
- try {
7617
- form = await loadCreateForm(env, workflowId);
7618
- } catch (error) {
7619
- throw meetingValidationError(
7620
- "flow_not_launchable",
7621
- `\u5F53\u524D\u8D26\u53F7**\u6CA1\u6709\u53D1\u8D77\u5EFA\u4F1A\u6D41\u7A0B\u7684\u6743\u9650**\uFF08\u6216\u6D41\u7A0B\u5DF2\u505C\u7528\uFF09\uFF1A\u5EFA\u4F1A\u6D41\u7A0B ${workflowId} \u7684\u8868\u5355\u8F7D\u5165\u5931\u8D25 \u2014\u2014 ${String(error?.message ?? error).slice(0, 200)}\u3002\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\uFF1A\u9700\u8981\u627E\u7BA1\u7406\u5458\u5F00\u901A\u8BE5\u6D41\u7A0B\u7684\u53D1\u8D77\u6743\u9650\uFF0C\u6216\u8BF7\u6709\u6743\u9650\u7684\u540C\u4E8B\u4EE3\u4E3A\u53D1\u8D77\uFF1B**\u4E0D\u8981**\u6539\u7528\u76F4\u8FDE\u5EFA\u4F1A\u7ED5\u8FC7\u6D41\u7A0B\u7BA1\u63A7\u3002`,
7622
- { workflowId }
7623
- );
7624
- }
7625
- }
7626
- if (!form.continuation) {
7627
- throw meetingValidationError("flow_context_missing", "\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u6CA1\u6709\u8FD4\u56DE continuation\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u63D0\u4EA4");
7628
- }
7629
- decisions.timings = timings;
7630
- const crmMemberCount = (() => {
7631
- if (args.crm_member_count !== void 0 && args.crm_member_count !== "") return args.crm_member_count;
7632
- const raw = args.crm_members;
7633
- if (raw === void 0 || raw === null || raw === "") return void 0;
7634
- if (Array.isArray(raw)) return raw.length > 0 ? raw.length : void 0;
7635
- const text = String(raw).trim();
7636
- if (!text) return void 0;
7637
- const count = text.split(/[,;,;]+/).map((item) => item.trim()).filter((item) => item !== "").length;
7638
- return count > 0 ? count : void 0;
7639
- })();
7640
- const shaped = await shapeBrowserValues(env, {
7641
- mt_name: args.mt_name,
7642
- begin_datetime: args.begin_datetime,
7643
- end_datetime: args.end_datetime,
7644
- mt_desc: args.mt_desc,
7645
- address: addressInput,
7646
- customize_address: args.customize_address,
7647
- hrm_members: args.hrm_members,
7648
- total_member: args.total_member,
7649
- crm_members: args.crm_members,
7650
- ...crmMemberCount === void 0 ? {} : { crm_member_count: crmMemberCount },
7651
- caller: args.caller,
7652
- contacter: args.contacter,
7653
- other_remark: args.other_remark,
7654
- mt_type: args.mt_type,
7655
- ...args.extraFields && typeof args.extraFields === "object" && !Array.isArray(args.extraFields) ? args.extraFields : {}
7656
- });
7657
- const preferredFields = await readFlowFieldMap(env, workflowId);
7658
- const { main, mapped, unmapped, resolved: resolvedFields } = mapFields(form.fields, shaped.values, preferredFields);
7659
- await writeFlowFieldMap(env, workflowId, form.workflowName, resolvedFields);
7660
- const warnings = [];
7661
- if (autoFilledPerson.length > 0) {
7662
- const labels = autoFilledPerson.map((one) => `\u300C${PERSON_FIELD_LABELS[one.field]}\u300D`).join("");
7663
- warnings.push(
7664
- `${labels}\u6CA1\u6709\u4F20\u503C\uFF0C\u5DF2\u6309**\u5F53\u524D\u767B\u5F55\u4EBA**\u8865\u9F50\uFF1A${autoFilledPerson[0].name}\uFF08${autoFilledPerson[0].id}\uFF09\u3002\u8981\u6362\u6210\u522B\u4EBA\uFF08\u4F8B\u5982\u66FF\u4ED6\u4EBA\u5EFA\u4F1A\u3001\u6307\u5B9A\u522B\u7684\u8054\u7CFB\u4EBA\uFF09\u8BF7\u663E\u5F0F\u4F20 caller / contacter\u3002`
7665
- );
7666
- } else if (selfPersonWarning) {
7667
- warnings.push(selfPersonWarning);
7668
- }
7669
- if (flowPickNote) warnings.push(flowPickNote);
7670
- for (const note of shaped.notes) warnings.push(note);
7671
- const crmMentioned = detectCrmMentionInText(args.mt_name, args.mt_desc, args.other_remark);
7672
- if (crmMentioned && !args.crm_members) {
7673
- const hasCrmField = form.fields.some((field) => /参会客户/.test(String(field?.label ?? field?.name ?? field?.fieldName ?? "")));
7674
- warnings.push(
7675
- `\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u91CC\u63D0\u5230\u5BA2\u6237\u300C${crmMentioned}\u300D\uFF0C\u4F46\u672C\u6B21\u6CA1\u4F20 crm_members` + (hasCrmField ? `\uFF0C\u8BE5\u6D41\u7A0B\u8868\u5355**\u6709\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5B57\u6BB5\uFF0C\u73B0\u5728\u4F1A\u662F\u7A7A\u7684**\u3002\u8BF7\u5148 meeting.eb.crm.search {"keyword":"${crmMentioned}"} \u62FF items[].customerId\uFF0C\u518D\u7528 crm_members:[{id,name}] \u91CD\u65B0\u63D0\u4EA4\uFF08\u5FC5\u987B\u5E26\u5BA2\u6237\u540D\u79F0\uFF09\u3002` : "\uFF08\u8BE5\u6D41\u7A0B\u8868\u5355\u91CC\u6CA1\u6709\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5B57\u6BB5\uFF0C\u672C\u6761\u53EF\u5FFD\u7565\uFF09\u3002")
7676
- );
7677
- }
7678
- const crmMembersGiven = Array.isArray(args.crm_members) ? args.crm_members.length > 0 : String(args.crm_members ?? "").trim() !== "";
7679
- if (crmMembersGiven) {
7680
- const crmFieldId = String(resolvedFields.crm_members ?? "").trim();
7681
- const crmField = form.fields.find((field) => String(field?.id ?? "") === crmFieldId);
7682
- const componentKey = String(crmField?.componentKey ?? "").toLowerCase();
7683
- if (crmField && componentKey !== "" && componentKey !== "customer" && componentKey !== "customercomponent") {
7684
- warnings.push(
7685
- `\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5B57\u6BB5\uFF08${crmFieldId}\uFF09\u662F ${crmField.componentKey} \u7EC4\u4EF6\uFF1A\u5BA2\u6237 id \u4E0E\u540D\u79F0\u7167\u5E38\u5199\u8FDB\u6D41\u7A0B\u5355\u636E\uFF0C\u518D\u7531 ESB \u7684\u5B57\u6BB5\u6620\u5C04\u540C\u6B65\u5230\u4F1A\u8BAE\u8868 \u2014\u2014 \u6B63\u5E38\u914D\u7F6E\uFF0C\u4E0D\u9700\u8981\u6539\u8868\u5355\u3002`
7686
- );
7687
- }
7688
- }
7689
- const providedCrmDetailRows = normalizeCrmDetailRows(args.crm_member_details);
7690
- const onlyDetailMode = String(args.crm_detail_mode ?? "").trim().toLowerCase() === "only";
7691
- let crmDetailRows = onlyDetailMode ? providedCrmDetailRows : [];
7692
- if (crmMembersGiven && !onlyDetailMode) {
7693
- const detailTarget = resolveCrmDetailTarget(form.fields);
7694
- if (detailTarget) {
7695
- const auto = await resolveAutoCrmDetailRows(env, shaped.values.crm_members ?? args.crm_members);
7696
- if (auto.rows.length > 0) {
7697
- crmDetailRows = auto.rows;
7698
- if (providedCrmDetailRows.length > 0) {
7699
- const byName = new Map(providedCrmDetailRows.map((row) => [String(row.xm ?? "").trim(), row]));
7700
- crmDetailRows = crmDetailRows.map((row) => {
7701
- const given = byName.get(String(row.xm ?? "").trim());
7702
- if (!given) return row;
7703
- const merged = { ...row };
7704
- for (const [key, value] of Object.entries(given)) {
7705
- if (String(value ?? "").trim() !== "") merged[key] = String(value);
7706
- }
7707
- return merged;
7708
- });
7709
- }
7710
- warnings.push(
7711
- `\u5DF2\u81EA\u52A8\u628A\u300C${auto.customers.join("\u3001")}\u300D\u7684 ${auto.rows.length} \u4F4D\u8054\u7CFB\u4EBA\u5199\u8FDB\u300C\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\u300D\uFF1A${auto.rows.map((row) => `${row.xm}${row.sjhm ? ` ${row.sjhm}` : ""}`).join("\u3001")}\uFF08\u660E\u7EC6\u8868\u672C\u6765\u5C31\u4E00\u4EBA\u4E00\u884C\uFF0C\u4E0D\u9700\u8981\u8BA9\u7528\u6237\u6311\uFF09\u3002\u786E\u5B9E\u53EA\u60F3\u8981\u5176\u4E2D\u51E0\u4F4D\u65F6\uFF0C\u4F20 crm_detail_mode:"only" \u518D\u914D crm_member_details \u624D\u8986\u76D6\u672C\u6B21\u81EA\u52A8\u5E26\u5165\u3002`
7712
- );
7713
- } else if (auto.missing.length > 0) {
7714
- warnings.push(
7715
- `\u5DF2\u5199\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\uFF0C\u4F46\u6CA1\u80FD\u81EA\u52A8\u5E26\u51FA\u300C${auto.missing.join("\u3001")}\u300D\u7684\u8054\u7CFB\u4EBA\uFF08CRM \u91CC\u67E5\u4E0D\u5230\uFF09\u3002\u8BF7\u628A\u5DF2\u67E5\u5230\u7684\u8054\u7CFB\u4EBA\u76F4\u63A5\u544A\u7ED9\u7528\u6237\u6838\u5BF9\uFF1B\u786E\u5B9E\u6CA1\u6709\u8054\u7CFB\u4EBA\u65F6\u95EE\u4E00\u6B21\u59D3\u540D+\u624B\u673A\u53F7\uFF0C\u518D\u4EE5 crm_member_details:[{"xm":"\u5F20\u4E09","sjhm":"13800000000"}] \u91CD\u65B0 prepare\u3002`
7716
- );
7717
- }
7718
- }
7719
- }
7720
- let detailPayload;
7721
- if (crmDetailRows.length > 0) {
7722
- const target = resolveCrmDetailTarget(form.fields);
7723
- if (!target) {
7724
- warnings.push(
7725
- `\u4F20\u4E86 crm_member_details\uFF08${crmDetailRows.length} \u884C\uFF09\uFF0C\u4F46\u8BE5\u5EFA\u4F1A\u6D41\u7A0B\u7684**\u53D1\u8D77\u8282\u70B9\u8868\u5355\u91CC\u6CA1\u6709\u300C\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\u300D\u660E\u7EC6\u8868**\uFF08\u6216\u5B83\u88AB\u6446\u5728\u9690\u85CF\u884C\u4E0A\uFF09\uFF0C\u660E\u7EC6\u65E0\u6CD5\u5199\u5165\uFF0C\u5DF2\u5FFD\u7565\u8FD9\u4E9B\u884C\uFF1B\u4E3B\u8868\u7684\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u7167\u5E38\u5199\u5165\u3002`
7726
- );
7727
- } else {
7728
- detailPayload = {
7729
- [target.subFormId]: crmDetailRows.map((row) => {
7730
- const line = {};
7731
- for (const [semantic, fieldId] of Object.entries(target.columns)) {
7732
- const value = row[semantic];
7733
- if (value !== void 0 && value !== "") line[fieldId] = value;
7734
- }
7735
- return line;
7736
- })
7737
- };
7738
- warnings.push(
7739
- `\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\uFF1A${crmDetailRows.length} \u884C\u5199\u5165\u660E\u7EC6\u8868 ${target.subFormId}\uFF08\u5217\uFF1A${Object.values(target.labels).join("/")}\uFF09`
7740
- );
7741
- }
7742
- }
7743
- if (args.fieldValues && typeof args.fieldValues === "object" && !Array.isArray(args.fieldValues)) {
7744
- const knownIds = new Set(form.fields.map((field) => field.id));
7745
- for (const [fieldId, raw] of Object.entries(args.fieldValues)) {
7746
- if (raw === void 0 || raw === null || raw === "") continue;
7747
- if (!knownIds.has(fieldId)) {
7748
- warnings.push(`fieldValues \u91CC\u7684 datakey\u300C${fieldId}\u300D\u4E0D\u5728\u8BE5\u6D41\u7A0B\u8868\u5355\u91CC\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5148\u7528 prepare \u4E0D\u5E26 fieldValues \u8DD1\u4E00\u6B21\uFF0C\u770B unmapped/\u8868\u5355\u5B57\u6BB5\u6E05\u5355\uFF09`);
7749
- continue;
7750
- }
7751
- main[fieldId] = raw;
7752
- mapped[`datakey:${fieldId}`] = fieldId;
7753
- }
7754
- }
7755
- if (enrichFailures.length > 0) {
7756
- decisions.enrichFailures = enrichFailures;
7757
- for (const failure of enrichFailures) {
7758
- warnings.push(`\u26A0\uFE0F ${failure} \u2014\u2014 **\u8FD9\u4E0D\u4EE3\u8868\u6CA1\u6709\u51B2\u7A81**\uFF0C\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\u8BE5\u9879\u672A\u6838\u9A8C\uFF0C\u4E0D\u8981\u58F0\u79F0"\u65F6\u95F4\u5DF2\u786E\u8BA4\u7A7A\u95F2"`);
7759
- }
7760
- }
7761
- const picked = decisions.autoRoom?.picked;
7762
- if (picked && !hadAddressInput) {
7763
- warnings.push(
7764
- `\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4 \u2192 \u5DF2\u81EA\u52A8\u9009\u62E9\u300C${picked.name}\u300D\uFF08${(picked.reasons ?? []).join("\uFF1B")}\uFF09\uFF1B\u53E6\u6709\u5019\u9009 ${(decisions.roomOptions ?? []).slice(1).map((item) => item.label).join(" / ") || "\u65E0"}`
7765
- );
7766
- }
7767
- const slotOptions = decisions.slotOptions ?? [];
7768
- const memberConflictCount = decisions.memberConflicts?.length ?? 0;
7769
- if (memberConflictCount > 0 && slotOptions.length > 0) {
7770
- warnings.push(
7771
- `\u53C2\u4F1A\u4EBA\u65F6\u95F4\u6709\u51B2\u7A81\uFF08${memberConflictCount} \u6761\u5360\u7528\uFF09\uFF1B\u5F53\u5929\u6240\u6709\u4EBA\u90FD\u7A7A\u7684\u65F6\u6BB5\uFF1A` + slotOptions.map((item) => `[${item.key}] ${item.label}`).join("\uFF1B") + "\u2014\u2014\u8BF7\u7528\u9009\u9879\u65B9\u5F0F\u8BA9\u7528\u6237\u6311\uFF08\u9009\u5B9A\u540E\u91CD\u65B0 prepare \u5E76\u6539\u65F6\u95F4\uFF09\u3002"
7772
- );
7773
- } else if (memberConflictCount === 0 && slotOptions.length > 0) {
7774
- warnings.push(
7775
- `\u8BE5\u65F6\u6BB5\u53C2\u4F1A\u4EBA\u6CA1\u6709\u4F1A\u8BAE/\u65E5\u7A0B\u5360\u7528\uFF08\u5DF2\u6838\u5BF9\u4F1A\u8BAE\u56DE\u6267\u4E0E\u65E5\u7A0B\uFF09\u3002\u5F53\u5929\u5176\u4ED6\u5171\u540C\u7A7A\u95F2\u65F6\u6BB5\uFF1A${slotOptions.map((item) => `[${item.key}] ${item.label}`).join("\uFF1B")}`
7776
- );
7777
- } else if (decisions.dayBlocked?.summary) {
7778
- warnings.push(String(decisions.dayBlocked.summary));
7779
- }
7780
- const unmappedReal = unmapped.filter((name) => name !== "mt_name" && name !== "crm_member_count");
7781
- if (unmappedReal.length > 0) {
7782
- warnings.push(
7783
- `\u4EE5\u4E0B\u5B57\u6BB5\u6CA1\u6709\u5728\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u91CC\u627E\u5230\u540C\u540D\u5B57\u6BB5\uFF0C\u672A\u81EA\u52A8\u586B\u5199\uFF1A${unmappedReal.join("\u3001")}\uFF08\u8868\u5355\u73B0\u6709\u5B57\u6BB5\uFF1A${form.fields.map((field) => field.name).join("\u3001")}\uFF09`
7784
- );
7785
- }
7786
- if (!main[form.fields.find((field) => field.name === "\u4F1A\u8BAE\u540D\u79F0")?.id ?? ""] && !mapped.mt_name) {
7787
- warnings.push(
7788
- "\u8BE5\u5EFA\u4F1A\u6D41\u7A0B\u7684\u8868\u5355\u6CA1\u6709\u300C\u4F1A\u8BAE\u540D\u79F0\u300D\u5B57\u6BB5\uFF08\u90E8\u5206\u6D41\u7A0B\u7528\u6D41\u7A0B\u6807\u9898\u4EE3\u66FF\u4F1A\u8BAE\u540D\u79F0\uFF0C\u5C5E\u6B63\u5E38\u914D\u7F6E\uFF0C\u4E0D\u662F\u6D41\u7A0B\u914D\u9519\uFF09\u3002\u5982\u9700\u4F1A\u8BAE\u540D\u79F0\u72EC\u7ACB\u6210\u5B57\u6BB5\uFF0C\u8BF7\u6539\u9009\u5E26\u8BE5\u5B57\u6BB5\u7684\u6D41\u7A0B\uFF08\u5982\u300C\u4F1A\u8BAE\u7533\u8BF7\u6D41\u7A0B\uFF08NEW\uFF09\u300D\uFF09\u3002"
7789
- );
7790
- }
7791
- const crmPatchIds = (Array.isArray(shaped.values.crm_members) ? shaped.values.crm_members : []).map((row) => String(row?.id ?? "").trim()).filter((id) => id !== "");
7792
- const groupMemberIds = (Array.isArray(shaped.values.hrm_members) ? shaped.values.hrm_members : []).map((one) => String(one?.id ?? one ?? "").trim()).filter((id) => id !== "");
7793
- const session = await env.host.getSession();
7794
- const continuation = await env.continuation.issue(
7795
- {
7796
- operation: "meeting.eb.meeting.create.flow.apply",
7797
- baseUrl: session.baseUrl,
7798
- profile: session.profile,
7799
- userId: session.userId,
7800
- payload: {
7801
- workflowId,
7802
- requestName: String(args.mt_name ?? args.mt_subject ?? ""),
7803
- mtName: String(args.mt_name ?? args.mt_subject ?? ""),
7804
- workflowName: String(form.workflowName ?? ""),
7805
- data: { main, ...detailPayload ? { details: detailPayload } : {} },
7806
- surfaceContinuation: form.continuation,
7807
- // 供 apply 在「会议还没生成」时按申请单信息预生成邀请函(预置函)
7808
- invitationFields: shaped.readable,
7809
- // 提交后回显要用「字段名 → 值」,字段清单先存下来(apply 阶段拿不到 createForm 结果)
7810
- fieldLabels: form.fields.map((field) => ({ id: String(field.id), name: String(field.name) })),
7811
- // 已确认的「人员 id → 姓名」,供 apply 回显时把裸 id 换成姓名
7812
- ...autoFilledPerson.length > 0 ? { personLabels: Object.fromEntries(autoFilledPerson.map((one) => [one.id, one.name])) } : {},
7813
- // 会议记录的客户要靠 apply 补写(表单「参会客户」是 Ebuilder,单据↔会议表不同步)
7814
- ...crmPatchIds.length > 0 ? { crmPatch: { ids: crmPatchIds, count: crmMemberCount === void 0 ? crmPatchIds.length : crmMemberCount } } : {},
7815
- // 建群要素:apply 拿到会议 id 后先建群、再把群 id 回写 imchat_groupid
7816
- groupChat: {
7817
- memberIds: groupMemberIds,
7818
- beginDatetime: String(shaped.values.begin_datetime ?? ""),
7819
- endDatetime: String(shaped.values.end_datetime ?? ""),
7820
- address: String(shaped.values.address ?? "")
7821
- }
7822
- },
7823
- fingerprint: JSON.stringify({ workflowId, main, ...detailPayload ? { details: detailPayload } : {} })
7824
- },
7825
- 10 * 60 * 1e3
7826
- );
7827
- return meetingSuccess(
7828
- "meeting.eb.meeting.create.flow.prepare",
7829
- {
7830
- status: "AWAITING_CONFIRMATION",
7831
- preview: {
7832
- workflowId,
7833
- workflowCandidates: candidates,
7834
- ...probes.length > 0 ? { workflowProbes: probes } : {},
7835
- ...flowPickNote ? { workflowAutoPicked: { workflowId, source: resolved.source, note: flowPickNote } } : {},
7836
- requestName: String(args.mt_name ?? args.mt_subject ?? ""),
7837
- fieldMapping: mapped,
7838
- formData: { main },
7839
- // 人话版「即将提交的内容」—— 提交前必须先贴给用户核对(见 SKILL 建会章节)。
7840
- formPreview: renderFormPreview(
7841
- form.fields,
7842
- await decoratePreviewPersonNames(
7843
- env,
7844
- main,
7845
- form.fields,
7846
- new Map(autoFilledPerson.map((one) => [one.id, one.name]))
7847
- )
7848
- ),
7849
- // 召集人/联系人是不是"替用户默认填的"要说清楚,用户才知道能不能改。
7850
- ...autoFilledPerson.length > 0 ? {
7851
- autoFilled: Object.fromEntries(
7852
- autoFilledPerson.map((one) => [PERSON_FIELD_LABELS[one.field], `${one.name}(${one.id})`])
7853
- )
7854
- } : {},
7855
- ...detailPayload ? { detailRows: { subFormId: Object.keys(detailPayload)[0], count: crmDetailRows.length, rows: crmDetailRows } } : {},
7856
- formFieldCount: form.fields.length,
7857
- ...Object.keys(decisions).length > 0 ? { decisions } : {}
7858
- },
7859
- continuation,
7860
- expiresInSeconds: 600
7861
- },
7862
- warnings.length > 0 ? { warnings } : {}
7863
- );
7864
- }
7865
- };
7866
- var CRM_PATCH_SETTLE_MS = [4e3, 6e3];
7867
- async function patchMeetingCrmMembers(env, meetingId, ids, count, settleMsList = CRM_PATCH_SETTLE_MS) {
7868
- const list = ids.map((id) => String(id ?? "").trim()).filter((id) => id !== "");
7869
- if (String(meetingId).trim() === "" || list.length === 0) {
7870
- return { ok: false, error: "\u6CA1\u6709\u4F1A\u8BAE id \u6216\u5BA2\u6237 id" };
7871
- }
7872
- const mainTable = {
7873
- id: String(meetingId).trim(),
7874
- operate_type: "UPDATE",
7875
- crm_members: list.join(",")
7876
- };
7877
- const total = Number(count);
7878
- if (Number.isFinite(total) && total > 0) mainTable.crm_total_member = String(total);
7879
- const write = async () => {
7880
- const session = await env.host.getSession();
7881
- await env.host.request({
7882
- method: "POST",
7883
- path: `${EB_BASE}/updateFormData/change_meeting`,
7884
- query: { id: String(meetingId).trim() },
7885
- operation: "meeting.eb.meeting.create.flow.apply",
7886
- body: writeBody(String(session.userId), { mainTable, details: {}, operateType: {} }),
7887
- acceptBusiness: ebBusinessSuccess
7888
- });
7889
- };
7890
- const readBack = async () => {
7891
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
7892
- const detail = getMeetingOperation2("meeting.eb.meeting.detail");
7893
- const read = await detail.handler({ id: String(meetingId).trim() }, env);
7894
- return String(read?.data?.data?.crm_members ?? "").trim();
7895
- };
7896
- let lastError = "";
7897
- for (const settleMs of settleMsList) {
7898
- try {
7899
- await write();
7900
- } catch (error) {
7901
- return { ok: false, error: String(error?.message ?? error).slice(0, 160) };
7902
- }
7903
- await new Promise((resolve6) => setTimeout(resolve6, settleMs));
7904
- try {
7905
- const value = await readBack();
7906
- if (value !== "") return { ok: true, value };
7907
- lastError = "\u8865\u5199\u540E\u56DE\u8BFB crm_members \u4ECD\u4E3A\u7A7A\uFF08\u591A\u534A\u88AB\u4F1A\u8BAE\u521D\u59CB\u5316\u7684\u540E\u7EED\u5199\u5165\u8986\u76D6\u4E86\uFF09";
7908
- } catch (error) {
7909
- lastError = `\u8865\u5199\u6210\u529F\u4F46\u56DE\u8BFB\u5931\u8D25\uFF1A${String(error?.message ?? error).slice(0, 120)}`;
7910
- }
7911
- }
7912
- return { ok: false, error: lastError };
7913
- }
7914
- async function renderPreInvitation(payload, env) {
7915
- const fields = payload?.invitationFields ?? {};
7916
- const started = Date.now();
7917
- try {
7918
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
7919
- const render = getMeetingOperation2("meeting.invitation.render");
7920
- const rendered = await render.handler(
7921
- {
7922
- mt_name: String(fields.mt_name ?? payload?.mtName ?? "").trim(),
7923
- begin_datetime: String(fields.begin_datetime ?? "").trim(),
7924
- end_datetime: String(fields.end_datetime ?? "").trim(),
7925
- address: String(fields.address ?? fields.customize_address ?? "").trim(),
7926
- hrm_members: String(fields.hrm_members ?? "").trim(),
7927
- mt_desc: String(fields.mt_desc ?? "").trim(),
7928
- org_members: String(fields.org_members ?? "").trim(),
7929
- caller: String(fields.caller ?? "").trim(),
7930
- contacter: String(fields.contacter ?? "").trim(),
7931
- total_member: String(fields.total_member ?? "").trim(),
7932
- // 客户单位(邀请函开头「尊敬的 XXX」):建会时填了参会客户就直接带过去,
7933
- // 否则整句永远是【待补充】—— 用户看到的就是"客户明明填了,邀请函里却没有"。
7934
- extra: { guest_org: String(fields.crm_members ?? "").trim() }
7935
- },
7936
- env
7937
- );
7938
- return {
7939
- invitation: { pending: true, preRendered: true, ...rendered?.data ?? {} },
7940
- ms: Date.now() - started
7941
- };
7942
- } catch (error) {
7943
- return {
7944
- invitation: {
7945
- pending: true,
7946
- preRendered: false,
7947
- ok: false,
7948
- error: String(error?.message ?? error).slice(0, 200)
7949
- },
7950
- ms: Date.now() - started
7951
- };
7952
- }
7953
- }
7954
- var ebMeetingCreateFlowApply = {
7955
- name: "meeting.eb.meeting.create.flow.apply",
7956
- resource: "eb",
7957
- method: "meeting.eb.meeting.create.flow.apply",
7958
- action: "meeting.eb.meeting.create.flow.apply",
7959
- summary: "\u6D41\u7A0B\u5EFA\u4F1A\uFF08\u63D0\u4EA4\uFF09\uFF1A\u7528\u786E\u8BA4\u7968\u636E\u63D0\u4EA4\u5EFA\u4F1A\u6D41\u7A0B\uFF1B\u63D0\u4EA4\u540E\u8F6E\u8BE2\u4F1A\u8BAE\u5217\u8868\u786E\u8BA4\u4F1A\u8BAE\u662F\u5426\u5DF2\u751F\u6210\uFF0C\u751F\u6210\u5219\u81EA\u52A8\u51FA\u9080\u8BF7\u51FD",
7960
- capability: "eb.meeting",
7961
- risk: "high-risk-write",
7962
- requiresConfirmation: true,
7963
- inputSchema: schemaOf(
7964
- {
7965
- continuation: { type: "string", description: "prepare \u8FD4\u56DE\u7684\u786E\u8BA4\u7968\u636E\uFF08\u5FC5\u586B\uFF09" },
7966
- confirm: { type: "boolean", description: "\u5FC5\u987B\u663E\u5F0F\u4F20 true" },
7967
- submit_mode: {
7968
- type: "string",
7969
- enum: ["direct", "browser"],
7970
- description: '\u63D0\u4EA4\u65B9\u5F0F\uFF0C\u9ED8\u8BA4 browser\uFF1A\u5728\u5C0Fe \u91CC**\u5F39\u51FA\u6D41\u7A0B\u8868\u5355**\uFF0C\u5B57\u6BB5\u5DF2\u9884\u586B\uFF0C\u7528\u6237\u6838\u5BF9/\u4FEE\u6539\u540E\u81EA\u5DF1\u70B9\u63D0\u4EA4\u3002direct = \u76F4\u63A5\u5199\u670D\u52A1\u7AEF\uFF08\u4F1A\u8BAE\u5F53\u573A\u751F\u6210\u3001\u9080\u8BF7\u51FD\u7528\u771F\u5B9E\u6570\u636E\uFF0C\u4F46\u6CA1\u6709\u4EBA\u5DE5\u6838\u5BF9\u8868\u5355\u8FD9\u4E00\u6B65\uFF09\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8BF4"\u4E0D\u7528\u6211\u786E\u8BA4\uFF0C\u76F4\u63A5\u5EFA"\u65F6\u624D\u4F20 direct'
7971
- },
7972
- waitSeconds: { type: "number", description: "\u63D0\u4EA4\u540E\u7B49\u5F85\u4F1A\u8BAE\u751F\u6210\u7684\u6700\u957F\u79D2\u6570\uFF08\u9ED8\u8BA4 60\uFF0C0 = \u4E0D\u7B49\u5F85\uFF09" }
7973
- },
7974
- { required: ["continuation", "confirm"] }
7975
- ),
7976
- handler: async (args, env) => {
7977
- if (args.confirm !== true) {
7978
- throw meetingValidationError("confirmation_required", "\u6D41\u7A0B\u5EFA\u4F1A\u5C5E\u4E8E\u9AD8\u5F71\u54CD\u5199\u64CD\u4F5C\uFF0C\u5FC5\u987B\u663E\u5F0F\u4F20 confirm=true");
7979
- }
7980
- const lease = await env.continuation.verify(
7981
- String(args.continuation ?? ""),
7982
- "meeting.eb.meeting.create.flow.apply"
7983
- );
7984
- const session = await env.host.getSession();
7985
- if (lease.baseUrl !== session.baseUrl || lease.userId !== session.userId) {
7986
- throw meetingValidationError("context_mismatch", "\u786E\u8BA4\u4E0A\u4E0B\u6587\u5DF2\u53D8\u5316\uFF08\u79DF\u6237\u6216\u767B\u5F55\u8D26\u53F7\u4E0D\u540C\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
7987
- }
7988
- const payload = lease?.payload ?? {};
7989
- const { createWorkflowHost } = await import("./host-L3VLITMT.js");
7990
- const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
7991
- const { getWorkflowOperation } = await import("./registry-UGRBCBHO.js");
7992
- const wfEnv = {
7993
- ...workflowEnv(env),
7994
- host: createWorkflowHost(env.ctx),
7995
- continuation: createWorkflowContinuationSigner(env.ctx)
7996
- };
7997
- const submitStartedAt = Date.now();
7998
- const submit = getWorkflowOperation("workflow.createRequest");
7999
- const submitMode = String(args.submit_mode ?? "browser").trim();
8000
- const submitted = await submit.handler(
8001
- {
8002
- // 工作流的入参名是 context(createForm 返回的 continuation 就是它的 context 句柄)
8003
- context: payload.surfaceContinuation,
8004
- data: payload.data,
8005
- action: "submit",
8006
- requestName: payload.requestName,
8007
- confirm: true,
8008
- ...submitMode === "browser" ? {} : { forceServerSubmit: true }
8009
- },
8010
- wfEnv
8011
- );
8012
- const submittedData = submitted?.data ?? {};
8013
- const requestId = String(submittedData.requestId ?? submittedData.id ?? "").trim();
8014
- if (!requestId && String(submittedData.status ?? "") === "NEEDS_CONFIRMATION") {
8015
- return meetingSuccess(
8016
- "meeting.eb.meeting.create.flow.apply",
8017
- {
8018
- status: "NEEDS_CONFIRMATION",
8019
- workflowId: payload.workflowId,
8020
- requestName: payload.requestName,
8021
- message: String(submittedData.message ?? ""),
8022
- resolvedValues: submittedData.resolvedValues ?? [],
8023
- unresolved: submittedData.unresolved ?? submittedData.candidates ?? [],
8024
- submit: submittedData
8025
- },
8026
- {
8027
- warnings: [
8028
- "\u5EFA\u4F1A\u6D41\u7A0B\u672A\u63D0\u4EA4\uFF1A\u670D\u52A1\u7AEF\u6709\u5B57\u6BB5\u65E0\u6CD5\u552F\u4E00\u89E3\u6790\uFF08\u591A\u4E3A\u4F1A\u8BAE\u5730\u70B9/\u53C2\u4F1A\u4EBA\u5458/\u53EC\u96C6\u4EBA\u7B49\u6D4F\u89C8\u6309\u94AE\u5B57\u6BB5\uFF09\uFF0C\u8BF7\u6309 message / unresolved \u4E0E\u7528\u6237\u786E\u8BA4\u53D6\u503C\u540E\u91CD\u65B0 prepare\uFF08\u628A\u8FD9\u4E9B\u5B57\u6BB5\u6539\u6210\u670D\u52A1\u7AEF\u8BA4\u5F97\u7684\u683C\u5F0F\uFF0C\u5982\u300C\u540D\u79F0(ID)\u300D\uFF09\u3002"
8029
- ]
8030
- }
8031
- );
8032
- }
8033
- if (!requestId) {
8034
- const submitStatus = String(submittedData.status ?? submitted?.status ?? "");
8035
- if (submitStatus === "BROWSER_FILL") {
8036
- const pre = await renderPreInvitation(payload, env);
8037
- let groupChat2;
8038
- const groupPayload2 = payload?.groupChat;
8039
- if (groupPayload2) {
8040
- try {
8041
- const { ensureMeetingGroupChat } = await import("./group-chat-VYBNMJLG.js");
8042
- groupChat2 = {
8043
- ...await ensureMeetingGroupChat(env, {
8044
- meetingName: String(payload.mtName ?? ""),
8045
- beginDatetime: String(groupPayload2.beginDatetime ?? ""),
8046
- endDatetime: String(groupPayload2.endDatetime ?? ""),
8047
- memberIds: Array.isArray(groupPayload2.memberIds) ? groupPayload2.memberIds : [],
8048
- ...groupPayload2.address ? { address: String(groupPayload2.address) } : {}
8049
- })
8050
- };
8051
- } catch (error) {
8052
- groupChat2 = { ok: false, error: String(error?.message ?? error).slice(0, 200) };
8053
- }
8054
- }
8055
- if (groupChat2 && groupChat2.ok) {
8056
- try {
8057
- const { savePendingForm } = await import("./group-chat-VYBNMJLG.js");
8058
- await savePendingForm(env, {
8059
- workflowId: String(payload.workflowId ?? ""),
8060
- workflowName: String(payload.workflowName ?? ""),
8061
- mtName: String(payload.mtName ?? ""),
8062
- groupId: String(groupChat2.groupId ?? ""),
8063
- groupName: String(groupChat2.groupName ?? "")
8064
- });
8065
- } catch {
8066
- }
8067
- }
8068
- return meetingSuccess(
8069
- "meeting.eb.meeting.create.flow.apply",
8070
- {
8071
- status: "BROWSER_FILL",
8072
- workflowId: payload.workflowId,
8073
- requestName: payload.requestName,
8074
- requestId: null,
8075
- meetingId: null,
8076
- contextId: submittedData.contextId ?? null,
8077
- // 宿主要靠这段 <browsertool> 才能把表单拉到浏览器里填,必须原样透出
8078
- finalMarkdown: submittedData.finalMarkdown ?? null,
8079
- // 与 finalMarkdown 相邻的硬提示:模型「以为 CLI 已经打开了表单」是这次翻车的直接原因
8080
- finalMarkdownHint: '\u628A finalMarkdown \u539F\u6837\u8D34\u5728\u56DE\u590D\u6700\u540E\uFF08\u4ECE <browsertool> \u5230 </browsertool>\uFF0C\u4E0D\u5305\u4EE3\u7801\u5757\uFF09\uFF1B\u4E0D\u8D34\u8FD9\u6BB5\uFF1D\u7528\u6237\u770B\u4E0D\u5230\u8868\u5355\uFF0C\u4E5F\u4E0D\u80FD\u8BF4"\u8868\u5355\u5DF2\u6253\u5F00"\u3002',
8081
- message: String(submittedData.message ?? ""),
8082
- invitation: pre.invitation,
8083
- ...groupChat2 ? { groupChat: groupChat2 } : {},
8084
- timings: { submitMs: Date.now() - submitStartedAt, invitationMs: pre.ms }
8085
- },
8086
- {
8087
- warnings: [
8088
- '\u5F53\u524D\u662F\u5C0Fe \u73AF\u5883\uFF1A\u672C\u6B21**\u6CA1\u6709\u5411\u670D\u52A1\u7AEF\u5199\u5165**\uFF0C\u5EFA\u4F1A\u6D41\u7A0B\u6539\u7531\u6D4F\u89C8\u5668\u9875\u9762\u5B8C\u6210\u586B\u5355\uFF08\u89C1 finalMarkdown\uFF09\u3002\u56E0\u6B64\u8FD8\u6CA1\u6709 requestId / \u4F1A\u8BAE id\uFF0C\u4E5F**\u4E0D\u80FD\u8BF4"\u6D41\u7A0B\u5DF2\u63D0\u4EA4"**\u3002',
8089
- ...groupChat2 && groupChat2.ok ? [`\u7FA4\u804A\u5DF2\u540C\u6B65\u5EFA\u597D\uFF08\u7FA4 id ${String(groupChat2.groupId)}\uFF0C\u7FA4\u540D ${String(groupChat2.groupName)}\uFF09\uFF1A\u6D41\u7A0B\u8FD8\u6CA1\u63D0\u4EA4\u3001\u6CA1\u6709\u4F1A\u8BAE id\uFF0C\u6240\u4EE5 imchat_groupid \u6682\u65F6\u6CA1\u56DE\u5199\uFF1B\u4F1A\u8BAE\u751F\u6210\u540E\u518D\u8DD1\u4E00\u6B21 meeting.eb.meeting.group.ensure\uFF08\u4F20 meetingId + groupId\uFF09\u7ED1\u5B9A\u3002`] : groupChat2 ? [`\u7FA4\u804A\u6CA1\u5EFA\u6210\u529F\uFF08${String(groupChat2.error ?? "\u672A\u77E5\u539F\u56E0")}\uFF09\uFF1A\u4F1A\u8BAE\u7167\u5E38\u53EF\u4EE5\u5728\u9875\u9762\u91CC\u63D0\u4EA4\uFF0C\u7FA4\u9700\u8981\u624B\u5DE5\u5EFA\u6216\u7A0D\u540E\u91CD\u8BD5\u3002`] : [],
8090
- `\u9080\u8BF7\u51FD\u5DF2\u6309\u7533\u8BF7\u5355\u4FE1\u606F**\u9884\u751F\u6210**\uFF08\u9884\u7F6E\u51FD\uFF0C${String(pre.invitation.filePath ?? "\u89C1 filePath")}\uFF09\uFF1A\u8BF7\u4E0B\u8F7D\u540E\u4EBA\u5DE5\u6838\u5BF9\u3001\u81EA\u884C\u53D1\u9001\uFF1B\u6D41\u7A0B\u5BA1\u6279\u901A\u8FC7\u3001\u4F1A\u8BAE\u751F\u6210\u540E\u53EF\u7528 mtId \u518D\u8DD1\u4E00\u6B21 meeting.invitation.render \u62FF\u5B8C\u6574\u5B57\u6BB5\u7248\u672C\u3002`,
8091
- '\u26D4 \u4E0D\u8981\u56E0\u4E3A"\u6CA1\u6709 requestId / \u6CA1\u6709\u4F1A\u8BAE id"\u91CD\u590D apply \u2014\u2014 \u586B\u5355\u8981\u5728\u90A3\u4E2A\u6D4F\u89C8\u5668\u9875\u9762\u91CC\u70B9\u63D0\u4EA4\u3002'
8092
- ]
8093
- }
8094
- );
8095
- }
8096
- const missing = submittedData.missingFields ?? submittedData.requiredMissing ?? submittedData.missing ?? [];
8097
- throw meetingValidationError(
8098
- "flow_submit_incomplete",
8099
- `\u5EFA\u4F1A\u6D41\u7A0B\u672A\u63D0\u4EA4\u6210\u529F\uFF08status=${String(submittedData.status ?? submitted?.status ?? "\u672A\u77E5")}\uFF09\uFF1A` + (Array.isArray(missing) && missing.length > 0 ? `\u7F3A\u5C11\u5FC5\u586B\u9879 ${missing.map((item) => item?.name ?? item).join("\u3001")}` : "\u670D\u52A1\u7AEF\u672A\u8FD4\u56DE requestId\uFF0C\u8BF7\u67E5\u770B result \u6392\u67E5"),
8100
- { submit: submittedData, missing }
8101
- );
8102
- }
8103
- const warnings = [];
8104
- const submitDay = dayOf(String(payload?.groupChat?.beginDatetime ?? ""));
8105
- if (submitDay !== "") void invalidateDayUsages(env, submitDay).catch(() => void 0);
8106
- void rememberFlowPick(
8107
- env,
8108
- String(payload?.workflowId ?? ""),
8109
- typeof payload?.workflowName === "string" ? payload.workflowName : void 0
8110
- ).catch(() => void 0);
8111
- const waitSeconds = args.waitSeconds === void 0 ? 20 : Math.max(0, Math.min(180, Number(args.waitSeconds)));
8112
- let meetingId = "";
8113
- const timings = { submitMs: Date.now() - submitStartedAt };
8114
- if (waitSeconds > 0) {
8115
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
8116
- const list = getMeetingOperation2("meeting.eb.meeting.list");
8117
- const deadline = Date.now() + Math.min(waitSeconds, 30) * 1e3;
8118
- const pollStart = Date.now();
8119
- let waited = 0;
8120
- let stepIndex = 0;
8121
- const pollSteps = [500, 1e3, 2e3, 4e3];
8122
- while (Date.now() <= deadline) {
8123
- try {
8124
- const page = await list.handler({ mt_name: payload.mtName, pageSize: 5 }, env);
8125
- const rows = page?.data?.rows ?? [];
8126
- const hit = rows.map((row) => row?.mainTable ?? row ?? {}).find((main) => String(main.mt_name ?? "").trim() === String(payload.mtName).trim());
8127
- if (hit) {
8128
- meetingId = String(hit.id ?? "").trim();
8129
- if (meetingId) break;
8130
- }
8131
- } catch {
8132
- }
8133
- if (waited >= 7500) break;
8134
- const step = pollSteps[Math.min(stepIndex, pollSteps.length - 1)];
8135
- stepIndex += 1;
8136
- await new Promise((resolve6) => setTimeout(resolve6, step));
8137
- waited += step;
8138
- }
8139
- timings.pollMs = Date.now() - pollStart;
8140
- }
8141
- let crmLinked;
8142
- const crmPatch = payload?.crmPatch;
8143
- const crmPatchEnabled = process.env.WEAVER_MEETING_CRM_PATCH === "1";
8144
- if (meetingId && crmPatchEnabled && Array.isArray(crmPatch?.ids) && crmPatch.ids.length > 0) {
8145
- const patched = await patchMeetingCrmMembers(env, meetingId, crmPatch.ids, crmPatch.count);
8146
- crmLinked = {
8147
- ok: patched.ok,
8148
- requested: crmPatch.ids.length,
8149
- ...patched.value ? { readBack: patched.value } : {},
8150
- ...patched.error ? { error: patched.error } : {}
8151
- };
8152
- if (patched.ok) {
8153
- warnings.push(`\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5DF2\u8865\u5199\u5230\u4F1A\u8BAE\u8BB0\u5F55\uFF08crm_members=${patched.value}\uFF09\u3002`);
8154
- } else {
8155
- warnings.push(
8156
- `\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u6CA1\u6709\u56DE\u8BFB\u5230\uFF08${patched.error ?? "\u672A\u77E5\u539F\u56E0"}\uFF09\uFF1A\u5F53\u524D\u8D70\u7684\u662F CLI \u624B\u5DE5\u8865\u5199\uFF08WEAVER_MEETING_CRM_PATCH=1\uFF09\uFF0C\u4E0D\u4F9D\u8D56 ESB \u5B57\u6BB5\u6620\u5C04\u65F6\u624D\u9700\u8981\u5B83\u3002`
8157
- );
8158
- }
8159
- }
8160
- let groupChat;
8161
- const groupPayload = payload?.groupChat;
8162
- if (groupPayload) {
8163
- const groupStart = Date.now();
8164
- try {
8165
- const { ensureMeetingGroupChat } = await import("./group-chat-VYBNMJLG.js");
8166
- const group = await ensureMeetingGroupChat(env, {
8167
- meetingName: String(payload.mtName ?? ""),
8168
- beginDatetime: String(groupPayload.beginDatetime ?? ""),
8169
- endDatetime: String(groupPayload.endDatetime ?? ""),
8170
- memberIds: Array.isArray(groupPayload.memberIds) ? groupPayload.memberIds : [],
8171
- ...groupPayload.address ? { address: String(groupPayload.address) } : {},
8172
- ...meetingId ? { meetingId } : {}
8173
- });
8174
- groupChat = { ...group };
8175
- if (group.ok && group.bound) {
8176
- warnings.push(
8177
- `\u5DF2\u6309\u4F1A\u8BAE\u540C\u6B65\u5EFA\u7FA4\u300C${group.groupName ?? payload.mtName}\u300D\uFF08\u7FA4 id ${group.groupId}\uFF09\uFF0C\u5E76\u56DE\u5199\u5230\u4F1A\u8BAE\u8BB0\u5F55 imchat_groupid${group.readBack ? `\uFF08\u56DE\u8BFB ${group.readBack}\uFF09` : ""}\u3002`
8178
- );
8179
- } else if (group.ok) {
8180
- warnings.push(
8181
- `\u7FA4\u5DF2\u5EFA\u597D\uFF08\u7FA4 id ${group.groupId}\uFF09\uFF0C\u4F46\u4F1A\u8BAE\u8FD8\u6CA1\u751F\u6210\uFF0C\u6682\u65F6\u6CA1\u6CD5\u56DE\u5199 imchat_groupid\uFF1B\u4F1A\u8BAE\u751F\u6210\u540E\u4F20 meetingId+groupId \u8DD1\u4E00\u6B21 meeting.eb.meeting.group.ensure \u7ED1\u5B9A\u5373\u53EF\u3002`
8182
- );
8183
- } else {
8184
- warnings.push(
8185
- `\u7FA4\u804A\u6CA1\u5EFA\u6210\u529F/\u6CA1\u7ED1\u4E0A\uFF08${group.error ?? "\u672A\u77E5\u539F\u56E0"}\uFF09\uFF1A\u4F1A\u8BAE\u672C\u8EAB\u5DF2\u5EFA\u597D\uFF0C\u7FA4\u53EF\u5728 IM \u91CC\u624B\u5DE5\u5EFA\uFF0C\u518D\u628A\u7FA4 id \u4F20\u5230 meeting.eb.meeting.group.ensure \u7684 groupId \u7ED1\u5B9A\u3002`
8186
- );
8187
- }
8188
- } catch (error) {
8189
- warnings.push(`\u5EFA\u7FA4\u5F02\u5E38\uFF08\u4E0D\u5F71\u54CD\u5EFA\u4F1A\uFF09\uFF1A${String(error?.message ?? error).slice(0, 200)}`);
8190
- }
8191
- timings.groupMs = Date.now() - groupStart;
8192
- }
8193
- let invitation = { pending: true };
8194
- if (meetingId) {
8195
- const invitationStart = Date.now();
8196
- try {
8197
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
8198
- const render = getMeetingOperation2("meeting.invitation.render");
8199
- const rendered = await render.handler(
8200
- {
8201
- mtId: meetingId,
8202
- // 同理:会议主表不存客户名,用建会时填的参会客户补「客户单位」
8203
- extra: { guest_org: String(payload?.invitationFields?.crm_members ?? "").trim() }
8204
- },
8205
- env
8206
- );
8207
- invitation = { pending: false, ...rendered?.data ?? {} };
8208
- timings.invitationMs = Date.now() - invitationStart;
8209
- } catch (error) {
8210
- invitation = {
8211
- pending: false,
8212
- ok: false,
8213
- error: String(error?.message ?? error).slice(0, 200)
8214
- };
8215
- }
8216
- } else {
8217
- const pre = await renderPreInvitation(payload, env);
8218
- invitation = pre.invitation;
8219
- timings.invitationMs = pre.ms;
8220
- warnings.push(
8221
- `\u6D41\u7A0B\u5DF2\u63D0\u4EA4\uFF08requestId=${requestId || "\u672A\u8FD4\u56DE"}\uFF09\uFF0C\u4F46 ${waitSeconds}s \u5185\u6CA1\u5728\u4F1A\u8BAE\u8868\u91CC\u67E5\u5230\u300C${payload.mtName}\u300D\u2014\u2014\u591A\u6570\u60C5\u51B5\u662F\u8FD8\u5728\u5BA1\u6279\u4E2D\u3002\u5DF2\u6309\u7533\u8BF7\u5355\u4FE1\u606F**\u9884\u751F\u6210**\u9080\u8BF7\u51FD\uFF08\u5C5E\u9884\u7F6E\u51FD\uFF0C\u8BF7\u4EBA\u5DE5\u6838\u5BF9\u540E\u81EA\u884C\u53D1\u9001\uFF09\uFF1B\u5BA1\u6279\u901A\u8FC7\u3001\u4F1A\u8BAE\u751F\u6210\u540E\u53EF\u7528 mtId \u518D\u8DD1\u4E00\u6B21 meeting.invitation.render \u62FF\u5230\u5B8C\u6574\u5B57\u6BB5\u7248\u672C\u3002\u26D4 \u672C operation \u4E0D\u91CD\u590D\u63D0\u4EA4\u6D41\u7A0B \u2014\u2014 \u4E0D\u8981\u56E0\u4E3A"\u6CA1\u6709\u4F1A\u8BAE id"\u5C31\u91CD\u590D apply\u3002`
8222
- );
8223
- }
8224
- return meetingSuccess(
8225
- "meeting.eb.meeting.create.flow.apply",
8226
- {
8227
- status: "COMPLETE",
8228
- timings,
8229
- workflowId: payload.workflowId,
8230
- requestId,
8231
- requestName: payload.requestName,
8232
- meetingId: meetingId || null,
8233
- // 参会客户有没有真的写进会议记录(表单侧是 Ebuilder,需 apply 补写;回读确认才算 ok)
8234
- ...crmLinked ? { crmLinked } : {},
8235
- // 同步建的群(群 id / 群名 / 有没有回写 imchat_groupid)
8236
- ...groupChat ? { groupChat } : {},
8237
- // 提交后回显「实际提交了什么」:字段名 → 值(人员/客户显示姓名,不显示 id)。
8238
- // 用户要的就是"能看见内容",替代走不通的浏览器填单核对。
8239
- submittedPreview: renderFormPreview(
8240
- payload?.fieldLabels ?? [],
8241
- await decoratePreviewPersonNames(
8242
- env,
8243
- payload?.data?.main ?? {},
8244
- payload?.fieldLabels ?? [],
8245
- new Map(Object.entries(payload?.personLabels ?? {}))
8246
- )
8247
- ),
8248
- invitation,
8249
- result: submitted?.data ?? null
8250
- },
8251
- warnings.length > 0 ? { warnings } : {}
8252
- );
8253
- }
8254
- };
8255
- var ebMeetingCreateFlowQuick = {
8256
- name: "meeting.eb.meeting.create.flow.quick",
8257
- resource: "eb",
8258
- method: "meeting.eb.meeting.create.flow.quick",
8259
- action: "meeting.eb.meeting.create.flow.quick",
8260
- summary: '\u4E00\u6B65\u6D41\u7A0B\u5EFA\u4F1A\uFF08prepare+apply \u5408\u5E76\uFF09\uFF1A\u5185\u90E8\u5E76\u884C\u505A\u4F1A\u8BAE\u5BA4\u63A8\u8350/\u51B2\u7A81\u68C0\u6D4B/\u7A7A\u95F2\u65F6\u6BB5\uFF0C\u9ED8\u8BA4**\u5F39\u6D4F\u89C8\u5668\u8868\u5355**\u7ED9\u7528\u6237\u6838\u5BF9\u63D0\u4EA4\uFF08submit_mode=browser\uFF0C\u5C0Fe \u91CC\u9884\u586B\u4EBA\u5458/\u5BA2\u6237\u540E\u7531\u7528\u6237\u70B9\u63D0\u4EA4\uFF1B\u975E\u5C0Fe \u73AF\u5883\u4F1A\u81EA\u52A8\u5199\u670D\u52A1\u7AEF\uFF09\uFF1B\u4F20 submit_mode=direct \u624D\u662F\u670D\u52A1\u7AEF\u76F4\u63D0\uFF08\u62FF requestId + meetingId\uFF0C\u4F1A\u8BAE\u5F53\u573A\u751F\u6210\u3001\u9080\u8BF7\u51FD\u7528\u771F\u5B9E\u6570\u636E\uFF09\u3002\u591A\u6D41\u7A0B\u6216\u9700\u9009\u62E9\u65F6\u4E0D\u63D0\u4EA4\uFF0C\u8FD4\u56DE\u9009\u9879\u3002\u26A0\uFE0F \u7528\u6237\u63D0\u5230\u5BA2\u6237\u540D\u65F6**\u5FC5\u987B\u5148** meeting.eb.crm.search {"keyword":"X"} \u62FF customerId \u518D\u4F20 crm_members:[{id,name}]\uFF1B\u53EA\u628A\u5BA2\u6237\u540D\u5199\u8FDB\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u800C\u4E0D\u4F20 crm_members \u4F1A\u88AB\u76F4\u63A5\u62D2\u7EDD\uFF08crm_member_required\uFF09\u3002\u26D4 \u4E0D\u8981\u7528 submit_mode=browser \u2014\u2014 \u5C0Fe \u586B\u5355\u9875\u4E0D\u7ED9\u6D4F\u89C8\u6309\u94AE\u8D4B\u503C\uFF0C\u53C2\u4F1A\u4EBA\u5458/\u53C2\u4F1A\u5BA2\u6237\u4F1A\u6574\u6BB5\u4E22\u5931',
8261
- capability: "eb.meeting",
8262
- risk: "high-risk-write",
8263
- requiresConfirmation: true,
8264
- inputSchema: schemaOf(
8265
- {
8266
- mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
8267
- begin_datetime: {
8268
- ...SCHEMA_DATETIME_MINUTE,
8269
- description: "\u5F00\u59CB\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\u3002**\u53EF\u4EE5\u4E0D\u4F20**\uFF1A\u4E0D\u4F20\u4F1A\u6309\u53C2\u4F1A\u4EBA\u4E0E\u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u60C5\u51B5\u63A8\u8350 3 \u4E2A\u65F6\u6BB5\u8BA9\u4F60\u9009\uFF1B\u53EA\u4F20\u5F00\u59CB\u65F6\u95F4\u3001\u4E0D\u4F20\u7ED3\u675F\u65F6\u95F4\u65F6\uFF0C\u6309 durationMinutes\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09\u81EA\u52A8\u7B97\u7ED3\u675F\u65F6\u95F4"
8270
- },
8271
- end_datetime: {
8272
- ...SCHEMA_DATETIME_MINUTE,
8273
- description: "\u7ED3\u675F\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\uFF1B\u4E0D\u4F20\u5219\u6309 durationMinutes \u4ECE\u5F00\u59CB\u65F6\u95F4\u63A8\u7B97\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09"
8274
- },
8275
- mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
8276
- address: { type: "string", description: "\u4F1A\u8BAE\u5BA4\uFF08id \u6216\u540D\u79F0\uFF1B\u4E0D\u4F20\u5219\u8FD4\u56DE\u5019\u9009\u8BA9\u7528\u6237\u9009\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u51B3\u5B9A\uFF09" },
8277
- customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
8278
- hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u5458 id\uFF0C\u9017\u53F7\u5206\u9694" },
8279
- total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
8280
- caller: { type: "string", description: "\u53EC\u96C6\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u53EC\u96C6\u4EBA\u624D\u4F20" },
8281
- contacter: { type: "string", description: "\u8054\u7CFB\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u8054\u7CFB\u4EBA\u624D\u4F20" },
8282
- mt_type: {
8283
- type: "string",
8284
- description: "\u4F1A\u8BAE\u7C7B\u578B\uFF1A\u53EF\u4F20\u7C7B\u578B\u540D\u79F0\u6216 id\uFF08\u5148\u7528 `meeting.eb.type.list` \u67E5\u6709\u54EA\u4E9B\uFF09\u3002**\u5F88\u591A\u79DF\u6237\u7684\u6D41\u7A0B\u8868\u5355\u628A\u300C\u4F1A\u8BAE\u7C7B\u578B\u300D\u8BBE\u4E3A\u5FC5\u586B**\uFF0C\u4E0D\u4F20\u4F1A\u88AB `workflow.createRequest` \u6253\u56DE\u7F3A\u5B57\u6BB5"
8285
- },
8286
- other_remark: { type: "string", description: "\u5907\u6CE8" },
8287
- workflowId: {
8288
- oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
8289
- description: "\u6307\u5B9A\u5EFA\u4F1A\u6D41\u7A0B id\uFF08\u5355\u4E2A / \u6570\u7EC4 / \u9017\u53F7\u5206\u9694\uFF09\u3002\u4F20\u591A\u4E2A\u65F6\u4E0D\u4F1A\u66FF\u4F60\u9009\uFF1A\u4F1A\u8FD4\u56DE NEEDS_SELECTION \u8BA9\u7528\u6237\u6311"
8290
- },
8291
- autoRoom: { type: "boolean", description: "\u9ED8\u8BA4 false\uFF1A\u4E0D\u6307\u5B9A\u4F1A\u8BAE\u5BA4\u65F6\u8FD4\u56DE\u5019\u9009\u8BA9\u7528\u6237\u9009\uFF1B\u4F20 true \u624D\u81EA\u52A8\u91C7\u7528\u63A8\u8350\u4F1A\u8BAE\u5BA4" },
8292
- allowNoRoom: { type: "boolean", description: "\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\u7B49\uFF09\u65F6\u4F20 true" },
8293
- timeConfirmed: {
8294
- type: "boolean",
8295
- description: '\u65F6\u95F4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0\uFF1A\u7528\u6237\u539F\u8BDD\u660E\u786E\u7ED9\u4E86\u65F6\u95F4\u3001\u6216\u5728\u65F6\u6BB5\u9009\u9879\u91CC\u70B9\u9009\u540E\u539F\u6837\u56DE\u4F20 value\uFF08\u81EA\u5E26\u6807\u8BB0\uFF09\u65F6\u624D\u4F20 true\uFF1B\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF0CCLI \u4F1A\u8FD4\u56DE\u65F6\u6BB5\u9009\u9879\u8BA9\u7528\u6237\u70B9\u9009'
8296
- },
8297
- roomConfirmed: {
8298
- type: "boolean",
8299
- description: '\u4F1A\u8BAE\u5BA4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0\uFF1A\u7528\u6237\u539F\u8BDD\u660E\u786E\u6307\u5B9A\u3001\u6216\u5728\u623F\u95F4\u9009\u9879\u91CC\u70B9\u9009\u540E\u539F\u6837\u56DE\u4F20 value\uFF08\u81EA\u5E26\u6807\u8BB0\uFF09\u65F6\u624D\u4F20 true\uFF1B\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF0CCLI \u4F1A\u628A\u6307\u5B9A\u623F\u95F4\u548C\u5019\u9009\u4E00\u8D77\u5217\u51FA\u6765\u8BA9\u7528\u6237\u70B9\u9009'
8300
- },
8301
- confirm: { type: "boolean", description: "\u5FC5\u987B\u663E\u5F0F true \u624D\u4F1A\u771F\u6B63\u63D0\u4EA4" },
8302
- waitSeconds: { type: "number", description: "\u63D0\u4EA4\u540E\u7B49\u5F85\u4F1A\u8BAE\u751F\u6210\u7684\u79D2\u6570\uFF08\u9ED8\u8BA4 20\uFF1B\u7B97\u6CD5\u662F\u7ACB\u5373\u67E5\u4E00\u6B21 + 5s \u518D\u67E5\u4E00\u6B21\uFF0C\u4ECD\u672A\u751F\u6210\u5C31\u8FD4\u56DE pending\uFF09" },
8303
- enrich: { type: "boolean", description: "\u662F\u5426\u987A\u5E26\u505A\u4F1A\u8BAE\u5BA4\u63A8\u8350/\u51B2\u7A81\u68C0\u6D4B/\u7A7A\u95F2\u65F6\u6BB5\uFF08\u9ED8\u8BA4 true\uFF1B\u4EBA\u3001\u65F6\u95F4\u3001\u623F\u95F4\u90FD\u5DF2\u786E\u5B9A\u65F6\u4F20 false \u53EF\u663E\u8457\u52A0\u5FEB\uFF09" },
8304
- extraFields: {
8305
- type: "object",
8306
- description: '\u6309\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u540D\u586B\u989D\u5916\u5B57\u6BB5\uFF08\u79DF\u6237\u81EA\u5EFA\u5B57\u6BB5\u7528\u8FD9\u4E2A\u53E3\u5B50\u5E26\u8FDB\u53BB\uFF09\uFF0C\u5F62\u5982 {"\u53C2\u4F1A\u5BA2\u6237": "xx\u516C\u53F8"}'
8307
- },
8308
- dateFrom: {
8309
- type: "string",
8310
- description: "\u6CA1\u7ED9\u5177\u4F53\u65F6\u95F4\u65F6\u6309\u54EA\u4E00\u5929\u63A8\u8350\u65F6\u6BB5\uFF08yyyy-MM-dd\uFF1B\u4E0D\u4F20\u9ED8\u8BA4\u660E\u5929\uFF09\u3002\u26A0\uFE0F \u7528\u6237\u8BF4\u4E86\u300C\u4E0A\u5348/\u4E0B\u5348/\u665A\u4E0A\u300D\u5C31\u5FC5\u987B\u540C\u65F6\u4F20 time_slot \u2014\u2014 \u53EA\u4F20 dateFrom \u4F1A\u5F39\u65F6\u6BB5\u9009\u62E9\u5668\u8BA9\u7528\u6237\u518D\u9009\u4E00\u6B21"
8311
- },
8312
- time_slot: {
8313
- type: "string",
8314
- enum: ["\u4E0A\u5348", "\u65E9\u4E0A", "\u4E0B\u5348", "\u665A\u4E0A"],
8315
- description: '\u7528\u6237\u53EA\u8BF4\u4E86\u300C\u4E0A\u5348/\u4E0B\u5348/\u665A\u4E0A\u300D\u65F6\u4F20\u8FD9\u4E2A\uFF08\u914D\u5408 dateFrom\uFF09\uFF1A\u4E0A\u5348/\u65E9\u4E0A=09:00\u201312:00\u3001\u4E0B\u5348=13:00\u201318:00\u3001\u665A\u4E0A=18:00\u201321:00\uFF0CCLI \u76F4\u63A5\u5B9A\u4E0B\u6765\u3001\u4E0D\u518D\u8FD4\u56DE\u65F6\u6BB5\u5019\u9009\u3002\u26D4 \u4E0D\u8981\u53EA\u4F20 dateFrom \u5C31\u671F\u5F85"\u8BA9\u7528\u6237\u9009\u65F6\u6BB5"\u2014\u2014\u7528\u6237\u5DF2\u7ECF\u8BF4\u4E86\u65F6\u6BB5\u5C31\u522B\u518D\u95EE'
8316
- },
8317
- durationMinutes: {
8318
- type: "number",
8319
- description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09\uFF1A\u53EA\u7ED9\u4E86\u5F00\u59CB\u65F6\u95F4\u65F6\u7528\u6765\u7B97\u7ED3\u675F\u65F6\u95F4\uFF1B\u63A8\u8350\u65F6\u6BB5\u65F6\u4E5F\u6309\u8FD9\u4E2A\u65F6\u957F\u627E"
8320
- },
8321
- workStartHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u65E9\u5C0F\u65F6\uFF08\u9ED8\u8BA4 9\uFF09" },
8322
- workEndHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u665A\u5C0F\u65F6\uFF08\u9ED8\u8BA4 18\uFF09" },
8323
- fieldValues: {
8324
- type: "object",
8325
- additionalProperties: true,
8326
- description: '\u6309**\u8868\u5355\u5B57\u6BB5 datakey\uFF08fieldId\uFF09**\u76F4\u63A5\u7ED9\u503C\uFF0C\u5F62\u5982 {"1325677252711735881": "\u7814\u8BA8\u4F1A"}\uFF1B\u4F18\u5148\u7EA7\u6700\u9AD8\uFF0C\u9002\u5408\u5B57\u6BB5\u540D\u5E26\u63D0\u793A\u8BED\u6216\u79DF\u6237\u81EA\u5EFA\u5B57\u6BB5\u3002datakey \u89C1 prepare \u7684 preview.mapped'
8327
- },
8328
- flowChoice: {
8329
- type: "string",
8330
- enum: ["auto", "ask"],
8331
- description: "\u591A\u4E2A\u5EFA\u4F1A\u6D41\u7A0B**\u90FD\u6709\u53D1\u8D77\u6743\u9650**\u65F6\uFF1A\u9ED8\u8BA4\uFF08\u4E0D\u4F20 / ask\uFF09= \u8FD4\u56DE\u9009\u9879\u8BA9\u7528\u6237\u6311\uFF1Bauto = \u81EA\u52A8\u53D6\u4F18\u5148\u7EA7\u6700\u9AD8\u7684\u3002\u6709\u6D41\u7A0B\u8BB0\u5FC6\uFF08\u4E0A\u6B21\u6210\u529F\u7528\u8FC7\u7684\u6D41\u7A0B\uFF09\u4E14\u4ECD\u53EF\u53D1\u8D77\u65F6\u9ED8\u8BA4\u6CBF\u7528\u4E0A\u6B21\u9009\u62E9\uFF0C\u4F20 ask \u5F3A\u5236\u6BCF\u6B21\u90FD\u95EE\u3002\u53EA\u6709 1 \u4E2A\u6709\u6743\u9650\u65F6\u76F4\u63A5\u53D1\u8D77"
8332
- },
8333
- crm_skip: {
8334
- type: "boolean",
8335
- description: "\u663E\u5F0F\u58F0\u660E\u300C\u8FD9\u6B21\u4E0D\u586B\u53C2\u4F1A\u5BA2\u6237\u300D\u3002\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u91CC\u51FA\u73B0 `\u5BA2\u6237\uFF1AX`\u3001`\u5BA2\u6237\u662FX` \u8FD9\u7C7B\u5B57\u6837\u5374**\u6CA1\u4F20 `crm_members`**\u65F6\uFF0C\u4E00\u6B65\u5EFA\u4F1A\u4F1A\u76F4\u63A5\u62D2\u7EDD\uFF08crm_member_required\uFF09\u2014\u2014\u786E\u8BA4\u8FD9\u4E9B\u5B57\u6837\u4E0D\u662F\u8981\u4E0A\u4F1A\u8868\u7684\u5BA2\u6237\uFF0C\u624D\u4F20 true"
8336
- },
8337
- submit_mode: {
8338
- type: "string",
8339
- enum: ["direct", "browser"],
8340
- description: '\u63D0\u4EA4\u65B9\u5F0F\uFF0C\u9ED8\u8BA4 browser\uFF1A\u5728\u5C0Fe \u91CC**\u5F39\u51FA\u6D41\u7A0B\u8868\u5355**\uFF08\u5B57\u6BB5\u5DF2\u9884\u586B\u542B\u4EBA\u5458/\u5BA2\u6237\uFF09\uFF0C\u7528\u6237\u6838\u5BF9\u4FEE\u6539\u540E\u81EA\u5DF1\u70B9\u63D0\u4EA4\u3002direct = \u76F4\u63A5\u5199\u670D\u52A1\u7AEF\uFF08\u4F1A\u8BAE\u5F53\u573A\u751F\u6210\u3001\u9080\u8BF7\u51FD\u7528\u771F\u5B9E\u6570\u636E\uFF0C\u4F46\u6CA1\u6709\u4EBA\u5DE5\u6838\u5BF9\u8868\u5355\u8FD9\u4E00\u6B65\uFF09\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8BF4"\u4E0D\u7528\u6211\u786E\u8BA4\uFF0C\u76F4\u63A5\u5EFA"\u65F6\u624D\u4F20 direct'
8341
- }
8342
- },
8343
- { required: ["mt_name", "confirm"] }
8344
- ),
8345
- handler: async (args, env) => {
8346
- if (args.confirm !== true) {
8347
- throw meetingValidationError(
8348
- "confirmation_required",
8349
- "\u4E00\u6B65\u5EFA\u4F1A\u4F1A\u76F4\u63A5\u63D0\u4EA4\u6D41\u7A0B\uFF0C\u5FC5\u987B\u663E\u5F0F\u4F20 confirm=true\uFF1B\u5982\u53EA\u60F3\u770B\u65B9\u6848\uFF0C\u8BF7\u7528 meeting.eb.meeting.create.flow.prepare"
8350
- );
8351
- }
8352
- const crmMentioned = detectCrmMentionInText(args.mt_name, args.mt_desc, args.other_remark);
8353
- const crmSkipped = args.crm_skip === true;
8354
- if (crmMentioned && !args.crm_members && !crmSkipped) {
8355
- throw meetingValidationError(
8356
- "crm_member_required",
8357
- `\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u91CC\u63D0\u5230\u5BA2\u6237\u300C${crmMentioned}\u300D\uFF0C\u4F46\u6CA1\u4F20 crm_members \u2014\u2014 \u63D0\u4EA4\u540E\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u4F1A\u662F\u7A7A\u7684\u3002\u5148 meeting.eb.crm.search {"keyword":"${crmMentioned}"} \u62FF items[].customerId\uFF0C\u518D\u628A crm_members:[{"id":"<customerId>","name":"<\u5B8C\u6574\u5BA2\u6237\u540D>"}] \u4E00\u8D77\u4F20\uFF08\u5FC5\u987B\u5E26\u540D\u79F0\uFF0C\u53EA\u7ED9 id \u4F1A\u88AB\u9759\u9ED8\u5B58\u7A7A\uFF09\uFF1B\u786E\u5B9E\u4E0D\u9700\u8981\u586B\u53C2\u4F1A\u5BA2\u6237\u5C31\u4F20 crm_skip:true\u3002`
8358
- );
8359
- }
8360
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
8361
- const prepareStartedAt = Date.now();
8362
- const { submit_mode: _submitMode, confirm: _confirm, ...prepareArgs } = args;
8363
- const prepared = await getMeetingOperation2("meeting.eb.meeting.create.flow.prepare").handler(
8364
- // submit_mode 只属于提交阶段,prepare 的 schema 不接受它(additionalProperties:false)
8365
- prepareArgs,
8366
- env
8367
- );
8368
- if (prepared?.data?.status === "NEEDS_SELECTION") {
8369
- return prepared;
8370
- }
8371
- const continuation = String(prepared?.data?.continuation ?? "");
8372
- if (!continuation) {
8373
- throw meetingValidationError("flow_prepare_failed", "\u5EFA\u4F1A\u6D41\u7A0B\u51C6\u5907\u9636\u6BB5\u6CA1\u6709\u8FD4\u56DE\u786E\u8BA4\u7968\u636E\uFF0C\u672A\u63D0\u4EA4");
8374
- }
8375
- const prepareMs = Date.now() - prepareStartedAt;
8376
- const applyStartedAt = Date.now();
8377
- const applied = await getMeetingOperation2("meeting.eb.meeting.create.flow.apply").handler(
8378
- {
8379
- continuation,
8380
- confirm: true,
8381
- ...args.submit_mode ? { submit_mode: args.submit_mode } : {},
8382
- ...args.waitSeconds !== void 0 ? { waitSeconds: args.waitSeconds } : {}
8383
- },
8384
- env
8385
- );
8386
- const warnings = [
8387
- ...prepared?.warnings ?? [],
8388
- ...applied?.warnings ?? []
8389
- ];
8390
- return meetingSuccess(
8391
- "meeting.eb.meeting.create.flow.quick",
8392
- {
8393
- status: applied?.data?.status ?? "COMPLETE",
8394
- workflowId: applied?.data?.workflowId,
8395
- requestId: applied?.data?.requestId,
8396
- meetingId: applied?.data?.meetingId ?? null,
8397
- invitation: applied?.data?.invitation ?? null,
8398
- // 同步建的群(群 id / 群名 / 有没有回写 imchat_groupid)
8399
- ...applied?.data?.groupChat ? { groupChat: (applied?.data).groupChat } : {},
8400
- // 已提交内容回显(字段名 → 值),提交后可直接贴给用户看"到底填进去了什么"
8401
- submittedPreview: applied?.data?.submittedPreview ?? null,
8402
- // 小e 环境(BROWSER_FILL)不写服务端,表单靠这段 <browsertool> 在浏览器里填 —— 必须一起透出,
8403
- // 否则宿主拿不到表单,用户看到的就是"提交了但没反应"。
8404
- ...applied?.data?.contextId ? { contextId: (applied?.data).contextId } : {},
8405
- ...applied?.data?.finalMarkdown ? { finalMarkdown: (applied?.data).finalMarkdown } : {},
8406
- ...applied?.data?.finalMarkdownHint ? { finalMarkdownHint: (applied?.data).finalMarkdownHint } : {},
8407
- decisions: prepared?.data?.preview?.decisions ?? null,
8408
- timings: {
8409
- ...prepared?.data?.preview?.decisions?.timings ?? {},
8410
- // apply 侧的分段耗时(提交/轮询/邀请函)也要带出来,否则"到底慢在哪"还是看不清
8411
- ...applied?.data?.timings ?? {},
8412
- prepareMs,
8413
- applyMs: Date.now() - applyStartedAt,
8414
- totalMs: Date.now() - prepareStartedAt
8415
- }
8416
- },
8417
- warnings.length > 0 ? { warnings } : {}
8418
- );
8419
- }
8420
- };
8421
- var ebMeetingCreateSuggest = {
8422
- name: "meeting.eb.meeting.create.suggest",
8423
- resource: "eb",
8424
- method: "meeting.eb.meeting.create.suggest",
8425
- action: "meeting.eb.meeting.create.suggest",
8426
- summary: "\u5EFA\u4F1A\u5EFA\u8BAE\uFF1A\u7ED9\u5B9A\u65E5\u671F\u8303\u56F4\u4E0E\u53C2\u4F1A\u4EBA\uFF0C\u63A8\u8350\u300C\u6240\u6709\u4EBA\u90FD\u7A7A\u95F2 + \u8BE5\u65F6\u6BB5\u6709\u53EF\u7528\u4F1A\u8BAE\u5BA4\u300D\u7684\u65F6\u95F4\u5019\u9009\uFF08\u53EA\u8BFB\uFF0C\u4E0D\u5EFA\u4F1A\uFF09",
8427
- capability: "eb.meeting",
8428
- risk: "read",
8429
- inputSchema: schemaOf(
8430
- {
8431
- dateFrom: { type: "string", description: "\u8D77\u59CB\u65E5\u671F\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd\uFF09" },
8432
- dateTo: { type: "string", description: "\u7ED3\u675F\u65E5\u671F\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u540C dateFrom\uFF1B\u6700\u591A\u8DE8 14 \u5929\uFF09" },
8433
- durationMinutes: { type: "number", description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09" },
8434
- hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u5458\uFF08\u5FC5\u586B\uFF0C\u5458\u5DE5 id \u6216\u59D3\u540D\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u59D3\u540D\u4F1A\u81EA\u52A8\u53CD\u67E5 id\uFF09" },
8435
- memberCount: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570\uFF08\u53EF\u9009\uFF0C\u7528\u4E8E\u4F1A\u8BAE\u5BA4\u5BB9\u91CF\u7B5B\u9009\uFF1B\u4E0D\u4F20\u5219\u6309 hrm_members \u4E2A\u6570\uFF09" },
8436
- workStartHour: { type: "number", description: "\u53EA\u5728\u51E0\u70B9\u4EE5\u540E\u627E\uFF08\u9ED8\u8BA4 9\uFF09" },
8437
- workEndHour: { type: "number", description: "\u53EA\u5728\u51E0\u70B9\u4EE5\u524D\u627E\uFF08\u9ED8\u8BA4 18\uFF09" },
8438
- maxSlots: { type: "number", description: "\u6700\u591A\u7ED9\u51E0\u4E2A\u65F6\u95F4\u5019\u9009\uFF08\u9ED8\u8BA4 3\uFF0C\u6700\u5927 8\uFF09" },
8439
- topN: { type: "number", description: "\u6BCF\u4E2A\u65F6\u95F4\u5019\u9009\u6700\u591A\u5E26\u51E0\u95F4\u4F1A\u8BAE\u5BA4\uFF08\u9ED8\u8BA4 3\uFF09" },
8440
- includeSchedule: { type: "boolean", description: "\u662F\u5426\u628A\u65E5\u7A0B\uFF08ESB\uFF09\u4E5F\u7B97\u8FDB\u5360\u7528\uFF08\u9ED8\u8BA4 true\uFF09" }
8441
- },
8442
- { required: ["dateFrom", "hrm_members"] }
8443
- ),
8444
- handler: async (args, env) => {
8445
- const dateFrom = String(args.dateFrom ?? "").trim().slice(0, 10);
8446
- if (!/^\d{4}-\d{2}-\d{2}$/.test(dateFrom)) {
8447
- throw meetingValidationError("datetime_invalid", `dateFrom \u5FC5\u987B\u662F yyyy-MM-dd\uFF0C\u6536\u5230\u300C${String(args.dateFrom ?? "")}\u300D`);
8448
- }
8449
- const dateTo = String(args.dateTo ?? "").trim().slice(0, 10) || dateFrom;
8450
- if (!/^\d{4}-\d{2}-\d{2}$/.test(dateTo)) {
8451
- throw meetingValidationError("datetime_invalid", `dateTo \u5FC5\u987B\u662F yyyy-MM-dd\uFF0C\u6536\u5230\u300C${String(args.dateTo ?? "")}\u300D`);
8452
- }
8453
- const durationMinutes = Number(args.durationMinutes) > 0 ? Number(args.durationMinutes) : 60;
8454
- const maxSlots = Math.max(1, Math.min(8, Number(args.maxSlots) || 3));
8455
- const topN = Math.max(1, Math.min(5, Number(args.topN) || 3));
8456
- const rawMembers = String(args.hrm_members ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
8457
- const nameLike = rawMembers.filter((item) => !/^\d+$/.test(item));
8458
- const nameToId = nameLike.length > 0 ? await import("./schedule-5GCACCK7.js").then((m) => m.resolveMemberIdsByName(env, nameLike)).catch(() => /* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
8459
- const memberIds = rawMembers.map((item) => nameToId.get(item) ?? item);
8460
- const unresolved = rawMembers.filter((item) => nameToId.get(item) === void 0 && !/^\d+$/.test(item));
8461
- const selfId = await env.host.getSession().then((s) => String(s?.userId ?? "")).catch(() => "");
8462
- const selfIncluded = selfId !== "" && memberIds.includes(selfId);
8463
- const memberCount = Number(args.memberCount) > 0 ? Number(args.memberCount) : memberIds.length > 0 ? memberIds.length + (selfIncluded ? 0 : 1) : void 0;
8464
- const warnings = [];
8465
- if (unresolved.length > 0) {
8466
- warnings.push(`\u26A0\uFE0F \u8FD9\u4E9B\u53C2\u4F1A\u4EBA\u6CA1\u67E5\u5230\u5458\u5DE5 id\uFF1A${unresolved.join("\u3001")} \u2014\u2014 \u5DF2\u8DF3\u8FC7\uFF0C\u5176\u7A7A\u95F2\u60C5\u51B5**\u672A\u6838\u9A8C**`);
8467
- }
8468
- const free = await findCommonFreeSlots(env, {
8469
- rangeStart: `${dateFrom} 00:00`,
8470
- rangeEnd: `${dateTo} 23:59`,
8471
- durationMinutes,
8472
- members: memberIds,
8473
- maxSlots,
8474
- maxDays: 14,
8475
- includeSchedule: args.includeSchedule !== false,
8476
- ...args.workStartHour !== void 0 ? { workStartHour: Number(args.workStartHour) } : {},
8477
- ...args.workEndHour !== void 0 ? { workEndHour: Number(args.workEndHour) } : {}
8478
- });
8479
- await loadRooms(env, { refresh: true }).catch(() => null);
8480
- const withRooms = await Promise.all((free.slots ?? []).map(async (slot) => {
8481
- try {
8482
- const rec = await recommendRooms(env, {
8483
- beginDatetime: slot.begin,
8484
- endDatetime: slot.end,
8485
- ...memberCount ? { memberCount } : {},
8486
- topN
8487
- });
8488
- return {
8489
- begin: slot.begin,
8490
- end: slot.end,
8491
- rooms: rec.candidates.map((candidate) => ({
8492
- id: candidate.id,
8493
- name: candidate.name,
8494
- capacityMax: candidate.capacity.max,
8495
- reasons: candidate.reasons
8496
- }))
8497
- };
8498
- } catch {
8499
- return { begin: slot.begin, end: slot.end, rooms: [] };
8500
- }
8501
- }));
8502
- const usable = withRooms.filter((slot) => slot.rooms.length > 0);
8503
- if (usable.length === 0) {
8504
- const why = (free.slots ?? []).length === 0 ? "\u8BE5\u8303\u56F4\u5185\u6240\u6709\u53C2\u4F1A\u4EBA\u6CA1\u6709\u5171\u540C\u7684\u7A7A\u95F2\u65F6\u6BB5" : `${(free.slots ?? []).length} \u4E2A\u300C\u4EBA\u7A7A\u95F2\u300D\u7684\u65F6\u6BB5\u91CC\uFF0C\u6CA1\u6709\u4E00\u4E2A\u8FD8\u80FD\u8BA2\u5230\u4F1A\u8BAE\u5BA4`;
8505
- warnings.push(
8506
- `\u6CA1\u627E\u5230\u540C\u65F6\u6EE1\u8DB3\u300C\u4EBA\u5458\u7A7A\u95F2 + \u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u300D\u7684\u65F6\u95F4\u5019\u9009\uFF1A${why}\u3002\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\uFF0C\u5E76\u5EFA\u8BAE\u6362\u4E2A\u65E5\u671F\u8303\u56F4\u3001\u7F29\u77ED\u65F6\u957F\uFF0C\u6216\u6539\u4E3A\u7EBF\u4E0A\u4F1A\u8BAE\uFF08allowNoRoom: true\uFF09\u3002`
8507
- );
8508
- if (free.blockingSummary) warnings.push(`\u5F53\u5929\u5360\u7528\u6982\u51B5\uFF1A${free.blockingSummary}`);
8509
- }
8510
- return meetingSuccess(
8511
- "meeting.eb.meeting.create.suggest",
8512
- {
8513
- dateFrom,
8514
- dateTo,
8515
- durationMinutes,
8516
- // 同样是"让用户点一下":时段候选用选项控件呈现,别写成文本列表
8517
- ui: { component: "choice", multiple: false, recommendedKey: "T1" },
8518
- slots: usable.map((slot, index) => ({
8519
- key: `T${index + 1}`,
8520
- label: `${slot.begin.slice(5, 10)} ${slot.begin.slice(11)}~${slot.end.slice(11)}`,
8521
- value: { begin: slot.begin, end: slot.end, address: slot.rooms[0]?.id ?? null },
8522
- reason: `${memberCount ? `${memberCount} \u4EBA\u5168\u90E8\u7A7A\u95F2\uFF08\u4F1A\u8BAE\u56DE\u6267 + \u65E5\u7A0B\u5DF2\u6838\uFF09\uFF1B` : ""}${slot.rooms.length} \u95F4\u4F1A\u8BAE\u5BA4\u53EF\u7528\uFF1A${slot.rooms.map((room) => room.name).join("\u3001")}`,
8523
- rooms: slot.rooms
8524
- })),
8525
- // 把"人空闲但没房间"的时段也带出来,方便调用方解释为什么被剔除
8526
- skippedSlots: withRooms.filter((slot) => slot.rooms.length === 0),
8527
- memberIds,
8528
- scheduleItems: free.scheduleItems,
8529
- idle: free.idle,
8530
- cost: free.cost
8531
- },
8532
- warnings.length > 0 ? { warnings } : {}
8533
- );
8534
- }
8535
- };
8536
- var meetingEbCreateFlowOperations = [
8537
- ebMeetingCreateSuggest,
8538
- ebMeetingCreateFlowPrepare,
8539
- ebMeetingCreateFlowApply,
8540
- ebMeetingCreateFlowQuick
8541
- ];
8542
-
8543
6165
  // src/shortcuts/meeting/operations/eb/index.ts
8544
6166
  var ebAutoRoomPreflight = async (context) => {
8545
6167
  const { extras } = context;
@@ -8627,7 +6249,7 @@ var ebAutoInvitationAfterWrite = async (context) => {
8627
6249
  const mtId = String(context.dataIds?.[0] ?? "").trim();
8628
6250
  if (!isCreate || !enabled || !mtId) return association;
8629
6251
  try {
8630
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-KMHCPAAD.js");
6252
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-IM5G23LS.js");
8631
6253
  const render = getMeetingOperation2("meeting.invitation.render");
8632
6254
  const result = await render.handler({ mtId }, context.env);
8633
6255
  return { ...association ?? {}, invitation: result?.data ?? null };