weaver-work-cli 0.1.33 → 0.1.38

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 (126) hide show
  1. package/dist/chunks/{archive-FVFY6GZN.js → archive-PDV724YK.js} +5 -4
  2. package/dist/chunks/{archive-oa-NW3OD4UV.js → archive-oa-4XE4MNXQ.js} +4 -3
  3. package/dist/chunks/{asset-7QJKMIDV.js → asset-PDL2QE2N.js} +8 -7
  4. package/dist/chunks/{attachment-content-OSAVA6K3.js → attachment-content-MDDGOE5E.js} +3 -3
  5. package/dist/chunks/{blog-I7SDPNW4.js → blog-UYR3EUXW.js} +5 -4
  6. package/dist/chunks/{caizhilian-O37ZIQNY.js → caizhilian-LG2X5NMF.js} +5 -4
  7. package/dist/chunks/{calendar-7KXE4ED3.js → calendar-FG4BAZHE.js} +4 -3
  8. package/dist/chunks/{chunk-Q6LWB5HX.js → chunk-6FTTSA45.js} +4 -3
  9. package/dist/chunks/{chunk-MQ2I5AA3.js → chunk-6LTFIFLM.js} +3 -2
  10. package/dist/chunks/{chunk-WRRJ4GG2.js → chunk-CORFRD7Q.js} +4 -3
  11. package/dist/chunks/{chunk-WY74UBJ6.js → chunk-DMV2TOMH.js} +2194 -240
  12. package/dist/chunks/{chunk-MEEFGWTM.js → chunk-ELYDWBZJ.js} +135 -10
  13. package/dist/chunks/{chunk-EEWPQE3O.js → chunk-FUWVHMVV.js} +7 -6
  14. package/dist/chunks/{chunk-HEL5XTYI.js → chunk-GGJFMNJM.js} +26 -4
  15. package/dist/chunks/{chunk-KAS45KNR.js → chunk-IZUDA353.js} +1 -1
  16. package/dist/chunks/{chunk-2FLWXFVS.js → chunk-J7USS3ED.js} +4 -4
  17. package/dist/chunks/{chunk-IHUYP6LO.js → chunk-JSMFPO43.js} +1 -1
  18. package/dist/chunks/{chunk-RBGOMK4Y.js → chunk-KKRL3REV.js} +5 -4
  19. package/dist/chunks/{chunk-OCU4RLHC.js → chunk-NI6GIPIM.js} +195 -36
  20. package/dist/chunks/{chunk-PRHJGPMA.js → chunk-NR6RKXPA.js} +2 -2
  21. package/dist/chunks/{chunk-D223PTXU.js → chunk-OJQUJZQF.js} +33 -7
  22. package/dist/chunks/{chunk-ILMBNVSG.js → chunk-UJJD4QWF.js} +4 -3
  23. package/dist/chunks/{chunk-6ATGWRZM.js → chunk-UZZBA6PV.js} +177 -14
  24. package/dist/chunks/{chunk-GFPXQIY2.js → chunk-VRYHGG6O.js} +2 -2
  25. package/dist/chunks/{chunk-NHA62QD7.js → chunk-XJY7G4DD.js} +3 -3
  26. package/dist/chunks/{chunk-VBCFFFGT.js → chunk-Z32KWY6G.js} +4 -1
  27. package/dist/chunks/{conflict-SFNEVJY5.js → conflict-BQZEQ4SP.js} +2 -2
  28. package/dist/chunks/contract-XIRAFTEV.js +9111 -0
  29. package/dist/chunks/{cowork-CKWYHXYB.js → cowork-BLG62BL2.js} +46 -26
  30. package/dist/chunks/{ebuilder-form-KOLJRVZD.js → ebuilder-form-NUKG5QW4.js} +3 -3
  31. package/dist/chunks/{ehr-WFOC3B4D.js → ehr-2STW5ILH.js} +174 -10
  32. package/dist/chunks/{esb-LJZTN663.js → esb-UUDQUNKY.js} +4 -4
  33. package/dist/chunks/{fna-F7QRIIZC.js → fna-6RCY4NU5.js} +15 -9
  34. package/dist/chunks/{host-VQ6JJXGQ.js → host-7RXEDMAH.js} +3 -3
  35. package/dist/chunks/{host-KXPTEWFS.js → host-EJZFROU3.js} +3 -3
  36. package/dist/chunks/{host-BCGUVEWX.js → host-FWDOSRH5.js} +3 -3
  37. package/dist/chunks/{host-DGE2TZD4.js → host-RHM3NPXV.js} +3 -3
  38. package/dist/chunks/{host-BQBRHVR3.js → host-UFF33TWJ.js} +3 -3
  39. package/dist/chunks/{hrm-NI6XAKW5.js → hrm-PKJ6ELSH.js} +3 -3
  40. package/dist/chunks/{im-7TRTF3KT.js → im-YJAXS7CO.js} +3 -3
  41. package/dist/chunks/{invoice-AOXWJKYT.js → invoice-HWVSXGX6.js} +3 -3
  42. package/dist/chunks/{jiuchuanhui-7NQWEZAW.js → jiuchuanhui-L7VKILZB.js} +4 -3
  43. package/dist/chunks/{lazy-dispatch-RNS4EE4S.js → lazy-dispatch-NMYEIHRH.js} +4 -4
  44. package/dist/chunks/{mail-VDHJAB4O.js → mail-B42RRU7G.js} +46 -24
  45. package/dist/chunks/{meeting-GA7XCNNP.js → meeting-CFYVBJSS.js} +77 -12
  46. package/dist/chunks/{okr-TQIRERPQ.js → okr-GCLF6V7W.js} +4 -3
  47. package/dist/chunks/{plan-4RY4LN2P.js → plan-ZVL7GBRI.js} +4 -3
  48. package/dist/chunks/{project-D6XT2OC5.js → project-4YWAAE2K.js} +4 -3
  49. package/dist/chunks/{registry-QKMI43Q6.js → registry-EP4VTHZS.js} +8 -8
  50. package/dist/chunks/{registry-JHRIDQ3A.js → registry-FRJ6H7BT.js} +4 -4
  51. package/dist/chunks/{registry-VOGKFFTR.js → registry-SG2PGVCF.js} +2 -2
  52. package/dist/chunks/{room-recommend-D4EUOOWY.js → room-recommend-R3JVUUAC.js} +4 -4
  53. package/dist/chunks/{schedule-XPFBHPCV.js → schedule-NIJBTYDO.js} +4 -4
  54. package/dist/chunks/{workflow-HLBZRWIY.js → workflow-BB24DFBY.js} +11 -4
  55. package/dist/index.js +31 -26
  56. package/dist/internal/e10/auth-recovery.js +114 -1
  57. package/dist/internal/e10/client.js +16 -2
  58. package/dist/internal/e10/fetch-timing.js +31 -0
  59. package/dist/internal/e10/request-runtime.js +108 -7
  60. package/dist/shortcuts/archive/host.js +3 -2
  61. package/dist/shortcuts/archive-oa/host.js +2 -1
  62. package/dist/shortcuts/asset/host.js +6 -5
  63. package/dist/shortcuts/blog/host.js +3 -2
  64. package/dist/shortcuts/caizhilian/host.js +3 -2
  65. package/dist/shortcuts/calendar/host.js +2 -1
  66. package/dist/shortcuts/contract/host.js +2 -1
  67. package/dist/shortcuts/cowork/host.js +10 -1
  68. package/dist/shortcuts/cowork/operations/types.js +17 -2
  69. package/dist/shortcuts/ebuilder-form/host.js +3 -1
  70. package/dist/shortcuts/ehr/host.js +2 -1
  71. package/dist/shortcuts/ehr/operations/recruit-write.js +35 -0
  72. package/dist/shortcuts/ehr/operations/recruit.js +147 -0
  73. package/dist/shortcuts/esb/host.js +2 -1
  74. package/dist/shortcuts/fna/host.js +2 -1
  75. package/dist/shortcuts/fna/operations/expense-chart.js +19 -7
  76. package/dist/shortcuts/hrm/host.js +2 -1
  77. package/dist/shortcuts/im/host.js +3 -2
  78. package/dist/shortcuts/index.js +5 -0
  79. package/dist/shortcuts/invoice/host.js +5 -4
  80. package/dist/shortcuts/jiuchuanhui/host.js +2 -1
  81. package/dist/shortcuts/mail/host.js +10 -1
  82. package/dist/shortcuts/mail/operations/types.js +17 -2
  83. package/dist/shortcuts/meeting/host.js +3 -2
  84. package/dist/shortcuts/meeting/index.js +79 -1
  85. package/dist/shortcuts/meeting/invitation/text.js +71 -0
  86. package/dist/shortcuts/meeting/manifest.js +10 -0
  87. package/dist/shortcuts/meeting/operations/eb/catalog.js +5 -0
  88. package/dist/shortcuts/meeting/operations/eb/conflict.js +6 -1
  89. package/dist/shortcuts/meeting/operations/eb/create-flow.js +2105 -169
  90. package/dist/shortcuts/meeting/operations/eb/crm-search.js +478 -0
  91. package/dist/shortcuts/meeting/operations/eb/factory.js +161 -8
  92. package/dist/shortcuts/meeting/operations/eb/index.js +2 -0
  93. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +36 -2
  94. package/dist/shortcuts/meeting/operations/eb-fallback.js +4 -0
  95. package/dist/shortcuts/meeting/operations/env.js +6 -0
  96. package/dist/shortcuts/meeting/operations/invitation.js +200 -28
  97. package/dist/shortcuts/okr/host.js +2 -1
  98. package/dist/shortcuts/plan/host.js +2 -1
  99. package/dist/shortcuts/project/host.js +2 -1
  100. package/dist/shortcuts/workflow/endpoints.js +8 -3
  101. package/dist/shortcuts/workflow/operations/form.js +341 -36
  102. package/dist/shortcuts/workflow/operations.js +23 -1
  103. package/docs/ehr.md +1 -1
  104. package/docs/fna.md +2 -1
  105. package/package.json +1 -1
  106. package/skill-template/business-info.json +18 -0
  107. package/skill-template/domains/cowork.md +14 -0
  108. package/skills/weaver-e10-cowork/SKILL.md +101 -0
  109. package/skills/weaver-e10-cowork/references/cowork-read.md +90 -0
  110. package/skills/weaver-e10-cowork/references/cowork-write.md +131 -0
  111. package/skills/weaver-e10-cowork/references/safety-boundaries.md +45 -0
  112. package/skills/weaver-e10-jucailin/SKILL.md +21 -3
  113. package/skills/weaver-e10-jucailin/references/recruit-read.md +25 -0
  114. package/skills/weaver-e10-jucailin/references/recruit-write.md +13 -0
  115. package/skills/weaver-e10-jucailin/references/salary.md +15 -11
  116. package/skills/weaver-e10-mail/SKILL.md +12 -9
  117. package/skills/weaver-e10-meeting/SKILL.md +499 -300
  118. package/skills/weaver-e10-meeting/references/meeting-eb.md +334 -0
  119. package/skills/weaver-e10-meeting/references/meeting-invitation.md +64 -6
  120. package/skills/weaver-e10-meeting.zip +0 -0
  121. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  122. package/skills/weaver-e10-qiyecheng/SKILL.md +5 -2
  123. package/skills/weaver-e10-qiyecheng/references/catalog.md +2 -2
  124. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +15 -1
  125. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +22 -21
  126. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
