weaver-work-cli 0.1.33 → 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 (100) hide show
  1. package/dist/chunks/{archive-FVFY6GZN.js → archive-XBVH7JU7.js} +2 -2
  2. package/dist/chunks/{archive-oa-NW3OD4UV.js → archive-oa-MZM3EKFQ.js} +2 -2
  3. package/dist/chunks/{asset-7QJKMIDV.js → asset-4XO7UOUW.js} +2 -2
  4. package/dist/chunks/{attachment-content-OSAVA6K3.js → attachment-content-VXSWANAC.js} +3 -3
  5. package/dist/chunks/{blog-I7SDPNW4.js → blog-PGZKOPSC.js} +2 -2
  6. package/dist/chunks/{caizhilian-O37ZIQNY.js → caizhilian-BH4ZVGUN.js} +2 -2
  7. package/dist/chunks/{calendar-7KXE4ED3.js → calendar-MXEMTIO4.js} +2 -2
  8. package/dist/chunks/{chunk-VBCFFFGT.js → chunk-5DQEEGCC.js} +4 -1
  9. package/dist/chunks/{chunk-KAS45KNR.js → chunk-6LLJFKJE.js} +1 -1
  10. package/dist/chunks/{chunk-HEL5XTYI.js → chunk-BPE37FPB.js} +26 -4
  11. package/dist/chunks/{chunk-IHUYP6LO.js → chunk-F746NKNF.js} +1 -1
  12. package/dist/chunks/{chunk-MQ2I5AA3.js → chunk-HXJQI5NM.js} +2 -2
  13. package/dist/chunks/{chunk-ILMBNVSG.js → chunk-I6QGIBDM.js} +2 -2
  14. package/dist/chunks/{chunk-EEWPQE3O.js → chunk-JCSN3JGM.js} +2 -2
  15. package/dist/chunks/{chunk-D223PTXU.js → chunk-JNG42JKG.js} +29 -1
  16. package/dist/chunks/{chunk-6ATGWRZM.js → chunk-JUXVYKII.js} +4 -1
  17. package/dist/chunks/{chunk-GFPXQIY2.js → chunk-JYKABYCV.js} +2 -2
  18. package/dist/chunks/{chunk-Q6LWB5HX.js → chunk-NCOVUAZK.js} +2 -2
  19. package/dist/chunks/{chunk-WY74UBJ6.js → chunk-QHFANTX7.js} +900 -204
  20. package/dist/chunks/{chunk-WRRJ4GG2.js → chunk-QYGO5EE2.js} +2 -2
  21. package/dist/chunks/{chunk-RBGOMK4Y.js → chunk-T72N74ZT.js} +2 -2
  22. package/dist/chunks/{chunk-MEEFGWTM.js → chunk-TC6MZAO3.js} +84 -9
  23. package/dist/chunks/{chunk-OCU4RLHC.js → chunk-VPUTVEMC.js} +98 -34
  24. package/dist/chunks/{chunk-PRHJGPMA.js → chunk-VPXOPQJI.js} +2 -2
  25. package/dist/chunks/{chunk-NHA62QD7.js → chunk-WXFPWCXG.js} +3 -3
  26. package/dist/chunks/{chunk-2FLWXFVS.js → chunk-XMGSYD6S.js} +4 -4
  27. package/dist/chunks/{conflict-SFNEVJY5.js → conflict-JAB2LJEZ.js} +2 -2
  28. package/dist/chunks/contract-XI2EEIZU.js +9110 -0
  29. package/dist/chunks/{cowork-CKWYHXYB.js → cowork-SCPGLBA4.js} +44 -25
  30. package/dist/chunks/{ebuilder-form-KOLJRVZD.js → ebuilder-form-EYLHNOTA.js} +3 -3
  31. package/dist/chunks/{ehr-WFOC3B4D.js → ehr-EAP77IMT.js} +172 -9
  32. package/dist/chunks/{esb-LJZTN663.js → esb-2TGGXEE7.js} +4 -4
  33. package/dist/chunks/{fna-F7QRIIZC.js → fna-2X7ZE7BU.js} +13 -8
  34. package/dist/chunks/{host-VQ6JJXGQ.js → host-C6EL2RKL.js} +3 -3
  35. package/dist/chunks/{host-BCGUVEWX.js → host-I4NRK4MX.js} +3 -3
  36. package/dist/chunks/{host-DGE2TZD4.js → host-Q4LZGCRU.js} +3 -3
  37. package/dist/chunks/{host-BQBRHVR3.js → host-UEI5FGDM.js} +3 -3
  38. package/dist/chunks/{host-KXPTEWFS.js → host-XCLDDXKQ.js} +3 -3
  39. package/dist/chunks/{hrm-NI6XAKW5.js → hrm-YXERJM76.js} +3 -3
  40. package/dist/chunks/{im-7TRTF3KT.js → im-A4VZN2TQ.js} +3 -3
  41. package/dist/chunks/{invoice-AOXWJKYT.js → invoice-2Z6YPMIS.js} +3 -3
  42. package/dist/chunks/{jiuchuanhui-7NQWEZAW.js → jiuchuanhui-AR5GMKZB.js} +2 -2
  43. package/dist/chunks/{lazy-dispatch-RNS4EE4S.js → lazy-dispatch-QXW7P4X3.js} +4 -4
  44. package/dist/chunks/{mail-VDHJAB4O.js → mail-7GZ6CPBJ.js} +44 -23
  45. package/dist/chunks/{meeting-GA7XCNNP.js → meeting-3NMGA3MB.js} +74 -10
  46. package/dist/chunks/{okr-TQIRERPQ.js → okr-BZ6XUOAG.js} +2 -2
  47. package/dist/chunks/{plan-4RY4LN2P.js → plan-DR5CMUYP.js} +2 -2
  48. package/dist/chunks/{project-D6XT2OC5.js → project-6J63MK33.js} +2 -2
  49. package/dist/chunks/{registry-JHRIDQ3A.js → registry-KDD7DHNK.js} +4 -4
  50. package/dist/chunks/{registry-VOGKFFTR.js → registry-TKX2E7C7.js} +2 -2
  51. package/dist/chunks/{registry-QKMI43Q6.js → registry-VRTNC6UR.js} +8 -8
  52. package/dist/chunks/{room-recommend-D4EUOOWY.js → room-recommend-XCWRMB5P.js} +4 -4
  53. package/dist/chunks/{schedule-XPFBHPCV.js → schedule-IVBICP32.js} +4 -4
  54. package/dist/chunks/{workflow-HLBZRWIY.js → workflow-D74NFK3C.js} +11 -4
  55. package/dist/index.js +31 -26
  56. package/dist/internal/e10/fetch-timing.js +31 -0
  57. package/dist/internal/e10/request-runtime.js +5 -0
  58. package/dist/shortcuts/cowork/host.js +8 -0
  59. package/dist/shortcuts/cowork/operations/types.js +17 -2
  60. package/dist/shortcuts/ehr/operations/recruit-write.js +35 -0
  61. package/dist/shortcuts/ehr/operations/recruit.js +147 -0
  62. package/dist/shortcuts/fna/operations/expense-chart.js +19 -7
  63. package/dist/shortcuts/index.js +5 -0
  64. package/dist/shortcuts/mail/host.js +8 -0
  65. package/dist/shortcuts/mail/operations/types.js +17 -2
  66. package/dist/shortcuts/meeting/index.js +79 -1
  67. package/dist/shortcuts/meeting/manifest.js +10 -0
  68. package/dist/shortcuts/meeting/operations/eb/catalog.js +5 -0
  69. package/dist/shortcuts/meeting/operations/eb/conflict.js +6 -1
  70. package/dist/shortcuts/meeting/operations/eb/create-flow.js +1047 -134
  71. package/dist/shortcuts/meeting/operations/eb/factory.js +101 -7
  72. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +36 -2
  73. package/dist/shortcuts/meeting/operations/eb-fallback.js +4 -0
  74. package/dist/shortcuts/meeting/operations/env.js +6 -0
  75. package/dist/shortcuts/meeting/operations/invitation.js +79 -20
  76. package/dist/shortcuts/workflow/endpoints.js +8 -3
  77. package/dist/shortcuts/workflow/operations/form.js +181 -34
  78. package/dist/shortcuts/workflow/operations.js +23 -1
  79. package/docs/ehr.md +1 -1
  80. package/docs/fna.md +2 -1
  81. package/package.json +1 -1
  82. package/skill-template/business-info.json +18 -0
  83. package/skill-template/domains/cowork.md +14 -0
  84. package/skills/weaver-e10-cowork/SKILL.md +101 -0
  85. package/skills/weaver-e10-cowork/references/cowork-read.md +90 -0
  86. package/skills/weaver-e10-cowork/references/cowork-write.md +131 -0
  87. package/skills/weaver-e10-cowork/references/safety-boundaries.md +45 -0
  88. package/skills/weaver-e10-jucailin/SKILL.md +21 -3
  89. package/skills/weaver-e10-jucailin/references/recruit-read.md +25 -0
  90. package/skills/weaver-e10-jucailin/references/recruit-write.md +13 -0
  91. package/skills/weaver-e10-jucailin/references/salary.md +15 -11
  92. package/skills/weaver-e10-mail/SKILL.md +12 -9
  93. package/skills/weaver-e10-meeting/SKILL.md +284 -34
  94. package/skills/weaver-e10-meeting/references/meeting-eb.md +131 -0
  95. package/skills/weaver-e10-meeting/references/meeting-invitation.md +28 -2
  96. package/skills/weaver-e10-meeting.zip +0 -0
  97. package/skills/weaver-e10-qiyecheng/SKILL.md +5 -2
  98. package/skills/weaver-e10-qiyecheng/references/catalog.md +2 -2
  99. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +15 -1
  100. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +22 -21
