weaver-work-cli 0.1.32 → 0.1.36

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 (211) hide show
  1. package/README.md +2 -2
  2. package/dist/chunks/{archive-UMGX72K6.js → archive-XBVH7JU7.js} +2 -2
  3. package/dist/chunks/{archive-oa-N2IYBLF3.js → archive-oa-MZM3EKFQ.js} +2 -2
  4. package/dist/chunks/{asset-GLEGKFG5.js → asset-4XO7UOUW.js} +2 -2
  5. package/dist/chunks/{attachment-content-AQNX5N3S.js → attachment-content-VXSWANAC.js} +3 -2
  6. package/dist/chunks/{blog-E44OTVDA.js → blog-PGZKOPSC.js} +2 -2
  7. package/dist/chunks/{caizhilian-DQUFZXZL.js → caizhilian-BH4ZVGUN.js} +2 -2
  8. package/dist/chunks/{calendar-JKPIRKFD.js → calendar-MXEMTIO4.js} +2 -2
  9. package/dist/chunks/{chunk-QWY6PGL6.js → chunk-2LV74IWP.js} +361 -56
  10. package/dist/chunks/chunk-3SO6QL6U.js +73 -0
  11. package/dist/chunks/chunk-5DQEEGCC.js +229 -0
  12. package/dist/chunks/{chunk-G3QJULO2.js → chunk-6LLJFKJE.js} +1 -1
  13. package/dist/chunks/{chunk-C6R3B2ML.js → chunk-BPE37FPB.js} +35 -7
  14. package/dist/chunks/chunk-BYATLLEF.js +68 -0
  15. package/dist/chunks/chunk-BYBSCN4X.js +932 -0
  16. package/dist/chunks/{chunk-CVZ2JOSW.js → chunk-F746NKNF.js} +1 -1
  17. package/dist/chunks/{chunk-GCG2NMWR.js → chunk-HXJQI5NM.js} +4 -2
  18. package/dist/chunks/{chunk-YRVDW4WN.js → chunk-I6QGIBDM.js} +2 -2
  19. package/dist/chunks/{chunk-H7J4DC5R.js → chunk-JCSN3JGM.js} +2 -2
  20. package/dist/chunks/{chunk-2GA5ZIQL.js → chunk-JNG42JKG.js} +30 -1
  21. package/dist/chunks/{chunk-DW6AUUKS.js → chunk-JUXVYKII.js} +9 -4
  22. package/dist/chunks/{chunk-6RKD4DRZ.js → chunk-JYKABYCV.js} +2 -2
  23. package/dist/chunks/{chunk-6EFWDL7Y.js → chunk-NCOVUAZK.js} +2 -2
  24. package/dist/chunks/{chunk-E4Z23GHM.js → chunk-QHFANTX7.js} +1114 -904
  25. package/dist/chunks/{ebuilder-form-V5FG2EHC.js → chunk-QYGO5EE2.js} +22 -1148
  26. package/dist/chunks/{chunk-IURUFGZK.js → chunk-T72N74ZT.js} +50 -33
  27. package/dist/chunks/{chunk-H6XSTSLM.js → chunk-TC6MZAO3.js} +137 -204
  28. package/dist/chunks/{chunk-WKI2FBIQ.js → chunk-VPUTVEMC.js} +737 -341
  29. package/dist/chunks/{chunk-WSKBSQ2U.js → chunk-VPXOPQJI.js} +2 -2
  30. package/dist/chunks/chunk-WXFPWCXG.js +774 -0
  31. package/dist/chunks/{chunk-4YC43QQ4.js → chunk-XMGSYD6S.js} +4 -4
  32. package/dist/chunks/conflict-JAB2LJEZ.js +21 -0
  33. package/dist/chunks/continuation-RN6PZN2M.js +11 -0
  34. package/dist/chunks/contract-XI2EEIZU.js +9110 -0
  35. package/dist/chunks/cowork-SCPGLBA4.js +2527 -0
  36. package/dist/chunks/ebuilder-form-EYLHNOTA.js +121 -0
  37. package/dist/chunks/{ehr-HMFY6VIL.js → ehr-EAP77IMT.js} +1344 -27
  38. package/dist/chunks/{esb-ZYSVB7SG.js → esb-2TGGXEE7.js} +4 -4
  39. package/dist/chunks/{fna-B7RKPAZD.js → fna-2X7ZE7BU.js} +13 -8
  40. package/dist/chunks/{host-OCH2BCCV.js → host-C6EL2RKL.js} +3 -3
  41. package/dist/chunks/{host-45WED2KK.js → host-I4NRK4MX.js} +3 -3
  42. package/dist/chunks/{host-I4Z6BFYX.js → host-Q4LZGCRU.js} +3 -3
  43. package/dist/chunks/host-UEI5FGDM.js +23 -0
  44. package/dist/chunks/{host-KNZ52LJZ.js → host-XCLDDXKQ.js} +3 -3
  45. package/dist/chunks/{hrm-2KAZGUHI.js → hrm-YXERJM76.js} +3 -3
  46. package/dist/chunks/{im-ACJJWH4U.js → im-A4VZN2TQ.js} +88 -12
  47. package/dist/chunks/{invoice-ZK3WCX2U.js → invoice-2Z6YPMIS.js} +3 -3
  48. package/dist/chunks/{jiuchuanhui-5PQD3IL2.js → jiuchuanhui-AR5GMKZB.js} +2 -2
  49. package/dist/chunks/{lazy-dispatch-JQXBW3GM.js → lazy-dispatch-QXW7P4X3.js} +4 -4
  50. package/dist/chunks/{mail-S2HDDXO2.js → mail-7GZ6CPBJ.js} +45 -24
  51. package/dist/chunks/{meeting-QVN3I37L.js → meeting-3NMGA3MB.js} +278 -43
  52. package/dist/chunks/{okr-QNG4VC2Q.js → okr-BZ6XUOAG.js} +2 -2
  53. package/dist/chunks/operations-5QL3AECO.js +11 -0
  54. package/dist/chunks/{plan-A25EMW6U.js → plan-DR5CMUYP.js} +2 -2
  55. package/dist/chunks/{project-G6XV66DZ.js → project-6J63MK33.js} +2 -2
  56. package/dist/chunks/{registry-DC6KR3NH.js → registry-KDD7DHNK.js} +4 -4
  57. package/dist/chunks/{registry-2VLUAESA.js → registry-OZSMDVPP.js} +2 -2
  58. package/dist/chunks/{registry-7C5UMIPL.js → registry-TKX2E7C7.js} +2 -2
  59. package/dist/chunks/{registry-TI3CIUXF.js → registry-VRTNC6UR.js} +8 -6
  60. package/dist/chunks/{room-recommend-WRTHO6Y2.js → room-recommend-XCWRMB5P.js} +4 -3
  61. package/dist/chunks/{schedule-KFIITGSK.js → schedule-IVBICP32.js} +4 -3
  62. package/dist/chunks/{workflow-DJ7SYWAF.js → workflow-D74NFK3C.js} +179 -6
  63. package/dist/index.js +35 -25
  64. package/dist/internal/e10/auth-recovery.js +14 -4
  65. package/dist/internal/e10/fetch-timing.js +31 -0
  66. package/dist/internal/e10/request-runtime.js +5 -0
  67. package/dist/shortcuts/contract/host.js +34 -59
  68. package/dist/shortcuts/cowork/continuation.js +70 -0
  69. package/dist/shortcuts/cowork/errors.js +59 -0
  70. package/dist/shortcuts/cowork/host.js +180 -0
  71. package/dist/shortcuts/cowork/index.js +166 -0
  72. package/dist/shortcuts/cowork/manifest.js +65 -0
  73. package/dist/shortcuts/cowork/operations/discuss-write.js +277 -0
  74. package/dist/shortcuts/cowork/operations/item-write.js +380 -0
  75. package/dist/shortcuts/cowork/operations/member-write.js +283 -0
  76. package/dist/shortcuts/cowork/operations/permission-write.js +286 -0
  77. package/dist/shortcuts/cowork/operations/read.js +423 -0
  78. package/dist/shortcuts/cowork/operations/registry.js +39 -0
  79. package/dist/shortcuts/cowork/operations/review-write.js +157 -0
  80. package/dist/shortcuts/cowork/operations/shared.js +215 -0
  81. package/dist/shortcuts/cowork/operations/types.js +39 -0
  82. package/dist/shortcuts/cowork/operations.js +19 -0
  83. package/dist/shortcuts/ehr/host.js +4 -1
  84. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +757 -0
  85. package/dist/shortcuts/ehr/operations/recruit-position.js +367 -0
  86. package/dist/shortcuts/ehr/operations/recruit-stats.js +133 -0
  87. package/dist/shortcuts/ehr/operations/recruit-write.js +43 -16
  88. package/dist/shortcuts/ehr/operations/recruit.js +182 -10
  89. package/dist/shortcuts/ehr/operations/registry.js +6 -0
  90. package/dist/shortcuts/fna/operations/expense-chart.js +19 -7
  91. package/dist/shortcuts/im/diagnostics.js +97 -0
  92. package/dist/shortcuts/im/host.js +58 -31
  93. package/dist/shortcuts/im/index.js +7 -2
  94. package/dist/shortcuts/im/operations/at-mention.js +127 -0
  95. package/dist/shortcuts/im/operations/file-user.js +10 -2
  96. package/dist/shortcuts/im/operations/group-read.js +26 -5
  97. package/dist/shortcuts/im/operations/group-write.js +35 -28
  98. package/dist/shortcuts/im/operations/msg-sync.js +7 -2
  99. package/dist/shortcuts/im/operations/msg-write.js +76 -10
  100. package/dist/shortcuts/im/operations/quote-mention.js +119 -0
  101. package/dist/shortcuts/im/operations/session.js +1 -1
  102. package/dist/shortcuts/im/operations/shared.js +10 -0
  103. package/dist/shortcuts/im/operations/types.js +13 -0
  104. package/dist/shortcuts/index.js +10 -0
  105. package/dist/shortcuts/mail/host.js +12 -1
  106. package/dist/shortcuts/mail/operations/types.js +17 -2
  107. package/dist/shortcuts/meeting/host.js +27 -34
  108. package/dist/shortcuts/meeting/index.js +79 -1
  109. package/dist/shortcuts/meeting/manifest.js +10 -0
  110. package/dist/shortcuts/meeting/operations/create.js +4 -1
  111. package/dist/shortcuts/meeting/operations/eb/catalog.js +10 -0
  112. package/dist/shortcuts/meeting/operations/eb/conflict.js +84 -8
  113. package/dist/shortcuts/meeting/operations/eb/create-flow.js +1195 -140
  114. package/dist/shortcuts/meeting/operations/eb/factory.js +170 -8
  115. package/dist/shortcuts/meeting/operations/eb/index.js +16 -3
  116. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +50 -5
  117. package/dist/shortcuts/meeting/operations/eb-fallback.js +163 -0
  118. package/dist/shortcuts/meeting/operations/env.js +99 -46
  119. package/dist/shortcuts/meeting/operations/form-fields.js +110 -0
  120. package/dist/shortcuts/meeting/operations/invitation.js +79 -20
  121. package/dist/shortcuts/meeting/operations/registry.js +2 -0
  122. package/dist/shortcuts/meeting/operations/standard-guard.js +71 -0
  123. package/dist/shortcuts/meeting/operations.js +16 -0
  124. package/dist/shortcuts/workflow/endpoints.js +8 -3
  125. package/dist/shortcuts/workflow/index.js +110 -1
  126. package/dist/shortcuts/workflow/operations/form.js +204 -36
  127. package/dist/shortcuts/workflow/operations/read.js +104 -23
  128. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupRules.js +448 -0
  129. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupStore.js +106 -0
  130. package/dist/shortcuts/workflow/operations/todoSmartConvert/businessRules.js +47 -0
  131. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +30 -23
  132. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +1 -0
  133. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +1 -0
  134. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +2 -1
  135. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +2 -4
  136. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +138 -181
  137. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +12 -7
  138. package/dist/shortcuts/workflow/operations.js +23 -1
  139. package/docs/e10-auth.md +1 -1
  140. package/docs/ehr.md +1 -1
  141. package/docs/fna.md +2 -1
  142. package/docs/im.md +8 -1
  143. package/docs/todo-smart-convert/README.md +1 -1
  144. package/docs/todo-smart-convert/data-contract.md +2 -2
  145. package/docs/todo-smart-convert/subgroup-rules.md +6 -0
  146. package/package.json +1 -1
  147. package/skill-template/business-info.json +18 -0
  148. package/skill-template/domains/cowork.md +14 -0
  149. package/skill-template/domains/yimiaoban.md +3 -3
  150. package/skill-template/skill-template.md +1 -1
  151. package/skills/weaver-e10-blog/SKILL.md +5 -5
  152. package/skills/weaver-e10-caizhilian/SKILL.md +5 -5
  153. package/skills/weaver-e10-calendar/SKILL.md +5 -5
  154. package/skills/weaver-e10-cowork/SKILL.md +101 -0
  155. package/skills/weaver-e10-cowork/references/cowork-read.md +90 -0
  156. package/skills/weaver-e10-cowork/references/cowork-write.md +131 -0
  157. package/skills/weaver-e10-cowork/references/safety-boundaries.md +45 -0
  158. package/skills/weaver-e10-esb/SKILL.md +5 -5
  159. package/skills/weaver-e10-hrm/SKILL.md +5 -5
  160. package/skills/weaver-e10-jinchengda/SKILL.md +2 -2
  161. package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -5
  162. package/skills/weaver-e10-jucailin/SKILL.md +38 -14
  163. package/skills/weaver-e10-jucailin/references/recruit-create.md +104 -0
  164. package/skills/weaver-e10-jucailin/references/recruit-read.md +25 -0
  165. package/skills/weaver-e10-jucailin/references/recruit-write.md +13 -0
  166. package/skills/weaver-e10-jucailin/references/salary.md +15 -11
  167. package/skills/weaver-e10-mail/SKILL.md +17 -14
  168. package/skills/weaver-e10-meeting/SKILL.md +442 -46
  169. package/skills/weaver-e10-meeting/references/meeting-eb.md +135 -3
  170. package/skills/weaver-e10-meeting/references/meeting-invitation.md +28 -2
  171. package/skills/weaver-e10-meeting/references/meeting-queries.md +9 -6
  172. package/skills/weaver-e10-meeting/references/meeting-verification.md +8 -6
  173. package/skills/weaver-e10-meeting.zip +0 -0
  174. package/skills/weaver-e10-okr/SKILL.md +5 -5
  175. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  176. package/skills/weaver-e10-plan/SKILL.md +5 -5
  177. package/skills/weaver-e10-qiyecheng/SKILL.md +5 -2
  178. package/skills/weaver-e10-qiyecheng/references/catalog.md +2 -2
  179. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +15 -1
  180. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +22 -21
  181. package/skills/weaver-e10-shared/SKILL.md +12 -12
  182. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +4 -4
  183. package/skills/weaver-e10-wenshuding/SKILL.md +5 -5
  184. package/skills/weaver-e10-workflow/SKILL.md +29 -5
  185. package/skills/weaver-e10-workflow/aigroup/default.json +88 -0
  186. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +66 -14
  187. package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +1 -1
  188. package/skills/weaver-e10-workflow/references/workflow-memory.md +1 -1
  189. package/skills/weaver-e10-workflow/references/workflow-query.md +12 -10
  190. package/skills/weaver-e10-workflow/references/workflow-view.md +2 -2
  191. package/skills/weaver-e10-workflow/tools/todo-serve.cjs +239 -0
  192. package/skills/weaver-e10-workflow/{scripts → tools}/todo-summary.cjs +218 -28
  193. package/skills/weaver-e10-yepiaotong/SKILL.md +10 -8
  194. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +7 -7
  195. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +10 -10
  196. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +40 -37
  197. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +4 -4
  198. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +27 -38
  199. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +4 -4
  200. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +37 -29
  201. package/skills/weaver-e10-yimiaoban/SKILL.md +156 -33
  202. package/skills/weaver-e10-yimiaoban/references/ding-write.md +1 -1
  203. package/skills/weaver-e10-yimiaoban/references/error-codes.md +5 -1
  204. package/skills/weaver-e10-yimiaoban/references/group-read.md +5 -1
  205. package/skills/weaver-e10-yimiaoban/references/group-write.md +6 -4
  206. package/skills/weaver-e10-yimiaoban/references/msg-read.md +1 -0
  207. package/skills/weaver-e10-yimiaoban/references/msg-write.md +34 -2
  208. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +5 -2
  209. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +79 -58
  210. package/skills/weaver-e10-yimiaoban/references/user-remind.md +2 -2
  211. package/skills/weaver-e10-ziguanjia/SKILL.md +5 -5
@@ -1,18 +1,30 @@
1
1
  import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