@@ -774,6 +774,11 @@ var EB_ENDPOINTS = [
774
774
  interfacePk: "query_meeting_room_list",
775
775
  countPk: "query_meeting_room_count",
776
776
  queryParams: ["manager", "departmentId", "mr_type", "room_attr"],
777
+ // 按 e-builder openApi 文档:这些是 `mainTable` 节点的传入字段,服务端据此过滤。
778
+ // ⚠️ 2026-10-30 实测(用户刚在后端把「会议室名称」配成传入字段后):
779
+ // 服务端是**精确匹配** —— room_name=测试会议室1 → 1 条;room_name=测试 / 重庆 → 0 条
780
+ // (全量里明明有「重庆会议室一/二」)。模糊由 factory 的 fallback 在本地兜底。
781
+ mainTableParams: ["room_name", "status", "place", "org_id", "hrm_ids"],
777
782
  summarizeRows: summarizeRoomRows,
778
783
  summary: "EB \u7248\u4F1A\u8BAE\u5BA4\u5217\u8868\uFF08query_meeting_room_list + count\uFF09\uFF1A\u81EA\u5E26 statusText \u4E0E\u72B6\u6001\u5B57\u5178",
779
784
  emptyHint: 'EB \u4F1A\u8BAE\u5BA4\u8868\uFF08`uf_mt_room_base`\uFF09\u67E5\u4E0D\u5230\u4EFB\u4F55\u8BB0\u5F55\u3002\u53EF\u80FD\u662F\uFF1A\u2460 \u8BE5\u73AF\u5883\u786E\u5B9E\u8FD8\u6CA1\u5EFA\u8FC7\u4F1A\u8BAE\u5BA4\uFF1B\u2461 \u4F1A\u8BAE\u5E94\u7528\u7684\u300C\u4F1A\u8BAE\u5BA4\u5217\u8868\u300D\u63A5\u53E3/\u89C6\u56FE\u672A\u914D\u7F6E\u597D\uFF08`query_meeting_room_list` \u8BFB\u4E0D\u5230\u6570\u636E\uFF0C\u4F46\u8868\u91CC\u6709\u6570\u636E\uFF09\u3002**\u8FD9\u4E0D\u4EE3\u8868"\u73AF\u5883\u662F\u6807\u51C6\u7248"\u2014\u2014\u7EDD\u5BF9\u4E0D\u8981\u6539\u7528 `meeting.room.list`**\uFF1A\u90A3\u662F\u6807\u51C6\u7248\u4F1A\u8BAE\u5E94\u7528\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u4E0E EB \u5B8C\u5168\u662F\u4E24\u5957\u6570\u636E\uFF0C\u62FF\u7ED9\u7528\u6237\u5C31\u662F\u51ED\u7A7A\u634F\u9020\u623F\u95F4\u3002\u8BF7\u5982\u5B9E\u544A\u8BC9\u7528\u6237"EB \u4F1A\u8BAE\u5BA4\u67E5\u4E0D\u5230"\uFF0C\u5E76\u8BF7\u7BA1\u7406\u5458\u68C0\u67E5\u4F1A\u8BAE\u5E94\u7528\u7684\u4F1A\u8BAE\u5BA4\u914D\u7F6E\u3002',
@@ -1525,6 +1530,50 @@ function isWriteKind(kind) {
1525
1530
  var EB_BASE = "/api/ebuilder/form/formdata/v2";
1526
1531
  var EB_READ_OP = { list: "getFormDataList", detail: "getFormDataByPk", get: "getFormDataList" };
1527
1532
  var EB_WRITE_OP = { create: "saveFormData", update: "updateFormData", delete: "deleteFormData" };
1533
+ var PERSONNEL_FIELDS = [
1534
+ "caller",
1535
+ "contacter",
1536
+ "mt_creator",
1537
+ "creator",
1538
+ "updater",
1539
+ "hrm_members",
1540
+ "attend_user",
1541
+ "inviters",
1542
+ "reporting_user",
1543
+ "topic_presenter"
1544
+ ];
1545
+ async function buildPersonnelText(env, data) {
1546
+ const ids = [];
1547
+ for (const key of PERSONNEL_FIELDS) {
1548
+ const raw = String(data?.[key] ?? "").trim();
1549
+ if (raw === "" || !/^[\d,\s]+$/u.test(raw)) continue;
1550
+ ids.push(...raw.split(",").map((one) => one.trim()).filter((one) => one !== ""));
1551
+ }
1552
+ if (ids.length === 0) return {};
1553
+ const names = /* @__PURE__ */ new Map();
1554
+ try {
1555
+ const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
1556
+ const batch = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.batch");
1557
+ if (batch) {
1558
+ const result = await batch.handler({ ids: [...new Set(ids)] }, env);
1559
+ for (const row of result?.data?.rows ?? result?.data?.userList ?? []) {
1560
+ const id = String(row.id ?? "").trim();
1561
+ const name = String(row.name ?? "").trim();
1562
+ if (id && name) names.set(id, name);
1563
+ }
1564
+ }
1565
+ } catch {
1566
+ return {};
1567
+ }
1568
+ const out = {};
1569
+ for (const key of PERSONNEL_FIELDS) {
1570
+ const raw = String(data?.[key] ?? "").trim();
1571
+ if (raw === "" || !/^[\d,\s]+$/u.test(raw)) continue;
1572
+ const mapped = raw.split(",").map((one) => names.get(one.trim()) ?? one.trim()).filter((one) => one !== "");
1573
+ if (mapped.length > 0) out[key] = mapped.join(",");
1574
+ }
1575
+ return out;
1576
+ }
1528
1577
  var CONTINUATION_TTL_SECONDS = 600;
1529
1578
  function ebBusinessSuccess(value) {
1530
1579
  if (!value || typeof value !== "object") return false;
@@ -1562,10 +1611,12 @@ async function verifyLease(args, action, env) {
1562
1611
  function isNetworkError(error) {
1563
1612
  return error instanceof Error && error.type === "network";
1564
1613
  }
1565
- function queryBody(userId, page) {
1614
+ function queryBody(userId, page, mainTable) {
1566
1615
  return {
1567
1616
  datajson: {
1568
- mainTable: {},
1617
+ // 传入字段即过滤条件(e-builder openApi 文档:getFormDataList 的传入字段挂 mainTable 节点)。
1618
+ // 空对象 = 不过滤。
1619
+ mainTable: mainTable ?? {},
1569
1620
  // ⚠️ 分页必须放在 body 的 pageInfo 里(值为字符串):只放 URL query 时 EB 会忽略,
1570
1621
  // 恒定返回首页 10 条(2026-09-21 真机暴露:pageSize=60 仍只回 10 条)。
1571
1622
  ...page ? { pageInfo: { pageNo: String(page.pageNo), pageSize: String(page.pageSize) } } : {},
@@ -1573,6 +1624,20 @@ function queryBody(userId, page) {
1573
1624
  }
1574
1625
  };
1575
1626
  }
1627
+ function readFallbackMaxPages() {
1628
+ const raw = Number(process.env.WEAVER_MEETING_EB_FALLBACK_MAX_PAGES ?? "");
1629
+ if (Number.isFinite(raw) && raw >= 1) return Math.min(Math.floor(raw), 100);
1630
+ return 30;
1631
+ }
1632
+ function pickMainTableFilters(args, names) {
1633
+ const out = {};
1634
+ for (const name of names ?? []) {
1635
+ const value = args[name];
1636
+ if (value === void 0 || value === null || value === "") continue;
1637
+ out[name] = typeof value === "string" ? value : String(value);
1638
+ }
1639
+ return out;
1640
+ }
1576
1641
  function detailBody(userId, id) {
1577
1642
  return { datajson: { mainTable: { id }, header: { operator: userId } } };
1578
1643
  }
@@ -1618,11 +1683,23 @@ function buildReadInputSchema(endpoint) {
1618
1683
  for (const param of endpoint.queryParams ?? []) {
1619
1684
  properties[param] = { type: "string", description: `EB \u7B5B\u9009\u53C2\u6570\uFF08URL \u5360\u4F4D\u7B26\u540D ${param}\uFF09` };
1620
1685
  }
1686
+ for (const param of endpoint.mainTableParams ?? []) {
1687
+ properties[param] = {
1688
+ type: "string",
1689
+ description: `\u6309 ${param} \u8FC7\u6EE4\uFF08\u8D70 body datajson.mainTable\uFF0C\u670D\u52A1\u7AEF**\u7CBE\u786E\u5339\u914D**\uFF1B\u4F20\u90E8\u5206\u8BCD\u65F6\u670D\u52A1\u7AEF\u4F1A\u8FD4\u56DE 0 \u6761\uFF0CCLI \u4F1A\u81EA\u52A8\u7FFB\u9875\u626B\u5168\u91CF\u5E76\u6309\u300C\u5305\u542B\u300D\u91CD\u65B0\u7B5B\uFF0C\u7ED3\u679C\u4E00\u6837\u662F\u6A21\u7CCA\u7684\uFF09`
1690
+ };
1691
+ }
1621
1692
  properties.pageNo = { type: "integer", minimum: 1, description: "\u9875\u7801\uFF0C\u9ED8\u8BA4 1" };
1622
1693
  properties.pageSize = { type: "integer", minimum: 1, maximum: 200, description: "\u6BCF\u9875\u6761\u6570\uFF0C\u9ED8\u8BA4 20" };
1623
1694
  if (endpoint.countPk) {
1624
1695
  properties.withCount = { type: "boolean", description: "\u662F\u5426\u5148\u67E5\u603B\u6570\uFF08\u9ED8\u8BA4 true\uFF0C\u6761\u4EF6\u4E0E\u5217\u8868\u4E00\u81F4\uFF09" };
1625
1696
  }
1697
+ if ((endpoint.mainTableParams ?? []).length > 0) {
1698
+ properties.noFallback = {
1699
+ type: "boolean",
1700
+ description: "\u8DF3\u8FC7\u300C\u6A21\u7CCA\u515C\u5E95\u300D\uFF1A\u670D\u52A1\u7AEF\u7CBE\u786E\u5339\u914D\u4E0D\u5230\u65F6\uFF0C\u4E0D\u518D\u7FFB\u9875\u626B\u5168\u91CF\uFF08\u9ED8\u8BA4 false=\u4F1A\u626B\uFF0C\u4FDD\u8BC1\u90E8\u5206\u8BCD\u4E5F\u80FD\u67E5\u5230\uFF09"
1701
+ };
1702
+ }
1626
1703
  }
1627
1704
  return {
1628
1705
  type: "object",
@@ -1672,9 +1749,15 @@ function buildReadOperation(endpoint) {
1672
1749
  if (key !== "mainTable") detailNodes[key] = value;
1673
1750
  }
1674
1751
  }
1752
+ const personnelText = endpoint.operation.startsWith("meeting.") ? await buildPersonnelText(env, data) : {};
1675
1753
  return meetingSuccess(
1676
1754
  endpoint.operation,
1677
- { id, data, ...Object.keys(detailNodes).length > 0 ? { details: detailNodes } : {} },
1755
+ {
1756
+ id,
1757
+ data,
1758
+ ...Object.keys(personnelText).length > 0 ? { personnelText } : {},
1759
+ ...Object.keys(detailNodes).length > 0 ? { details: detailNodes } : {}
1760
+ },
1678
1761
  endpoint.notes ? { meta: { notes: endpoint.notes } } : {}
1679
1762
  );
1680
1763
  }
@@ -1697,6 +1780,7 @@ function buildReadOperation(endpoint) {
1697
1780
  }
1698
1781
  const pageNo = typeof args.pageNo === "number" ? args.pageNo : 1;
1699
1782
  const pageSize = typeof args.pageSize === "number" ? args.pageSize : 20;
1783
+ const mainTableFilters = pickMainTableFilters(args, endpoint.mainTableParams);
1700
1784
  let total;
1701
1785
  if (endpoint.countPk && args.withCount !== false) {
1702
1786
  const countResponse = await env.host.request({
@@ -1704,7 +1788,7 @@ function buildReadOperation(endpoint) {
1704
1788
  path: `${EB_BASE}/getFormDataCount/${endpoint.countPk}`,
1705
1789
  operation: endpoint.operation,
1706
1790
  query,
1707
- body: queryBody(session.userId),
1791
+ body: queryBody(session.userId, void 0, mainTableFilters),
1708
1792
  acceptBusiness
1709
1793
  });
1710
1794
  total = extractEbCount(countResponse);
@@ -1715,16 +1799,52 @@ function buildReadOperation(endpoint) {
1715
1799
  operation: endpoint.operation,
1716
1800
  query: { ...query, pageNo, pageSize },
1717
1801
  // 分页同时进 body.pageInfo:EB 只认 body 里的 pageInfo,仅放 URL query 会被忽略。
1718
- body: queryBody(session.userId, { pageNo, pageSize }),
1802
+ body: queryBody(session.userId, { pageNo, pageSize }, mainTableFilters),
1719
1803
  acceptBusiness
1720
1804
  });
1721
- const { rows, total: listTotal } = extractEbRows(response);
1722
- const resolvedTotal = total ?? listTotal ?? rows.length;
1805
+ const { rows: rawRows, total: listTotal } = extractEbRows(response);
1806
+ const filterKeys = Object.keys(mainTableFilters);
1807
+ const matchesFilters = (row) => {
1808
+ const main = row?.mainTable ?? row ?? {};
1809
+ return filterKeys.every((key) => {
1810
+ const cell = main[key];
1811
+ if (cell === void 0 || cell === null) return false;
1812
+ return String(cell).includes(String(mainTableFilters[key]));
1813
+ });
1814
+ };
1815
+ let rows = filterKeys.length === 0 ? rawRows : rawRows.filter(matchesFilters);
1816
+ let fallback;
1817
+ if (filterKeys.length > 0 && rows.length === 0 && args.noFallback !== true) {
1818
+ const maxPages = readFallbackMaxPages();
1819
+ const collected = [];
1820
+ let pages = 0;
1821
+ for (let p = 1; p <= maxPages; p += 1) {
1822
+ const pageResponse = await env.host.request({
1823
+ method: "POST",
1824
+ path,
1825
+ operation: endpoint.operation,
1826
+ query: { ...query, pageNo: p, pageSize },
1827
+ // 不带 mainTableFilters:服务端只会做精确匹配,带上就又变成 0 条了
1828
+ body: queryBody(session.userId, { pageNo: p, pageSize }),
1829
+ acceptBusiness
1830
+ });
1831
+ const { rows: pageRows } = extractEbRows(pageResponse);
1832
+ pages = p;
1833
+ if (pageRows.length === 0) break;
1834
+ collected.push(...pageRows);
1835
+ if (p >= maxPages) break;
1836
+ }
1837
+ fallback = { pages, scanned: collected.length };
1838
+ rows = collected.filter(matchesFilters);
1839
+ }
1840
+ const resolvedTotal = filterKeys.length > 0 ? rows.length : total ?? listTotal ?? rawRows.length;
1723
1841
  const pageMeta = {
1724
1842
  pageNo,
1725
1843
  pageSize,
1726
1844
  pageCount: rows.length,
1727
- total: Math.max(resolvedTotal, rows.length)
1845
+ total: Math.max(resolvedTotal, rows.length),
1846
+ // 模糊回退时告知调用方:结果是客户端筛出来的,扫了多少条
1847
+ ...fallback ? { fallback } : {}
1728
1848
  };
1729
1849
  const summarized = endpoint.summarizeRows ? endpoint.summarizeRows(rows, {
1730
1850
  pageCount: rows.length,
@@ -1744,6 +1864,11 @@ function buildReadOperation(endpoint) {
1744
1864
  `\u672C\u9875\u8FD4\u56DE ${rows.length} \u6761\uFF0C\u5171 ${effectiveTotal} \u6761\uFF1A\u8FD8\u6709 ${missing} \u6761\u672A\u53D6\u5230\u3002\u9700\u8981\u5168\u91CF\u8BF7\u7FFB\u9875\uFF08pageNo=${pageNo + 1} \u8D77\uFF09\u6216\u52A0\u5927 pageSize\uFF0C\u6216\u6536\u7A84\u7B5B\u9009\u6761\u4EF6`
1745
1865
  );
1746
1866
  }
1867
+ if (fallback) {
1868
+ pageWarnings.push(
1869
+ `\u670D\u52A1\u7AEF\u53EA\u652F\u6301\u300C\u7CBE\u786E\u5339\u914D\u300D\uFF0C\u6309 ${filterKeys.join("/")} \u8FC7\u6EE4\u540E 0 \u6761\uFF1B\u5DF2\u7FFB\u9875\u626B\u63CF\u5168\u91CF ${fallback.scanned} \u6761\uFF08${fallback.pages} \u9875\uFF09\u5728\u5BA2\u6237\u7AEF\u6309\u300C\u5305\u542B\u300D\u91CD\u65B0\u7B5B\u9009\uFF0C\u547D\u4E2D ${rows.length} \u6761\u3002\u4F20 noFallback:true \u53EF\u8DF3\u8FC7\u8FD9\u6B21\u626B\u63CF`
1870
+ );
1871
+ }
1747
1872
  return meetingSuccess(
1748
1873
  endpoint.operation,
1749
1874
  {
@@ -1753,7 +1878,7 @@ function buildReadOperation(endpoint) {
1753
1878
  count: rows.length,
1754
1879
  ...progress ? { progress } : {},
1755
1880
  rows,
1756
- filters: query
1881
+ filters: { ...query, ...mainTableFilters }
1757
1882
  },
1758
1883
  {
1759
1884
  ...endpoint.notes ? { meta: { notes: endpoint.notes } } : {},
@@ -2126,7 +2251,7 @@ function buildWriteOperations(endpoint, preflight, afterWrite) {
2126
2251
  );
2127
2252
  }
2128
2253
  if (endpoint.interfacePk === "create_meeting") {
2129
- const { fetchEbAppSettings, assertEbCreatePathAllowed } = await import("./conflict-SFNEVJY5.js");
2254
+ const { fetchEbAppSettings, assertEbCreatePathAllowed } = await import("./conflict-BQZEQ4SP.js");
2130
2255
  assertEbCreatePathAllowed(await fetchEbAppSettings(env, applyName));
2131
2256
  }
2132
2257
  const pkQuery = writePkQuery(endpoint, payload);
@@ -2,13 +2,14 @@ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
4
  createE10RequestRuntime,
5
+ isE10SessionExpiredResponse,
5
6
  requireE10Session
6
- } from "./chunk-6ATGWRZM.js";
7
+ } from "./chunk-UZZBA6PV.js";
7
8
  import {
8
9
  E10_REAUTH_GUIDANCE,
9
10
  E10_SESSION_EXPIRED_MESSAGE,
10
11
  getActiveProfile
11
- } from "./chunk-D223PTXU.js";
12
+ } from "./chunk-OJQUJZQF.js";
12
13
  import {
13
14
  CliError
14
15
  } from "./chunk-LUSPKZKY.js";
@@ -264,7 +265,7 @@ function createInvoiceHost(ctx, dependencies = {}) {
264
265
  timeoutMs,
265
266
  trustedHeaders: trustedInvoiceHeaders(token)
266
267
  });
267
- if (response.status === 401 || response.status === 302) {
268
+ if (isE10SessionExpiredResponse(response)) {
268
269
  throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
269
270
  }
270
271
  if (response.parseError) {
@@ -331,7 +332,7 @@ function createInvoiceHost(ctx, dependencies = {}) {
331
332
  timeoutMs,
332
333
  trustedHeaders: trustedInvoiceHeaders(token)
333
334
  });
334
- if (response.status === 401 || response.status === 302) {
335
+ if (isE10SessionExpiredResponse(response)) {
335
336
  throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
336
337
  }
337
338
  if (response.parseError) {
@@ -373,7 +374,7 @@ function createInvoiceHost(ctx, dependencies = {}) {
373
374
  timeoutMs,
374
375
  trustedHeaders: trustedInvoiceHeaders(token)
375
376
  });
376
- if (response.status === 401 || response.status === 302) {
377
+ if (isE10SessionExpiredResponse(response)) {
377
378
  throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
378
379
  }
379
380
  if (response.parseError) {
@@ -400,7 +401,7 @@ function createInvoiceHost(ctx, dependencies = {}) {
400
401
  timeoutMs,
401
402
  trustedHeaders: trustedInvoiceHeaders(token)
402
403
  });
403
- if (response.status === 401 || response.status === 302) {
404
+ if (isE10SessionExpiredResponse(response)) {
404
405
  throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
405
406
  }
406
407
  const contentType = response.contentType;
@@ -4,7 +4,7 @@ import {
4
4
  cacheScopeSuffix,
5
5
  readCache,
6
6
  writeCache
7
- } from "./chunk-IHUYP6LO.js";
7
+ } from "./chunk-JSMFPO43.js";
8
8
  import {
9
9
  EB_BASE,
10
10
  SCHEMA_DATETIME_MINUTE,
@@ -13,10 +13,11 @@ import {
13
13
  meetingSuccess,
14
14
  queryBody,
15
15
  schemaOf
16
- } from "./chunk-MEEFGWTM.js";
16
+ } from "./chunk-ELYDWBZJ.js";
17
17
 
18
18
  // src/shortcuts/meeting/operations/eb/room-recommend.ts
19
19
  var ROOMS_TTL_MS = 24 * 60 * 60 * 1e3;
20
+ var STALE_NOTICE_MS = 4 * 60 * 60 * 1e3;
20
21
  var FREQUENT_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
21
22
  var FREQUENT_WINDOW_DAYS = 180;
22
23
  var PAGE_SIZE = 100;
@@ -120,7 +121,7 @@ async function loadFrequentRooms(env, options = {}) {
120
121
  const counts = /* @__PURE__ */ new Map();
121
122
  let requests = 0;
122
123
  try {
123
- const { getMeetingOperation } = await import("./registry-QKMI43Q6.js");
124
+ const { getMeetingOperation } = await import("./registry-EP4VTHZS.js");
124
125
  const listOp = getMeetingOperation("meeting.eb.meeting.list");
125
126
  for (let pageNo = 1; pageNo <= 5; pageNo += 1) {
126
127
  const page = await listOp.handler(
@@ -174,6 +175,11 @@ async function recommendRooms(env, input) {
174
175
  const topN = Math.max(1, Math.min(10, input.topN ?? 3));
175
176
  const roomData = await loadRooms(env, { refresh: input.refreshRooms === true });
176
177
  warnings.push(...roomData.warnings);
178
+ if (roomData.fromCache && (roomData.ageSeconds ?? 0) * 1e3 > STALE_NOTICE_MS) {
179
+ warnings.push(
180
+ `\u4F1A\u8BAE\u5BA4\u53F0\u8D26\u6765\u81EA ${Math.round((roomData.ageSeconds ?? 0) / 3600)} \u5C0F\u65F6\u524D\u7684\u7F13\u5B58\uFF08\u5171 ${roomData.rooms.length} \u95F4\uFF09\u3002\u5982\u679C\u6700\u8FD1\u65B0\u5EFA/\u5BFC\u5165/\u5C01\u5B58\u8FC7\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u5E26 \`refresh: true\` \u91CD\u65B0\u67E5\u8BE2\uFF0C\u5426\u5219\u770B\u5230\u7684\u662F\u65E7\u6E05\u5355\u3002`
181
+ );
182
+ }
177
183
  const frequent = await loadFrequentRooms(env, { refresh: input.refreshFrequent === true });
178
184
  warnings.push(...frequent.warnings);
179
185
  const busy = await fetchBusyRoomIds(env, input.beginDatetime, input.endDatetime);
@@ -192,9 +198,10 @@ async function recommendRooms(env, input) {
192
198
  busyCount += 1;
193
199
  if (!input.includeBusy) continue;
194
200
  }
201
+ let belowMinCapacity = false;
195
202
  if (memberCount !== null) {
196
203
  if (room.maxNum > 0 && room.maxNum < memberCount) continue;
197
- if (room.minNum > 0 && room.minNum > memberCount) continue;
204
+ if (room.minNum > 0 && room.minNum > memberCount) belowMinCapacity = true;
198
205
  }
199
206
  if (requirement.roomAttr && room.roomAttr !== requirement.roomAttr) continue;
200
207
  if (requirement.mrType && room.mrType !== requirement.mrType) continue;
@@ -216,6 +223,10 @@ async function recommendRooms(env, input) {
216
223
  reasons.push(`\u5BB9\u91CF ${room.maxNum} \u4EBA`);
217
224
  score += 5;
218
225
  }
226
+ if (belowMinCapacity) {
227
+ reasons.push(`\u8BE5\u623F\u95F4\u5EFA\u8BAE\u81F3\u5C11 ${room.minNum} \u4EBA\u4F7F\u7528\uFF08\u672C\u6B21 ${memberCount} \u4EBA\uFF0C\u672A\u8FBE\u5EFA\u8BAE\u4E0B\u9650\uFF0C\u5982\u53EF\u7528\u8BF7\u81EA\u884C\u786E\u8BA4\uFF09`);
228
+ score -= 15;
229
+ }
219
230
  if (requirement.placeKeyword) {
220
231
  reasons.push(`\u5730\u70B9\u5339\u914D\u300C${requirement.placeKeyword}\u300D`);
221
232
  score += 10;
@@ -249,6 +260,17 @@ async function recommendRooms(env, input) {
249
260
  if (leftCap !== rightCap) return leftCap - rightCap;
250
261
  return left.name.localeCompare(right.name, "zh-Hans-CN");
251
262
  });
263
+ if (candidates.length === 0 && roomData.fromCache && input.refreshRooms !== true) {
264
+ const retried = await recommendRooms(env, { ...input, refreshRooms: true, refreshFrequent: true });
265
+ return {
266
+ ...retried,
267
+ meta: { ...retried.meta, cacheRetried: true },
268
+ warnings: [
269
+ `\u7F13\u5B58\u91CC\u7684\u4F1A\u8BAE\u5BA4\u51D1\u4E0D\u51FA\u5019\u9009\uFF08\u7F13\u5B58 ${Math.round((roomData.ageSeconds ?? 0) / 60)} \u5206\u949F\u524D\uFF0C${roomData.rooms.length} \u95F4\uFF09\u2192 \u5DF2\u5F3A\u5236\u91CD\u65B0\u62C9\u53D6\u53F0\u8D26\u540E\u91CD\u7B97`,
270
+ ...retried.warnings
271
+ ]
272
+ };
273
+ }
252
274
  if (candidates.length === 0) {
253
275
  if (roomData.rooms.length === 0) {
254
276
  warnings.push(
@@ -2,7 +2,7 @@ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
4
  isEsbFlowUnavailable
5
- } from "./chunk-ILMBNVSG.js";
5
+ } from "./chunk-UJJD4QWF.js";
6
6
  import {
7
7
  esbValidationError
8
8
  } from "./chunk-GPMFD4RD.js";
@@ -3,13 +3,13 @@ const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
4
  readCache,
5
5
  writeCache
6
- } from "./chunk-IHUYP6LO.js";
6
+ } from "./chunk-JSMFPO43.js";
7
7
  import {
8
8
  SCHEMA_DATETIME_MINUTE,
9
9
  meetingSuccess,
10
10
  meetingValidationError,
11
11
  schemaOf
12
- } from "./chunk-MEEFGWTM.js";
12
+ } from "./chunk-ELYDWBZJ.js";
13
13
 
14
14
  // src/shortcuts/meeting/operations/eb/schedule.ts
15
15
  var SCHEDULE_TYPE_PATH = "/api/ebuilder/form/formdata/v2/getFormDataList/queryAgendaType";
@@ -110,9 +110,9 @@ async function runScheduleConflictFlow(env, input) {
110
110
  if (!employeeId) {
111
111
  throw meetingValidationError("schedule_employee_required", "\u53D6\u4E0D\u5230\u5F53\u524D\u767B\u5F55\u7528\u6237 id\uFF0C\u65E0\u6CD5\u89E6\u53D1 ESB \u65E5\u7A0B\u67E5\u8BE2");
112
112
  }
113
- const { createEsbHost } = await import("./host-BCGUVEWX.js");
113
+ const { createEsbHost } = await import("./host-FWDOSRH5.js");
114
114
  const { createEsbContinuationSigner } = await import("./continuation-NLECEJPX.js");
115
- const { getEsbOperation } = await import("./registry-JHRIDQ3A.js");
115
+ const { getEsbOperation } = await import("./registry-FRJ6H7BT.js");
116
116
  const esbEnv = {
117
117
  ctx: env.ctx,
118
118
  host: createEsbHost(env.ctx),
@@ -2,7 +2,7 @@ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
4
  meetingStateDir
5
- } from "./chunk-VBCFFFGT.js";
5
+ } from "./chunk-Z32KWY6G.js";
6
6
 
7
7
  // src/shortcuts/meeting/operations/eb/cache.ts
8
8
  import { mkdir, readFile, writeFile } from "node:fs/promises";
@@ -9,12 +9,13 @@ import {
9
9
  import {
10
10
  E10ApiError,
11
11
  createE10RequestRuntime,
12
+ isE10SessionExpiredResponse,
12
13
  requireE10Session
13
- } from "./chunk-6ATGWRZM.js";
14
+ } from "./chunk-UZZBA6PV.js";
14
15
  import {
15
16
  E10_SESSION_EXPIRED_MESSAGE,
16
17
  getActiveProfile
17
- } from "./chunk-D223PTXU.js";
18
+ } from "./chunk-OJQUJZQF.js";
18
19
 
19
20
  // src/shortcuts/im/host.ts
20
21
  import { createHash } from "node:crypto";
@@ -149,7 +150,7 @@ function createImHost(ctx, dependencies = {}) {
149
150
  } catch (error) {
150
151
  mapRuntimeNetworkError(error);
151
152
  }
152
- if (response.status === 401 || response.status === 302) {
153
+ if (isE10SessionExpiredResponse(response)) {
153
154
  throw imAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
154
155
  }
155
156
  if (response.parseError) {
@@ -205,7 +206,7 @@ function createImHost(ctx, dependencies = {}) {
205
206
  } catch (error) {
206
207
  mapRuntimeNetworkError(error);
207
208
  }
208
- if (response.status === 401 || response.status === 302) {
209
+ if (isE10SessionExpiredResponse(response)) {
209
210
  throw imAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE);
210
211
  }
211
212
  if (response.status !== 200) {