@@ -2,28 +2,29 @@ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
4
  ebRoomRecommendOperation,
5
+ loadRooms,
5
6
  recommendRooms,
6
7
  rememberFrequentRoom
7
- } from "./chunk-HEL5XTYI.js";
8
+ } from "./chunk-BPE37FPB.js";
8
9
  import {
9
10
  meetingEbScheduleOperations
10
- } from "./chunk-2FLWXFVS.js";
11
+ } from "./chunk-XMGSYD6S.js";
11
12
  import {
12
13
  ebMeetingWritePreflight,
13
14
  fetchEbAppSettings,
14
15
  findCommonFreeSlots,
15
16
  meetingEbConflictOperations
16
- } from "./chunk-NHA62QD7.js";
17
+ } from "./chunk-WXFPWCXG.js";
17
18
  import {
18
19
  listMeetingAttachments,
19
20
  meetingAttachmentContentOperations,
20
21
  renderDocx
21
- } from "./chunk-MQ2I5AA3.js";
22
+ } from "./chunk-HXJQI5NM.js";
22
23
  import {
23
24
  meetingEnvOperations,
24
25
  meetingStateDir,
25
26
  resolveMeetingEnvMode
26
- } from "./chunk-VBCFFFGT.js";
27
+ } from "./chunk-5DQEEGCC.js";
27
28
  import {
28
29
  EB_BASE,
29
30
  EB_ENDPOINTS,
@@ -55,7 +56,7 @@ import {
55
56
  toIdString,
56
57
  verifyLease,
57
58
  writeBody
58
- } from "./chunk-MEEFGWTM.js";
59
+ } from "./chunk-TC6MZAO3.js";
59
60
 
60
61
  // src/shortcuts/meeting/operations/meetings.ts