- import {
4
- meetingEbScheduleOperations
5
- } from "./chunk-4YC43QQ4.js";
6
3
  import {
7
4
  ebRoomRecommendOperation,
5
+ loadRooms,
8
6
  recommendRooms,
9
7
  rememberFrequentRoom
10
- } from "./chunk-C6R3B2ML.js";
8
+ } from "./chunk-BPE37FPB.js";
9
+ import {
10
+ meetingEbScheduleOperations
11
+ } from "./chunk-XMGSYD6S.js";
12
+ import {
13
+ ebMeetingWritePreflight,
14
+ fetchEbAppSettings,
15
+ findCommonFreeSlots,
16
+ meetingEbConflictOperations
17
+ } from "./chunk-WXFPWCXG.js";
11
18
  import {
12
19
  listMeetingAttachments,
13
20
  meetingAttachmentContentOperations,
14
21
  renderDocx
15
- } from "./chunk-GCG2NMWR.js";
22
+ } from "./chunk-HXJQI5NM.js";
23
+ import {
24
+ meetingEnvOperations,
25
+ meetingStateDir,
26
+ resolveMeetingEnvMode
27
+ } from "./chunk-5DQEEGCC.js";
16
28
  import {
17
29
  EB_BASE,
18
30
  EB_ENDPOINTS,
@@ -31,9 +43,7 @@ import {
31
43
  fingerprint,
32
44
  meetingConfirmationError,
33
45
  meetingConflictError,
34
- meetingEnvOperations,
35
46
  meetingPartialError,
36
- meetingStateDir,
37
47
  meetingSuccess,
38
48
  meetingValidationError,
39
49
  mergeSnapshot,
@@ -41,13 +51,12 @@ import {
41
51
  pickBusinessInput,
42
52
  queryBody,
43
53
  requireConfirm,
44
- resolveMeetingEnvMode,
45
54
  schemaOf,
46
55
  toIdCsv,
47
56
  toIdString,
48
57
  verifyLease,
49
58
  writeBody
50
- } from "./chunk-H6XSTSLM.js";
59
+ } from "./chunk-TC6MZAO3.js";
51
60
 
52
61
  // src/shortcuts/meeting/operations/meetings.ts
53
62
  function overlapsDate(beginDatetime, endDatetime, date) {
@@ -776,7 +785,7 @@ async function assertCreatePathAllowed(args, env) {
776
785
  if (!isRepeat && Number(base.onlyFlowCreate) === 1) {
777
786
  throw meetingConflictError(
778
787
  "conflict_rejected",
779
- "\u8BE5\u79DF\u6237 onlyFlowCreate=1\uFF1A\u4F1A\u8BAE\u53EA\u80FD\u901A\u8FC7\u6D41\u7A0B\u521B\u5EFA\uFF1BCLI v1 \u672A\u96C6\u6210\u5DE5\u4F5C\u6D41\u53D1\u8D77\uFF0C\u8BF7\u901A\u8FC7\u5DE5\u4F5C\u6D41\u6D41\u7A0B\u521B\u5EFA",
788
+ "\u8BE5\u79DF\u6237 onlyFlowCreate=1\uFF1A\u4F1A\u8BAE\u53EA\u80FD\u901A\u8FC7\u6D41\u7A0B\u521B\u5EFA\uFF0C\u76F4\u8FDE\u5EFA\u4F1A\u5DF2\u88AB\u62D2\u7EDD\uFF08\u4E0D\u4F1A\u5199\u5165\u4EFB\u4F55\u6570\u636E\uFF09\u3002\u4E0D\u7528\u505C\u624B \u2014\u2014 \u6539\u8D70 **meeting.eb.meeting.create.flow**\uFF08prepare\u2192apply\uFF09\u5373\u53EF\uFF1A\u5B83\u4F1A\u8F7D\u5165\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u3001\u63D0\u4EA4\u5BA1\u6279\uFF0C\u5E76\u5728\u4F1A\u8BAE\u751F\u6210\u540E\u81EA\u52A8\u51FA\u9080\u8BF7\u51FD\u3002\u5982\u9700\u76F4\u8FDE\u5EFA\u4F1A\uFF0C\u8BF7\u7BA1\u7406\u5458\u5148\u5728\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\u4E2D\u5173\u95ED\u8BE5\u5F00\u5173\u3002",
780
789
  { workFlowBaseIds: base.workFlowBaseIds ?? "" }
781
790
  );
782
791
  }
@@ -2213,7 +2222,7 @@ var meetingAttachmentAttach = {
2213
2222
  if (mode === "append" && existingIds.length === 0) {
2214
2223
  existingIds.push(...beforeIds);
2215
2224
  }
2216
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
2225
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2217
2226
  const list = getMeetingOperation2("meeting.eb.meeting.list");
2218
2227
  let fileId = incomingFileId;
2219
2228
  let name = String(args.name ?? "").trim();
@@ -2301,7 +2310,7 @@ function textOf(value) {
2301
2310
  return value === void 0 || value === null ? "" : String(value);
2302
2311
  }
2303
2312
  async function readMinute(env, id) {
2304
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
2313
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2305
2314
  const detail = getMeetingOperation2("meeting.eb.minute.detail");
2306
2315
  const result = await detail.handler({ id }, env);
2307
2316
  const row = result?.data?.data;
@@ -2380,7 +2389,7 @@ var meetingMinuteWriteContent = {
2380
2389
  } else {
2381
2390
  statusReason = "\u4EC5\u6E05\u7A7A\u5185\u5BB9\uFF0C\u672A\u6539\u72B6\u6001";
2382
2391
  }
2383
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
2392
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2384
2393
  const prepare = getMeetingOperation2("meeting.eb.minute.update.prepare");
2385
2394
  const apply = getMeetingOperation2("meeting.eb.minute.update.apply");
2386
2395
  const prepared = await prepare.handler({ id, mt_id: mtId, ...patch }, env);
@@ -2510,8 +2519,8 @@ function parseLocalTime(value) {
2510
2519
  return Number.isNaN(parsed.getTime()) ? null : parsed;
2511
2520
  }
2512
2521
  function formatStamp(d) {
2513
- const pad2 = (n) => String(n).padStart(2, "0");
2514
- return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
2522
+ const pad3 = (n) => String(n).padStart(2, "0");
2523
+ return `${d.getFullYear()}-${pad3(d.getMonth() + 1)}-${pad3(d.getDate())} ${pad3(d.getHours())}:${pad3(d.getMinutes())}:${pad3(d.getSeconds())}`;
2515
2524
  }
2516
2525
  function computeChatWindow(meeting, now = /* @__PURE__ */ new Date()) {
2517
2526
  const begin = parseLocalTime(meeting.begin_datetime);
@@ -2639,16 +2648,16 @@ function buildDigest(messages, nameByUid, keepSystem, maxChars) {
2639
2648
  return { transcript, kept: lines.length, dropped, truncated };
2640
2649
  }
2641
2650
  async function saveTranscript(ctx, mtId, transcript) {
2642
- const { mkdir: mkdir4, writeFile: writeFile4 } = await import("node:fs/promises");
2651
+ const { mkdir: mkdir5, writeFile: writeFile5 } = await import("node:fs/promises");
2643
2652
  const { join: join3 } = await import("node:path");
2644
2653
  const { stateDir } = await import("./state-Y2XBP6YE.js");
2645
2654
  const dir = join3(stateDir(ctx), "transcripts");
2646
- await mkdir4(dir, { recursive: true });
2647
- const pad2 = (n) => String(n).padStart(2, "0");
2655
+ await mkdir5(dir, { recursive: true });
2656
+ const pad3 = (n) => String(n).padStart(2, "0");
2648
2657
  const now = /* @__PURE__ */ new Date();
2649
- const stamp2 = `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}-${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`;
2658
+ const stamp2 = `${now.getFullYear()}${pad3(now.getMonth() + 1)}${pad3(now.getDate())}-${pad3(now.getHours())}${pad3(now.getMinutes())}${pad3(now.getSeconds())}`;
2650
2659
  const filePath = join3(dir, `${mtId}-${stamp2}.txt`);
2651
- await writeFile4(filePath, transcript, "utf8");
2660
+ await writeFile5(filePath, transcript, "utf8");
2652
2661
  return filePath;
2653
2662
  }
2654
2663
  var meetingMinuteFromGroupChat = {
@@ -2738,7 +2747,7 @@ var meetingMinuteFromGroupChat = {
2738
2747
  const mtId = textOf2(args.mt_id).trim();
2739
2748
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
2740
2749
  const pipeline = ["text", "minutes", "document"].includes(args.pipeline) ? args.pipeline : "text";
2741
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
2750
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2742
2751
  const ctx = env.ctx;
2743
2752
  let stepStart = Date.now();
2744
2753
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
@@ -2762,9 +2771,9 @@ var meetingMinuteFromGroupChat = {
2762
2771
  }
2763
2772
  mark("readMeeting", stepStart);
2764
2773
  const pullStart = Date.now();
2765
- const { createImHost } = await import("./host-I4Z6BFYX.js");
2774
+ const { createImHost } = await import("./host-Q4LZGCRU.js");
2766
2775
  const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
2767
- const { getImOperation } = await import("./registry-2VLUAESA.js");
2776
+ const { getImOperation } = await import("./registry-OZSMDVPP.js");
2768
2777
  const imEnv = { ctx, host: createImHost(ctx), continuation: createImContinuationSigner(ctx) };
2769
2778
  const syncOp = getImOperation("im.msg.sync.group");
2770
2779
  const chatWindow = computeChatWindow(meeting);
@@ -2830,9 +2839,9 @@ var meetingMinuteFromGroupChat = {
2830
2839
  const extraSections = [];
2831
2840
  for (const file of extraFiles) {
2832
2841
  try {
2833
- const { readFile: readFile4 } = await import("node:fs/promises");
2834
- const buffer = await readFile4(file);
2835
- const { extractText } = await import("./attachment-content-AQNX5N3S.js");
2842
+ const { readFile: readFile5 } = await import("node:fs/promises");
2843
+ const buffer = await readFile5(file);
2844
+ const { extractText } = await import("./attachment-content-VXSWANAC.js");
2836
2845
  const extracted = extractText(buffer, file, "");
2837
2846
  if (extracted.text.trim()) {
2838
2847
  extraSections.push(`\u3010\u6750\u6599\uFF1A${file.split(/[\\/]/).pop() ?? file}\u3011
@@ -2959,9 +2968,9 @@ ${groupTranscript}` : ""
2959
2968
  if (!employeeId) {
2960
2969
  warnings.push("\u672A\u53D6\u5230 ESB \u89E6\u53D1\u4EBA id\uFF08employeeId\uFF09\uFF0C\u5DF2\u8DF3\u8FC7\u540E\u7EED ESB \u8C03\u7528");
2961
2970
  } else {
2962
- const { createEsbHost } = await import("./host-45WED2KK.js");
2971
+ const { createEsbHost } = await import("./host-I4NRK4MX.js");
2963
2972
  const { createEsbContinuationSigner } = await import("./continuation-NLECEJPX.js");
2964
- const { getEsbOperation } = await import("./registry-DC6KR3NH.js");
2973
+ const { getEsbOperation } = await import("./registry-KDD7DHNK.js");
2965
2974
  const esbEnv = { ctx, host: createEsbHost(ctx), continuation: createEsbContinuationSigner(ctx) };
2966
2975
  const prepareOp = getEsbOperation("esb.trigger.prepare");
2967
2976
  const applyOp = getEsbOperation("esb.trigger.apply");
@@ -3145,7 +3154,7 @@ var meetingDecisionNotifyGroup = {
3145
3154
  const warnings = [];
3146
3155
  const mtId = textOf3(args.mt_id).trim();
3147
3156
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
3148
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
3157
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
3149
3158
  const ctx = env.ctx;
3150
3159
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
3151
3160
  { mt_id: mtId, pageNo: 1, pageSize: 1 },
@@ -3209,7 +3218,7 @@ var meetingDecisionNotifyGroup = {
3209
3218
  charCount: formatted.text.length,
3210
3219
  text: formatted.text
3211
3220
  };
3212
- const { createImHost } = await import("./host-I4Z6BFYX.js");
3221
+ const { createImHost } = await import("./host-Q4LZGCRU.js");
3213
3222
  const imHost = createImHost(ctx);
3214
3223
  let displayText = formatted.text;
3215
3224
  let wireText = formatted.text;
@@ -3217,7 +3226,7 @@ var meetingDecisionNotifyGroup = {
3217
3226
  const mentioned = [];
3218
3227
  if (args.mention !== false) {
3219
3228
  try {
3220
- const { getImOperation } = await import("./registry-2VLUAESA.js");
3229
+ const { getImOperation } = await import("./registry-OZSMDVPP.js");
3221
3230
  const membersResult = await getImOperation("im.group.users").handler(
3222
3231
  { groupId },
3223
3232
  { ctx, host: imHost }
@@ -3351,14 +3360,14 @@ function defaultDueDate(begin, days) {
3351
3360
  const base = new Date(normalized.replace(/-/g, "/"));
3352
3361
  const start = Number.isNaN(base.getTime()) ? /* @__PURE__ */ new Date() : base;
3353
3362
  const due = new Date(start.getTime() + Math.max(days, 1) * 24 * 36e5);
3354
- const pad2 = (n) => String(n).padStart(2, "0");
3355
- return `${due.getFullYear()}-${pad2(due.getMonth() + 1)}-${pad2(due.getDate())} 18:00`;
3363
+ const pad3 = (n) => String(n).padStart(2, "0");
3364
+ return `${due.getFullYear()}-${pad3(due.getMonth() + 1)}-${pad3(due.getDate())} 18:00`;
3356
3365
  }
3357
3366
  async function waitForTaskIncrease(fetchTotal, baseline, timeoutMs = 15e3, intervalMs = 2e3) {
3358
3367
  const start = Date.now();
3359
3368
  let total = baseline;
3360
3369
  while (Date.now() - start < timeoutMs) {
3361
- await new Promise((resolve5) => setTimeout(resolve5, intervalMs));
3370
+ await new Promise((resolve6) => setTimeout(resolve6, intervalMs));
3362
3371
  total = await fetchTotal();
3363
3372
  if (total > baseline) return { total, waitedMs: Date.now() - start, increased: true };
3364
3373
  }
@@ -3447,7 +3456,7 @@ var meetingPipelineRun = {
3447
3456
  const needsConfirm = level === "tasks" || level === "notify";
3448
3457
  const confirmed = args.confirm === true;
3449
3458
  const executedLevel = needsConfirm && !confirmed ? "document" : level;
3450
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
3459
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
3451
3460
  const ctx = env.ctx;
3452
3461
  let stepStart = Date.now();
3453
3462
  const reuseMinuteId = textOf4(args.minuteId).trim();
@@ -3516,7 +3525,7 @@ var meetingPipelineRun = {
3516
3525
  ]);
3517
3526
  }
3518
3527
  stepStart = Date.now();
3519
- const { createHrmHost } = await import("./host-KNZ52LJZ.js");
3528
+ const { createHrmHost } = await import("./host-XCLDDXKQ.js");
3520
3529
  const { getHrmOperation } = await import("./registry-NYPYMZXG.js");
3521
3530
  const hrmEnv = { ctx, host: createHrmHost(ctx) };
3522
3531
  const queryOp = getHrmOperation("hrm.employee.query");
@@ -3554,8 +3563,8 @@ var meetingPipelineRun = {
3554
3563
  })();
3555
3564
  const beginAt = textOf4(meetingInfo.end_datetime).trim() || textOf4(meetingInfo.begin_datetime).trim() || (() => {
3556
3565
  const now = /* @__PURE__ */ new Date();
3557
- const pad2 = (n) => String(n).padStart(2, "0");
3558
- return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())} ${pad2(now.getHours())}:${pad2(now.getMinutes())}`;
3566
+ const pad3 = (n) => String(n).padStart(2, "0");
3567
+ return `${now.getFullYear()}-${pad3(now.getMonth() + 1)}-${pad3(now.getDate())} ${pad3(now.getHours())}:${pad3(now.getMinutes())}`;
3559
3568
  })();
3560
3569
  const dueDays = typeof args.taskDueDays === "number" && args.taskDueDays > 0 ? args.taskDueDays : 7;
3561
3570
  const dueAt = defaultDueDate(beginAt, dueDays);
@@ -3713,6 +3722,7 @@ var meetingPipelineRun = {
3713
3722
  var meetingPipelineOperations = [meetingPipelineRun];
3714
3723
 
3715
3724
  // src/shortcuts/meeting/operations/invitation.ts
3725
+ import { existsSync as existsSync2 } from "node:fs";
3716
3726
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
3717
3727
  import { dirname, join, resolve as resolve3 } from "node:path";
3718
3728
  import { fileURLToPath } from "node:url";
@@ -3720,6 +3730,14 @@ function templatePath() {
3720
3730
  const override = process.env.WEAVER_MEETING_INVITATION_TEMPLATE;
3721
3731
  if (override) return resolve3(override);
3722
3732
  const here = dirname(fileURLToPath(import.meta.url));
3733
+ let dir = here;
3734
+ for (let depth = 0; depth < 6; depth += 1) {
3735
+ const candidate = join(dir, "templates", "meeting", "invitation.docx");
3736
+ if (existsSync2(candidate)) return candidate;
3737
+ const parent = dirname(dir);
3738
+ if (parent === dir) break;
3739
+ dir = parent;
3740
+ }
3723
3741
  return resolve3(here, "../../../../templates/meeting/invitation.docx");
3724
3742
  }
3725
3743
  var WEEKDAYS = ["\u661F\u671F\u65E5", "\u661F\u671F\u4E00", "\u661F\u671F\u4E8C", "\u661F\u671F\u4E09", "\u661F\u671F\u56DB", "\u661F\u671F\u4E94", "\u661F\u671F\u516D"];
@@ -3757,7 +3775,7 @@ function formatTimeRange(start, end) {
3757
3775
  }
3758
3776
  async function loadAgendaFromTopics(env, mtId) {
3759
3777
  try {
3760
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
3778
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
3761
3779
  const operation = getMeetingOperation2("meeting.eb.topic.list");
3762
3780
  const result = await operation.handler({ mt_id: mtId, pageNo: 1, pageSize: 200 }, env);
3763
3781
  const rows = result.data?.rows ?? [];
@@ -3944,7 +3962,17 @@ var meetingInvitationRender = {
3944
3962
  type: "object",
3945
3963
  additionalProperties: false,
3946
3964
  properties: {
3947
- mtId: { ...SCHEMA_ID, description: "\u4F1A\u8BAE id\uFF08EB \u7248 mt_detail \u4E3B\u952E\uFF09" },
3965
+ mtId: { ...SCHEMA_ID, description: "\u4F1A\u8BAE id\uFF08EB \u7248 mt_detail \u4E3B\u952E\uFF09\u3002**\u4E0E\u4E0B\u9762\u7684\u5B57\u6BB5\u4E8C\u9009\u4E00**\uFF1A\u6709 mtId \u8D70\u771F\u5B9E\u4F1A\u8BAE\u6570\u636E\uFF1B\u6CA1\u6709\u5219\u7528\u4F20\u5165\u5B57\u6BB5\u76F4\u63A5\u751F\u6210\uFF08\u6D41\u7A0B\u5EFA\u4F1A\u5BA1\u6279\u4E2D\u4E5F\u80FD\u51FA\u9080\u8BF7\u51FD\uFF09" },
3966
+ mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u65E0 mtId \u65F6\u5FC5\u586B\uFF09" },
3967
+ begin_datetime: { type: "string", description: "\u5F00\u59CB\u65F6\u95F4 `yyyy-MM-dd HH:mm`\uFF08\u65E0 mtId \u65F6\u5FC5\u586B\uFF09" },
3968
+ end_datetime: { type: "string", description: "\u7ED3\u675F\u65F6\u95F4 `yyyy-MM-dd HH:mm`\uFF08\u65E0 mtId \u65F6\u5EFA\u8BAE\u586B\uFF0C\u7F3A\u4E86\u7ED3\u675F\u65F6\u95F4\u4F1A\u662F\u3010\u5F85\u8865\u5145\u3011\uFF09" },
3969
+ address: { type: "string", description: "\u4F1A\u8BAE\u5730\u70B9/\u4F1A\u8BAE\u5BA4**\u540D\u79F0**\uFF08\u65E0 mtId \u65F6\u7528\uFF1B\u8FD9\u91CC\u8981\u4F20\u540D\u79F0\uFF0C\u4E0D\u662F id\uFF09" },
3970
+ hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u59D3\u540D\uFF08\u9017\u53F7/\u987F\u53F7\u5206\u9694\uFF0C\u65E0 mtId \u65F6\u7528\uFF09" },
3971
+ mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BAE\u9898\u6982\u8981" },
3972
+ org_members: { type: "string", description: "\u843D\u6B3E\u5355\u4F4D\uFF08\u4E0D\u4F20\u5219\u5C1D\u8BD5\u7528\u53D1\u8D77\u4EBA\u90E8\u95E8 / \u7559\u3010\u5F85\u8865\u5145\u3011\uFF09" },
3973
+ caller: { type: "string", description: "\u53EC\u96C6\u4EBA" },
3974
+ contacter: { type: "string", description: "\u8054\u7CFB\u4EBA" },
3975
+ total_member: { type: "string", description: "\u53C2\u4F1A\u4EBA\u6570" },
3948
3976
  extra: {
3949
3977
  type: "object",
3950
3978
  additionalProperties: { type: "string" },
@@ -3955,41 +3983,66 @@ var meetingInvitationRender = {
3955
3983
  description: "\u8F93\u51FA\u6587\u4EF6\u5B8C\u6574\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09\u3002\u7F3A\u7701\u5199\u5230 ~/.weaver-work-cli/meeting/invitations/\u9080\u8BF7\u51FD-{\u4F1A\u8BAE\u540D}-{\u65E5\u671F}.docx"
3956
3984
  }
3957
3985
  },
3958
- required: ["mtId"]
3986
+ required: []
3959
3987
  },
3960
3988
  handler: async (args, env) => {
3961
3989
  const mtId = String(args.mtId ?? "").trim();
3962
- if (!mtId) {
3963
- throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mtId\uFF09");
3964
- }
3965
3990
  const extra = {};
3966
3991
  if (args.extra && typeof args.extra === "object") {
3967
3992
  for (const [key, value] of Object.entries(args.extra)) {
3968
3993
  if (value !== void 0 && value !== null) extra[key] = String(value);
3969
3994
  }
3970
3995
  }
3971
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
3972
- const listOperation = getMeetingOperation2("meeting.eb.meeting.list");
3973
3996
  let row;
3974
- try {
3975
- const listed = await listOperation.handler({ mt_id: mtId, pageNo: 1, pageSize: 1 }, env);
3976
- const rows = listed.data?.rows ?? [];
3977
- row = rows[0]?.mainTable ?? rows[0];
3978
- } catch (error) {
3979
- throw meetingValidationError(
3980
- "invitation_source_unavailable",
3981
- `\u8BFB\u53D6\u4F1A\u8BAE\u6570\u636E\u5931\u8D25\uFF08\u9080\u8BF7\u51FD\u5F53\u524D\u4F9D\u8D56 EB \u7248\u4F1A\u8BAE\u5217\u8868\uFF09\uFF1A${error instanceof Error ? error.message : String(error)}`,
3982
- { mtId }
3983
- );
3984
- }
3985
- if (!row) {
3986
- throw meetingValidationError("not_found", `\u672A\u627E\u5230\u4F1A\u8BAE id=${mtId}\uFF0C\u6216\u5F53\u524D\u8D26\u53F7\u65E0\u6743\u9650\u67E5\u770B`, { mtId });
3997
+ let dataSource = "meeting";
3998
+ if (!mtId) {
3999
+ const mtName = String(args.mt_name ?? "").trim();
4000
+ const beginText = String(args.begin_datetime ?? "").trim();
4001
+ if (!mtName || !beginText) {
4002
+ throw meetingValidationError(
4003
+ "invitation_source_required",
4004
+ "\u8981\u4E48\u4F20 mtId\uFF08\u6309\u771F\u5B9E\u4F1A\u8BAE\u751F\u6210\uFF09\uFF0C\u8981\u4E48\u4F20 mt_name + begin_datetime\uFF08\u6309\u7533\u8BF7\u5355\u4FE1\u606F\u9884\u586B\u751F\u6210\uFF09"
4005
+ );
4006
+ }
4007
+ const session = await env.host.getSession().catch(() => null);
4008
+ const sessionUserId = String(session?.userId ?? "");
4009
+ row = {
4010
+ mt_name: mtName,
4011
+ begin_datetime: beginText,
4012
+ end_datetime: String(args.end_datetime ?? "").trim(),
4013
+ address: String(args.address ?? "").trim(),
4014
+ hrm_members: String(args.hrm_members ?? "").trim(),
4015
+ mt_desc: String(args.mt_desc ?? "").trim(),
4016
+ org_members: String(args.org_members ?? "").trim(),
4017
+ caller: String(args.caller ?? "").trim(),
4018
+ contacter: String(args.contacter ?? "").trim(),
4019
+ total_member: String(args.total_member ?? "").trim(),
4020
+ creator: sessionUserId
4021
+ };
4022
+ dataSource = "payload";
4023
+ } else {
4024
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
4025
+ const listOperation = getMeetingOperation2("meeting.eb.meeting.list");
4026
+ try {
4027
+ const listed = await listOperation.handler({ mt_id: mtId, pageNo: 1, pageSize: 1 }, env);
4028
+ const rows = listed.data?.rows ?? [];
4029
+ row = rows[0]?.mainTable ?? rows[0];
4030
+ } catch (error) {
4031
+ throw meetingValidationError(
4032
+ "invitation_source_unavailable",
4033
+ `\u8BFB\u53D6\u4F1A\u8BAE\u6570\u636E\u5931\u8D25\uFF08\u9080\u8BF7\u51FD\u5F53\u524D\u4F9D\u8D56 EB \u7248\u4F1A\u8BAE\u5217\u8868\uFF09\uFF1A${error instanceof Error ? error.message : String(error)}`,
4034
+ { mtId }
4035
+ );
4036
+ }
4037
+ if (!row) {
4038
+ throw meetingValidationError("not_found", `\u672A\u627E\u5230\u4F1A\u8BAE id=${mtId}\uFF0C\u6216\u5F53\u524D\u8D26\u53F7\u65E0\u6743\u9650\u67E5\u770B`, { mtId });
4039
+ }
3987
4040
  }
3988
4041
  const creatorId = String(row.creator ?? "").trim();
3989
4042
  const needsIssuerOrg = !String(row.org_members ?? "").trim() && creatorId !== "";
3990
4043
  const issuerOrg = needsIssuerOrg ? await resolveIssuerOrganization(env, creatorId) : null;
3991
4044
  const { resolver, orgSource } = buildResolver(row, extra, issuerOrg);
3992
- let agendaRows = await loadAgendaFromTopics(env, mtId);
4045
+ let agendaRows = dataSource === "meeting" && mtId ? await loadAgendaFromTopics(env, mtId) : [];
3993
4046
  let agendaSource = agendaRows.length > 0 ? "meeting.topic" : "template";
3994
4047
  if (agendaRows.length === 0) {
3995
4048
  const fromExtra = parseAgendaFromExtra(extra.agenda);
@@ -4018,6 +4071,11 @@ var meetingInvitationRender = {
4018
4071
  await mkdir2(dirname(target), { recursive: true });
4019
4072
  await writeFile2(target, rendered.buffer);
4020
4073
  const warnings = [];
4074
+ if (dataSource === "payload") {
4075
+ warnings.push(
4076
+ "\u672C\u9080\u8BF7\u51FD\u6309**\u7533\u8BF7\u5355\u5DF2\u77E5\u4FE1\u606F**\u9884\u751F\u6210\uFF08\u4F1A\u8BAE\u53EF\u80FD\u8FD8\u5728\u5BA1\u6279\u4E2D\u3001\u5C1A\u672A\u751F\u6210\uFF09\uFF0C\u5C5E\u4E8E**\u9884\u7F6E\u51FD**\uFF1A\u8BF7\u4E0B\u8F7D\u540E\u4EBA\u5DE5\u6838\u5BF9/\u4FEE\u6539\u518D\u81EA\u884C\u53D1\u9001\u3002\u4F1A\u8BAE\u6B63\u5F0F\u751F\u6210\u540E\u53EF\u7528 mtId \u91CD\u65B0\u751F\u6210\u4E00\u7248\u62FF\u5230\u5B8C\u6574\u5B57\u6BB5\u3002"
4077
+ );
4078
+ }
4021
4079
  if (rendered.pending.length > 0) {
4022
4080
  warnings.push(
4023
4081
  `\u4EE5\u4E0B\u5B57\u6BB5\u53D6\u4E0D\u5230\u503C\uFF0C\u5DF2\u6E32\u67D3\u6210\u9EC4\u8272\u9AD8\u4EAE\u3010\u5F85\u8865\u5145\u3011\uFF0C\u8BF7\u4EBA\u5DE5\u8865\u5145\uFF1A${rendered.pending.join("\u3001")}`
@@ -4042,8 +4100,10 @@ var meetingInvitationRender = {
4042
4100
  filePath: target,
4043
4101
  fileName,
4044
4102
  bytes: rendered.buffer.length,
4045
- meetingId: mtId,
4103
+ meetingId: mtId || null,
4046
4104
  meetingName: String(row.mt_name ?? ""),
4105
+ // meeting=按真实会议数据;payload=按申请单字段预生成(会议可能还没生成,属预置函)
4106
+ dataSource,
4047
4107
  filledFields: rendered.filled,
4048
4108
  pendingFields: rendered.pending,
4049
4109
  // 落款单位的实际来源,便于调用方判断是否需要人工改写
@@ -4346,7 +4406,7 @@ function buildCodewords(bytes, version, ecc) {
4346
4406
  for (const byte of bytes) appendBits(byte, 8);
4347
4407
  appendBits(0, Math.min(4, capacityBits - bits.length));
4348
4408
  appendBits(0, (8 - bits.length % 8) % 8);
4349
- for (let pad2 = 236; bits.length < capacityBits; pad2 ^= 236 ^ 17) appendBits(pad2, 8);
4409
+ for (let pad3 = 236; bits.length < capacityBits; pad3 ^= 236 ^ 17) appendBits(pad3, 8);
4350
4410
  const dataCodewords = new Array(bits.length / 8).fill(0);
4351
4411
  bits.forEach((bit, i) => {
4352
4412
  dataCodewords[i >>> 3] |= bit << 7 - (i & 7);
@@ -4532,8 +4592,8 @@ function renderQrSvg(matrix, options = {}) {
4532
4592
  var ECC_LEVELS = ["L", "M", "Q", "H"];
4533
4593
  function stamp() {
4534
4594
  const now = /* @__PURE__ */ new Date();
4535
- const pad2 = (n) => String(n).padStart(2, "0");
4536
- return `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}-${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`;
4595
+ const pad3 = (n) => String(n).padStart(2, "0");
4596
+ return `${now.getFullYear()}${pad3(now.getMonth() + 1)}${pad3(now.getDate())}-${pad3(now.getHours())}${pad3(now.getMinutes())}${pad3(now.getSeconds())}`;
4537
4597
  }
4538
4598
  function safeName(input) {
4539
4599
  return input.replace(/[\\/:*?"<>|\s]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
@@ -4698,7 +4758,7 @@ var meetingSummaryGet = {
4698
4758
  const mtId = textOf5(args.mt_id).trim();
4699
4759
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
4700
4760
  const ctx = env.ctx;
4701
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
4761
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
4702
4762
  const warnings = [];
4703
4763
  const timings = {};
4704
4764
  const include = Array.isArray(args.include) && args.include.length > 0 ? args.include.filter((item) => ALL_SECTIONS.includes(item)) : ALL_SECTIONS;
@@ -4834,9 +4894,9 @@ var meetingSummaryGet = {
4834
4894
  warnings.push("\u8BE5\u4F1A\u8BAE\u6CA1\u6709\u5173\u8054\u7FA4\u804A\uFF08imchat_groupid \u4E3A\u7A7A\uFF09\uFF0Cchat \u6BB5\u4E3A null");
4835
4895
  } else {
4836
4896
  try {
4837
- const { createImHost } = await import("./host-I4Z6BFYX.js");
4897
+ const { createImHost } = await import("./host-Q4LZGCRU.js");
4838
4898
  const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
4839
- const { getImOperation } = await import("./registry-2VLUAESA.js");
4899
+ const { getImOperation } = await import("./registry-OZSMDVPP.js");
4840
4900
  const imEnv = {
4841
4901
  ctx,
4842
4902
  // 测试环境靠 env.imHost 注入假实现,否则会真的打到线上群聊
@@ -4917,719 +4977,110 @@ var meetingSummaryGet = {
4917
4977
  };
4918
4978
  var meetingSummaryOperations = [meetingSummaryGet];
4919
4979
 
4920
- // src/shortcuts/meeting/operations/eb/conflict.ts
4921
- var ACTIVE_MT_STATUS = "1,2,8,9";
4922
- var PAGE_SIZE = 200;
4923
- var MT_ID_BATCH = 50;
4924
- var MAX_PAGES = 50;
4925
- function errorText(error) {
4926
- return error instanceof Error ? error.message : String(error);
4927
- }
4928
- async function requestEbList(env, interfacePk, query, operation) {
4929
- const session = await env.host.getSession();
4930
- const pageNo = typeof query.pageNo === "number" ? query.pageNo : 1;
4931
- const pageSize = typeof query.pageSize === "number" ? query.pageSize : PAGE_SIZE;
4932
- const response = await env.host.request({
4933
- method: "POST",
4934
- path: `${EB_BASE}/getFormDataList/${interfacePk}`,
4935
- operation,
4936
- query,
4937
- body: queryBody(session.userId, { pageNo, pageSize }),
4938
- acceptBusiness: ebBusinessSuccess
4939
- });
4940
- return extractEbRows(response).rows.map((row) => row?.mainTable ? row.mainTable : row);
4941
- }
4942
- async function listAllEbRows(env, interfacePk, baseQuery, operation) {
4943
- const rows = [];
4944
- let requests = 0;
4945
- for (let pageNo = 1; pageNo <= MAX_PAGES; pageNo += 1) {
4946
- const page = await requestEbList(env, interfacePk, { ...baseQuery, pageNo, pageSize: PAGE_SIZE }, operation);
4947
- requests += 1;
4948
- rows.push(...page);
4949
- if (page.length < PAGE_SIZE) break;
4950
- }
4951
- return { rows, requests };
4952
- }
4953
- async function fetchEbAppSettings(env, operation) {
4954
- try {
4955
- const rows = await requestEbList(env, "query_meeting_baseset", { pageNo: 1, pageSize: 20 }, operation);
4956
- const valid = rows.filter((row) => String(row.data_status ?? "1") === "1");
4957
- const ordered = [...valid].sort((left, right) => String(right.update_time ?? "").localeCompare(String(left.update_time ?? "")));
4958
- const base = ordered[0] ?? {};
4959
- return {
4960
- roomChk: String(base.room_conflict_chk ?? ""),
4961
- roomAction: String(base.room_conflict ?? ""),
4962
- memberChk: String(base.member_conflict_chk ?? ""),
4963
- memberAction: String(base.member_conflict ?? ""),
4964
- onlyFlowCreate: String(base.only_flow_create ?? ""),
4965
- openMtApprove: String(base.open_mt_approve ?? ""),
4966
- mtNewWf: String(base.mt_new_wf ?? ""),
4967
- mtRepeatNewWf: String(base.mt_repeat_new_wf ?? ""),
4968
- settingsRows: valid.length,
4969
- settingsId: String(base.id ?? ""),
4970
- settingsUpdatedAt: String(base.update_time ?? "")
4971
- };
4972
- } catch (error) {
4973
- return {
4974
- roomChk: "",
4975
- roomAction: "",
4976
- memberChk: "",
4977
- memberAction: "",
4978
- onlyFlowCreate: "",
4979
- openMtApprove: "",
4980
- mtNewWf: "",
4981
- mtRepeatNewWf: "",
4982
- settingsRows: 0,
4983
- error: errorText(error)
4984
- };
4985
- }
4986
- }
4987
- function assertEbCreatePathAllowed(settings) {
4988
- if (settings.error) {
4989
- throw meetingConflictError(
4990
- "conflict_check_failed",
4991
- `\u65E0\u6CD5\u8BFB\u53D6\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\uFF08query_meeting_baseset\uFF09\uFF0C\u65E0\u6CD5\u5224\u5B9A\u662F\u5426\u5141\u8BB8\u76F4\u63A5\u5EFA\u4F1A\uFF08only_flow_create / open_mt_approve\uFF09\uFF0C\u5DF2\u6309\u4FDD\u5B88\u7B56\u7565\u62D2\u7EDD\uFF1A${settings.error}`
4992
- );
4993
- }
4994
- const blocked = [];
4995
- if (settings.onlyFlowCreate === "1") {
4996
- blocked.push("only_flow_create=1\uFF08\u53EA\u5141\u8BB8\u901A\u8FC7\u6D41\u7A0B\u65B0\u5EFA\u4F1A\u8BAE\uFF09");
4997
- }
4998
- if (settings.openMtApprove === "1") {
4999
- blocked.push("open_mt_approve=1\uFF08\u4F1A\u8BAE\u63D0\u4EA4\u9700\u5BA1\u6279\uFF09");
5000
- }
5001
- if (blocked.length === 0) return;
5002
- throw meetingConflictError(
5003
- "conflict_rejected",
5004
- `\u5E94\u7528\u8BBE\u7F6E\u4E0D\u5141\u8BB8\u76F4\u63A5\u5EFA\u4F1A\uFF1A${blocked.join("\uFF1B")}\u3002\u8BE5\u5E94\u7528\u7684\u4F1A\u8BAE\u5FC5\u987B\u7ECF\u6D41\u7A0B\u521B\u5EFA\uFF08\u65B0\u5EFA\u4F1A\u8BAE\u5DE5\u4F5C\u6D41 mt_new_wf=${settings.mtNewWf || "\u672A\u914D\u7F6E"}\uFF0C\u5468\u671F\u4F1A\u8BAE\u5DE5\u4F5C\u6D41 mt_repeat_new_wf=${settings.mtRepeatNewWf || "\u672A\u914D\u7F6E"}\uFF09\u2014\u2014CLI \u4E0D\u76F4\u63A5\u5EFA\u4F1A\u3001\u4E5F\u4E0D\u4EE3\u66FF\u6D41\u7A0B\u5EFA\u4F1A\uFF08\u5426\u5219\u4F1A\u4EA7\u751F\u6D41\u7A0B\u4E4B\u5916\u3001request_id \u4E3A\u7A7A\u7684\u4F1A\u8BAE\uFF0C\u4E14\u4E0E\u6D41\u7A0B/ESB \u81EA\u52A8\u5EFA\u4F1A\u91CD\u590D\uFF09\u3002\u8FD9\u5C5E\u4E8E\u5E94\u7528\u7BA1\u63A7\uFF0CCLI \u4E0D\u4F1A\u7ED5\u8FC7 \u2014\u2014 \u4F46\u4E5F\u4E0D\u7528\u505C\u624B\uFF1A\u6539\u8D70 **meeting.eb.meeting.create.flow**\uFF08prepare\u2192apply\uFF09\u5373\u53EF\uFF0C\u5B83\u4F1A\u6309 mt_new_wf \u8F7D\u5165\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u3001\u63D0\u4EA4\u5BA1\u6279\uFF0C\u5E76\u5728\u4F1A\u8BAE\u751F\u6210\u540E\u81EA\u52A8\u51FA\u9080\u8BF7\u51FD\u3002\u5982\u9700\u76F4\u8FDE\u5EFA\u4F1A\uFF0C\u8BF7\u7BA1\u7406\u5458\u5148\u5728\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\u4E2D\u5173\u95ED\u8BE5\u5F00\u5173\u3002`,
5005
- {
5006
- onlyFlowCreate: settings.onlyFlowCreate,
5007
- openMtApprove: settings.openMtApprove,
5008
- mtNewWf: settings.mtNewWf,
5009
- mtRepeatNewWf: settings.mtRepeatNewWf
5010
- }
5011
- );
5012
- }
5013
- async function checkRoomConflict(roomId, begin, end, excludeMtId, env, operation) {
5014
- const { rows, requests } = await listAllEbRows(
5015
- env,
5016
- "query_roomusage_list",
5017
- // 重叠判定:占用开始 < 我的结束(enddatetime 算子 lt)且 占用结束 > 我的开始(begindatetime 算子 gt)
5018
- { address: roomId, enddatetime: end, begindatetime: begin },
5019
- operation
5020
- );
5021
- const conflicts = rows.map((row) => ({
5022
- mtId: String(row.mt_id ?? ""),
5023
- begin: String(row.startdate ?? ""),
5024
- end: String(row.enddate ?? "")
5025
- })).filter((item) => item.mtId && item.mtId !== excludeMtId);
5026
- return { conflicts, requests };
5027
- }
5028
- async function collectMemberConflicts(members, begin, end, excludeMtId, env, operation) {
5029
- const wanted = new Set(members);
5030
- const candidate = await listAllEbRows(
5031
- env,
5032
- "query_mtDetail_list",
5033
- { begindatetime: begin, enddatetime: end, mt_status: ACTIVE_MT_STATUS },
5034
- operation
5035
- );
5036
- const candidates = candidate.rows.map((row) => ({
5037
- id: String(row.id ?? ""),
5038
- name: String(row.mt_name ?? row.name ?? ""),
5039
- begin: String(row.begin_datetime ?? ""),
5040
- end: String(row.end_datetime ?? "")
5041
- })).filter((item) => item.id && item.id !== excludeMtId);
5042
- const byId = new Map(candidates.map((item) => [item.id, item]));
5043
- const byMeeting = /* @__PURE__ */ new Map();
5044
- let receiptCalls = 0;
5045
- let receipts = 0;
5046
- for (let index = 0; index < candidates.length; index += MT_ID_BATCH) {
5047
- const csv = candidates.slice(index, index + MT_ID_BATCH).map((item) => item.id).join(",");
5048
- const page = await listAllEbRows(env, "query_meeting_receipt_list", { mt_id: csv }, operation);
5049
- receiptCalls += page.requests;
5050
- receipts += page.rows.length;
5051
- for (const row of page.rows) {
5052
- const meetingId = String(row.mt_id ?? "");
5053
- const memberId = String(row.member_id ?? "");
5054
- const memberType = String(row.member_type ?? "");
5055
- if (!meetingId || !memberId) continue;
5056
- if (memberType && memberType !== "1") continue;
5057
- if (!wanted.has(memberId)) continue;
5058
- if (!byMeeting.has(meetingId)) byMeeting.set(meetingId, /* @__PURE__ */ new Set());
5059
- byMeeting.get(meetingId).add(memberId);
5060
- }
5061
- }
5062
- const conflicts = [...byMeeting.entries()].map(([meetingId, ids]) => {
5063
- const meeting = byId.get(meetingId);
5064
- return {
5065
- meetingId,
5066
- name: meeting?.name ?? "",
5067
- begin: meeting?.begin ?? "",
5068
- end: meeting?.end ?? "",
5069
- conflictedMembers: [...ids]
5070
- };
5071
- });
5072
- conflicts.sort((left, right) => left.begin.localeCompare(right.begin));
5073
- return {
5074
- conflicts,
5075
- listCalls: candidate.requests,
5076
- receiptCalls,
5077
- candidates: candidates.length,
5078
- receipts
5079
- };
4980
+ // src/shortcuts/meeting/operations/form-fields.ts
4981
+ function textOf6(value) {
4982
+ return value === void 0 || value === null ? "" : String(value);
5080
4983
  }
5081
- async function runEbConflictCheck(input, env, operation, options = {}) {
5082
- const throwOnReject = options.throwOnReject !== false;
5083
- const begin = assertDateTimeMinute(input.beginDatetime, "begin_datetime");
5084
- const end = assertDateTimeMinute(input.endDatetime, "end_datetime");
5085
- const warnings = [];
5086
- const policy = options.settings ?? await fetchEbAppSettings(env, operation);
5087
- const outcome = { warnings, policy };
5088
- if (policy.error) {
5089
- warnings.push(
5090
- `\u5E94\u7528\u8BBE\u7F6E\uFF08query_meeting_baseset\uFF09\u8BFB\u53D6\u5931\u8D25\uFF0C\u51B2\u7A81\u7B56\u7565\u6309\u300C\u5F00\u542F\u68C0\u6D4B + \u4EC5\u63D0\u9192\u300D\u5904\u7406\uFF1A${policy.error}`
5091
- );
5092
- }
5093
- const handleHit = (action, message, details) => {
5094
- if (action === "1") {
5095
- const text = `${message}\uFF1B\u5E94\u7528\u8BBE\u7F6E\u7981\u6B62\u63D0\u4EA4\uFF08action=1\uFF09\uFF0C\u5DF2\u62D2\u7EDD\uFF0C\u8BF7\u66F4\u6362\u65F6\u95F4\u6216\u5730\u70B9\u540E\u91CD\u8BD5`;
5096
- if (throwOnReject) throw meetingConflictError("conflict_rejected", text, details);
5097
- warnings.push(text);
5098
- return;
5099
- }
5100
- warnings.push(
5101
- `${message}\uFF1B\u5E94\u7528\u8BBE\u7F6E\u4EC5\u63D0\u9192\uFF08action=0\uFF09\uFF1A\u672C\u6B21\u4E0D\u963B\u6B62\u63D0\u4EA4\uFF0C\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\u8BE5\u51B2\u7A81\u5E76\u5EFA\u8BAE\u66F4\u6362\u65F6\u95F4\u6216\u5730\u70B9\uFF0C\u7531\u7528\u6237\u51B3\u5B9A\u662F\u5426\u7EE7\u7EED\uFF08\u4E0D\u8981\u4E3B\u52A8\u5EFA\u8BAE\u5FFD\u7565\u51B2\u7A81\uFF0C\u4E5F\u4E0D\u8981\u66FF\u7528\u6237\u505A\u51B3\u5B9A\uFF09`
5102
- );
5103
- };
5104
- if (input.address) {
5105
- if (policy.roomChk === "0") {
5106
- outcome.room = { skipped: true, hasConflict: false, conflicts: [], requests: 0 };
5107
- warnings.push("\u5E94\u7528\u8BBE\u7F6E room_conflict_chk=0\uFF08\u5173\u95ED\uFF09\uFF0C\u5DF2\u8DF3\u8FC7\u4F1A\u8BAE\u5BA4\u51B2\u7A81\u68C0\u6D4B");
5108
- } else {
5109
- let result;
5110
- try {
5111
- result = await checkRoomConflict(input.address, begin, end, input.excludeMtId, env, operation);
5112
- } catch (error) {
5113
- throw meetingConflictError(
5114
- "conflict_check_failed",
5115
- `\u4F1A\u8BAE\u5BA4\u51B2\u7A81\u68C0\u6D4B\u5931\u8D25\uFF08\u89C6\u4E3A\u51B2\u7A81\uFF0C\u62D2\u7EDD\u5EFA\u4F1A\uFF09\uFF1A${errorText(error)}`
5116
- );
5117
- }
5118
- const hasConflict = result.conflicts.length > 0;
5119
- outcome.room = { skipped: false, hasConflict, conflicts: result.conflicts, requests: result.requests };
5120
- if (hasConflict) {
5121
- const detail = result.conflicts.map((item) => `${item.mtId}${item.begin ? `(${item.begin}~${item.end})` : ""}`).join("\u3001");
5122
- handleHit(
5123
- policy.roomAction,
5124
- `\u4F1A\u8BAE\u5BA4\u51B2\u7A81\uFF1A\u4F1A\u8BAE\u5BA4 ${input.address} \u5728 ${begin} ~ ${end} \u5DF2\u88AB\u5360\u7528\uFF08\u5360\u7528\u4F1A\u8BAE ${detail}\uFF09`,
5125
- { address: input.address, conflicts: result.conflicts, policy: policy.roomAction }
5126
- );
5127
- }
5128
- }
5129
- }
5130
- const members = toIdCsv(input.hrmMembers, "hrm_members");
5131
- if (policy.memberChk === "0") {
5132
- outcome.member = {
5133
- skipped: true,
5134
- hasConflict: false,
5135
- conflicts: [],
5136
- listCalls: 0,
5137
- receiptCalls: 0,
5138
- candidates: 0,
5139
- receipts: 0
5140
- };
5141
- warnings.push("\u5E94\u7528\u8BBE\u7F6E member_conflict_chk=0\uFF08\u5173\u95ED\uFF09\uFF0C\u5DF2\u8DF3\u8FC7\u53C2\u4F1A\u4EBA\u5458\u51B2\u7A81\u68C0\u6D4B");
5142
- } else if (members) {
5143
- let result;
5144
- try {
5145
- result = await collectMemberConflicts(members.split(","), begin, end, input.excludeMtId, env, operation);
5146
- } catch (error) {
5147
- throw meetingConflictError(
5148
- "conflict_check_failed",
5149
- `\u53C2\u4F1A\u4EBA\u5458\u51B2\u7A81\u68C0\u6D4B\u5931\u8D25\uFF08\u89C6\u4E3A\u51B2\u7A81\uFF0C\u62D2\u7EDD\u5EFA\u4F1A\uFF09\uFF1A${errorText(error)}`
5150
- );
5151
- }
5152
- const hasConflict = result.conflicts.length > 0;
5153
- outcome.member = {
5154
- skipped: false,
5155
- hasConflict,
5156
- conflicts: result.conflicts,
5157
- listCalls: result.listCalls,
5158
- receiptCalls: result.receiptCalls,
5159
- candidates: result.candidates,
5160
- receipts: result.receipts
5161
- };
5162
- if (hasConflict) {
5163
- const detail = result.conflicts.map((item) => `${item.name || item.meetingId}(${item.begin}~${item.end}) \u51B2\u7A81\u4EBA ${item.conflictedMembers.join(",")}`).join("\uFF1B");
5164
- handleHit(
5165
- policy.memberAction,
5166
- `\u53C2\u4F1A\u4EBA\u5458\u51B2\u7A81\uFF1A${result.conflicts.length} \u573A\u4F1A\u8BAE\u4E0E\u672C\u6B21\u53C2\u4F1A\u4EBA\u65F6\u95F4\u91CD\u53E0 \u2014\u2014 ${detail}`,
5167
- { conflicts: result.conflicts, policy: policy.memberAction }
5168
- );
5169
- }
5170
- if (input.orgMembers) {
5171
- warnings.push(
5172
- "org_members\uFF08\u53C2\u4F1A\u90E8\u95E8\uFF09\u672A\u5C55\u5F00\u4E3A\u5458\u5DE5\u540D\u5355\uFF0C\u672C\u6B21\u4EBA\u5458\u51B2\u7A81\u68C0\u6D4B\u4EC5\u8986\u76D6 hrm_members \u663E\u5F0F\u6307\u5B9A\u7684\u4EBA\u5458"
5173
- );
5174
- }
5175
- } else if (input.orgMembers) {
5176
- warnings.push(
5177
- "\u4EC5\u63D0\u4F9B org_members\uFF08\u53C2\u4F1A\u90E8\u95E8\uFF09\u800C\u672A\u63D0\u4F9B hrm_members\uFF1ACLI \u4E0D\u5C55\u5F00\u90E8\u95E8\u6210\u5458\uFF0C\u5DF2\u8DF3\u8FC7\u53C2\u4F1A\u4EBA\u5458\u51B2\u7A81\u68C0\u6D4B"
5178
- );
5179
- }
5180
- return outcome;
5181
- }
5182
- var ebMeetingWritePreflight = async ({ endpoint, payload, args, env, extras }) => {
5183
- const isCreate = endpoint.interfacePk === "create_meeting";
5184
- const isChange = endpoint.interfacePk === "change_meeting";
5185
- if (!isCreate && !isChange) return [];
5186
- const operation = isChange ? "meeting.eb.meeting.change.prepare" : "meeting.eb.meeting.create.prepare";
5187
- const main = payload.mainTable;
5188
- const begin = typeof main.begin_datetime === "string" ? main.begin_datetime : "";
5189
- const end = typeof main.end_datetime === "string" ? main.end_datetime : "";
5190
- const address = typeof main.address === "string" && main.address ? main.address : void 0;
5191
- const hrmMembers = typeof main.hrm_members === "string" && main.hrm_members ? main.hrm_members : void 0;
5192
- const settings = isCreate || address || hrmMembers ? await fetchEbAppSettings(env, operation) : void 0;
5193
- const preflightWarnings = [];
5194
- if (settings && isCreate) {
5195
- assertEbCreatePathAllowed(settings);
5196
- if ((settings.settingsRows ?? 0) > 1) {
5197
- preflightWarnings.push(
5198
- `\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\u5B58\u5728 ${settings.settingsRows} \u6761\u8BB0\u5F55\uFF0C\u672C\u6B21\u6309\u6700\u65B0\u4E00\u6761\uFF08id=${settings.settingsId ?? "\u672A\u77E5"}\uFF0C\u66F4\u65B0\u4E8E ${settings.settingsUpdatedAt || "\u672A\u77E5"}\uFF09\u5224\u65AD\u5EFA\u4F1A\u8DEF\u5F84\u4E0E\u51B2\u7A81\u7B56\u7565\uFF1B\u5982\u9700\u4EE5\u53E6\u4E00\u6761\u4E3A\u51C6\uFF0C\u8BF7\u5148\u5728\u7CFB\u7EDF\u9875\u9762\u6E05\u7406\u91CD\u590D\u7684\u8BBE\u7F6E\u8BB0\u5F55\u3002`
5199
- );
5200
- }
5201
- }
5202
- if (!begin || !end) return preflightWarnings;
5203
- if (!address && !hrmMembers) return preflightWarnings;
5204
- const outcome = await runEbConflictCheck(
5205
- {
5206
- beginDatetime: begin,
5207
- endDatetime: end,
5208
- ...address ? { address } : {},
5209
- ...hrmMembers ? { hrmMembers } : {},
5210
- ...typeof main.org_members === "string" && main.org_members ? { orgMembers: main.org_members } : {},
5211
- ...typeof args.id === "string" || typeof args.id === "number" ? { excludeMtId: String(args.id) } : {}
5212
- },
5213
- env,
5214
- operation,
5215
- settings ? { settings } : {}
5216
- );
5217
- const extraWarnings = [];
5218
- if (outcome.member && outcome.member.conflicts.length > 0) {
5219
- extras.memberConflicts = outcome.member.conflicts;
5220
- if (begin && end && hrmMembers) {
5221
- try {
5222
- const durationMinutes = Math.max(15, Math.round((Date.parse(end.replace(" ", "T")) - Date.parse(begin.replace(" ", "T"))) / 6e4) || 60);
5223
- const day = begin.slice(0, 10);
5224
- const free = await findCommonFreeSlots(env, {
5225
- rangeStart: `${day} 00:00`,
5226
- rangeEnd: `${day} 23:59`,
5227
- durationMinutes,
5228
- members: hrmMembers.split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== ""),
5229
- ...typeof args.id === "string" || typeof args.id === "number" ? { excludeMtId: String(args.id) } : {},
5230
- maxSlots: 3,
5231
- maxDays: 1,
5232
- includeSchedule: true
5233
- });
5234
- if (free.slots.length > 0) {
5235
- extras.suggestedSlots = free.slots;
5236
- extras.slotOptions = free.slots.map((slot, index) => ({
5237
- key: `T${index + 1}`,
5238
- // 选项里必须写清"为什么推荐这个时段",否则用户看到的只是两个时间点(2026-10-28 用户反馈)
5239
- label: `${slot.begin.slice(11)}~${slot.end.slice(11)}\uFF08${day}\uFF09 \xB7 \u5168\u90E8\u53C2\u4F1A\u4EBA\u7A7A\u95F2`,
5240
- value: { begin: slot.begin, end: slot.end },
5241
- reason: "\u8BE5\u65F6\u6BB5\u6240\u6709\u53C2\u4F1A\u4EBA\u90FD\u6CA1\u6709\u4F1A\u8BAE\u4E0E\u65E5\u7A0B\u5360\u7528"
5242
- }));
5243
- extraWarnings.push(
5244
- `\u5F53\u5929\uFF08${day}\uFF09\u63A8\u8350\u6539\u671F\u5230\uFF1A${free.slots.map((slot, index) => `[T${index + 1}] ${slot.begin.slice(11)}~${slot.end.slice(11)}`).join("\uFF1B")}\uFF08\u5DF2\u540C\u65F6\u6838\u5BF9\u4F1A\u8BAE\u56DE\u6267\u4E0E\u65E5\u7A0B\uFF09\u2014\u2014\u8BF7\u7528\u9009\u9879\u65B9\u5F0F\u8BA9\u7528\u6237\u6311\u4E00\u4E2A\u3002`
5245
- );
5246
- } else if (free.blockingSummary) {
5247
- extraWarnings.push(free.blockingSummary);
5248
- extras.dayBlocked = { day, summary: free.blockingSummary };
5249
- }
5250
- extras.scheduleItems = free.scheduleItems;
5251
- extras.busyByMember = free.busyByMember;
5252
- extras.availabilityCost = free.cost;
5253
- } catch (error) {
5254
- extraWarnings.push(`\u5171\u540C\u7A7A\u95F2\u65F6\u6BB5\u8BA1\u7B97\u5931\u8D25\uFF08${String(error?.message ?? error).slice(0, 80)}\uFF09\uFF0C\u8BF7\u624B\u52A8\u6362\u65F6\u95F4`);
5255
- }
5256
- }
5257
- }
5258
- return [...preflightWarnings, ...outcome.warnings, ...extraWarnings];
5259
- };
5260
- var ebConflictRoom = {
5261
- name: "meeting.eb.conflict.room",
4984
+ var TYPES = Object.keys(MEETING_EB_TAGS);
4985
+ var meetingFormFields = {
4986
+ name: "meeting.form.fields",
5262
4987
  resource: "eb",
5263
- method: "meeting.eb.conflict.room",
5264
- action: "meeting.eb.conflict.room",
5265
- summary: "EB \u7248\u4F1A\u8BAE\u5BA4\u51B2\u7A81\u68C0\u6D4B\uFF08query_roomusage_list \u67E5\u8BE5\u4F1A\u8BAE\u5BA4\u65F6\u6BB5\u5185\u5360\u7528\uFF09\uFF1A\u6309\u5E94\u7528\u8BBE\u7F6E room_conflict_chk/room_conflict \u7ED9\u51FA verdict",
5266
- capability: "eb.conflict",
4988
+ method: "meeting.form.fields",
4989
+ action: "meeting.form.fields",
4990
+ summary: "\u8BFB\u53D6\u4F1A\u8BAE\u8868\u5355\u7684\u771F\u5B9E\u5B57\u6BB5\u6E05\u5355\uFF08\u4E2D\u6587\u540D / dataKey / \u5B57\u6BB5 id / \u7EC4\u4EF6\u7C7B\u578B / \u662F\u5426\u591A\u9009\uFF09\uFF0C\u4F9B extraFields \u6309\u771F\u5B9E\u5B57\u6BB5\u540D\u5199\u5165\u79DF\u6237\u81EA\u5B9A\u4E49\u5B57\u6BB5",
4991
+ capability: "eb.meta",
5267
4992
  risk: "read",
5268
4993
  inputSchema: {
5269
4994
  type: "object",
5270
4995
  additionalProperties: false,
5271
4996
  properties: {
5272
- beginDatetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5273
- endDatetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5274
- address: { ...SCHEMA_ID, description: "\u4F1A\u8BAE\u5BA4 id\uFF08\u5FC5\u586B\uFF09" },
5275
- mtId: { ...SCHEMA_ID, description: "\u53D8\u66F4\u4F1A\u8BAE\u65F6\u6392\u9664\u81EA\u8EAB" }
5276
- },
5277
- required: ["beginDatetime", "endDatetime", "address"]
5278
- },
5279
- handler: async (args, env) => {
5280
- const outcome = await runEbConflictCheck(
5281
- {
5282
- beginDatetime: args.beginDatetime,
5283
- endDatetime: args.endDatetime,
5284
- address: String(args.address),
5285
- ...args.mtId !== void 0 ? { excludeMtId: String(args.mtId) } : {}
5286
- },
5287
- env,
5288
- "meeting.eb.conflict.room",
5289
- { throwOnReject: false }
5290
- );
5291
- const room = outcome.room ?? { skipped: true, hasConflict: false, conflicts: [], requests: 0 };
5292
- const verdict = room.skipped ? "skipped" : !room.hasConflict ? "ok" : outcome.policy.roomAction === "1" ? "rejected" : "warn";
5293
- return meetingSuccess(
5294
- "meeting.eb.conflict.room",
5295
- {
5296
- verdict,
5297
- hasConflict: room.hasConflict,
5298
- skipped: room.skipped,
5299
- conflicts: room.conflicts,
5300
- policy: { chk: outcome.policy.roomChk, action: outcome.policy.roomAction },
5301
- requests: 1 + room.requests
4997
+ type: {
4998
+ type: "string",
4999
+ enum: TYPES,
5000
+ description: "\u8981\u67E5\u54EA\u5F20\u8868\uFF1Ameeting=\u4F1A\u8BAE\u3001topic=\u8BAE\u9898\u3001minutes=\u7EAA\u8981\u3001room=\u4F1A\u8BAE\u5BA4\u3001sign=\u7B7E\u5230\u3001receipt=\u56DE\u6267\u2026\uFF08\u9ED8\u8BA4 meeting\uFF09"
5302
5001
  },
5303
- outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
5304
- );
5305
- }
5306
- };
5307
- var ebConflictMember = {
5308
- name: "meeting.eb.conflict.member",
5309
- resource: "eb",
5310
- method: "meeting.eb.conflict.member",
5311
- action: "meeting.eb.conflict.member",
5312
- summary: "EB \u7248\u53C2\u4F1A\u4EBA\u5458\u51B2\u7A81\u68C0\u6D4B\uFF08query_mtDetail_list \u5019\u9009 \u2192 query_meeting_receipt_list?mt_id=\u591A\u503C\u6279\u91CF \u2192 \u672C\u5730\u6BD4\u5BF9\uFF1B2 \u6B21\u8BF7\u6C42\uFF0C\u65E0 N+1\uFF09\uFF1A\u6309 member_conflict_chk/member_conflict \u7ED9\u51FA verdict",
5313
- capability: "eb.conflict",
5314
- risk: "read",
5315
- inputSchema: {
5316
- type: "object",
5317
- additionalProperties: false,
5318
- properties: {
5319
- beginDatetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5320
- endDatetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5321
- hrmMembers: { type: "string", description: "\u53C2\u4F1A\u4EBA\u5458 id\uFF0C\u9017\u53F7\u5206\u9694\u5B57\u7B26\u4E32\uFF08\u5FC5\u586B\uFF09" },
5322
- mtId: { ...SCHEMA_ID, description: "\u53D8\u66F4\u4F1A\u8BAE\u65F6\u6392\u9664\u81EA\u8EAB" }
5323
- },
5324
- required: ["beginDatetime", "endDatetime", "hrmMembers"]
5002
+ keyword: { type: "string", description: "\u53EA\u8FD4\u56DE\u4E2D\u6587\u540D/dataKey \u5305\u542B\u8BE5\u5173\u952E\u8BCD\u7684\u5B57\u6BB5\uFF08\u5982\u300C\u5BA2\u6237\u300D\u300C\u8054\u7CFB\u300D\uFF09" },
5003
+ refresh: { type: "boolean", description: "\u9ED8\u8BA4\u8BFB\u7F13\u5B58\uFF1B\u4F20 true \u5F3A\u5236\u91CD\u65B0\u89E3\u6790\u8868 id \u4E0E\u5B57\u6BB5\u5B9A\u4E49" }
5004
+ }
5325
5005
  },
5326
5006
  handler: async (args, env) => {
5327
- const outcome = await runEbConflictCheck(
5328
- {
5329
- beginDatetime: args.beginDatetime,
5330
- endDatetime: args.endDatetime,
5331
- hrmMembers: String(args.hrmMembers),
5332
- ...args.mtId !== void 0 ? { excludeMtId: String(args.mtId) } : {}
5333
- },
5334
- env,
5335
- "meeting.eb.conflict.member",
5336
- { throwOnReject: false }
5337
- );
5338
- const member = outcome.member ?? {
5339
- skipped: true,
5340
- hasConflict: false,
5341
- conflicts: [],
5342
- listCalls: 0,
5343
- receiptCalls: 0,
5344
- candidates: 0,
5345
- receipts: 0
5007
+ const type = TYPES.includes(args.type) ? args.type : "meeting";
5008
+ const tag = MEETING_EB_TAGS[type];
5009
+ const resolved = await resolveMeetingEbObjs(env.host, env.ctx, {
5010
+ tags: [tag],
5011
+ ...args.refresh === true ? { refresh: true } : {}
5012
+ });
5013
+ const obj = resolved.objs[tag];
5014
+ if (!obj?.objId) {
5015
+ return meetingSuccess("meeting.form.fields", {
5016
+ type,
5017
+ tag,
5018
+ objId: "",
5019
+ fields: [],
5020
+ 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"
5021
+ }, { warnings: resolved.warnings });
5022
+ }
5023
+ const { createEbuilderFormHost } = await import("./host-UEI5FGDM.js");
5024
+ const { createEbuilderFormContinuationSigner } = await import("./continuation-RN6PZN2M.js");
5025
+ const { executeEbuilderFormOperation } = await import("./operations-5QL3AECO.js");
5026
+ const formEnv = {
5027
+ ctx: env.ctx,
5028
+ host: createEbuilderFormHost(env.ctx),
5029
+ continuation: createEbuilderFormContinuationSigner(env.ctx)
5346
5030
  };
5347
- const verdict = member.skipped ? "skipped" : !member.hasConflict ? "ok" : outcome.policy.memberAction === "1" ? "rejected" : "warn";
5348
- return meetingSuccess(
5349
- "meeting.eb.conflict.member",
5350
- {
5351
- verdict,
5352
- hasConflict: member.hasConflict,
5353
- skipped: member.skipped,
5354
- conflicts: member.conflicts,
5355
- policy: { chk: outcome.policy.memberChk, action: outcome.policy.memberAction },
5356
- cost: {
5357
- baseSetCalls: 1,
5358
- listCalls: member.listCalls,
5359
- receiptCalls: member.receiptCalls,
5360
- candidates: member.candidates,
5361
- receipts: member.receipts
5362
- }
5363
- },
5364
- outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
5365
- );
5366
- }
5367
- };
5368
- function parseMinute(text) {
5369
- const match = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2})/.exec(String(text ?? "").trim());
5370
- if (!match) return null;
5371
- return new Date(
5372
- Number(match[1]),
5373
- Number(match[2]) - 1,
5374
- Number(match[3]),
5375
- Number(match[4]),
5376
- Number(match[5]),
5377
- 0,
5378
- 0
5379
- );
5380
- }
5381
- function formatMinute(date) {
5382
- const pad2 = (n) => String(n).padStart(2, "0");
5383
- return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`;
5384
- }
5385
- async function resolveMemberNames(env, ids) {
5386
- const map = /* @__PURE__ */ new Map();
5387
- const unique = [...new Set(ids.filter((id) => id !== ""))];
5388
- if (unique.length === 0) return map;
5389
- try {
5390
- const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
5391
- const batch = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.batch");
5392
- if (!batch) return map;
5393
- const result = await batch.handler({ ids: unique }, env);
5394
- const rows = result?.data?.rows ?? result?.data?.userList ?? [];
5395
- for (const row of rows) {
5396
- const id = String(row.id ?? "").trim();
5397
- const name = String(row.name ?? "").trim();
5398
- if (id && name) map.set(id, name);
5399
- }
5400
- } catch {
5401
- }
5402
- return map;
5403
- }
5404
- async function findCommonFreeSlots(env, input) {
5405
- const members = input.members.map((item) => String(item).trim()).filter((item) => item !== "");
5406
- const wanted = new Set(members);
5407
- const duration = Math.max(15, Math.min(24 * 60, Math.round(input.durationMinutes || 60)));
5408
- const step = Math.max(15, Math.min(120, Math.round(input.stepMinutes ?? 30)));
5409
- const workStart = Math.max(0, Math.min(23, input.workStartHour ?? 9));
5410
- const workEnd = Math.max(workStart + 1, Math.min(24, input.workEndHour ?? 18));
5411
- const maxSlots = Math.max(1, Math.min(20, input.maxSlots ?? 3));
5412
- const maxDays = Math.max(1, Math.min(14, input.maxDays ?? 1));
5413
- const includeSchedule = input.includeSchedule !== false;
5414
- const rangeStart = parseMinute(input.rangeStart);
5415
- const rangeEnd = parseMinute(input.rangeEnd);
5416
- const cost = { candidateCalls: 0, receiptCalls: 0, candidates: 0, busyIntervals: 0, scheduleCalls: 0 };
5417
- const empty = { slots: [], idle: false, cost, scheduleItems: [], busyByMember: [] };
5418
- if (!rangeStart || !rangeEnd) return empty;
5419
- const detail = /* @__PURE__ */ new Map();
5420
- const pushBusy = (memberId, item) => {
5421
- const list = detail.get(memberId) ?? [];
5422
- list.push(item);
5423
- detail.set(memberId, list);
5424
- cost.busyIntervals += 1;
5425
- };
5426
- const candidate = await listAllEbRows(
5427
- env,
5428
- "query_mtDetail_list",
5429
- { begindatetime: input.rangeStart, enddatetime: input.rangeEnd, mt_status: ACTIVE_MT_STATUS },
5430
- "meeting.eb.conflict.availability"
5431
- );
5432
- cost.candidateCalls += candidate.requests;
5433
- const meetings = candidate.rows.map((row) => ({
5434
- id: String(row.id ?? ""),
5435
- name: String(row.mt_name ?? row.name ?? row.mt_name ?? ""),
5436
- begin: parseMinute(String(row.begin_datetime ?? "")),
5437
- end: parseMinute(String(row.end_datetime ?? ""))
5438
- })).filter((item) => item.id && item.id !== (input.excludeMtId ?? "") && item.begin && item.end);
5439
- cost.candidates = meetings.length;
5440
- const byId = new Map(meetings.map((item) => [item.id, item]));
5441
- for (let index = 0; index < meetings.length; index += MT_ID_BATCH) {
5442
- const csv = meetings.slice(index, index + MT_ID_BATCH).map((item) => item.id).join(",");
5443
- const page = await listAllEbRows(env, "query_meeting_receipt_list", { mt_id: csv }, "meeting.eb.conflict.availability");
5444
- cost.receiptCalls += page.requests;
5445
- for (const row of page.rows) {
5446
- const meetingId = String(row.mt_id ?? "");
5447
- const memberId = String(row.member_id ?? "");
5448
- const memberType = String(row.member_type ?? "");
5449
- if (!meetingId || !memberId) continue;
5450
- if (memberType && memberType !== "1") continue;
5451
- if (!wanted.has(memberId)) continue;
5452
- const meeting = byId.get(meetingId);
5453
- if (!meeting?.begin || !meeting?.end) continue;
5454
- pushBusy(memberId, {
5455
- source: "meeting",
5456
- title: meeting.name || "\u4F1A\u8BAE",
5457
- begin: formatMinute(meeting.begin),
5458
- end: formatMinute(meeting.end)
5459
- });
5460
- }
5461
- }
5462
- const scheduleItems = [];
5463
- if (includeSchedule) {
5464
- try {
5465
- const { runScheduleConflictFlow, parseScheduleConflictMessage, resolveMemberIdsByName } = await import("./schedule-KFIITGSK.js");
5466
- const dayBegin = new Date(rangeStart.getFullYear(), rangeStart.getMonth(), rangeStart.getDate(), 0, 0, 0, 0);
5467
- const dayEnd = new Date(rangeStart.getFullYear(), rangeStart.getMonth(), rangeStart.getDate(), 23, 59, 0, 0);
5468
- const flow = await runScheduleConflictFlow(env, {
5469
- startDate: formatMinute(dayBegin),
5470
- endDate: formatMinute(dayEnd),
5471
- memberIds: members
5472
- });
5473
- cost.scheduleCalls += 1;
5474
- const rawItems = [];
5475
- for (const row of flow.rows) {
5476
- const main = row?.mainTable ?? row ?? {};
5477
- const type = main.agn_type;
5478
- const typeId = Array.isArray(type) ? String(type[0]?.id ?? "") : String(type?.id ?? type ?? "");
5479
- void typeId;
5480
- rawItems.push({
5481
- title: String(main.agn_name ?? main.name ?? "").trim() || "\u65E5\u7A0B",
5482
- begin: String(main.start_time ?? "").trim(),
5483
- end: String(main.end_time ?? "").trim(),
5484
- names: String(main.participants ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "")
5485
- });
5486
- }
5487
- if (rawItems.length === 0) {
5488
- for (const item of parseScheduleConflictMessage(flow.message)) {
5489
- rawItems.push({ title: item.title, begin: item.startTime, end: item.endTime, names: item.memberNames });
5490
- }
5491
- }
5492
- const idsByName = await resolveMemberIdsByName(env, rawItems.flatMap((item) => item.names));
5493
- const datePrefix = `${rangeStart.getFullYear()}-${String(rangeStart.getMonth() + 1).padStart(2, "0")}-${String(rangeStart.getDate()).padStart(2, "0")}`;
5494
- for (const item of rawItems) {
5495
- const beginText = item.begin.includes("-") ? item.begin : `${datePrefix} ${item.begin}`;
5496
- const endText = item.end.includes("-") ? item.end : `${datePrefix} ${item.end}`;
5497
- const beginDate = parseMinute(beginText);
5498
- const endDate = parseMinute(endText);
5499
- if (!beginDate || !endDate) continue;
5500
- const memberIds = item.names.map((name) => idsByName.get(name) ?? "").filter((id) => id !== "");
5501
- scheduleItems.push({ title: item.title, begin: beginText, end: endText, members: memberIds.length > 0 ? memberIds : item.names });
5502
- for (const memberId of memberIds) {
5503
- if (!wanted.has(memberId)) continue;
5504
- pushBusy(memberId, { source: "schedule", title: item.title, begin: beginText, end: endText });
5505
- }
5031
+ const raw = await executeEbuilderFormOperation("ebuilder-form.fields.get", { objId: obj.objId }, formEnv);
5032
+ const nodes = Array.isArray(raw?.data?.result?.data) ? raw.data.result.data : [];
5033
+ const rows = [];
5034
+ const detailTables = [];
5035
+ for (const node of nodes) {
5036
+ const fields = Array.isArray(node?.fields) ? node.fields : [];
5037
+ if (fields.length === 0 && textOf6(node?.name)) {
5038
+ detailTables.push(textOf6(node.name));
5039
+ continue;
5506
5040
  }
5507
- } catch {
5508
- }
5509
- }
5510
- const names = await resolveMemberNames(env, [...detail.keys()]);
5511
- const busyByMember = [...detail.entries()].map(([memberId, items]) => ({
5512
- memberId,
5513
- ...names.get(memberId) ? { memberName: names.get(memberId) } : {},
5514
- items: items.sort((left, right) => left.begin.localeCompare(right.begin))
5515
- }));
5516
- const overlaps = (slotStart, slotEnd) => {
5517
- for (const entry of busyByMember) {
5518
- for (const item of entry.items) {
5519
- const begin = parseMinute(item.begin);
5520
- const end = parseMinute(item.end);
5521
- if (!begin || !end) continue;
5522
- if (slotStart < end && slotEnd > begin) return true;
5041
+ for (const field of fields) {
5042
+ const config = field?.config ?? {};
5043
+ const dataKey = textOf6(config.dataKey || config.columnName || field.physicalField);
5044
+ rows.push({
5045
+ dataKey,
5046
+ fieldId: textOf6(field.name || field.id),
5047
+ label: textOf6(field.text || config.title),
5048
+ compType: textOf6(field.compType || config.componentKey),
5049
+ type: textOf6(field.type || config.type),
5050
+ multiSelect: String(field.multiSelect ?? "false") === "true"
5051
+ });
5523
5052
  }
5524
5053
  }
5525
- return false;
5526
- };
5527
- const now = /* @__PURE__ */ new Date();
5528
- const slots = [];
5529
- const dayCount = Math.min(maxDays, Math.ceil((rangeEnd.getTime() - rangeStart.getTime()) / 864e5) + 1);
5530
- for (let day = 0; day < dayCount && slots.length < maxSlots; day += 1) {
5531
- const dayStart = new Date(rangeStart.getFullYear(), rangeStart.getMonth(), rangeStart.getDate() + day, workStart, 0, 0, 0);
5532
- const dayLimit = new Date(rangeStart.getFullYear(), rangeStart.getMonth(), rangeStart.getDate() + day, workEnd, 0, 0, 0);
5533
- for (let cursor = new Date(dayStart); cursor.getTime() + duration * 6e4 <= dayLimit.getTime(); cursor = new Date(cursor.getTime() + step * 6e4)) {
5534
- const slotStart = new Date(cursor);
5535
- const slotEnd = new Date(cursor.getTime() + duration * 6e4);
5536
- if (slotStart.getTime() < now.getTime() + 5 * 6e4) continue;
5537
- if (slotStart < rangeStart || slotEnd > rangeEnd) continue;
5538
- if (overlaps(slotStart, slotEnd)) continue;
5539
- slots.push({ begin: formatMinute(slotStart), end: formatMinute(slotEnd) });
5540
- if (slots.length >= maxSlots) break;
5541
- }
5542
- }
5543
- let blockingSummary;
5544
- if (slots.length === 0) {
5545
- const day = `${rangeStart.getFullYear()}-${String(rangeStart.getMonth() + 1).padStart(2, "0")}-${String(rangeStart.getDate()).padStart(2, "0")}`;
5546
- const perMember = busyByMember.map((entry) => {
5547
- const items = entry.items.slice(0, 3).map((item) => `${item.source === "meeting" ? "\u4F1A\u8BAE" : "\u65E5\u7A0B"}\u300A${item.title}\u300B${item.begin.slice(11)}~${item.end.slice(11)}`).join("\u3001");
5548
- const more = entry.items.length > 3 ? ` \u7B49 ${entry.items.length} \u9879` : "";
5549
- return `${entry.memberName ?? entry.memberId}\uFF1A${items}${more}`;
5550
- });
5551
- blockingSummary = perMember.length > 0 ? `${day} \u5F53\u5929 ${workStart}:00-${workEnd}:00 \u5185\u6CA1\u6709\u6240\u6709\u4EBA\u90FD\u7A7A\u95F2\u7684 ${duration} \u5206\u949F\u65F6\u6BB5\uFF08\u5DF2\u540C\u65F6\u6838\u5BF9\u4F1A\u8BAE\u56DE\u6267\u4E0E\u65E5\u7A0B\uFF09\u2014\u2014${perMember.join("\uFF1B")}` : `${day} \u5F53\u5929 ${workStart}:00-${workEnd}:00 \u5185\u6CA1\u6709\u627E\u5230\u7B26\u5408\u6761\u4EF6\u7684 ${duration} \u5206\u949F\u65F6\u6BB5\uFF0C\u5EFA\u8BAE\u6362\u4E2A\u65E5\u671F\u6216\u7F29\u77ED\u65F6\u957F`;
5552
- }
5553
- return {
5554
- slots,
5555
- idle: cost.busyIntervals === 0,
5556
- cost,
5557
- scheduleItems,
5558
- busyByMember,
5559
- ...blockingSummary ? { blockingSummary } : {}
5560
- };
5561
- }
5562
- var ebConflictAvailability = {
5563
- name: "meeting.eb.conflict.availability",
5564
- resource: "eb",
5565
- method: "meeting.eb.conflict.availability",
5566
- action: "meeting.eb.conflict.availability",
5567
- summary: "\u53C2\u4F1A\u4EBA\u5171\u540C\u7A7A\u95F2\u65F6\u6BB5\u63A8\u8350\uFF08\u4F1A\u8BAE\u7EF4\u5EA6\uFF09\uFF1A\u4E00\u6B21\u62C9\u5019\u9009\u4F1A\u8BAE + \u6279\u91CF\u56DE\u6267\uFF0C\u5185\u5B58\u5207 30 \u5206\u949F slot\uFF0C\u7ED9\u51FA\u6240\u6709\u4EBA\u90FD\u7A7A\u95F2\u7684\u65F6\u95F4\u6BB5\uFF08\u9ED8\u8BA4\u6700\u591A 3 \u4E2A\uFF0C\u5F80\u540E 7 \u5929\uFF09",
5568
- capability: "eb.conflict",
5569
- risk: "read",
5570
- inputSchema: {
5571
- type: "object",
5572
- additionalProperties: false,
5573
- properties: {
5574
- rangeStart: { ...SCHEMA_DATETIME_MINUTE, description: "\u641C\u7D22\u8303\u56F4\u5F00\u59CB\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5575
- rangeEnd: { ...SCHEMA_DATETIME_MINUTE, description: "\u641C\u7D22\u8303\u56F4\u7ED3\u675F\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5576
- durationMinutes: { type: "number", description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09" },
5577
- hrmMembers: { type: "string", description: "\u53C2\u4F1A\u4EBA id\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u5FC5\u586B\uFF09" },
5578
- mtId: { ...SCHEMA_ID, description: "\u53D8\u66F4\u4F1A\u8BAE\u65F6\u6392\u9664\u81EA\u8EAB" },
5579
- workStartHour: { type: "number", description: "\u5DE5\u4F5C\u65F6\u6BB5\u8D77\u59CB\u5C0F\u65F6\uFF08\u9ED8\u8BA4 9\uFF09" },
5580
- workEndHour: { type: "number", description: "\u5DE5\u4F5C\u65F6\u6BB5\u7ED3\u675F\u5C0F\u65F6\uFF08\u9ED8\u8BA4 18\uFF09" },
5581
- stepMinutes: { type: "number", description: "\u5019\u9009\u6B65\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 30\uFF09" },
5582
- maxSlots: { type: "number", description: "\u8FD4\u56DE\u51E0\u4E2A\u65F6\u6BB5\uFF08\u9ED8\u8BA4 3\uFF0C\u6700\u591A 20\uFF09" },
5583
- maxDays: { type: "number", description: '\u5F80\u540E\u627E\u51E0\u5929\uFF08\u9ED8\u8BA4 1 = \u53EA\u627E\u5F53\u5929\uFF0C\u7B26\u5408"\u7EA6\u7684\u662F\u54EA\u5929\u5C31\u63A8\u8350\u54EA\u5929"\uFF09' },
5584
- includeSchedule: { type: "boolean", description: "\u662F\u5426\u540C\u65F6\u6838\u5BF9\u65E5\u7A0B\uFF08ESB\uFF09\uFF0C\u9ED8\u8BA4 true" }
5585
- },
5586
- required: ["rangeStart", "rangeEnd", "hrmMembers"]
5587
- },
5588
- handler: async (args, env) => {
5589
- const members = String(args.hrmMembers ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
5590
- if (members.length === 0) {
5591
- throw meetingValidationError("members_required", "hrmMembers \u4E0D\u80FD\u4E3A\u7A7A");
5592
- }
5593
- const result = await findCommonFreeSlots(env, {
5594
- rangeStart: String(args.rangeStart),
5595
- rangeEnd: String(args.rangeEnd),
5596
- durationMinutes: Number(args.durationMinutes ?? 60),
5597
- members,
5598
- ...args.mtId ? { excludeMtId: String(args.mtId) } : {},
5599
- ...args.workStartHour !== void 0 ? { workStartHour: Number(args.workStartHour) } : {},
5600
- ...args.workEndHour !== void 0 ? { workEndHour: Number(args.workEndHour) } : {},
5601
- ...args.stepMinutes !== void 0 ? { stepMinutes: Number(args.stepMinutes) } : {},
5602
- ...args.maxSlots !== void 0 ? { maxSlots: Number(args.maxSlots) } : {},
5603
- ...args.maxDays !== void 0 ? { maxDays: Number(args.maxDays) } : {},
5604
- ...args.includeSchedule !== void 0 ? { includeSchedule: args.includeSchedule !== false } : {}
5605
- });
5606
- return meetingSuccess("meeting.eb.conflict.availability", {
5607
- slots: result.slots,
5608
- idle: result.idle,
5609
- members,
5610
- scheduleItems: result.scheduleItems,
5611
- busyByMember: result.busyByMember,
5612
- ...result.blockingSummary ? { blockingSummary: result.blockingSummary } : {},
5613
- cost: result.cost
5614
- }, result.slots.length === 0 ? { warnings: [result.blockingSummary ?? "\u8303\u56F4\u5185\u6CA1\u6709\u627E\u5230\u6240\u6709\u4EBA\u90FD\u7A7A\u95F2\u7684\u65F6\u6BB5\uFF0C\u5EFA\u8BAE\u6362\u4E2A\u65E5\u671F\u6216\u7F29\u77ED\u65F6\u957F"] } : {});
5054
+ const keyword = textOf6(args.keyword).trim();
5055
+ const matched = keyword ? rows.filter((row) => row.label.includes(keyword) || row.dataKey.includes(keyword) || row.fieldId.includes(keyword)) : rows;
5056
+ return meetingSuccess("meeting.form.fields", {
5057
+ type,
5058
+ tag,
5059
+ objId: obj.objId,
5060
+ tableName: obj.tableName,
5061
+ total: matched.length,
5062
+ fields: matched,
5063
+ detailTables,
5064
+ hint: keyword && matched.length === 0 ? `\u6CA1\u6709\u5339\u914D\u300C${keyword}\u300D\u7684\u5B57\u6BB5 \u2014\u2014 \u8FD9\u5F20\u8868\u91CC\u786E\u5B9E\u6CA1\u6709\u8BE5\u5B57\u6BB5\uFF0C\u4E0D\u8981\u786C\u586B\uFF08\u786C\u586B\u4F1A\u88AB\u670D\u52A1\u7AEF\u9759\u9ED8\u4E22\u5F03\uFF09` : "\u5199\u4F1A\u8BAE\u5B57\u6BB5\u7528 dataKey\uFF08extraFields\uFF09\uFF1B\u5199\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u7528 label\uFF08\u4E2D\u6587\u540D\uFF09"
5065
+ }, { warnings: resolved.warnings });
5615
5066
  }
5616
5067
  };
5617
- var meetingEbConflictOperations = [ebConflictRoom, ebConflictMember, ebConflictAvailability];
5068
+ var meetingFormFieldOperations = [meetingFormFields];
5618
5069
 
5619
5070
  // src/shortcuts/meeting/operations/eb/decision.ts
5620
5071
  var CONTINUATION_TTL_SECONDS6 = 600;
5621
5072
  var DATE_PATTERN = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}$";
5622
5073
  function formatSecondNow() {
5623
5074
  const now = /* @__PURE__ */ new Date();
5624
- const pad2 = (value) => String(value).padStart(2, "0");
5625
- return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())} ${pad2(now.getHours())}:${pad2(now.getMinutes())}:${pad2(now.getSeconds())}`;
5075
+ const pad3 = (value) => String(value).padStart(2, "0");
5076
+ return `${now.getFullYear()}-${pad3(now.getMonth() + 1)}-${pad3(now.getDate())} ${pad3(now.getHours())}:${pad3(now.getMinutes())}:${pad3(now.getSeconds())}`;
5626
5077
  }
5627
5078
  var DECISION_DONE = "2";
5628
5079
  var MT_STATUS_OVER = "8";
5629
5080
  var CANCELLED_MARK_DELAY_MS = 800;
5630
5081
  async function isCancelledMeeting(env, mtId) {
5631
5082
  try {
5632
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
5083
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
5633
5084
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
5634
5085
  // withCount:false —— 这里只要一行状态,不必额外请求 count(少一次往返,也便于测试替身)
5635
5086
  { mt_id: mtId, pageNo: 1, pageSize: 1, withCount: false },
@@ -5848,8 +5299,8 @@ var decisionPublishApply = {
5848
5299
  );
5849
5300
  }
5850
5301
  if (cancelled) {
5851
- await new Promise((resolve5) => {
5852
- setTimeout(resolve5, CANCELLED_MARK_DELAY_MS);
5302
+ await new Promise((resolve6) => {
5303
+ setTimeout(resolve6, CANCELLED_MARK_DELAY_MS);
5853
5304
  });
5854
5305
  warnings.push(
5855
5306
  `\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`
@@ -6055,7 +5506,7 @@ function splitIds(value) {
6055
5506
  }
6056
5507
  return [...seen];
6057
5508
  }
6058
- function errorText2(error) {
5509
+ function errorText(error) {
6059
5510
  return error instanceof Error ? error.message : String(error);
6060
5511
  }
6061
5512
  async function writeOne(env, interfacePk, args) {
@@ -6074,7 +5525,7 @@ async function writeOne(env, interfacePk, args) {
6074
5525
  }
6075
5526
  return { ok: true };
6076
5527
  } catch (error) {
6077
- return { ok: false, error: `${interfacePk}: ${errorText2(error)}` };
5528
+ return { ok: false, error: `${interfacePk}: ${errorText(error)}` };
6078
5529
  }
6079
5530
  }
6080
5531
  var ebMeetingAssociation = async (ctx) => {
@@ -6151,6 +5602,10 @@ var ebMeetingAssociation = async (ctx) => {
6151
5602
  };
6152
5603
 
6153
5604
  // src/shortcuts/meeting/operations/eb/create-flow.ts
5605
+ import { existsSync as existsSync3 } from "node:fs";
5606
+ import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
5607
+ import { homedir } from "node:os";
5608
+ import { resolve as resolve5 } from "node:path";
6154
5609
  var FIELD_ALIASES = {
6155
5610
  mt_name: ["\u4F1A\u8BAE\u540D\u79F0", "\u4F1A\u8BAE\u4E3B\u9898", "\u4E3B\u9898"],
6156
5611
  begin_datetime: ["\u5F00\u59CB\u65F6\u95F4", "\u4F1A\u8BAE\u5F00\u59CB\u65F6\u95F4"],
@@ -6169,9 +5624,9 @@ function workflowEnv(env) {
6169
5624
  return env;
6170
5625
  }
6171
5626
  async function loadCreateForm(env, workflowId) {
6172
- const { createWorkflowHost } = await import("./host-OCH2BCCV.js");
5627
+ const { createWorkflowHost } = await import("./host-C6EL2RKL.js");
6173
5628
  const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
6174
- const { getWorkflowOperation } = await import("./registry-7C5UMIPL.js");
5629
+ const { getWorkflowOperation } = await import("./registry-TKX2E7C7.js");
6175
5630
  const wfEnv = {
6176
5631
  ...workflowEnv(env),
6177
5632
  host: createWorkflowHost(env.ctx),
@@ -6218,9 +5673,9 @@ async function resolveEmployeeNames(env, ids) {
6218
5673
  async function resolveRoomValue(env, input) {
6219
5674
  const text = String(input ?? "").trim();
6220
5675
  if (!text) return null;
6221
- const { loadRooms } = await import("./room-recommend-WRTHO6Y2.js");
5676
+ const { loadRooms: loadRooms2 } = await import("./room-recommend-XCWRMB5P.js");
6222
5677
  try {
6223
- const { rooms } = await loadRooms(env, {});
5678
+ const { rooms } = await loadRooms2(env, {});
6224
5679
  const byId = rooms.find((room) => room.id === text);
6225
5680
  if (byId) return { id: byId.id, name: byId.name };
6226
5681
  const byName = rooms.find((room) => room.name === text);
@@ -6229,7 +5684,7 @@ async function resolveRoomValue(env, input) {
6229
5684
  }
6230
5685
  if (/^\d+$/.test(text)) {
6231
5686
  try {
6232
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
5687
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6233
5688
  const detail = await getMeetingOperation2("meeting.eb.room.detail").handler({ id: text }, env);
6234
5689
  const main = detail?.data?.mainTable ?? detail?.data?.data?.mainTable ?? {};
6235
5690
  const name = String(main.room_name ?? "").trim();
@@ -6243,11 +5698,15 @@ async function resolveRoomValue(env, input) {
6243
5698
  async function shapeBrowserValues(env, values) {
6244
5699
  const notes = [];
6245
5700
  const shaped = { ...values };
5701
+ const readable = {};
6246
5702
  if (shaped.address !== void 0 && shaped.address !== "") {
6247
5703
  const room = await resolveRoomValue(env, String(shaped.address));
6248
5704
  if (room) {
6249
5705
  shaped.address = room;
5706
+ readable.address = room.name;
6250
5707
  notes.push(`\u4F1A\u8BAE\u5730\u70B9\u6309\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${room.name}(${room.id})`);
5708
+ } else {
5709
+ readable.address = String(shaped.address);
6251
5710
  }
6252
5711
  }
6253
5712
  const personFields = ["hrm_members", "caller", "contacter"];
@@ -6261,67 +5720,258 @@ async function shapeBrowserValues(env, values) {
6261
5720
  if (idPool.length > 0) {
6262
5721
  const names = await resolveEmployeeNames(env, idPool);
6263
5722
  const toObject = (id) => ({ id, name: names.get(id) ?? id });
5723
+ const toName = (id) => names.get(id) ?? id;
6264
5724
  if (shaped.hrm_members !== void 0 && shaped.hrm_members !== "") {
6265
5725
  const ids = String(shaped.hrm_members).split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6266
5726
  shaped.hrm_members = ids.map(toObject);
5727
+ readable.hrm_members = ids.map(toName).join("\u3001");
6267
5728
  notes.push(`\u53C2\u4F1A\u4EBA\u5458\u6309\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${ids.length} \u4EBA`);
6268
5729
  }
6269
5730
  if (shaped.caller !== void 0 && shaped.caller !== "") {
6270
5731
  const id = String(shaped.caller).trim();
6271
5732
  shaped.caller = toObject(id);
5733
+ readable.caller = toName(id);
6272
5734
  }
6273
5735
  if (shaped.contacter !== void 0 && shaped.contacter !== "") {
6274
5736
  const id = String(shaped.contacter).trim();
6275
5737
  shaped.contacter = toObject(id);
5738
+ readable.contacter = toName(id);
6276
5739
  }
6277
5740
  }
6278
- return { values: shaped, notes };
5741
+ for (const [key, raw] of Object.entries(values)) {
5742
+ if (readable[key] !== void 0) continue;
5743
+ if (raw === void 0 || raw === null || raw === "") continue;
5744
+ if (typeof raw === "object") continue;
5745
+ readable[key] = String(raw);
5746
+ }
5747
+ return { values: shaped, notes, readable };
6279
5748
  }
6280
- function mapFields(fields, values) {
5749
+ function normalizeFieldName(name) {
5750
+ return String(name ?? "").replace(/[((][^(())]*[))]/g, "").replace(/[\s\u3000]+/g, "").trim();
5751
+ }
5752
+ function mapFields(fields, values, preferred = {}) {
6281
5753
  const byName = new Map(fields.map((field) => [field.name.trim(), field]));
5754
+ const byId = new Map(fields.map((field) => [field.id, field]));
5755
+ const byNormalized = /* @__PURE__ */ new Map();
5756
+ for (const field of fields) {
5757
+ const key = normalizeFieldName(field.name);
5758
+ if (key && !byNormalized.has(key)) byNormalized.set(key, field);
5759
+ }
6282
5760
  const main = {};
6283
5761
  const mapped = {};
6284
5762
  const unmapped = [];
5763
+ const resolved = {};
5764
+ const findField = (aliases) => {
5765
+ for (const name of aliases) {
5766
+ const field = byName.get(name);
5767
+ if (field) return field;
5768
+ }
5769
+ for (const name of aliases) {
5770
+ const field = byNormalized.get(normalizeFieldName(name));
5771
+ if (field) return field;
5772
+ }
5773
+ for (const name of aliases) {
5774
+ const needle = normalizeFieldName(name);
5775
+ if (needle.length < 2) continue;
5776
+ for (const [key, field] of byNormalized) {
5777
+ if (key.includes(needle)) return field;
5778
+ }
5779
+ }
5780
+ return void 0;
5781
+ };
6285
5782
  for (const [key, raw] of Object.entries(values)) {
6286
5783
  if (raw === void 0 || raw === null || raw === "") continue;
6287
- const aliases = FIELD_ALIASES[key] ?? [];
6288
- const hit = aliases.map((name) => byName.get(name)).find((field) => field !== void 0);
5784
+ const aliases = FIELD_ALIASES[key] ?? [key];
5785
+ const prefId = preferred[key];
5786
+ const hit = (prefId ? byId.get(prefId) : void 0) ?? findField(aliases);
6289
5787
  if (!hit) {
6290
5788
  unmapped.push(key);
6291
5789
  continue;
6292
5790
  }
6293
5791
  main[hit.id] = raw;
6294
5792
  mapped[key] = `${hit.name}(${hit.id})`;
5793
+ resolved[key] = hit.id;
5794
+ }
5795
+ return { main, mapped, unmapped, resolved };
5796
+ }
5797
+ function flowFieldCacheDir(env) {
5798
+ const configured = env?.ctx?.config?.path?.();
5799
+ const root = configured ? resolve5(String(configured), "..") : process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve5(homedir(), ".weaver-work-cli");
5800
+ return resolve5(root, "meeting", "cache");
5801
+ }
5802
+ function flowFieldCacheFile(env, workflowId) {
5803
+ return resolve5(flowFieldCacheDir(env), `flow-fields-${workflowId}.json`);
5804
+ }
5805
+ async function readFlowFieldMap(env, workflowId) {
5806
+ try {
5807
+ const file = flowFieldCacheFile(env, workflowId);
5808
+ if (!existsSync3(file)) return {};
5809
+ const parsed = JSON.parse(await readFile4(file, "utf8"));
5810
+ return parsed && typeof parsed.mapping === "object" && parsed.mapping ? parsed.mapping : {};
5811
+ } catch {
5812
+ return {};
5813
+ }
5814
+ }
5815
+ async function writeFlowFieldMap(env, workflowId, workflowName, mapping) {
5816
+ if (Object.keys(mapping).length === 0) return;
5817
+ try {
5818
+ const file = flowFieldCacheFile(env, workflowId);
5819
+ await mkdir4(resolve5(file, ".."), { recursive: true });
5820
+ const cache = {
5821
+ workflowId,
5822
+ ...workflowName ? { workflowName } : {},
5823
+ savedAt: (/* @__PURE__ */ new Date()).toISOString(),
5824
+ mapping
5825
+ };
5826
+ await writeFile4(file, JSON.stringify(cache, null, 2), "utf8");
5827
+ } catch {
5828
+ }
5829
+ }
5830
+ function normalizeWorkflowIds(raw) {
5831
+ if (raw === void 0 || raw === null) return [];
5832
+ const list = Array.isArray(raw) ? raw : [raw];
5833
+ const ids = [];
5834
+ for (const item of list) {
5835
+ for (const piece of String(item ?? "").split(/[,;,;\s]+/)) {
5836
+ const term = piece.trim();
5837
+ if (!term) continue;
5838
+ const matched = term.match(/[((](\d{6,})[))]$/);
5839
+ const id = matched ? matched[1] : term;
5840
+ if (!ids.includes(id)) ids.push(id);
5841
+ }
6295
5842
  }
6296
- return { main, mapped, unmapped };
5843
+ return ids;
5844
+ }
5845
+ var FIXED_FLOW_IDS = ["1325677244111462606", "1326190634427154474"];
5846
+ var FIXED_FLOW_PROFILES = [
5847
+ {
5848
+ host: "www.e-cology.com.cn",
5849
+ tenantKey: "t7akvdnf84",
5850
+ label: "\u6CDB\u5FAE\u751F\u4EA7\uFF08\u6CDB\u5FAE\u7F51\u7EDC\uFF09",
5851
+ ids: [...FIXED_FLOW_IDS]
5852
+ }
5853
+ ];
5854
+ function fixedFlowFlagOn() {
5855
+ const flag = String(process.env.WEAVER_MEETING_FIXED_FLOW ?? "1").trim().toLowerCase();
5856
+ return !(flag === "0" || flag === "false" || flag === "off");
5857
+ }
5858
+ function fixedFlowOverride() {
5859
+ const override = String(process.env.WEAVER_MEETING_FIXED_FLOW_IDS ?? "").trim();
5860
+ if (!override) return [];
5861
+ return override.split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
5862
+ }
5863
+ async function fixedFlowIdsForEnv(env) {
5864
+ if (!fixedFlowFlagOn()) return { ids: [] };
5865
+ const override = fixedFlowOverride();
5866
+ if (override.length > 0) return { ids: override, label: "\u73AF\u5883\u53D8\u91CF\u6307\u5B9A" };
5867
+ let baseUrl = "";
5868
+ let tenantKey = "";
5869
+ try {
5870
+ const session = await env?.host?.getSession?.();
5871
+ baseUrl = String(session?.baseUrl ?? "");
5872
+ tenantKey = String(session?.tenantKey ?? session?.tenantId ?? "");
5873
+ } catch {
5874
+ }
5875
+ if (!baseUrl) return { ids: [...FIXED_FLOW_IDS], label: "\u9ED8\u8BA4\u56FA\u5316\u914D\u7F6E\uFF08\u672A\u53D6\u5230\u767B\u5F55\u73AF\u5883\uFF09" };
5876
+ const host = baseUrl.replace(/^https?:\/\//i, "").replace(/\/.*$/, "").toLowerCase();
5877
+ const hit = FIXED_FLOW_PROFILES.find((profile) => profile.host === host && (!profile.tenantKey || !tenantKey || profile.tenantKey === tenantKey));
5878
+ return hit ? { ids: [...hit.ids], label: hit.label } : { ids: [] };
5879
+ }
5880
+ function shouldAutoPickFlow(args) {
5881
+ if (args.flowChoice === "auto") return true;
5882
+ return String(process.env.WEAVER_MEETING_FLOW_CHOICE ?? "").trim().toLowerCase() === "auto";
6297
5883
  }
6298
5884
  async function resolveWorkflowId(env, args) {
6299
- const explicit = String(args.workflowId ?? "").trim();
6300
- if (explicit) return { workflowId: explicit, candidates: [explicit] };
5885
+ const explicitList = normalizeWorkflowIds(args.workflowId);
5886
+ if (explicitList.length > 0) {
5887
+ return {
5888
+ workflowId: explicitList.length === 1 ? explicitList[0] : "",
5889
+ candidates: explicitList,
5890
+ source: "argument"
5891
+ };
5892
+ }
5893
+ const fixed = await fixedFlowIdsForEnv(env);
5894
+ if (fixed.ids.length > 0) {
5895
+ return {
5896
+ workflowId: fixed.ids.length === 1 ? fixed.ids[0] : "",
5897
+ candidates: fixed.ids,
5898
+ source: "fixed",
5899
+ ...fixed.label ? { label: fixed.label } : {}
5900
+ };
5901
+ }
6301
5902
  const settings = await fetchEbAppSettings(env, "meeting.eb.meeting.create.flow.prepare");
6302
5903
  const candidates = String(settings.mtNewWf ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6303
5904
  if (candidates.length === 0) {
6304
5905
  throw meetingValidationError(
6305
5906
  "flow_not_configured",
6306
- "\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\u65E0\u6CD5\u8D70\u6D41\u7A0B\u5EFA\u4F1A\uFF1B\u8BF7\u7BA1\u7406\u5458\u5728\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\u91CC\u914D\u7F6E\uFF0C\u6216\u5173\u95ED\u300C\u53EA\u5141\u8BB8\u901A\u8FC7\u6D41\u7A0B\u65B0\u5EFA\u4F1A\u8BAE\u300D"
5907
+ "\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"
6307
5908
  );
6308
5909
  }
6309
- return { workflowId: candidates.length === 1 ? candidates[0] : "", candidates };
5910
+ return { workflowId: candidates.length === 1 ? candidates[0] : "", candidates, source: "settings" };
5911
+ }
5912
+ function pad2(value) {
5913
+ return String(value).padStart(2, "0");
5914
+ }
5915
+ function tomorrowIso() {
5916
+ const date = new Date(Date.now() + 24 * 60 * 60 * 1e3);
5917
+ return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
5918
+ }
5919
+ function formatMinute(date) {
5920
+ return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`;
5921
+ }
5922
+ async function probeWorkflowCandidates(env, ids) {
5923
+ const probed = await Promise.all(ids.map(async (id) => {
5924
+ try {
5925
+ const probeForm = await loadCreateForm(env, id);
5926
+ return {
5927
+ id,
5928
+ probeForm,
5929
+ probe: {
5930
+ workflowId: id,
5931
+ ...probeForm.workflowName ? { name: probeForm.workflowName } : {},
5932
+ launchable: true
5933
+ }
5934
+ };
5935
+ } catch (error) {
5936
+ return {
5937
+ id,
5938
+ probeForm: null,
5939
+ probe: {
5940
+ workflowId: id,
5941
+ launchable: false,
5942
+ reason: String(error?.message ?? error).slice(0, 160)
5943
+ }
5944
+ };
5945
+ }
5946
+ }));
5947
+ const probes = [];
5948
+ const loadedForms = /* @__PURE__ */ new Map();
5949
+ for (const item of probed) {
5950
+ if (item.probeForm) loadedForms.set(item.id, item.probeForm);
5951
+ probes.push(item.probe);
5952
+ }
5953
+ return { probes, loadedForms };
6310
5954
  }
6311
5955
  var ebMeetingCreateFlowPrepare = {
6312
5956
  name: "meeting.eb.meeting.create.flow.prepare",
6313
5957
  resource: "eb",
6314
5958
  method: "meeting.eb.meeting.create.flow.prepare",
6315
5959
  action: "meeting.eb.meeting.create.flow.prepare",
6316
- summary: "\u6D41\u7A0B\u5EFA\u4F1A\uFF08\u51C6\u5907\uFF09\uFF1A\u6309\u5E94\u7528\u8BBE\u7F6E mt_new_wf \u8F7D\u5165\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\uFF0C\u628A\u4F1A\u8BAE\u5B57\u6BB5\u6309\u4E2D\u6587\u540D\u6620\u5C04\u6210\u8868\u5355\u503C\uFF0C\u8FD4\u56DE\u9884\u89C8\u4E0E\u786E\u8BA4\u7968\u636E\uFF08\u4E0D\u63D0\u4EA4\uFF09",
5960
+ 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",
6317
5961
  capability: "eb.meeting",
6318
5962
  risk: "read-before-write",
6319
5963
  requiresConfirmation: true,
6320
5964
  inputSchema: schemaOf(
6321
5965
  {
6322
5966
  mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
6323
- begin_datetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
6324
- end_datetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5967
+ begin_datetime: {
5968
+ ...SCHEMA_DATETIME_MINUTE,
5969
+ 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"
5970
+ },
5971
+ end_datetime: {
5972
+ ...SCHEMA_DATETIME_MINUTE,
5973
+ 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"
5974
+ },
6325
5975
  mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
6326
5976
  address: { type: "string", description: "\u4F1A\u8BAE\u5BA4\uFF08\u540D\u79F0\u6216 id\uFF0C\u6309\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u8981\u6C42\uFF09" },
6327
5977
  customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
@@ -6329,103 +5979,172 @@ var ebMeetingCreateFlowPrepare = {
6329
5979
  total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
6330
5980
  caller: { type: "string", description: "\u53EC\u96C6\u4EBA" },
6331
5981
  contacter: { type: "string", description: "\u8054\u7CFB\u4EBA" },
5982
+ mt_type: {
5983
+ type: "string",
5984
+ 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"
5985
+ },
6332
5986
  other_remark: { type: "string", description: "\u5907\u6CE8" },
6333
- workflowId: { type: "string", description: "\u6307\u5B9A\u5EFA\u4F1A\u6D41\u7A0B id\uFF08\u9ED8\u8BA4\u53D6\u5E94\u7528\u8BBE\u7F6E mt_new_wf \u7684\u7B2C\u4E00\u4E2A\uFF09" },
5987
+ workflowId: {
5988
+ oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
5989
+ 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"
5990
+ },
6334
5991
  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" },
6335
- 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" }
5992
+ 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" },
5993
+ timeConfirmed: {
5994
+ type: "boolean",
5995
+ 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'
5996
+ },
5997
+ roomConfirmed: {
5998
+ type: "boolean",
5999
+ 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'
6000
+ },
6001
+ extraFields: {
6002
+ type: "object",
6003
+ 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'
6004
+ },
6005
+ dateFrom: {
6006
+ type: "string",
6007
+ 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"
6008
+ },
6009
+ durationMinutes: {
6010
+ type: "number",
6011
+ 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"
6012
+ },
6013
+ workStartHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u65E9\u5C0F\u65F6\uFF08\u9ED8\u8BA4 9\uFF09" },
6014
+ workEndHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u665A\u5C0F\u65F6\uFF08\u9ED8\u8BA4 18\uFF09" },
6015
+ fieldValues: {
6016
+ type: "object",
6017
+ additionalProperties: true,
6018
+ 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'
6019
+ },
6020
+ flowChoice: {
6021
+ type: "string",
6022
+ enum: ["auto", "ask"],
6023
+ 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\u53EA\u6709 1 \u4E2A\u6709\u6743\u9650\u65F6\u4E0D\u53D7\u6B64\u53C2\u6570\u5F71\u54CD\uFF0CCLI \u76F4\u63A5\u53D1\u8D77"
6024
+ }
6336
6025
  },
6337
- { required: ["mt_name", "begin_datetime", "end_datetime"] }
6026
+ { required: ["mt_name"] }
6338
6027
  ),
6339
6028
  handler: async (args, env) => {
6340
- const resolved = await resolveWorkflowId(env, args);
6341
- const candidates = resolved.candidates;
6342
- let workflowId = resolved.workflowId;
6343
- const probes = [];
6344
- const loadedForms = /* @__PURE__ */ new Map();
6345
- if (!workflowId && candidates.length > 1) {
6346
- const probed = await Promise.all(candidates.map(async (id) => {
6347
- try {
6348
- const probeForm = await loadCreateForm(env, id);
6349
- return {
6350
- id,
6351
- probeForm,
6352
- probe: {
6353
- workflowId: id,
6354
- ...probeForm.workflowName ? { name: probeForm.workflowName } : {},
6355
- launchable: true
6356
- }
6357
- };
6358
- } catch (error) {
6359
- return {
6360
- id,
6361
- probeForm: null,
6362
- probe: {
6363
- workflowId: id,
6364
- launchable: false,
6365
- reason: String(error?.message ?? error).slice(0, 160)
6366
- }
6367
- };
6368
- }
6369
- }));
6370
- for (const item of probed) {
6371
- if (item.probeForm) loadedForms.set(item.id, item.probeForm);
6372
- probes.push(item.probe);
6373
- }
6374
- const launchable = probes.filter((probe) => probe.launchable);
6375
- if (launchable.length === 0) {
6376
- throw meetingValidationError(
6377
- "flow_not_launchable",
6378
- `\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E\u4E86 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u4F46\u5F53\u524D\u8D26\u53F7\u4E00\u4E2A\u90FD\u53D1\u8D77\u4E0D\u4E86\uFF08\u65E0\u53D1\u8D77\u6743\u9650\u6216\u6D41\u7A0B\u5DF2\u505C\u7528\uFF09\uFF1A` + probes.map((probe) => `${probe.workflowId}\uFF08${probe.reason ?? "\u4E0D\u53EF\u53D1\u8D77"}\uFF09`).join("\uFF1B"),
6379
- { probes }
6380
- );
6381
- }
6382
- if (launchable.length > 1) {
6383
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
6384
- status: "NEEDS_SELECTION",
6385
- message: `\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77 ${launchable.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u8BF7\u8BA9\u7528\u6237\u9009\u62E9\u8981\u89E6\u53D1\u54EA\u4E00\u4E2A`,
6386
- options: launchable.map((probe, index) => ({
6387
- key: `W${index + 1}`,
6388
- label: probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId,
6389
- value: { workflowId: probe.workflowId },
6390
- reason: "\u5F53\u524D\u8D26\u53F7\u6709\u53D1\u8D77\u6743\u9650"
6391
- })),
6392
- probes
6393
- }, {
6394
- warnings: [
6395
- `\u68C0\u6D4B\u5230 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5176\u4E2D ${launchable.length} \u4E2A\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77\uFF1B\u8BF7\u628A\u8FD9\u51E0\u4E2A\u6D41\u7A0B\u505A\u6210\u9009\u9879\u8BA9\u7528\u6237\u6311\u4E00\u4E2A\uFF0C\u9009\u5B9A\u540E\u5E26 workflowId \u91CD\u65B0 prepare\u3002`,
6396
- ...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`)
6397
- ]
6398
- });
6399
- }
6400
- workflowId = launchable[0].workflowId;
6401
- }
6402
- const form = loadedForms.get(workflowId) ?? await loadCreateForm(env, workflowId);
6403
- if (!form.continuation) {
6404
- throw meetingValidationError("flow_context_missing", "\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u6CA1\u6709\u8FD4\u56DE continuation\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u63D0\u4EA4");
6405
- }
6029
+ let workflowId = "";
6030
+ let flowPickNote = null;
6406
6031
  const decisions = {};
6407
6032
  const enrich = args.enrich !== false;
6408
6033
  const beginText = String(args.begin_datetime ?? "").trim();
6409
- const endText = String(args.end_datetime ?? "").trim();
6410
- const memberIds = String(args.hrm_members ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6034
+ let endText = String(args.end_datetime ?? "").trim();
6035
+ const rawMembers = String(args.hrm_members ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6036
+ const nameLike = rawMembers.filter((item) => !/^\d+$/.test(item));
6037
+ const nameToId = nameLike.length > 0 ? await import("./schedule-IVBICP32.js").then((m) => m.resolveMemberIdsByName(env, nameLike)).catch(() => /* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
6038
+ const memberIds = rawMembers.map((item) => nameToId.get(item) ?? item);
6039
+ const timeConfirmed = args.timeConfirmed === true;
6040
+ const callerWorkflowId = String(args.workflowId ?? "").trim();
6041
+ 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`;
6042
+ const beginHasTime = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(beginText);
6043
+ const endHasTime = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(endText);
6044
+ if (beginHasTime && !endHasTime) {
6045
+ const duration = Number(args.durationMinutes) > 0 ? Math.round(Number(args.durationMinutes)) : 60;
6046
+ const startMs = Date.parse(beginText.slice(0, 16).replace(" ", "T"));
6047
+ if (Number.isFinite(startMs)) endText = formatMinute(new Date(startMs + duration * 6e4));
6048
+ }
6049
+ if (!beginHasTime || !timeConfirmed) {
6050
+ const day2 = /^\d{4}-\d{2}-\d{2}/.test(beginText) ? beginText.slice(0, 10) : String(args.dateFrom ?? "").trim().slice(0, 10) || tomorrowIso();
6051
+ const duration = Number(args.durationMinutes) > 0 ? Math.round(Number(args.durationMinutes)) : 60;
6052
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6053
+ const suggested = await getMeetingOperation2("meeting.eb.meeting.create.suggest").handler(
6054
+ {
6055
+ dateFrom: day2,
6056
+ durationMinutes: duration,
6057
+ hrm_members: memberIds.join(","),
6058
+ maxSlots: 3,
6059
+ topN: 3,
6060
+ ...Number(args.total_member) > 0 ? { memberCount: Number(args.total_member) } : {},
6061
+ ...args.workStartHour !== void 0 ? { workStartHour: Number(args.workStartHour) } : {},
6062
+ ...args.workEndHour !== void 0 ? { workEndHour: Number(args.workEndHour) } : {}
6063
+ },
6064
+ env
6065
+ ).catch((error) => ({ data: { slots: [] }, slotError: String(error?.message ?? error).slice(0, 160) }));
6066
+ const slotOptions2 = suggested?.data?.slots ?? [];
6067
+ const slotWarnings = [
6068
+ ...suggested?.warnings ?? [],
6069
+ ...suggested?.slotError ? [`\u65F6\u6BB5\u63A8\u8350\u672A\u8DD1\u6210\u529F\uFF1A${suggested.slotError}`] : [],
6070
+ ...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'] : []
6071
+ ];
6072
+ return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
6073
+ status: "NEEDS_SELECTION",
6074
+ selectionType: "slot",
6075
+ ui: { component: "choice", multiple: false, recommendedKey: "T1" },
6076
+ 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`,
6077
+ options: slotOptions2.map((slot, index) => ({
6078
+ key: `T${index + 1}`,
6079
+ label: String(slot.label ?? ""),
6080
+ // ⛔ 时间不在 slot 顶层,而在 slot.value 里(suggest 的返回结构)—— 取错会让调用方
6081
+ // 拿不到 begin/end,只能再问用户一次时间(2026-10-30 冒烟实测踩到)。
6082
+ // `timeConfirmed: true` 在这里是**关键**:用户点选后 value 原样回传,下一轮才被认作"已确认";
6083
+ // agent 自己编的时间不带这个标记,就永远停在选项这一步。
6084
+ value: {
6085
+ begin_datetime: String(slot.value?.begin ?? slot.begin ?? "").trim(),
6086
+ end_datetime: String(slot.value?.end ?? slot.end ?? "").trim(),
6087
+ address: slot.value?.address ?? null,
6088
+ timeConfirmed: true
6089
+ },
6090
+ reason: String(slot.reason ?? ""),
6091
+ rooms: slot.rooms ?? []
6092
+ })),
6093
+ day: day2,
6094
+ durationMinutes: duration,
6095
+ memberIds,
6096
+ // ⛔ 这里**不能**出现 workflowId:流程确认在四要素之后(2026-10-30 顺序调整)。
6097
+ // 返回 workflowId 会让 agent 误以为"流程已定",于是在回复里先讲流程、再问时间。
6098
+ workflowPending: true,
6099
+ 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"
6100
+ }, {
6101
+ warnings: [
6102
+ `${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`,
6103
+ ...slotWarnings,
6104
+ ...earlyWorkflowNote ? [earlyWorkflowNote] : []
6105
+ ]
6106
+ });
6107
+ }
6411
6108
  let addressInput = args.address;
6109
+ const hadAddressInput = String(args.address ?? "").trim() !== "";
6412
6110
  const day = beginText.slice(0, 10);
6413
6111
  const durationMinutes = beginText && endText ? Math.max(15, Math.round((Date.parse(endText.replace(" ", "T")) - Date.parse(beginText.replace(" ", "T"))) / 6e4) || 60) : 60;
6414
6112
  const timings = {};
6415
6113
  const startedAt = Date.now();
6416
- const roomTask = enrich && !addressInput && beginText && endText ? recommendRooms(env, {
6114
+ const enrichFailures = [];
6115
+ const noteFailure = (label) => (error) => {
6116
+ enrichFailures.push(`${label}\u672A\u5B8C\u6210\uFF1A${String(error?.message ?? error).slice(0, 120)}`);
6117
+ return null;
6118
+ };
6119
+ const declaredTotal = Number(args.total_member) > 0 ? Number(args.total_member) : null;
6120
+ const callerToken = String(args.caller ?? "").trim();
6121
+ const callerInMembers = callerToken !== "" && (rawMembers.includes(callerToken) || memberIds.includes(callerToken));
6122
+ const roomMemberCount = declaredTotal ?? (memberIds.length > 0 ? memberIds.length + (callerInMembers ? 0 : 1) : void 0);
6123
+ const roomTask = enrich && beginText && endText ? recommendRooms(env, {
6417
6124
  beginDatetime: beginText,
6418
6125
  endDatetime: endText,
6419
- ...memberIds.length > 0 ? { memberCount: memberIds.length } : {},
6126
+ ...roomMemberCount ? { memberCount: roomMemberCount } : {},
6127
+ // 建会是"要下单"的场景:宁可多一次请求也必须拿最新台账(24h 缓存会让刚导入的会议室看不到)。
6128
+ refreshRooms: true,
6420
6129
  topN: 3
6421
- }).catch(() => null) : Promise.resolve(null);
6130
+ }).catch(noteFailure("\u4F1A\u8BAE\u5BA4\u63A8\u8350")) : Promise.resolve(null);
6131
+ const addressId = String(addressInput ?? "").trim();
6132
+ const addressIsRoomId = /^\d+$/.test(addressId);
6133
+ const roomConfirmed = args.roomConfirmed === true;
6134
+ const roomConflictTask = enrich && beginText && endText && addressIsRoomId ? (async () => {
6135
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6136
+ return getMeetingOperation2("meeting.eb.conflict.room").handler(
6137
+ { beginDatetime: beginText, endDatetime: endText, address: addressId },
6138
+ env
6139
+ );
6140
+ })().catch(noteFailure("\u4F1A\u8BAE\u5BA4**\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
6422
6141
  const conflictTask = enrich && beginText && endText && memberIds.length > 0 ? (async () => {
6423
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
6142
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6424
6143
  return getMeetingOperation2("meeting.eb.conflict.member").handler(
6425
6144
  { beginDatetime: beginText, endDatetime: endText, hrmMembers: memberIds.join(",") },
6426
6145
  env
6427
6146
  );
6428
- })().catch(() => null) : Promise.resolve(null);
6147
+ })().catch(noteFailure("\u53C2\u4F1A\u4EBA**\u4F1A\u8BAE\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
6429
6148
  const availabilityTask = enrich && beginText && endText && memberIds.length > 0 ? findCommonFreeSlots(env, {
6430
6149
  rangeStart: `${day} 00:00`,
6431
6150
  rangeEnd: `${day} 23:59`,
@@ -6434,16 +6153,75 @@ var ebMeetingCreateFlowPrepare = {
6434
6153
  maxSlots: 3,
6435
6154
  maxDays: 1,
6436
6155
  includeSchedule: true
6437
- }).catch(() => null) : Promise.resolve(null);
6438
- const [roomRec, memberConflict, free] = await Promise.all([roomTask, conflictTask, availabilityTask]);
6156
+ }).catch(noteFailure("\u53C2\u4F1A\u4EBA**\u65E5\u7A0B\u7A7A\u95F2**\u68C0\u6D4B")) : Promise.resolve(null);
6157
+ const [roomRec, memberConflict, free, roomConflict] = await Promise.all([
6158
+ roomTask,
6159
+ conflictTask,
6160
+ availabilityTask,
6161
+ roomConflictTask
6162
+ ]);
6439
6163
  timings.parallelMs = Date.now() - startedAt;
6164
+ const memberConflicts = memberConflict?.data?.conflicts ?? [];
6165
+ if (memberConflicts.length > 0) decisions.memberConflicts = memberConflicts;
6166
+ const freeSlots = free?.slots ?? [];
6167
+ if (free) {
6168
+ decisions.scheduleItems = free.scheduleItems;
6169
+ decisions.availabilityCost = free.cost;
6170
+ if (freeSlots.length > 0) {
6171
+ decisions.suggestedSlots = freeSlots;
6172
+ decisions.slotOptions = freeSlots.map((slot, index) => ({
6173
+ key: `T${index + 1}`,
6174
+ label: `${slot.begin.slice(11)}~${slot.end.slice(11)}\uFF08${day}\uFF09 \xB7 \u5168\u90E8\u53C2\u4F1A\u4EBA\u7A7A\u95F2`,
6175
+ value: { begin: slot.begin, end: slot.end },
6176
+ 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"
6177
+ }));
6178
+ } else if (free.blockingSummary) {
6179
+ decisions.dayBlocked = { day, summary: free.blockingSummary };
6180
+ }
6181
+ }
6182
+ const conflictBrief = {
6183
+ memberConflicts,
6184
+ suggestedSlots: freeSlots,
6185
+ ...enrichFailures.length > 0 ? { enrichFailures } : {}
6186
+ };
6187
+ const failureWarnings = enrichFailures.map(
6188
+ (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"`
6189
+ );
6190
+ const roomOptions = (roomRec?.candidates ?? []).map((candidate, index) => ({
6191
+ key: `R${index + 1}`,
6192
+ label: `${candidate.name}${candidate.capacity.max > 0 ? `\uFF08\u53EF\u5BB9 ${candidate.capacity.max} \u4EBA\uFF09` : ""}${index === 0 ? " \xB7 \u63A8\u8350" : ""}`,
6193
+ // roomConfirmed: true = 用户点选该选项即代表"确认用这间",原样回传后下一轮才被认。
6194
+ value: { id: candidate.id, name: candidate.name, roomConfirmed: true },
6195
+ reason: candidate.reasons.join("\uFF1B")
6196
+ }));
6197
+ const roomConflictData = roomConflict?.data;
6198
+ if (addressInput && roomConfirmed && roomConflictData?.hasConflict === true) {
6199
+ const busy = Array.isArray(roomConflictData.conflicts) ? roomConflictData.conflicts : [];
6200
+ decisions.roomConflict = {
6201
+ address: addressId,
6202
+ hasConflict: true,
6203
+ conflicts: busy,
6204
+ verdict: roomConflictData.verdict ?? "conflict"
6205
+ };
6206
+ if (roomOptions.length > 0) decisions.roomOptions = roomOptions;
6207
+ return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
6208
+ status: "NEEDS_SELECTION",
6209
+ selectionType: "room_conflict",
6210
+ ui: { component: "choice", multiple: false, recommendedKey: "R1" },
6211
+ message: `\u4F60\u6307\u5B9A\u7684\u4F1A\u8BAE\u5BA4\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`,
6212
+ workflowPending: true,
6213
+ options: roomOptions,
6214
+ recommended: roomOptions[0]?.value ?? null,
6215
+ conflicts: busy,
6216
+ 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"
6217
+ }, {
6218
+ warnings: [
6219
+ `\u4F1A\u8BAE\u5BA4 ${addressId} \u5728\u8BE5\u65F6\u6BB5\u5DF2\u6709 ${busy.length} \u6761\u5360\u7528\uFF0C\u5DF2\u62E6\u4E0B\u672A\u63D0\u4EA4\u3002`,
6220
+ 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"
6221
+ ]
6222
+ });
6223
+ }
6440
6224
  if (roomRec) {
6441
- const roomOptions = roomRec.candidates.map((candidate, index) => ({
6442
- key: `R${index + 1}`,
6443
- label: `${candidate.name}${candidate.capacity.max > 0 ? `\uFF08\u53EF\u5BB9 ${candidate.capacity.max} \u4EBA\uFF09` : ""}${index === 0 ? " \xB7 \u63A8\u8350" : ""}`,
6444
- value: { id: candidate.id, name: candidate.name },
6445
- reason: candidate.reasons.join("\uFF1B")
6446
- }));
6447
6225
  decisions.roomOptions = roomOptions;
6448
6226
  decisions.autoRoom = {
6449
6227
  picked: roomRec.best ? { id: roomRec.best.id, name: roomRec.best.name, score: roomRec.best.score, reasons: roomRec.best.reasons } : null,
@@ -6451,18 +6229,38 @@ var ebMeetingCreateFlowPrepare = {
6451
6229
  meta: roomRec.meta
6452
6230
  };
6453
6231
  const autoRoom = args.autoRoom === true;
6454
- if (!addressInput && !autoRoom && roomOptions.length > 0 && args.allowNoRoom !== true) {
6232
+ const needRoomPick = !addressInput || !roomConfirmed;
6233
+ let pickOptions = roomOptions;
6234
+ if (addressInput && !roomConfirmed) {
6235
+ const hit = roomOptions.find((item) => String(item.value?.id) === addressId);
6236
+ const specified = hit ? { ...hit, label: `${hit.label}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`, value: { ...hit.value, roomConfirmed: true } } : {
6237
+ key: "R0",
6238
+ label: `${addressInput}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`,
6239
+ value: { ...addressIsRoomId ? { id: addressId } : {}, name: addressInput, roomConfirmed: true },
6240
+ reason: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u672A\u63D0\u4EA4\u3001\u672A\u786E\u8BA4"
6241
+ };
6242
+ pickOptions = [specified, ...roomOptions.filter((item) => String(item.value?.id) !== addressId)].map((item, index) => ({ ...item, key: `R${index + 1}` }));
6243
+ }
6244
+ if (needRoomPick && !autoRoom && pickOptions.length > 0 && args.allowNoRoom !== true) {
6455
6245
  return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
6456
6246
  status: "NEEDS_SELECTION",
6457
6247
  selectionType: "room",
6458
- message: `\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u4ECE ${roomOptions.length} \u4E2A\u5019\u9009\u91CC\u9009\u62E9\uFF08\u5DF2\u6309\u4EBA\u6570/\u5E38\u7528/\u65F6\u6BB5\u5360\u7528\u6392\u5E8F\uFF09`,
6459
- options: roomOptions,
6460
- recommended: roomOptions[0]?.value ?? null,
6461
- hint: "\u9009\u5B9A\u540E\u628A value.id \u4F5C\u4E3A address \u91CD\u65B0\u8C03\u7528\uFF08quick \u6216 prepare\uFF09\uFF1B\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\u8BF7\u4F20 allowNoRoom: true"
6248
+ ui: { component: "choice", multiple: false, recommendedKey: "R1" },
6249
+ message: addressInput ? `\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\u300C${addressInput}\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`,
6250
+ // 固化自动选的流程要带出来:调用方下一轮带 address 重调时不用再猜用的是哪条流程。
6251
+ workflowPending: true,
6252
+ options: pickOptions,
6253
+ recommended: pickOptions[0]?.value ?? null,
6254
+ 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",
6255
+ ...conflictBrief
6462
6256
  }, {
6463
6257
  warnings: [
6464
- "\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF1A\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\uFF0C\u4E5F\u6CA1\u6709\u66FF\u7528\u6237\u6311\u623F\u95F4\u3002",
6465
- "\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"
6258
+ addressInput ? `\u4F1A\u8BAE\u5BA4\u300C${addressInput}\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",
6259
+ "\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",
6260
+ ...earlyWorkflowNote ? [earlyWorkflowNote] : [],
6261
+ ...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`] : [],
6262
+ ...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")}`] : [],
6263
+ ...failureWarnings
6466
6264
  ]
6467
6265
  });
6468
6266
  }
@@ -6471,23 +6269,157 @@ var ebMeetingCreateFlowPrepare = {
6471
6269
  addressInput = roomRec.best.id;
6472
6270
  }
6473
6271
  }
6474
- const conflicts = memberConflict?.data?.conflicts ?? [];
6475
- if (conflicts.length > 0) decisions.memberConflicts = conflicts;
6476
- if (free) {
6477
- decisions.scheduleItems = free.scheduleItems;
6478
- decisions.availabilityCost = free.cost;
6479
- if (free.slots.length > 0) {
6480
- decisions.suggestedSlots = free.slots;
6481
- decisions.slotOptions = free.slots.map((slot, index) => ({
6482
- key: `T${index + 1}`,
6483
- label: `${slot.begin.slice(11)}~${slot.end.slice(11)}\uFF08${day}\uFF09 \xB7 \u5168\u90E8\u53C2\u4F1A\u4EBA\u7A7A\u95F2`,
6484
- value: { begin: slot.begin, end: slot.end },
6485
- 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"
6486
- }));
6487
- } else if (free.blockingSummary) {
6488
- decisions.dayBlocked = { day, summary: free.blockingSummary };
6272
+ if (enrich && !addressInput && args.allowNoRoom !== true) {
6273
+ decisions.roomUnavailable = {
6274
+ 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",
6275
+ meta: roomRec?.meta ?? null
6276
+ };
6277
+ return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
6278
+ status: "NEEDS_SELECTION",
6279
+ selectionType: "room_unavailable",
6280
+ ui: { component: "choice", multiple: false, recommendedKey: "C2" },
6281
+ 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",
6282
+ workflowPending: true,
6283
+ options: [
6284
+ { 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" } },
6285
+ { key: "C2", label: "\u6539\u7528\u7EBF\u4E0A\u4F1A\u8BAE\uFF08\u817E\u8BAF\u4F1A\u8BAE/\u89C6\u9891\uFF09", value: { action: "no_room" } },
6286
+ { key: "C3", label: '\u5148\u6309"\u5730\u70B9\u5F85\u5B9A"\u63D0\u4EA4', value: { action: "allow_no_room" } }
6287
+ ],
6288
+ roomUnavailable: decisions.roomUnavailable,
6289
+ ...conflictBrief
6290
+ }, {
6291
+ warnings: [
6292
+ `\u4F1A\u8BAE\u5BA4\u63A8\u8350\u65E0\u7ED3\u679C\uFF1A${String(decisions.roomUnavailable.reason)}\u3002\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002`,
6293
+ "\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",
6294
+ ...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`] : [],
6295
+ ...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")}`] : [],
6296
+ ...failureWarnings
6297
+ ]
6298
+ });
6299
+ }
6300
+ if (enrich && addressInput && !roomConfirmed && roomOptions.length === 0 && args.allowNoRoom !== true) {
6301
+ const specified = {
6302
+ key: "R1",
6303
+ label: `${addressInput}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`,
6304
+ value: { ...addressIsRoomId ? { id: addressId } : {}, name: addressInput, roomConfirmed: true },
6305
+ reason: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u672A\u63D0\u4EA4\u3001\u672A\u786E\u8BA4"
6306
+ };
6307
+ return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
6308
+ status: "NEEDS_SELECTION",
6309
+ selectionType: "room",
6310
+ ui: { component: "choice", multiple: false, recommendedKey: "R1" },
6311
+ 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",
6312
+ workflowPending: true,
6313
+ options: [specified],
6314
+ recommended: specified.value,
6315
+ hint: "\u7528\u6237\u786E\u8BA4\u7528\u8FD9\u95F4\u5C31\u628A value \u539F\u6837\u5E26\u56DE\uFF08\u542B roomConfirmed: true\uFF09"
6316
+ }, {
6317
+ warnings: ["\u4F1A\u8BAE\u5BA4\u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF0C\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\u3002", ...failureWarnings]
6318
+ });
6319
+ }
6320
+ const resolved = await resolveWorkflowId(env, args);
6321
+ const confirmedAddressId = String(addressInput ?? "").trim();
6322
+ const confirmedAddressLabel = confirmedAddressId === "" ? "" : String(roomOptions.find((item) => String(item.value?.id ?? "") === confirmedAddressId)?.value?.name ?? "") || confirmedAddressId;
6323
+ const confirmedWhen = `${beginText}~${String(endText).slice(11) || endText}`;
6324
+ let candidates = resolved.candidates;
6325
+ workflowId = resolved.workflowId;
6326
+ 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";
6327
+ let probes = [];
6328
+ let loadedForms = /* @__PURE__ */ new Map();
6329
+ const autoPick = shouldAutoPickFlow(args);
6330
+ if (!workflowId && candidates.length > 1) {
6331
+ let probed = await probeWorkflowCandidates(env, candidates);
6332
+ probes = probed.probes;
6333
+ loadedForms = probed.loadedForms;
6334
+ let launchable = probes.filter((probe) => probe.launchable);
6335
+ if (launchable.length === 0 && resolved.source === "fixed") {
6336
+ const settings = await fetchEbAppSettings(env, "meeting.eb.meeting.create.flow.prepare");
6337
+ const fallbackIds = String(settings.mtNewWf ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6338
+ if (fallbackIds.length > 0) {
6339
+ probed = await probeWorkflowCandidates(env, fallbackIds);
6340
+ probes = probed.probes;
6341
+ loadedForms = probed.loadedForms;
6342
+ candidates = fallbackIds;
6343
+ sourceLabel = "\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E";
6344
+ launchable = probes.filter((probe) => probe.launchable);
6345
+ }
6346
+ }
6347
+ if (launchable.length === 0) {
6348
+ throw meetingValidationError(
6349
+ "flow_not_launchable",
6350
+ `\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`,
6351
+ { probes }
6352
+ );
6353
+ }
6354
+ if (launchable.length > 1 && !autoPick) {
6355
+ return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
6356
+ status: "NEEDS_SELECTION",
6357
+ // ⚠️ 以前漏了这个字段(agent 拿到 undefined 无法判断是哪类选择,2026-10-30 真机发现)。
6358
+ selectionType: "flow",
6359
+ // 明确告诉调用方"这是一道选择题,请用选项控件呈现",不要降级成文本列表
6360
+ // (2026-10-30 用户反馈:agent 把会议室候选写成文本 + "需要你指定一间",没给选项卡)。
6361
+ ui: { component: "choice", multiple: false, recommendedKey: "W1" },
6362
+ // 四要素已经确认到这一步了:摘要一起给出去,用户只需点一下流程,就能直接提交。
6363
+ confirmed: {
6364
+ mt_name: String(args.mt_name ?? ""),
6365
+ begin_datetime: beginText,
6366
+ end_datetime: endText,
6367
+ address: confirmedAddressId || null,
6368
+ addressName: confirmedAddressLabel || null,
6369
+ hrm_members: memberIds
6370
+ },
6371
+ 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`,
6372
+ options: launchable.map((probe, index) => ({
6373
+ key: `W${index + 1}`,
6374
+ label: probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId,
6375
+ // ⛔ 把已确认的四要素一起带回去:用户点选流程后**原样回传 value** 就能直接出确认摘要,
6376
+ // 不用再走一遍时间/房间闸门(否则"先定四要素再选流程"会多出一轮无效往返)。
6377
+ value: {
6378
+ workflowId: probe.workflowId,
6379
+ begin_datetime: beginText,
6380
+ end_datetime: endText,
6381
+ timeConfirmed: true,
6382
+ ...confirmedAddressId ? { address: confirmedAddressId, roomConfirmed: true } : {}
6383
+ },
6384
+ reason: "\u5F53\u524D\u8D26\u53F7\u6709\u53D1\u8D77\u6743\u9650",
6385
+ // 把该流程的字段名如实带出来:不同流程字段差异很大(有的有设备需求/涉密项目,有的没有),
6386
+ // 用户要靠这个才能选对(2026-10-29 用户反馈:选错方式后字段全填不进去)。
6387
+ fields: (loadedForms.get(probe.workflowId)?.fields ?? []).map((f) => f.name).filter(Boolean)
6388
+ })),
6389
+ probes
6390
+ }, {
6391
+ warnings: [
6392
+ `${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`,
6393
+ ...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`)
6394
+ ]
6395
+ });
6396
+ }
6397
+ workflowId = launchable[0].workflowId;
6398
+ if (launchable.length === 1 && candidates.length > 1) {
6399
+ const only = launchable[0];
6400
+ 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`;
6401
+ }
6402
+ if (launchable.length > 1) {
6403
+ const picked2 = launchable[0];
6404
+ const others = launchable.slice(1).map((probe) => probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId);
6405
+ 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`;
6406
+ }
6407
+ }
6408
+ let form = loadedForms.get(workflowId);
6409
+ if (!form) {
6410
+ try {
6411
+ form = await loadCreateForm(env, workflowId);
6412
+ } catch (error) {
6413
+ throw meetingValidationError(
6414
+ "flow_not_launchable",
6415
+ `\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`,
6416
+ { workflowId }
6417
+ );
6489
6418
  }
6490
6419
  }
6420
+ if (!form.continuation) {
6421
+ throw meetingValidationError("flow_context_missing", "\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u6CA1\u6709\u8FD4\u56DE continuation\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u63D0\u4EA4");
6422
+ }
6491
6423
  decisions.timings = timings;
6492
6424
  const shaped = await shapeBrowserValues(env, {
6493
6425
  mt_name: args.mt_name,
@@ -6501,32 +6433,62 @@ var ebMeetingCreateFlowPrepare = {
6501
6433
  caller: args.caller,
6502
6434
  contacter: args.contacter,
6503
6435
  other_remark: args.other_remark,
6504
- mt_type: args.mt_type
6436
+ mt_type: args.mt_type,
6437
+ ...args.extraFields && typeof args.extraFields === "object" && !Array.isArray(args.extraFields) ? args.extraFields : {}
6505
6438
  });
6506
- const { main, mapped, unmapped } = mapFields(form.fields, shaped.values);
6439
+ const preferredFields = await readFlowFieldMap(env, workflowId);
6440
+ const { main, mapped, unmapped, resolved: resolvedFields } = mapFields(form.fields, shaped.values, preferredFields);
6441
+ await writeFlowFieldMap(env, workflowId, form.workflowName, resolvedFields);
6507
6442
  const warnings = [];
6443
+ if (flowPickNote) warnings.push(flowPickNote);
6508
6444
  for (const note of shaped.notes) warnings.push(note);
6445
+ if (args.fieldValues && typeof args.fieldValues === "object" && !Array.isArray(args.fieldValues)) {
6446
+ const knownIds = new Set(form.fields.map((field) => field.id));
6447
+ for (const [fieldId, raw] of Object.entries(args.fieldValues)) {
6448
+ if (raw === void 0 || raw === null || raw === "") continue;
6449
+ if (!knownIds.has(fieldId)) {
6450
+ 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`);
6451
+ continue;
6452
+ }
6453
+ main[fieldId] = raw;
6454
+ mapped[`datakey:${fieldId}`] = fieldId;
6455
+ }
6456
+ }
6457
+ if (enrichFailures.length > 0) {
6458
+ decisions.enrichFailures = enrichFailures;
6459
+ for (const failure of enrichFailures) {
6460
+ 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"`);
6461
+ }
6462
+ }
6509
6463
  const picked = decisions.autoRoom?.picked;
6510
- if (picked) {
6464
+ if (picked && !hadAddressInput) {
6511
6465
  warnings.push(
6512
6466
  `\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"}`
6513
6467
  );
6514
6468
  }
6515
6469
  const slotOptions = decisions.slotOptions ?? [];
6516
- if (slotOptions.length > 0) {
6470
+ const memberConflictCount = decisions.memberConflicts?.length ?? 0;
6471
+ if (memberConflictCount > 0 && slotOptions.length > 0) {
6472
+ warnings.push(
6473
+ `\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"
6474
+ );
6475
+ } else if (memberConflictCount === 0 && slotOptions.length > 0) {
6517
6476
  warnings.push(
6518
- `\u53C2\u4F1A\u4EBA\u65F6\u95F4\u6709\u51B2\u7A81\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`
6477
+ `\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")}`
6519
6478
  );
6520
6479
  } else if (decisions.dayBlocked?.summary) {
6521
6480
  warnings.push(String(decisions.dayBlocked.summary));
6522
6481
  }
6523
- if (unmapped.length > 0) {
6482
+ const unmappedReal = unmapped.filter((name) => name !== "mt_name");
6483
+ if (unmappedReal.length > 0) {
6524
6484
  warnings.push(
6525
- `\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${unmapped.join("\u3001")}\uFF08\u8868\u5355\u73B0\u6709\u5B57\u6BB5\uFF1A${form.fields.map((field) => field.name).join("\u3001")}\uFF09`
6485
+ `\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`
6526
6486
  );
6527
6487
  }
6528
6488
  if (!main[form.fields.find((field) => field.name === "\u4F1A\u8BAE\u540D\u79F0")?.id ?? ""] && !mapped.mt_name) {
6529
- warnings.push("\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u91CC\u6CA1\u627E\u5230\u300C\u4F1A\u8BAE\u540D\u79F0\u300D\u5B57\u6BB5\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u6D41\u7A0B\u662F\u5426\u914D\u9519");
6489
+ warnings.push(
6490
+ "\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"
6491
+ );
6530
6492
  }
6531
6493
  const session = await env.host.getSession();
6532
6494
  const continuation = await env.continuation.issue(
@@ -6540,7 +6502,9 @@ var ebMeetingCreateFlowPrepare = {
6540
6502
  requestName: String(args.mt_name),
6541
6503
  mtName: String(args.mt_name),
6542
6504
  data: { main },
6543
- surfaceContinuation: form.continuation
6505
+ surfaceContinuation: form.continuation,
6506
+ // 供 apply 在「会议还没生成」时按申请单信息预生成邀请函(预置函)
6507
+ invitationFields: shaped.readable
6544
6508
  },
6545
6509
  fingerprint: JSON.stringify({ workflowId, main })
6546
6510
  },
@@ -6554,6 +6518,7 @@ var ebMeetingCreateFlowPrepare = {
6554
6518
  workflowId,
6555
6519
  workflowCandidates: candidates,
6556
6520
  ...probes.length > 0 ? { workflowProbes: probes } : {},
6521
+ ...flowPickNote ? { workflowAutoPicked: { workflowId, source: resolved.source, note: flowPickNote } } : {},
6557
6522
  requestName: String(args.mt_name),
6558
6523
  fieldMapping: mapped,
6559
6524
  formData: { main },
@@ -6567,6 +6532,43 @@ var ebMeetingCreateFlowPrepare = {
6567
6532
  );
6568
6533
  }
6569
6534
  };
6535
+ async function renderPreInvitation(payload, env) {
6536
+ const fields = payload?.invitationFields ?? {};
6537
+ const started = Date.now();
6538
+ try {
6539
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6540
+ const render = getMeetingOperation2("meeting.invitation.render");
6541
+ const rendered = await render.handler(
6542
+ {
6543
+ mt_name: String(fields.mt_name ?? payload?.mtName ?? "").trim(),
6544
+ begin_datetime: String(fields.begin_datetime ?? "").trim(),
6545
+ end_datetime: String(fields.end_datetime ?? "").trim(),
6546
+ address: String(fields.address ?? fields.customize_address ?? "").trim(),
6547
+ hrm_members: String(fields.hrm_members ?? "").trim(),
6548
+ mt_desc: String(fields.mt_desc ?? "").trim(),
6549
+ org_members: String(fields.org_members ?? "").trim(),
6550
+ caller: String(fields.caller ?? "").trim(),
6551
+ contacter: String(fields.contacter ?? "").trim(),
6552
+ total_member: String(fields.total_member ?? "").trim()
6553
+ },
6554
+ env
6555
+ );
6556
+ return {
6557
+ invitation: { pending: true, preRendered: true, ...rendered?.data ?? {} },
6558
+ ms: Date.now() - started
6559
+ };
6560
+ } catch (error) {
6561
+ return {
6562
+ invitation: {
6563
+ pending: true,
6564
+ preRendered: false,
6565
+ ok: false,
6566
+ error: String(error?.message ?? error).slice(0, 200)
6567
+ },
6568
+ ms: Date.now() - started
6569
+ };
6570
+ }
6571
+ }
6570
6572
  var ebMeetingCreateFlowApply = {
6571
6573
  name: "meeting.eb.meeting.create.flow.apply",
6572
6574
  resource: "eb",
@@ -6597,9 +6599,9 @@ var ebMeetingCreateFlowApply = {
6597
6599
  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");
6598
6600
  }
6599
6601
  const payload = lease?.payload ?? {};
6600
- const { createWorkflowHost } = await import("./host-OCH2BCCV.js");
6602
+ const { createWorkflowHost } = await import("./host-C6EL2RKL.js");
6601
6603
  const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
6602
- const { getWorkflowOperation } = await import("./registry-7C5UMIPL.js");
6604
+ const { getWorkflowOperation } = await import("./registry-TKX2E7C7.js");
6603
6605
  const wfEnv = {
6604
6606
  ...workflowEnv(env),
6605
6607
  host: createWorkflowHost(env.ctx),
@@ -6640,6 +6642,33 @@ var ebMeetingCreateFlowApply = {
6640
6642
  );
6641
6643
  }
6642
6644
  if (!requestId) {
6645
+ const submitStatus = String(submittedData.status ?? submitted?.status ?? "");
6646
+ if (submitStatus === "BROWSER_FILL") {
6647
+ const pre = await renderPreInvitation(payload, env);
6648
+ return meetingSuccess(
6649
+ "meeting.eb.meeting.create.flow.apply",
6650
+ {
6651
+ status: "BROWSER_FILL",
6652
+ workflowId: payload.workflowId,
6653
+ requestName: payload.requestName,
6654
+ requestId: null,
6655
+ meetingId: null,
6656
+ contextId: submittedData.contextId ?? null,
6657
+ // 宿主要靠这段 <browsertool> 才能把表单拉到浏览器里填,必须原样透出
6658
+ finalMarkdown: submittedData.finalMarkdown ?? null,
6659
+ message: String(submittedData.message ?? ""),
6660
+ invitation: pre.invitation,
6661
+ timings: { submitMs: Date.now() - submitStartedAt, invitationMs: pre.ms }
6662
+ },
6663
+ {
6664
+ warnings: [
6665
+ '\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',
6666
+ `\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`,
6667
+ '\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'
6668
+ ]
6669
+ }
6670
+ );
6671
+ }
6643
6672
  const missing = submittedData.missingFields ?? submittedData.requiredMissing ?? submittedData.missing ?? [];
6644
6673
  throw meetingValidationError(
6645
6674
  "flow_submit_incomplete",
@@ -6652,7 +6681,7 @@ var ebMeetingCreateFlowApply = {
6652
6681
  let meetingId = "";
6653
6682
  const timings = { submitMs: Date.now() - submitStartedAt };
6654
6683
  if (waitSeconds > 0) {
6655
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
6684
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6656
6685
  const list = getMeetingOperation2("meeting.eb.meeting.list");
6657
6686
  const deadline = Date.now() + Math.min(waitSeconds, 30) * 1e3;
6658
6687
  const pollStart = Date.now();
@@ -6669,7 +6698,7 @@ var ebMeetingCreateFlowApply = {
6669
6698
  } catch {
6670
6699
  }
6671
6700
  if (waited >= 5e3) break;
6672
- await new Promise((resolve5) => setTimeout(resolve5, 5e3));
6701
+ await new Promise((resolve6) => setTimeout(resolve6, 5e3));
6673
6702
  waited += 5e3;
6674
6703
  }
6675
6704
  timings.pollMs = Date.now() - pollStart;
@@ -6678,7 +6707,7 @@ var ebMeetingCreateFlowApply = {
6678
6707
  if (meetingId) {
6679
6708
  const invitationStart = Date.now();
6680
6709
  try {
6681
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
6710
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6682
6711
  const render = getMeetingOperation2("meeting.invitation.render");
6683
6712
  const rendered = await render.handler({ mtId: meetingId }, env);
6684
6713
  invitation = { pending: false, ...rendered?.data ?? {} };
@@ -6691,8 +6720,11 @@ var ebMeetingCreateFlowApply = {
6691
6720
  };
6692
6721
  }
6693
6722
  } else {
6723
+ const pre = await renderPreInvitation(payload, env);
6724
+ invitation = pre.invitation;
6725
+ timings.invitationMs = pre.ms;
6694
6726
  warnings.push(
6695
- `\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\u5BA1\u6279\u901A\u8FC7\u540E\uFF08\u6216\u540E\u53F0\u5EFA\u4F1A\u5B8C\u6210\u540E\uFF09\u518D\u8DD1\u4E00\u6B21 meeting.invitation.render \u51FA\u9080\u8BF7\u51FD\uFF1B\u672C operation \u4E0D\u91CD\u590D\u63D0\u4EA4\u6D41\u7A0B\u3002`
6727
+ `\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`
6696
6728
  );
6697
6729
  }
6698
6730
  return meetingSuccess(
@@ -6723,8 +6755,14 @@ var ebMeetingCreateFlowQuick = {
6723
6755
  inputSchema: schemaOf(
6724
6756
  {
6725
6757
  mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
6726
- begin_datetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
6727
- end_datetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
6758
+ begin_datetime: {
6759
+ ...SCHEMA_DATETIME_MINUTE,
6760
+ 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"
6761
+ },
6762
+ end_datetime: {
6763
+ ...SCHEMA_DATETIME_MINUTE,
6764
+ 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"
6765
+ },
6728
6766
  mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
6729
6767
  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" },
6730
6768
  customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
@@ -6732,15 +6770,54 @@ var ebMeetingCreateFlowQuick = {
6732
6770
  total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
6733
6771
  caller: { type: "string", description: "\u53EC\u96C6\u4EBA" },
6734
6772
  contacter: { type: "string", description: "\u8054\u7CFB\u4EBA" },
6773
+ mt_type: {
6774
+ type: "string",
6775
+ 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"
6776
+ },
6735
6777
  other_remark: { type: "string", description: "\u5907\u6CE8" },
6736
- workflowId: { type: "string", description: "\u6307\u5B9A\u5EFA\u4F1A\u6D41\u7A0B id\uFF08\u591A\u6D41\u7A0B\u65F6\u7528\u6765\u8DF3\u8FC7\u9009\u62E9\uFF09" },
6778
+ workflowId: {
6779
+ oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
6780
+ 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"
6781
+ },
6737
6782
  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" },
6738
6783
  allowNoRoom: { type: "boolean", description: "\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\u7B49\uFF09\u65F6\u4F20 true" },
6784
+ timeConfirmed: {
6785
+ type: "boolean",
6786
+ 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'
6787
+ },
6788
+ roomConfirmed: {
6789
+ type: "boolean",
6790
+ 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'
6791
+ },
6739
6792
  confirm: { type: "boolean", description: "\u5FC5\u987B\u663E\u5F0F true \u624D\u4F1A\u771F\u6B63\u63D0\u4EA4" },
6740
6793
  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" },
6741
- 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" }
6794
+ 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" },
6795
+ extraFields: {
6796
+ type: "object",
6797
+ 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"}'
6798
+ },
6799
+ dateFrom: {
6800
+ type: "string",
6801
+ 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"
6802
+ },
6803
+ durationMinutes: {
6804
+ type: "number",
6805
+ 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"
6806
+ },
6807
+ workStartHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u65E9\u5C0F\u65F6\uFF08\u9ED8\u8BA4 9\uFF09" },
6808
+ workEndHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u665A\u5C0F\u65F6\uFF08\u9ED8\u8BA4 18\uFF09" },
6809
+ fieldValues: {
6810
+ type: "object",
6811
+ additionalProperties: true,
6812
+ 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'
6813
+ },
6814
+ flowChoice: {
6815
+ type: "string",
6816
+ enum: ["auto", "ask"],
6817
+ 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\u53EA\u6709 1 \u4E2A\u6709\u6743\u9650\u65F6\u76F4\u63A5\u53D1\u8D77"
6818
+ }
6742
6819
  },
6743
- { required: ["mt_name", "begin_datetime", "end_datetime", "confirm"] }
6820
+ { required: ["mt_name", "confirm"] }
6744
6821
  ),
6745
6822
  handler: async (args, env) => {
6746
6823
  if (args.confirm !== true) {
@@ -6749,7 +6826,7 @@ var ebMeetingCreateFlowQuick = {
6749
6826
  "\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"
6750
6827
  );
6751
6828
  }
6752
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
6829
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6753
6830
  const prepareStartedAt = Date.now();
6754
6831
  const prepared = await getMeetingOperation2("meeting.eb.meeting.create.flow.prepare").handler(
6755
6832
  { ...args, confirm: void 0 },
@@ -6784,6 +6861,10 @@ var ebMeetingCreateFlowQuick = {
6784
6861
  requestId: applied?.data?.requestId,
6785
6862
  meetingId: applied?.data?.meetingId ?? null,
6786
6863
  invitation: applied?.data?.invitation ?? null,
6864
+ // 小e 环境(BROWSER_FILL)不写服务端,表单靠这段 <browsertool> 在浏览器里填 —— 必须一起透出,
6865
+ // 否则宿主拿不到表单,用户看到的就是"提交了但没反应"。
6866
+ ...applied?.data?.contextId ? { contextId: (applied?.data).contextId } : {},
6867
+ ...applied?.data?.finalMarkdown ? { finalMarkdown: (applied?.data).finalMarkdown } : {},
6787
6868
  decisions: prepared?.data?.preview?.decisions ?? null,
6788
6869
  timings: {
6789
6870
  ...prepared?.data?.preview?.decisions?.timings ?? {},
@@ -6798,7 +6879,123 @@ var ebMeetingCreateFlowQuick = {
6798
6879
  );
6799
6880
  }
6800
6881
  };
6882
+ var ebMeetingCreateSuggest = {
6883
+ name: "meeting.eb.meeting.create.suggest",
6884
+ resource: "eb",
6885
+ method: "meeting.eb.meeting.create.suggest",
6886
+ action: "meeting.eb.meeting.create.suggest",
6887
+ 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",
6888
+ capability: "eb.meeting",
6889
+ risk: "read",
6890
+ inputSchema: schemaOf(
6891
+ {
6892
+ dateFrom: { type: "string", description: "\u8D77\u59CB\u65E5\u671F\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd\uFF09" },
6893
+ dateTo: { type: "string", description: "\u7ED3\u675F\u65E5\u671F\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u540C dateFrom\uFF1B\u6700\u591A\u8DE8 14 \u5929\uFF09" },
6894
+ durationMinutes: { type: "number", description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09" },
6895
+ 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" },
6896
+ 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" },
6897
+ workStartHour: { type: "number", description: "\u53EA\u5728\u51E0\u70B9\u4EE5\u540E\u627E\uFF08\u9ED8\u8BA4 9\uFF09" },
6898
+ workEndHour: { type: "number", description: "\u53EA\u5728\u51E0\u70B9\u4EE5\u524D\u627E\uFF08\u9ED8\u8BA4 18\uFF09" },
6899
+ maxSlots: { type: "number", description: "\u6700\u591A\u7ED9\u51E0\u4E2A\u65F6\u95F4\u5019\u9009\uFF08\u9ED8\u8BA4 3\uFF0C\u6700\u5927 8\uFF09" },
6900
+ topN: { type: "number", description: "\u6BCF\u4E2A\u65F6\u95F4\u5019\u9009\u6700\u591A\u5E26\u51E0\u95F4\u4F1A\u8BAE\u5BA4\uFF08\u9ED8\u8BA4 3\uFF09" },
6901
+ includeSchedule: { type: "boolean", description: "\u662F\u5426\u628A\u65E5\u7A0B\uFF08ESB\uFF09\u4E5F\u7B97\u8FDB\u5360\u7528\uFF08\u9ED8\u8BA4 true\uFF09" }
6902
+ },
6903
+ { required: ["dateFrom", "hrm_members"] }
6904
+ ),
6905
+ handler: async (args, env) => {
6906
+ const dateFrom = String(args.dateFrom ?? "").trim().slice(0, 10);
6907
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(dateFrom)) {
6908
+ throw meetingValidationError("datetime_invalid", `dateFrom \u5FC5\u987B\u662F yyyy-MM-dd\uFF0C\u6536\u5230\u300C${String(args.dateFrom ?? "")}\u300D`);
6909
+ }
6910
+ const dateTo = String(args.dateTo ?? "").trim().slice(0, 10) || dateFrom;
6911
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(dateTo)) {
6912
+ throw meetingValidationError("datetime_invalid", `dateTo \u5FC5\u987B\u662F yyyy-MM-dd\uFF0C\u6536\u5230\u300C${String(args.dateTo ?? "")}\u300D`);
6913
+ }
6914
+ const durationMinutes = Number(args.durationMinutes) > 0 ? Number(args.durationMinutes) : 60;
6915
+ const maxSlots = Math.max(1, Math.min(8, Number(args.maxSlots) || 3));
6916
+ const topN = Math.max(1, Math.min(5, Number(args.topN) || 3));
6917
+ const rawMembers = String(args.hrm_members ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
6918
+ const nameLike = rawMembers.filter((item) => !/^\d+$/.test(item));
6919
+ const nameToId = nameLike.length > 0 ? await import("./schedule-IVBICP32.js").then((m) => m.resolveMemberIdsByName(env, nameLike)).catch(() => /* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
6920
+ const memberIds = rawMembers.map((item) => nameToId.get(item) ?? item);
6921
+ const unresolved = rawMembers.filter((item) => nameToId.get(item) === void 0 && !/^\d+$/.test(item));
6922
+ const selfId = await env.host.getSession().then((s) => String(s?.userId ?? "")).catch(() => "");
6923
+ const selfIncluded = selfId !== "" && memberIds.includes(selfId);
6924
+ const memberCount = Number(args.memberCount) > 0 ? Number(args.memberCount) : memberIds.length > 0 ? memberIds.length + (selfIncluded ? 0 : 1) : void 0;
6925
+ const warnings = [];
6926
+ if (unresolved.length > 0) {
6927
+ 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**`);
6928
+ }
6929
+ const free = await findCommonFreeSlots(env, {
6930
+ rangeStart: `${dateFrom} 00:00`,
6931
+ rangeEnd: `${dateTo} 23:59`,
6932
+ durationMinutes,
6933
+ members: memberIds,
6934
+ maxSlots,
6935
+ maxDays: 14,
6936
+ includeSchedule: args.includeSchedule !== false,
6937
+ ...args.workStartHour !== void 0 ? { workStartHour: Number(args.workStartHour) } : {},
6938
+ ...args.workEndHour !== void 0 ? { workEndHour: Number(args.workEndHour) } : {}
6939
+ });
6940
+ await loadRooms(env, { refresh: true }).catch(() => null);
6941
+ const withRooms = await Promise.all((free.slots ?? []).map(async (slot) => {
6942
+ try {
6943
+ const rec = await recommendRooms(env, {
6944
+ beginDatetime: slot.begin,
6945
+ endDatetime: slot.end,
6946
+ ...memberCount ? { memberCount } : {},
6947
+ topN
6948
+ });
6949
+ return {
6950
+ begin: slot.begin,
6951
+ end: slot.end,
6952
+ rooms: rec.candidates.map((candidate) => ({
6953
+ id: candidate.id,
6954
+ name: candidate.name,
6955
+ capacityMax: candidate.capacity.max,
6956
+ reasons: candidate.reasons
6957
+ }))
6958
+ };
6959
+ } catch {
6960
+ return { begin: slot.begin, end: slot.end, rooms: [] };
6961
+ }
6962
+ }));
6963
+ const usable = withRooms.filter((slot) => slot.rooms.length > 0);
6964
+ if (usable.length === 0) {
6965
+ 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`;
6966
+ warnings.push(
6967
+ `\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`
6968
+ );
6969
+ if (free.blockingSummary) warnings.push(`\u5F53\u5929\u5360\u7528\u6982\u51B5\uFF1A${free.blockingSummary}`);
6970
+ }
6971
+ return meetingSuccess(
6972
+ "meeting.eb.meeting.create.suggest",
6973
+ {
6974
+ dateFrom,
6975
+ dateTo,
6976
+ durationMinutes,
6977
+ // 同样是"让用户点一下":时段候选用选项控件呈现,别写成文本列表
6978
+ ui: { component: "choice", multiple: false, recommendedKey: "T1" },
6979
+ slots: usable.map((slot, index) => ({
6980
+ key: `T${index + 1}`,
6981
+ label: `${slot.begin.slice(5, 10)} ${slot.begin.slice(11)}~${slot.end.slice(11)}`,
6982
+ value: { begin: slot.begin, end: slot.end, address: slot.rooms[0]?.id ?? null },
6983
+ 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")}`,
6984
+ rooms: slot.rooms
6985
+ })),
6986
+ // 把"人空闲但没房间"的时段也带出来,方便调用方解释为什么被剔除
6987
+ skippedSlots: withRooms.filter((slot) => slot.rooms.length === 0),
6988
+ memberIds,
6989
+ scheduleItems: free.scheduleItems,
6990
+ idle: free.idle,
6991
+ cost: free.cost
6992
+ },
6993
+ warnings.length > 0 ? { warnings } : {}
6994
+ );
6995
+ }
6996
+ };
6801
6997
  var meetingEbCreateFlowOperations = [
6998
+ ebMeetingCreateSuggest,
6802
6999
  ebMeetingCreateFlowPrepare,
6803
7000
  ebMeetingCreateFlowApply,
6804
7001
  ebMeetingCreateFlowQuick
@@ -6808,8 +7005,10 @@ var meetingEbCreateFlowOperations = [
6808
7005
  var ebAutoRoomPreflight = async (context) => {
6809
7006
  const { extras } = context;
6810
7007
  const warnings = [];
6811
- const enabled = String(process.env.WEAVER_MEETING_AUTO_ROOM ?? "1") !== "0";
6812
7008
  const isCreate = context.endpoint.kind === "create" && context.endpoint.interfacePk === "create_meeting";
7009
+ const markRoomUnavailable = (reason, meta) => {
7010
+ extras.roomUnavailable = { reason, ...meta ? { meta } : {} };
7011
+ };
6813
7012
  const mode = String(process.env.WEAVER_MEETING_AUTO_ROOM ?? "").trim();
6814
7013
  if (isCreate && !context.payload.mainTable.address && mode !== "0") {
6815
7014
  const begin = String(context.payload.mainTable.begin_datetime ?? "").trim();
@@ -6853,15 +7052,25 @@ var ebAutoRoomPreflight = async (context) => {
6853
7052
  );
6854
7053
  } else {
6855
7054
  warnings.push(...result.warnings);
7055
+ markRoomUnavailable(
7056
+ `\u6CA1\u6709\u53EF\u7528\u7684\u4F1A\u8BAE\u5BA4\u5019\u9009\uFF08\u5171 ${result.meta?.roomsTotal ?? 0} \u95F4\uFF0C\u53EF\u7528 ${result.meta?.roomsUsable ?? 0} \u95F4\uFF0C\u8BE5\u65F6\u6BB5\u88AB\u5360\u7528 ${result.meta?.roomsBusy ?? 0} \u95F4\uFF09`,
7057
+ result.meta
7058
+ );
7059
+ warnings.push(
7060
+ "\u26A0\uFE0F \u672C\u6B21\u5EFA\u4F1A**\u6CA1\u6709\u4F1A\u8BAE\u5BA4**\uFF1A\u63A8\u8350\u4E0D\u51FA\u5019\u9009\uFF08\u89C1 roomUnavailable.reason\uFF09\u3002\u5FC5\u987B\u7528\u9009\u9879\u65B9\u5F0F\u8BA9\u7528\u6237\u786E\u8BA4\u5730\u70B9 \u2014\u2014 \u6539\u6307\u5B9A\u5177\u4F53\u4F1A\u8BAE\u5BA4\uFF08\u4F20 address\uFF09\u3001\u6539\u4E3A\u7EBF\u4E0A\u4F1A\u8BAE\uFF0C\u6216\u660E\u786E\u63A5\u53D7\u300C\u5730\u70B9\u5F85\u5B9A\u300D\u3002\u4E0D\u8981\u9ED8\u9ED8\u5EFA\u6210\u4E00\u573A\u6CA1\u6709\u5730\u70B9\u7684\u4F1A\u3002"
7061
+ );
6856
7062
  }
6857
7063
  } catch (error) {
6858
7064
  if (error?.subtype === "room_selection_required") throw error;
7065
+ const reason = String(error?.message ?? error).slice(0, 200);
7066
+ markRoomUnavailable(`\u4F1A\u8BAE\u5BA4\u63A8\u8350\u5931\u8D25\uFF1A${reason}`);
6859
7067
  warnings.push(
6860
- `\u4F1A\u8BAE\u5BA4\u63A8\u8350\u5931\u8D25\uFF08${String(error?.message ?? error).slice(0, 80)}\uFF09\uFF1A\u672C\u6B21\u4E0D\u586B\u4F1A\u8BAE\u5BA4\u7EE7\u7EED\uFF0C\u8BF7\u4E0E\u7528\u6237\u786E\u8BA4\u5730\u70B9`
7068
+ `\u26A0\uFE0F \u4F1A\u8BAE\u5BA4\u63A8\u8350\u5931\u8D25\uFF08${reason}\uFF09\uFF1A\u672C\u6B21**\u4E0D\u586B\u4F1A\u8BAE\u5BA4\u7EE7\u7EED**\uFF0C\u8BF7\u4E0E\u7528\u6237\u786E\u8BA4\u5730\u70B9\uFF0C\u4E0D\u8981\u9ED8\u8BA4\u300C\u5730\u70B9\u5F85\u5B9A\u300D\u3002`
6861
7069
  );
6862
7070
  }
6863
7071
  } else {
6864
- warnings.push("\u4F1A\u8BAE\u5F00\u59CB/\u7ED3\u675F\u65F6\u95F4\u4E0D\u5B8C\u6574\uFF0C\u8DF3\u8FC7\u4F1A\u8BAE\u5BA4\u63A8\u8350");
7072
+ markRoomUnavailable("\u4F1A\u8BAE\u5F00\u59CB/\u7ED3\u675F\u65F6\u95F4\u4E0D\u5B8C\u6574\uFF0C\u65E0\u6CD5\u6309\u65F6\u6BB5\u63A8\u8350");
7073
+ warnings.push("\u4F1A\u8BAE\u5F00\u59CB/\u7ED3\u675F\u65F6\u95F4\u4E0D\u5B8C\u6574\uFF0C\u8DF3\u8FC7\u4F1A\u8BAE\u5BA4\u63A8\u8350\uFF08\u672C\u6B21\u4E0D\u4F1A\u586B\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u4E0E\u7528\u6237\u786E\u8BA4\u5730\u70B9\uFF09");
6865
7074
  }
6866
7075
  }
6867
7076
  const conflictWarnings = await ebMeetingWritePreflight(context);
@@ -6879,7 +7088,7 @@ var ebAutoInvitationAfterWrite = async (context) => {
6879
7088
  const mtId = String(context.dataIds?.[0] ?? "").trim();
6880
7089
  if (!isCreate || !enabled || !mtId) return association;
6881
7090
  try {
6882
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-TI3CIUXF.js");
7091
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6883
7092
  const render = getMeetingOperation2("meeting.invitation.render");
6884
7093
  const result = await render.handler({ mtId }, context.env);
6885
7094
  return { ...association ?? {}, invitation: result?.data ?? null };
@@ -6930,6 +7139,7 @@ function buildRegistry() {
6930
7139
  ...meetingInvitationOperations,
6931
7140
  ...meetingQrOperations,
6932
7141
  ...meetingSummaryOperations,
7142
+ ...meetingFormFieldOperations,
6933
7143
  ...meetingEbOperations
6934
7144
  ];
6935
7145
  for (const definition of definitions) {