61
62
  function overlapsDate(beginDatetime, endDatetime, date) {
@@ -2221,7 +2222,7 @@ var meetingAttachmentAttach = {
2221
2222
  if (mode === "append" && existingIds.length === 0) {
2222
2223
  existingIds.push(...beforeIds);
2223
2224
  }
2224
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
2225
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2225
2226
  const list = getMeetingOperation2("meeting.eb.meeting.list");
2226
2227
  let fileId = incomingFileId;
2227
2228
  let name = String(args.name ?? "").trim();
@@ -2309,7 +2310,7 @@ function textOf(value) {
2309
2310
  return value === void 0 || value === null ? "" : String(value);
2310
2311
  }
2311
2312
  async function readMinute(env, id) {
2312
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
2313
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2313
2314
  const detail = getMeetingOperation2("meeting.eb.minute.detail");
2314
2315
  const result = await detail.handler({ id }, env);
2315
2316
  const row = result?.data?.data;
@@ -2388,7 +2389,7 @@ var meetingMinuteWriteContent = {
2388
2389
  } else {
2389
2390
  statusReason = "\u4EC5\u6E05\u7A7A\u5185\u5BB9\uFF0C\u672A\u6539\u72B6\u6001";
2390
2391
  }
2391
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
2392
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2392
2393
  const prepare = getMeetingOperation2("meeting.eb.minute.update.prepare");
2393
2394
  const apply = getMeetingOperation2("meeting.eb.minute.update.apply");
2394
2395
  const prepared = await prepare.handler({ id, mt_id: mtId, ...patch }, env);
@@ -2518,8 +2519,8 @@ function parseLocalTime(value) {
2518
2519
  return Number.isNaN(parsed.getTime()) ? null : parsed;
2519
2520
  }
2520
2521
  function formatStamp(d) {
2521
- const pad2 = (n) => String(n).padStart(2, "0");
2522
- 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())}`;
2523
2524
  }
2524
2525
  function computeChatWindow(meeting, now = /* @__PURE__ */ new Date()) {
2525
2526
  const begin = parseLocalTime(meeting.begin_datetime);
@@ -2647,16 +2648,16 @@ function buildDigest(messages, nameByUid, keepSystem, maxChars) {
2647
2648
  return { transcript, kept: lines.length, dropped, truncated };
2648
2649
  }
2649
2650
  async function saveTranscript(ctx, mtId, transcript) {
2650
- const { mkdir: mkdir4, writeFile: writeFile4 } = await import("node:fs/promises");
2651
+ const { mkdir: mkdir5, writeFile: writeFile5 } = await import("node:fs/promises");
2651
2652
  const { join: join3 } = await import("node:path");
2652
2653
  const { stateDir } = await import("./state-Y2XBP6YE.js");
2653
2654
  const dir = join3(stateDir(ctx), "transcripts");
2654
- await mkdir4(dir, { recursive: true });
2655
- const pad2 = (n) => String(n).padStart(2, "0");
2655
+ await mkdir5(dir, { recursive: true });
2656
+ const pad3 = (n) => String(n).padStart(2, "0");
2656
2657
  const now = /* @__PURE__ */ new Date();
2657
- 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())}`;
2658
2659
  const filePath = join3(dir, `${mtId}-${stamp2}.txt`);
2659
- await writeFile4(filePath, transcript, "utf8");
2660
+ await writeFile5(filePath, transcript, "utf8");
2660
2661
  return filePath;
2661
2662
  }
2662
2663
  var meetingMinuteFromGroupChat = {
@@ -2746,7 +2747,7 @@ var meetingMinuteFromGroupChat = {
2746
2747
  const mtId = textOf2(args.mt_id).trim();
2747
2748
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
2748
2749
  const pipeline = ["text", "minutes", "document"].includes(args.pipeline) ? args.pipeline : "text";
2749
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
2750
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
2750
2751
  const ctx = env.ctx;
2751
2752
  let stepStart = Date.now();
2752
2753
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
@@ -2770,7 +2771,7 @@ var meetingMinuteFromGroupChat = {
2770
2771
  }
2771
2772
  mark("readMeeting", stepStart);
2772
2773
  const pullStart = Date.now();
2773
- const { createImHost } = await import("./host-DGE2TZD4.js");
2774
+ const { createImHost } = await import("./host-Q4LZGCRU.js");
2774
2775
  const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
2775
2776
  const { getImOperation } = await import("./registry-OZSMDVPP.js");
2776
2777
  const imEnv = { ctx, host: createImHost(ctx), continuation: createImContinuationSigner(ctx) };
@@ -2838,9 +2839,9 @@ var meetingMinuteFromGroupChat = {
2838
2839
  const extraSections = [];
2839
2840
  for (const file of extraFiles) {
2840
2841
  try {
2841
- const { readFile: readFile4 } = await import("node:fs/promises");
2842
- const buffer = await readFile4(file);
2843
- const { extractText } = await import("./attachment-content-OSAVA6K3.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");
2844
2845
  const extracted = extractText(buffer, file, "");
2845
2846
  if (extracted.text.trim()) {
2846
2847
  extraSections.push(`\u3010\u6750\u6599\uFF1A${file.split(/[\\/]/).pop() ?? file}\u3011
@@ -2967,9 +2968,9 @@ ${groupTranscript}` : ""
2967
2968
  if (!employeeId) {
2968
2969
  warnings.push("\u672A\u53D6\u5230 ESB \u89E6\u53D1\u4EBA id\uFF08employeeId\uFF09\uFF0C\u5DF2\u8DF3\u8FC7\u540E\u7EED ESB \u8C03\u7528");
2969
2970
  } else {
2970
- const { createEsbHost } = await import("./host-BCGUVEWX.js");
2971
+ const { createEsbHost } = await import("./host-I4NRK4MX.js");
2971
2972
  const { createEsbContinuationSigner } = await import("./continuation-NLECEJPX.js");
2972
- const { getEsbOperation } = await import("./registry-JHRIDQ3A.js");
2973
+ const { getEsbOperation } = await import("./registry-KDD7DHNK.js");
2973
2974
  const esbEnv = { ctx, host: createEsbHost(ctx), continuation: createEsbContinuationSigner(ctx) };
2974
2975
  const prepareOp = getEsbOperation("esb.trigger.prepare");
2975
2976
  const applyOp = getEsbOperation("esb.trigger.apply");
@@ -3153,7 +3154,7 @@ var meetingDecisionNotifyGroup = {
3153
3154
  const warnings = [];
3154
3155
  const mtId = textOf3(args.mt_id).trim();
3155
3156
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
3156
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
3157
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
3157
3158
  const ctx = env.ctx;
3158
3159
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
3159
3160
  { mt_id: mtId, pageNo: 1, pageSize: 1 },
@@ -3217,7 +3218,7 @@ var meetingDecisionNotifyGroup = {
3217
3218
  charCount: formatted.text.length,
3218
3219
  text: formatted.text
3219
3220
  };
3220
- const { createImHost } = await import("./host-DGE2TZD4.js");
3221
+ const { createImHost } = await import("./host-Q4LZGCRU.js");
3221
3222
  const imHost = createImHost(ctx);
3222
3223
  let displayText = formatted.text;
3223
3224
  let wireText = formatted.text;
@@ -3359,14 +3360,14 @@ function defaultDueDate(begin, days) {
3359
3360
  const base = new Date(normalized.replace(/-/g, "/"));
3360
3361
  const start = Number.isNaN(base.getTime()) ? /* @__PURE__ */ new Date() : base;
3361
3362
  const due = new Date(start.getTime() + Math.max(days, 1) * 24 * 36e5);
3362
- const pad2 = (n) => String(n).padStart(2, "0");
3363
- 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`;
3364
3365
  }
3365
3366
  async function waitForTaskIncrease(fetchTotal, baseline, timeoutMs = 15e3, intervalMs = 2e3) {
3366
3367
  const start = Date.now();
3367
3368
  let total = baseline;
3368
3369
  while (Date.now() - start < timeoutMs) {
3369
- await new Promise((resolve5) => setTimeout(resolve5, intervalMs));
3370
+ await new Promise((resolve6) => setTimeout(resolve6, intervalMs));
3370
3371
  total = await fetchTotal();
3371
3372
  if (total > baseline) return { total, waitedMs: Date.now() - start, increased: true };
3372
3373
  }
@@ -3455,7 +3456,7 @@ var meetingPipelineRun = {
3455
3456
  const needsConfirm = level === "tasks" || level === "notify";
3456
3457
  const confirmed = args.confirm === true;
3457
3458
  const executedLevel = needsConfirm && !confirmed ? "document" : level;
3458
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
3459
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
3459
3460
  const ctx = env.ctx;
3460
3461
  let stepStart = Date.now();
3461
3462
  const reuseMinuteId = textOf4(args.minuteId).trim();
@@ -3524,7 +3525,7 @@ var meetingPipelineRun = {
3524
3525
  ]);
3525
3526
  }
3526
3527
  stepStart = Date.now();
3527
- const { createHrmHost } = await import("./host-KXPTEWFS.js");
3528
+ const { createHrmHost } = await import("./host-XCLDDXKQ.js");
3528
3529
  const { getHrmOperation } = await import("./registry-NYPYMZXG.js");
3529
3530
  const hrmEnv = { ctx, host: createHrmHost(ctx) };
3530
3531
  const queryOp = getHrmOperation("hrm.employee.query");
@@ -3562,8 +3563,8 @@ var meetingPipelineRun = {
3562
3563
  })();
3563
3564
  const beginAt = textOf4(meetingInfo.end_datetime).trim() || textOf4(meetingInfo.begin_datetime).trim() || (() => {
3564
3565
  const now = /* @__PURE__ */ new Date();
3565
- const pad2 = (n) => String(n).padStart(2, "0");
3566
- 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())}`;
3567
3568
  })();
3568
3569
  const dueDays = typeof args.taskDueDays === "number" && args.taskDueDays > 0 ? args.taskDueDays : 7;
3569
3570
  const dueAt = defaultDueDate(beginAt, dueDays);
@@ -3721,6 +3722,7 @@ var meetingPipelineRun = {
3721
3722
  var meetingPipelineOperations = [meetingPipelineRun];
3722
3723
 
3723
3724
  // src/shortcuts/meeting/operations/invitation.ts
3725
+ import { existsSync as existsSync2 } from "node:fs";
3724
3726
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
3725
3727
  import { dirname, join, resolve as resolve3 } from "node:path";
3726
3728
  import { fileURLToPath } from "node:url";
@@ -3728,6 +3730,14 @@ function templatePath() {
3728
3730
  const override = process.env.WEAVER_MEETING_INVITATION_TEMPLATE;
3729
3731
  if (override) return resolve3(override);
3730
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
+ }
3731
3741
  return resolve3(here, "../../../../templates/meeting/invitation.docx");
3732
3742
  }
3733
3743
  var WEEKDAYS = ["\u661F\u671F\u65E5", "\u661F\u671F\u4E00", "\u661F\u671F\u4E8C", "\u661F\u671F\u4E09", "\u661F\u671F\u56DB", "\u661F\u671F\u4E94", "\u661F\u671F\u516D"];
@@ -3765,7 +3775,7 @@ function formatTimeRange(start, end) {
3765
3775
  }
3766
3776
  async function loadAgendaFromTopics(env, mtId) {
3767
3777
  try {
3768
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
3778
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
3769
3779
  const operation = getMeetingOperation2("meeting.eb.topic.list");
3770
3780
  const result = await operation.handler({ mt_id: mtId, pageNo: 1, pageSize: 200 }, env);
3771
3781
  const rows = result.data?.rows ?? [];
@@ -3952,7 +3962,17 @@ var meetingInvitationRender = {
3952
3962
  type: "object",
3953
3963
  additionalProperties: false,
3954
3964
  properties: {
3955
- 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" },
3956
3976
  extra: {
3957
3977
  type: "object",
3958
3978
  additionalProperties: { type: "string" },
@@ -3963,41 +3983,66 @@ var meetingInvitationRender = {
3963
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"
3964
3984
  }
3965
3985
  },
3966
- required: ["mtId"]
3986
+ required: []
3967
3987
  },
3968
3988
  handler: async (args, env) => {
3969
3989
  const mtId = String(args.mtId ?? "").trim();
3970
- if (!mtId) {
3971
- throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mtId\uFF09");
3972
- }
3973
3990
  const extra = {};
3974
3991
  if (args.extra && typeof args.extra === "object") {
3975
3992
  for (const [key, value] of Object.entries(args.extra)) {
3976
3993
  if (value !== void 0 && value !== null) extra[key] = String(value);
3977
3994
  }
3978
3995
  }
3979
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
3980
- const listOperation = getMeetingOperation2("meeting.eb.meeting.list");
3981
3996
  let row;
3982
- try {
3983
- const listed = await listOperation.handler({ mt_id: mtId, pageNo: 1, pageSize: 1 }, env);
3984
- const rows = listed.data?.rows ?? [];
3985
- row = rows[0]?.mainTable ?? rows[0];
3986
- } catch (error) {
3987
- throw meetingValidationError(
3988
- "invitation_source_unavailable",
3989
- `\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)}`,
3990
- { mtId }
3991
- );
3992
- }
3993
- if (!row) {
3994
- 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
+ }
3995
4040
  }
3996
4041
  const creatorId = String(row.creator ?? "").trim();
3997
4042
  const needsIssuerOrg = !String(row.org_members ?? "").trim() && creatorId !== "";
3998
4043
  const issuerOrg = needsIssuerOrg ? await resolveIssuerOrganization(env, creatorId) : null;
3999
4044
  const { resolver, orgSource } = buildResolver(row, extra, issuerOrg);
4000
- let agendaRows = await loadAgendaFromTopics(env, mtId);
4045
+ let agendaRows = dataSource === "meeting" && mtId ? await loadAgendaFromTopics(env, mtId) : [];
4001
4046
  let agendaSource = agendaRows.length > 0 ? "meeting.topic" : "template";
4002
4047
  if (agendaRows.length === 0) {
4003
4048
  const fromExtra = parseAgendaFromExtra(extra.agenda);
@@ -4026,6 +4071,11 @@ var meetingInvitationRender = {
4026
4071
  await mkdir2(dirname(target), { recursive: true });
4027
4072
  await writeFile2(target, rendered.buffer);
4028
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
+ }
4029
4079
  if (rendered.pending.length > 0) {
4030
4080
  warnings.push(
4031
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")}`
@@ -4050,8 +4100,10 @@ var meetingInvitationRender = {
4050
4100
  filePath: target,
4051
4101
  fileName,
4052
4102
  bytes: rendered.buffer.length,
4053
- meetingId: mtId,
4103
+ meetingId: mtId || null,
4054
4104
  meetingName: String(row.mt_name ?? ""),
4105
+ // meeting=按真实会议数据;payload=按申请单字段预生成(会议可能还没生成,属预置函)
4106
+ dataSource,
4055
4107
  filledFields: rendered.filled,
4056
4108
  pendingFields: rendered.pending,
4057
4109
  // 落款单位的实际来源,便于调用方判断是否需要人工改写
@@ -4354,7 +4406,7 @@ function buildCodewords(bytes, version, ecc) {
4354
4406
  for (const byte of bytes) appendBits(byte, 8);
4355
4407
  appendBits(0, Math.min(4, capacityBits - bits.length));
4356
4408
  appendBits(0, (8 - bits.length % 8) % 8);
4357
- 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);
4358
4410
  const dataCodewords = new Array(bits.length / 8).fill(0);
4359
4411
  bits.forEach((bit, i) => {
4360
4412
  dataCodewords[i >>> 3] |= bit << 7 - (i & 7);
@@ -4540,8 +4592,8 @@ function renderQrSvg(matrix, options = {}) {
4540
4592
  var ECC_LEVELS = ["L", "M", "Q", "H"];
4541
4593
  function stamp() {
4542
4594
  const now = /* @__PURE__ */ new Date();
4543
- const pad2 = (n) => String(n).padStart(2, "0");
4544
- 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())}`;
4545
4597
  }
4546
4598
  function safeName(input) {
4547
4599
  return input.replace(/[\\/:*?"<>|\s]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
@@ -4706,7 +4758,7 @@ var meetingSummaryGet = {
4706
4758
  const mtId = textOf5(args.mt_id).trim();
4707
4759
  if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
4708
4760
  const ctx = env.ctx;
4709
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
4761
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
4710
4762
  const warnings = [];
4711
4763
  const timings = {};
4712
4764
  const include = Array.isArray(args.include) && args.include.length > 0 ? args.include.filter((item) => ALL_SECTIONS.includes(item)) : ALL_SECTIONS;
@@ -4842,7 +4894,7 @@ var meetingSummaryGet = {
4842
4894
  warnings.push("\u8BE5\u4F1A\u8BAE\u6CA1\u6709\u5173\u8054\u7FA4\u804A\uFF08imchat_groupid \u4E3A\u7A7A\uFF09\uFF0Cchat \u6BB5\u4E3A null");
4843
4895
  } else {
4844
4896
  try {
4845
- const { createImHost } = await import("./host-DGE2TZD4.js");
4897
+ const { createImHost } = await import("./host-Q4LZGCRU.js");
4846
4898
  const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
4847
4899
  const { getImOperation } = await import("./registry-OZSMDVPP.js");
4848
4900
  const imEnv = {
@@ -4968,7 +5020,7 @@ var meetingFormFields = {
4968
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"
4969
5021
  }, { warnings: resolved.warnings });
4970
5022
  }
4971
- const { createEbuilderFormHost } = await import("./host-BQBRHVR3.js");
5023
+ const { createEbuilderFormHost } = await import("./host-UEI5FGDM.js");
4972
5024
  const { createEbuilderFormContinuationSigner } = await import("./continuation-RN6PZN2M.js");
4973
5025
  const { executeEbuilderFormOperation } = await import("./operations-5QL3AECO.js");
4974
5026
  const formEnv = {
@@ -5020,15 +5072,15 @@ var CONTINUATION_TTL_SECONDS6 = 600;
5020
5072
  var DATE_PATTERN = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}$";
5021
5073
  function formatSecondNow() {
5022
5074
  const now = /* @__PURE__ */ new Date();
5023
- const pad2 = (value) => String(value).padStart(2, "0");
5024
- 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())}`;
5025
5077
  }
5026
5078
  var DECISION_DONE = "2";
5027
5079
  var MT_STATUS_OVER = "8";
5028
5080
  var CANCELLED_MARK_DELAY_MS = 800;
5029
5081
  async function isCancelledMeeting(env, mtId) {
5030
5082
  try {
5031
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
5083
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
5032
5084
  const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
5033
5085
  // withCount:false —— 这里只要一行状态,不必额外请求 count(少一次往返,也便于测试替身)
5034
5086
  { mt_id: mtId, pageNo: 1, pageSize: 1, withCount: false },
@@ -5247,8 +5299,8 @@ var decisionPublishApply = {
5247
5299
  );
5248
5300
  }
5249
5301
  if (cancelled) {
5250
- await new Promise((resolve5) => {
5251
- setTimeout(resolve5, CANCELLED_MARK_DELAY_MS);
5302
+ await new Promise((resolve6) => {
5303
+ setTimeout(resolve6, CANCELLED_MARK_DELAY_MS);
5252
5304
  });
5253
5305
  warnings.push(
5254
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`
@@ -5550,6 +5602,10 @@ var ebMeetingAssociation = async (ctx) => {
5550
5602
  };
5551
5603
 
5552
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";
5553
5609
  var FIELD_ALIASES = {
5554
5610
  mt_name: ["\u4F1A\u8BAE\u540D\u79F0", "\u4F1A\u8BAE\u4E3B\u9898", "\u4E3B\u9898"],
5555
5611
  begin_datetime: ["\u5F00\u59CB\u65F6\u95F4", "\u4F1A\u8BAE\u5F00\u59CB\u65F6\u95F4"],
@@ -5568,9 +5624,9 @@ function workflowEnv(env) {
5568
5624
  return env;
5569
5625
  }
5570
5626
  async function loadCreateForm(env, workflowId) {
5571
- const { createWorkflowHost } = await import("./host-VQ6JJXGQ.js");
5627
+ const { createWorkflowHost } = await import("./host-C6EL2RKL.js");
5572
5628
  const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
5573
- const { getWorkflowOperation } = await import("./registry-VOGKFFTR.js");
5629
+ const { getWorkflowOperation } = await import("./registry-TKX2E7C7.js");
5574
5630
  const wfEnv = {
5575
5631
  ...workflowEnv(env),
5576
5632
  host: createWorkflowHost(env.ctx),
@@ -5617,9 +5673,9 @@ async function resolveEmployeeNames(env, ids) {
5617
5673
  async function resolveRoomValue(env, input) {
5618
5674
  const text = String(input ?? "").trim();
5619
5675
  if (!text) return null;
5620
- const { loadRooms } = await import("./room-recommend-D4EUOOWY.js");
5676
+ const { loadRooms: loadRooms2 } = await import("./room-recommend-XCWRMB5P.js");
5621
5677
  try {
5622
- const { rooms } = await loadRooms(env, {});
5678
+ const { rooms } = await loadRooms2(env, {});
5623
5679
  const byId = rooms.find((room) => room.id === text);
5624
5680
  if (byId) return { id: byId.id, name: byId.name };
5625
5681
  const byName = rooms.find((room) => room.name === text);
@@ -5628,7 +5684,7 @@ async function resolveRoomValue(env, input) {
5628
5684
  }
5629
5685
  if (/^\d+$/.test(text)) {
5630
5686
  try {
5631
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
5687
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
5632
5688
  const detail = await getMeetingOperation2("meeting.eb.room.detail").handler({ id: text }, env);
5633
5689
  const main = detail?.data?.mainTable ?? detail?.data?.data?.mainTable ?? {};
5634
5690
  const name = String(main.room_name ?? "").trim();
@@ -5642,11 +5698,15 @@ async function resolveRoomValue(env, input) {
5642
5698
  async function shapeBrowserValues(env, values) {
5643
5699
  const notes = [];
5644
5700
  const shaped = { ...values };
5701
+ const readable = {};
5645
5702
  if (shaped.address !== void 0 && shaped.address !== "") {
5646
5703
  const room = await resolveRoomValue(env, String(shaped.address));
5647
5704
  if (room) {
5648
5705
  shaped.address = room;
5706
+ readable.address = room.name;
5649
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);
5650
5710
  }
5651
5711
  }
5652
5712
  const personFields = ["hrm_members", "caller", "contacter"];
@@ -5660,39 +5720,112 @@ async function shapeBrowserValues(env, values) {
5660
5720
  if (idPool.length > 0) {
5661
5721
  const names = await resolveEmployeeNames(env, idPool);
5662
5722
  const toObject = (id) => ({ id, name: names.get(id) ?? id });
5723
+ const toName = (id) => names.get(id) ?? id;
5663
5724
  if (shaped.hrm_members !== void 0 && shaped.hrm_members !== "") {
5664
5725
  const ids = String(shaped.hrm_members).split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
5665
5726
  shaped.hrm_members = ids.map(toObject);
5727
+ readable.hrm_members = ids.map(toName).join("\u3001");
5666
5728
  notes.push(`\u53C2\u4F1A\u4EBA\u5458\u6309\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${ids.length} \u4EBA`);
5667
5729
  }
5668
5730
  if (shaped.caller !== void 0 && shaped.caller !== "") {
5669
5731
  const id = String(shaped.caller).trim();
5670
5732
  shaped.caller = toObject(id);
5733
+ readable.caller = toName(id);
5671
5734
  }
5672
5735
  if (shaped.contacter !== void 0 && shaped.contacter !== "") {
5673
5736
  const id = String(shaped.contacter).trim();
5674
5737
  shaped.contacter = toObject(id);
5738
+ readable.contacter = toName(id);
5675
5739
  }
5676
5740
  }
5677
- 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 };
5748
+ }
5749
+ function normalizeFieldName(name) {
5750
+ return String(name ?? "").replace(/[((][^(())]*[))]/g, "").replace(/[\s\u3000]+/g, "").trim();
5678
5751
  }
5679
- function mapFields(fields, values) {
5752
+ function mapFields(fields, values, preferred = {}) {
5680
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
+ }
5681
5760
  const main = {};
5682
5761
  const mapped = {};
5683
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
+ };
5684
5782
  for (const [key, raw] of Object.entries(values)) {
5685
5783
  if (raw === void 0 || raw === null || raw === "") continue;
5686
5784
  const aliases = FIELD_ALIASES[key] ?? [key];
5687
- const hit = aliases.map((name) => byName.get(name)).find((field) => field !== void 0);
5785
+ const prefId = preferred[key];
5786
+ const hit = (prefId ? byId.get(prefId) : void 0) ?? findField(aliases);
5688
5787
  if (!hit) {
5689
5788
  unmapped.push(key);
5690
5789
  continue;
5691
5790
  }
5692
5791
  main[hit.id] = raw;
5693
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 {
5694
5828
  }
5695
- return { main, mapped, unmapped };
5696
5829
  }
5697
5830
  function normalizeWorkflowIds(raw) {
5698
5831
  if (raw === void 0 || raw === null) return [];
@@ -5709,6 +5842,45 @@ function normalizeWorkflowIds(raw) {
5709
5842
  }
5710
5843
  return ids;
5711
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";
5883
+ }
5712
5884
  async function resolveWorkflowId(env, args) {
5713
5885
  const explicitList = normalizeWorkflowIds(args.workflowId);
5714
5886
  if (explicitList.length > 0) {
@@ -5718,30 +5890,88 @@ async function resolveWorkflowId(env, args) {
5718
5890
  source: "argument"
5719
5891
  };
5720
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
+ }
5721
5902
  const settings = await fetchEbAppSettings(env, "meeting.eb.meeting.create.flow.prepare");
5722
5903
  const candidates = String(settings.mtNewWf ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
5723
5904
  if (candidates.length === 0) {
5724
5905
  throw meetingValidationError(
5725
5906
  "flow_not_configured",
5726
- "\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"
5727
5908
  );
5728
5909
  }
5729
5910
  return { workflowId: candidates.length === 1 ? candidates[0] : "", candidates, source: "settings" };
5730
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 };
5954
+ }
5731
5955
  var ebMeetingCreateFlowPrepare = {
5732
5956
  name: "meeting.eb.meeting.create.flow.prepare",
5733
5957
  resource: "eb",
5734
5958
  method: "meeting.eb.meeting.create.flow.prepare",
5735
5959
  action: "meeting.eb.meeting.create.flow.prepare",
5736
- 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",
5737
5961
  capability: "eb.meeting",
5738
5962
  risk: "read-before-write",
5739
5963
  requiresConfirmation: true,
5740
5964
  inputSchema: schemaOf(
5741
5965
  {
5742
5966
  mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
5743
- begin_datetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
5744
- 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
+ },
5745
5975
  mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
5746
5976
  address: { type: "string", description: "\u4F1A\u8BAE\u5BA4\uFF08\u540D\u79F0\u6216 id\uFF0C\u6309\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u8981\u6C42\uFF09" },
5747
5977
  customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
@@ -5749,6 +5979,10 @@ var ebMeetingCreateFlowPrepare = {
5749
5979
  total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
5750
5980
  caller: { type: "string", description: "\u53EC\u96C6\u4EBA" },
5751
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
+ },
5752
5986
  other_remark: { type: "string", description: "\u5907\u6CE8" },
5753
5987
  workflowId: {
5754
5988
  oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
@@ -5756,117 +5990,161 @@ var ebMeetingCreateFlowPrepare = {
5756
5990
  },
5757
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" },
5758
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
+ },
5759
6001
  extraFields: {
5760
6002
  type: "object",
5761
- 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'
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"
5762
6024
  }
5763
6025
  },
5764
- { required: ["mt_name", "begin_datetime", "end_datetime"] }
6026
+ { required: ["mt_name"] }
5765
6027
  ),
5766
6028
  handler: async (args, env) => {
5767
- const resolved = await resolveWorkflowId(env, args);
5768
- const candidates = resolved.candidates;
5769
- let workflowId = resolved.workflowId;
5770
- const sourceLabel = resolved.source === "argument" ? "\u8C03\u7528\u65B9\u4F20\u5165" : "\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E";
5771
- const probes = [];
5772
- const loadedForms = /* @__PURE__ */ new Map();
5773
- if (!workflowId && candidates.length > 1) {
5774
- const probed = await Promise.all(candidates.map(async (id) => {
5775
- try {
5776
- const probeForm = await loadCreateForm(env, id);
5777
- return {
5778
- id,
5779
- probeForm,
5780
- probe: {
5781
- workflowId: id,
5782
- ...probeForm.workflowName ? { name: probeForm.workflowName } : {},
5783
- launchable: true
5784
- }
5785
- };
5786
- } catch (error) {
5787
- return {
5788
- id,
5789
- probeForm: null,
5790
- probe: {
5791
- workflowId: id,
5792
- launchable: false,
5793
- reason: String(error?.message ?? error).slice(0, 160)
5794
- }
5795
- };
5796
- }
5797
- }));
5798
- for (const item of probed) {
5799
- if (item.probeForm) loadedForms.set(item.id, item.probeForm);
5800
- probes.push(item.probe);
5801
- }
5802
- const launchable = probes.filter((probe) => probe.launchable);
5803
- if (launchable.length === 0) {
5804
- throw meetingValidationError(
5805
- "flow_not_launchable",
5806
- `${sourceLabel}\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"),
5807
- { probes }
5808
- );
5809
- }
5810
- if (launchable.length > 1) {
5811
- return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
5812
- status: "NEEDS_SELECTION",
5813
- message: `${sourceLabel}\u4E86 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77\u5176\u4E2D ${launchable.length} \u4E2A\uFF0C\u8BF7\u8BA9\u7528\u6237\u9009\u62E9\u8981\u89E6\u53D1\u54EA\u4E00\u4E2A \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`,
5814
- options: launchable.map((probe, index) => ({
5815
- key: `W${index + 1}`,
5816
- label: probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId,
5817
- value: { workflowId: probe.workflowId },
5818
- reason: "\u5F53\u524D\u8D26\u53F7\u6709\u53D1\u8D77\u6743\u9650",
5819
- // 把该流程的字段名如实带出来:不同流程字段差异很大(有的有设备需求/涉密项目,有的没有),
5820
- // 用户要靠这个才能选对(2026-10-29 用户反馈:选错方式后字段全填不进去)。
5821
- fields: (loadedForms.get(probe.workflowId)?.fields ?? []).map((f) => f.name).filter(Boolean)
5822
- })),
5823
- probes
5824
- }, {
5825
- warnings: [
5826
- `${sourceLabel}\u4E86 ${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`,
5827
- ...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`)
5828
- ]
5829
- });
5830
- }
5831
- workflowId = launchable[0].workflowId;
5832
- }
5833
- const form = loadedForms.get(workflowId) ?? await loadCreateForm(env, workflowId);
5834
- if (!form.continuation) {
5835
- throw meetingValidationError("flow_context_missing", "\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u6CA1\u6709\u8FD4\u56DE continuation\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u63D0\u4EA4");
5836
- }
6029
+ let workflowId = "";
6030
+ let flowPickNote = null;
5837
6031
  const decisions = {};
5838
6032
  const enrich = args.enrich !== false;
5839
6033
  const beginText = String(args.begin_datetime ?? "").trim();
5840
- const endText = String(args.end_datetime ?? "").trim();
5841
- 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
+ }
5842
6108
  let addressInput = args.address;
5843
6109
  const hadAddressInput = String(args.address ?? "").trim() !== "";
5844
6110
  const day = beginText.slice(0, 10);
5845
6111
  const durationMinutes = beginText && endText ? Math.max(15, Math.round((Date.parse(endText.replace(" ", "T")) - Date.parse(beginText.replace(" ", "T"))) / 6e4) || 60) : 60;
5846
6112
  const timings = {};
5847
6113
  const startedAt = Date.now();
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);
5848
6123
  const roomTask = enrich && beginText && endText ? recommendRooms(env, {
5849
6124
  beginDatetime: beginText,
5850
6125
  endDatetime: endText,
5851
- ...memberIds.length > 0 ? { memberCount: memberIds.length } : {},
6126
+ ...roomMemberCount ? { memberCount: roomMemberCount } : {},
6127
+ // 建会是"要下单"的场景:宁可多一次请求也必须拿最新台账(24h 缓存会让刚导入的会议室看不到)。
6128
+ refreshRooms: true,
5852
6129
  topN: 3
5853
- }).catch(() => null) : Promise.resolve(null);
6130
+ }).catch(noteFailure("\u4F1A\u8BAE\u5BA4\u63A8\u8350")) : Promise.resolve(null);
5854
6131
  const addressId = String(addressInput ?? "").trim();
5855
6132
  const addressIsRoomId = /^\d+$/.test(addressId);
6133
+ const roomConfirmed = args.roomConfirmed === true;
5856
6134
  const roomConflictTask = enrich && beginText && endText && addressIsRoomId ? (async () => {
5857
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
6135
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
5858
6136
  return getMeetingOperation2("meeting.eb.conflict.room").handler(
5859
6137
  { beginDatetime: beginText, endDatetime: endText, address: addressId },
5860
6138
  env
5861
6139
  );
5862
- })().catch(() => null) : Promise.resolve(null);
6140
+ })().catch(noteFailure("\u4F1A\u8BAE\u5BA4**\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
5863
6141
  const conflictTask = enrich && beginText && endText && memberIds.length > 0 ? (async () => {
5864
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
6142
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
5865
6143
  return getMeetingOperation2("meeting.eb.conflict.member").handler(
5866
6144
  { beginDatetime: beginText, endDatetime: endText, hrmMembers: memberIds.join(",") },
5867
6145
  env
5868
6146
  );
5869
- })().catch(() => null) : Promise.resolve(null);
6147
+ })().catch(noteFailure("\u53C2\u4F1A\u4EBA**\u4F1A\u8BAE\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
5870
6148
  const availabilityTask = enrich && beginText && endText && memberIds.length > 0 ? findCommonFreeSlots(env, {
5871
6149
  rangeStart: `${day} 00:00`,
5872
6150
  rangeEnd: `${day} 23:59`,
@@ -5875,7 +6153,7 @@ var ebMeetingCreateFlowPrepare = {
5875
6153
  maxSlots: 3,
5876
6154
  maxDays: 1,
5877
6155
  includeSchedule: true
5878
- }).catch(() => null) : Promise.resolve(null);
6156
+ }).catch(noteFailure("\u53C2\u4F1A\u4EBA**\u65E5\u7A0B\u7A7A\u95F2**\u68C0\u6D4B")) : Promise.resolve(null);
5879
6157
  const [roomRec, memberConflict, free, roomConflict] = await Promise.all([
5880
6158
  roomTask,
5881
6159
  conflictTask,
@@ -5883,14 +6161,41 @@ var ebMeetingCreateFlowPrepare = {
5883
6161
  roomConflictTask
5884
6162
  ]);
5885
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
+ );
5886
6190
  const roomOptions = (roomRec?.candidates ?? []).map((candidate, index) => ({
5887
6191
  key: `R${index + 1}`,
5888
6192
  label: `${candidate.name}${candidate.capacity.max > 0 ? `\uFF08\u53EF\u5BB9 ${candidate.capacity.max} \u4EBA\uFF09` : ""}${index === 0 ? " \xB7 \u63A8\u8350" : ""}`,
5889
- value: { id: candidate.id, name: candidate.name },
6193
+ // roomConfirmed: true = 用户点选该选项即代表"确认用这间",原样回传后下一轮才被认。
6194
+ value: { id: candidate.id, name: candidate.name, roomConfirmed: true },
5890
6195
  reason: candidate.reasons.join("\uFF1B")
5891
6196
  }));
5892
6197
  const roomConflictData = roomConflict?.data;
5893
- if (addressInput && roomConflictData?.hasConflict === true) {
6198
+ if (addressInput && roomConfirmed && roomConflictData?.hasConflict === true) {
5894
6199
  const busy = Array.isArray(roomConflictData.conflicts) ? roomConflictData.conflicts : [];
5895
6200
  decisions.roomConflict = {
5896
6201
  address: addressId,
@@ -5902,7 +6207,9 @@ var ebMeetingCreateFlowPrepare = {
5902
6207
  return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
5903
6208
  status: "NEEDS_SELECTION",
5904
6209
  selectionType: "room_conflict",
6210
+ ui: { component: "choice", multiple: false, recommendedKey: "R1" },
5905
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,
5906
6213
  options: roomOptions,
5907
6214
  recommended: roomOptions[0]?.value ?? null,
5908
6215
  conflicts: busy,
@@ -5922,18 +6229,38 @@ var ebMeetingCreateFlowPrepare = {
5922
6229
  meta: roomRec.meta
5923
6230
  };
5924
6231
  const autoRoom = args.autoRoom === true;
5925
- 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) {
5926
6245
  return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
5927
6246
  status: "NEEDS_SELECTION",
5928
6247
  selectionType: "room",
5929
- 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`,
5930
- options: roomOptions,
5931
- recommended: roomOptions[0]?.value ?? null,
5932
- 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
5933
6256
  }, {
5934
6257
  warnings: [
5935
- "\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF1A\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\uFF0C\u4E5F\u6CA1\u6709\u66FF\u7528\u6237\u6311\u623F\u95F4\u3002",
5936
- "\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
5937
6264
  ]
5938
6265
  });
5939
6266
  }
@@ -5950,37 +6277,149 @@ var ebMeetingCreateFlowPrepare = {
5950
6277
  return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
5951
6278
  status: "NEEDS_SELECTION",
5952
6279
  selectionType: "room_unavailable",
6280
+ ui: { component: "choice", multiple: false, recommendedKey: "C2" },
5953
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,
5954
6283
  options: [
5955
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" } },
5956
6285
  { key: "C2", label: "\u6539\u7528\u7EBF\u4E0A\u4F1A\u8BAE\uFF08\u817E\u8BAF\u4F1A\u8BAE/\u89C6\u9891\uFF09", value: { action: "no_room" } },
5957
6286
  { key: "C3", label: '\u5148\u6309"\u5730\u70B9\u5F85\u5B9A"\u63D0\u4EA4', value: { action: "allow_no_room" } }
5958
6287
  ],
5959
- roomUnavailable: decisions.roomUnavailable
6288
+ roomUnavailable: decisions.roomUnavailable,
6289
+ ...conflictBrief
5960
6290
  }, {
5961
6291
  warnings: [
5962
6292
  `\u4F1A\u8BAE\u5BA4\u63A8\u8350\u65E0\u7ED3\u679C\uFF1A${String(decisions.roomUnavailable.reason)}\u3002\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002`,
5963
- "\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"
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
5964
6297
  ]
5965
6298
  });
5966
6299
  }
5967
- const conflicts = memberConflict?.data?.conflicts ?? [];
5968
- if (conflicts.length > 0) decisions.memberConflicts = conflicts;
5969
- if (free) {
5970
- decisions.scheduleItems = free.scheduleItems;
5971
- decisions.availabilityCost = free.cost;
5972
- if (free.slots.length > 0) {
5973
- decisions.suggestedSlots = free.slots;
5974
- decisions.slotOptions = free.slots.map((slot, index) => ({
5975
- key: `T${index + 1}`,
5976
- label: `${slot.begin.slice(11)}~${slot.end.slice(11)}\uFF08${day}\uFF09 \xB7 \u5168\u90E8\u53C2\u4F1A\u4EBA\u7A7A\u95F2`,
5977
- value: { begin: slot.begin, end: slot.end },
5978
- 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"
5979
- }));
5980
- } else if (free.blockingSummary) {
5981
- decisions.dayBlocked = { day, summary: free.blockingSummary };
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`;
5982
6406
  }
5983
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
+ );
6418
+ }
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
+ }
5984
6423
  decisions.timings = timings;
5985
6424
  const shaped = await shapeBrowserValues(env, {
5986
6425
  mt_name: args.mt_name,
@@ -5997,9 +6436,30 @@ var ebMeetingCreateFlowPrepare = {
5997
6436
  mt_type: args.mt_type,
5998
6437
  ...args.extraFields && typeof args.extraFields === "object" && !Array.isArray(args.extraFields) ? args.extraFields : {}
5999
6438
  });
6000
- 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);
6001
6442
  const warnings = [];
6443
+ if (flowPickNote) warnings.push(flowPickNote);
6002
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
+ }
6003
6463
  const picked = decisions.autoRoom?.picked;
6004
6464
  if (picked && !hadAddressInput) {
6005
6465
  warnings.push(
@@ -6007,20 +6467,28 @@ var ebMeetingCreateFlowPrepare = {
6007
6467
  );
6008
6468
  }
6009
6469
  const slotOptions = decisions.slotOptions ?? [];
6010
- 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) {
6011
6476
  warnings.push(
6012
- `\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")}`
6013
6478
  );
6014
6479
  } else if (decisions.dayBlocked?.summary) {
6015
6480
  warnings.push(String(decisions.dayBlocked.summary));
6016
6481
  }
6017
- if (unmapped.length > 0) {
6482
+ const unmappedReal = unmapped.filter((name) => name !== "mt_name");
6483
+ if (unmappedReal.length > 0) {
6018
6484
  warnings.push(
6019
- `\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`
6020
6486
  );
6021
6487
  }
6022
6488
  if (!main[form.fields.find((field) => field.name === "\u4F1A\u8BAE\u540D\u79F0")?.id ?? ""] && !mapped.mt_name) {
6023
- 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
+ );
6024
6492
  }
6025
6493
  const session = await env.host.getSession();
6026
6494
  const continuation = await env.continuation.issue(
@@ -6034,7 +6502,9 @@ var ebMeetingCreateFlowPrepare = {
6034
6502
  requestName: String(args.mt_name),
6035
6503
  mtName: String(args.mt_name),
6036
6504
  data: { main },
6037
- surfaceContinuation: form.continuation
6505
+ surfaceContinuation: form.continuation,
6506
+ // 供 apply 在「会议还没生成」时按申请单信息预生成邀请函(预置函)
6507
+ invitationFields: shaped.readable
6038
6508
  },
6039
6509
  fingerprint: JSON.stringify({ workflowId, main })
6040
6510
  },
@@ -6048,6 +6518,7 @@ var ebMeetingCreateFlowPrepare = {
6048
6518
  workflowId,
6049
6519
  workflowCandidates: candidates,
6050
6520
  ...probes.length > 0 ? { workflowProbes: probes } : {},
6521
+ ...flowPickNote ? { workflowAutoPicked: { workflowId, source: resolved.source, note: flowPickNote } } : {},
6051
6522
  requestName: String(args.mt_name),
6052
6523
  fieldMapping: mapped,
6053
6524
  formData: { main },
@@ -6061,6 +6532,43 @@ var ebMeetingCreateFlowPrepare = {
6061
6532
  );
6062
6533
  }
6063
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
+ }
6064
6572
  var ebMeetingCreateFlowApply = {
6065
6573
  name: "meeting.eb.meeting.create.flow.apply",
6066
6574
  resource: "eb",
@@ -6091,9 +6599,9 @@ var ebMeetingCreateFlowApply = {
6091
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");
6092
6600
  }
6093
6601
  const payload = lease?.payload ?? {};
6094
- const { createWorkflowHost } = await import("./host-VQ6JJXGQ.js");
6602
+ const { createWorkflowHost } = await import("./host-C6EL2RKL.js");
6095
6603
  const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
6096
- const { getWorkflowOperation } = await import("./registry-VOGKFFTR.js");
6604
+ const { getWorkflowOperation } = await import("./registry-TKX2E7C7.js");
6097
6605
  const wfEnv = {
6098
6606
  ...workflowEnv(env),
6099
6607
  host: createWorkflowHost(env.ctx),
@@ -6134,6 +6642,33 @@ var ebMeetingCreateFlowApply = {
6134
6642
  );
6135
6643
  }
6136
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
+ }
6137
6672
  const missing = submittedData.missingFields ?? submittedData.requiredMissing ?? submittedData.missing ?? [];
6138
6673
  throw meetingValidationError(
6139
6674
  "flow_submit_incomplete",
@@ -6146,7 +6681,7 @@ var ebMeetingCreateFlowApply = {
6146
6681
  let meetingId = "";
6147
6682
  const timings = { submitMs: Date.now() - submitStartedAt };
6148
6683
  if (waitSeconds > 0) {
6149
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
6684
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6150
6685
  const list = getMeetingOperation2("meeting.eb.meeting.list");
6151
6686
  const deadline = Date.now() + Math.min(waitSeconds, 30) * 1e3;
6152
6687
  const pollStart = Date.now();
@@ -6163,7 +6698,7 @@ var ebMeetingCreateFlowApply = {
6163
6698
  } catch {
6164
6699
  }
6165
6700
  if (waited >= 5e3) break;
6166
- await new Promise((resolve5) => setTimeout(resolve5, 5e3));
6701
+ await new Promise((resolve6) => setTimeout(resolve6, 5e3));
6167
6702
  waited += 5e3;
6168
6703
  }
6169
6704
  timings.pollMs = Date.now() - pollStart;
@@ -6172,7 +6707,7 @@ var ebMeetingCreateFlowApply = {
6172
6707
  if (meetingId) {
6173
6708
  const invitationStart = Date.now();
6174
6709
  try {
6175
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
6710
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6176
6711
  const render = getMeetingOperation2("meeting.invitation.render");
6177
6712
  const rendered = await render.handler({ mtId: meetingId }, env);
6178
6713
  invitation = { pending: false, ...rendered?.data ?? {} };
@@ -6185,8 +6720,11 @@ var ebMeetingCreateFlowApply = {
6185
6720
  };
6186
6721
  }
6187
6722
  } else {
6723
+ const pre = await renderPreInvitation(payload, env);
6724
+ invitation = pre.invitation;
6725
+ timings.invitationMs = pre.ms;
6188
6726
  warnings.push(
6189
- `\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`
6190
6728
  );
6191
6729
  }
6192
6730
  return meetingSuccess(
@@ -6217,8 +6755,14 @@ var ebMeetingCreateFlowQuick = {
6217
6755
  inputSchema: schemaOf(
6218
6756
  {
6219
6757
  mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
6220
- begin_datetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
6221
- 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
+ },
6222
6766
  mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
6223
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" },
6224
6768
  customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
@@ -6226,6 +6770,10 @@ var ebMeetingCreateFlowQuick = {
6226
6770
  total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
6227
6771
  caller: { type: "string", description: "\u53EC\u96C6\u4EBA" },
6228
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
+ },
6229
6777
  other_remark: { type: "string", description: "\u5907\u6CE8" },
6230
6778
  workflowId: {
6231
6779
  oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
@@ -6233,15 +6781,43 @@ var ebMeetingCreateFlowQuick = {
6233
6781
  },
6234
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" },
6235
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
+ },
6236
6792
  confirm: { type: "boolean", description: "\u5FC5\u987B\u663E\u5F0F true \u624D\u4F1A\u771F\u6B63\u63D0\u4EA4" },
6237
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" },
6238
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" },
6239
6795
  extraFields: {
6240
6796
  type: "object",
6241
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"
6242
6818
  }
6243
6819
  },
6244
- { required: ["mt_name", "begin_datetime", "end_datetime", "confirm"] }
6820
+ { required: ["mt_name", "confirm"] }
6245
6821
  ),
6246
6822
  handler: async (args, env) => {
6247
6823
  if (args.confirm !== true) {
@@ -6250,7 +6826,7 @@ var ebMeetingCreateFlowQuick = {
6250
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"
6251
6827
  );
6252
6828
  }
6253
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
6829
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6254
6830
  const prepareStartedAt = Date.now();
6255
6831
  const prepared = await getMeetingOperation2("meeting.eb.meeting.create.flow.prepare").handler(
6256
6832
  { ...args, confirm: void 0 },
@@ -6285,6 +6861,10 @@ var ebMeetingCreateFlowQuick = {
6285
6861
  requestId: applied?.data?.requestId,
6286
6862
  meetingId: applied?.data?.meetingId ?? null,
6287
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 } : {},
6288
6868
  decisions: prepared?.data?.preview?.decisions ?? null,
6289
6869
  timings: {
6290
6870
  ...prepared?.data?.preview?.decisions?.timings ?? {},
@@ -6299,7 +6879,123 @@ var ebMeetingCreateFlowQuick = {
6299
6879
  );
6300
6880
  }
6301
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
+ };
6302
6997
  var meetingEbCreateFlowOperations = [
6998
+ ebMeetingCreateSuggest,
6303
6999
  ebMeetingCreateFlowPrepare,
6304
7000
  ebMeetingCreateFlowApply,
6305
7001
  ebMeetingCreateFlowQuick
@@ -6392,7 +7088,7 @@ var ebAutoInvitationAfterWrite = async (context) => {
6392
7088
  const mtId = String(context.dataIds?.[0] ?? "").trim();
6393
7089
  if (!isCreate || !enabled || !mtId) return association;
6394
7090
  try {
6395
- const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
7091
+ const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-VRTNC6UR.js");
6396
7092
  const render = getMeetingOperation2("meeting.invitation.render");
6397
7093
  const result = await render.handler({ mtId }, context.env);
6398
7094
  return { ...association ?? {}, invitation: result?.data ?? null };