weaver-work-cli 0.1.39 → 0.1.42

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 (197) hide show
  1. package/README.md +4 -2
  2. package/dist/chunks/{archive-ENZYBBME.js → archive-J4I6MCKF.js} +2 -2
  3. package/dist/chunks/{archive-oa-YWLEC5V4.js → archive-oa-BRZKKTO4.js} +2 -2
  4. package/dist/chunks/{asset-OOV6DWPA.js → asset-L7D4FAOZ.js} +2 -2
  5. package/dist/chunks/{asset-idle-RE632MY5.js → asset-idle-DADLLV75.js} +2 -2
  6. package/dist/chunks/{attachment-content-RWN2FCLL.js → attachment-content-K4C7VLWQ.js} +3 -3
  7. package/dist/chunks/{blog-PEPOJAL7.js → blog-BVGQ7NZL.js} +2 -2
  8. package/dist/chunks/{caizhilian-WYIQDVPJ.js → caizhilian-SAADNFD6.js} +2 -2
  9. package/dist/chunks/{calendar-CIARBAOX.js → calendar-Q7NQY5Z2.js} +61 -23
  10. package/dist/chunks/{chunk-F2EQXUEE.js → chunk-3KTFS4IA.js} +397 -159
  11. package/dist/chunks/{chunk-G2JSIUWF.js → chunk-4PD5NWAX.js} +89 -0
  12. package/dist/chunks/{chunk-HJYVHXUQ.js → chunk-4RAE6JXP.js} +1 -1
  13. package/dist/chunks/{chunk-CQHGNCK2.js → chunk-72CKAUAG.js} +41 -8
  14. package/dist/chunks/{chunk-K3RUEEOL.js → chunk-APVFJUQH.js} +2 -2
  15. package/dist/chunks/{chunk-BJGXMFGD.js → chunk-BBKDXQEC.js} +2 -2
  16. package/dist/chunks/chunk-BIPYLLVS.js +501 -0
  17. package/dist/chunks/{chunk-GVPJZXJ2.js → chunk-EKWAQSLU.js} +92 -50
  18. package/dist/chunks/{chunk-XXJOSZTQ.js → chunk-FOAA27U5.js} +381 -57
  19. package/dist/chunks/{chunk-I2HB737U.js → chunk-G4UR6NXN.js} +2 -2
  20. package/dist/chunks/{chunk-YS5DPN4T.js → chunk-GEWYMQME.js} +1 -1
  21. package/dist/chunks/{chunk-P2DAISYW.js → chunk-GHXCDPTM.js} +1 -1
  22. package/dist/chunks/{chunk-L4N7B7ZD.js → chunk-IZ7S7QUS.js} +4 -4
  23. package/dist/chunks/{chunk-NLK2RZKG.js → chunk-JPRO6ER2.js} +122 -2214
  24. package/dist/chunks/{chunk-36DIFZAH.js → chunk-LADPYOWC.js} +2 -2
  25. package/dist/chunks/chunk-LDZQPUIA.js +1238 -0
  26. package/dist/chunks/chunk-NKZRQXST.js +2546 -0
  27. package/dist/chunks/{chunk-EINRJHQ3.js → chunk-QKNKR4RH.js} +3 -3
  28. package/dist/chunks/{chunk-T7JDJJ7H.js → chunk-R4CHUSKC.js} +126 -19
  29. package/dist/chunks/{chunk-EZGFHJFW.js → chunk-SA6VBIHY.js} +88 -15
  30. package/dist/chunks/{chunk-ZXRNHZTE.js → chunk-TTPJJJC4.js} +2 -2
  31. package/dist/chunks/{chunk-KTCB5R5H.js → chunk-W7BEHOSR.js} +2 -2
  32. package/dist/chunks/{chunk-MUQUHKPG.js → chunk-YRSZQUD2.js} +2 -2
  33. package/dist/chunks/{conflict-DRMDOL56.js → conflict-F2OMZRTO.js} +2 -2
  34. package/dist/chunks/{contract-73MERZWN.js → contract-5BETHRSG.js} +2 -2
  35. package/dist/chunks/{cowork-HNGBPD7A.js → cowork-3MN6EQQO.js} +27 -10
  36. package/dist/chunks/create-flow-5FQNNMVO.js +55 -0
  37. package/dist/chunks/{ebuilder-form-OY6DVNRK.js → ebuilder-form-SBHOYBUD.js} +3 -3
  38. package/dist/chunks/{ehr-RAQNEQO7.js → ehr-KMOJULKG.js} +432 -1234
  39. package/dist/chunks/env-LB7NBL2O.js +19 -0
  40. package/dist/chunks/{esb-6XV7C7YV.js → esb-W2PJCFCX.js} +4 -4
  41. package/dist/chunks/factory-6ZFQXQ46.js +30 -0
  42. package/dist/chunks/{fna-XTSRB7G7.js → fna-ZQPCUV4R.js} +2 -2
  43. package/dist/chunks/group-chat-2HHAJN46.js +20 -0
  44. package/dist/chunks/{host-YMBXWFWX.js → host-4CBHGOHT.js} +3 -3
  45. package/dist/chunks/{host-A7J6GDUP.js → host-ATKVNZAT.js} +3 -3
  46. package/dist/chunks/{host-3F5UM5GN.js → host-BQH22NTQ.js} +3 -3
  47. package/dist/chunks/{host-YAQAPYNP.js → host-X2CSLFM6.js} +3 -3
  48. package/dist/chunks/{host-VGPVP7YF.js → host-YTODKMSL.js} +3 -3
  49. package/dist/chunks/{hrm-TLHKC545.js → hrm-FFM4UJFS.js} +4 -4
  50. package/dist/chunks/{im-YOUCFMUK.js → im-VEHKDQPB.js} +8 -8
  51. package/dist/chunks/{invoice-WNBS2B4C.js → invoice-LVIKSIIF.js} +3 -3
  52. package/dist/chunks/{jiuchuanhui-XABWS5RN.js → jiuchuanhui-X6DINO5P.js} +2 -2
  53. package/dist/chunks/{lazy-dispatch-NLZ5UQQI.js → lazy-dispatch-KSWTN5L6.js} +4 -4
  54. package/dist/chunks/{mail-LRYMBFNL.js → mail-VDKRGUD3.js} +9 -4
  55. package/dist/chunks/{meeting-ESXL6MFI.js → meeting-CLC6HP3Z.js} +12 -10
  56. package/dist/chunks/{okr-EOV65SSF.js → okr-CHG4OO3U.js} +2 -2
  57. package/dist/chunks/{plan-YFPVKW6Y.js → plan-XWR75667.js} +2 -2
  58. package/dist/chunks/{project-MDVZUYQW.js → project-5BXOOKMG.js} +40 -23
  59. package/dist/chunks/recruit-stage-DGMFNNDE.js +4507 -0
  60. package/dist/chunks/{registry-VT5Y2HLA.js → registry-7FFOXIAW.js} +4 -4
  61. package/dist/chunks/{registry-QCLZEDAP.js → registry-BKBZPBAJ.js} +10 -8
  62. package/dist/chunks/{registry-YX4CSEMD.js → registry-RHMW6ANW.js} +2 -2
  63. package/dist/chunks/{registry-NYPYMZXG.js → registry-Z43434VG.js} +1 -1
  64. package/dist/chunks/{room-recommend-L3MWH4JW.js → room-recommend-62H7ZQQ6.js} +4 -4
  65. package/dist/chunks/{schedule-UASAVDVD.js → schedule-FNXKH3DQ.js} +4 -4
  66. package/dist/chunks/{workflow-KDGIUCNW.js → workflow-ADHKCAJK.js} +4 -4
  67. package/dist/index.js +33 -28
  68. package/dist/internal/e10/auth/commands.js +110 -56
  69. package/dist/internal/e10/auth/messages.js +6 -0
  70. package/dist/internal/e10/auth/session.js +28 -1
  71. package/dist/internal/e10/auth/xiaoe.js +315 -48
  72. package/dist/internal/e10/auth-recovery.js +36 -5
  73. package/dist/internal/e10/client.js +13 -0
  74. package/dist/internal/e10/context.js +61 -9
  75. package/dist/internal/e10/index.js +1 -1
  76. package/dist/internal/e10/network-error.js +93 -0
  77. package/dist/internal/e10/request-runtime.js +15 -0
  78. package/dist/shortcuts/calendar/operations/read.js +31 -22
  79. package/dist/shortcuts/calendar/operations/write.js +45 -1
  80. package/dist/shortcuts/cowork/operations/discuss-write.js +5 -1
  81. package/dist/shortcuts/cowork/operations/item-write.js +5 -3
  82. package/dist/shortcuts/cowork/operations/member-write.js +3 -1
  83. package/dist/shortcuts/cowork/operations/permission-write.js +5 -1
  84. package/dist/shortcuts/cowork/operations/shared.js +7 -0
  85. package/dist/shortcuts/ehr/operations/attend-write.js +43 -1
  86. package/dist/shortcuts/ehr/operations/hr-contact.js +7 -4
  87. package/dist/shortcuts/ehr/operations/hr-report.js +13 -7
  88. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +134 -59
  89. package/dist/shortcuts/ehr/operations/recruit-write.js +262 -17
  90. package/dist/shortcuts/ehr/operations/recruit.js +10 -4
  91. package/dist/shortcuts/ehr/operations/shared.js +47 -0
  92. package/dist/shortcuts/hrm/operations/org.js +118 -0
  93. package/dist/shortcuts/index.js +5 -0
  94. package/dist/shortcuts/mail/operations/mail-send.js +8 -2
  95. package/dist/shortcuts/meeting/operations/eb/catalog.js +9 -2
  96. package/dist/shortcuts/meeting/operations/eb/create-flow.js +461 -127
  97. package/dist/shortcuts/meeting/operations/eb/crm-search.js +87 -5
  98. package/dist/shortcuts/meeting/operations/eb/factory.js +33 -0
  99. package/dist/shortcuts/meeting/operations/eb/flow-memory.js +49 -0
  100. package/dist/shortcuts/meeting/operations/eb/group-chat.js +605 -0
  101. package/dist/shortcuts/meeting/operations/eb/index.js +2 -0
  102. package/dist/shortcuts/meeting/operations/eb/person-cache.js +96 -0
  103. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +44 -6
  104. package/dist/shortcuts/meeting/operations/eb/room-summary.js +2 -0
  105. package/dist/shortcuts/meeting/operations/eb/usage-cache.js +99 -0
  106. package/dist/shortcuts/meeting/operations/from-group-chat.js +35 -12
  107. package/dist/shortcuts/project/operations/read.js +6 -25
  108. package/dist/shortcuts/project/operations/shared.js +22 -0
  109. package/dist/shortcuts/project/operations/write.js +28 -2
  110. package/dist/shortcuts/recruit-stage/context.js +119 -0
  111. package/dist/shortcuts/recruit-stage/continuation.js +73 -0
  112. package/dist/shortcuts/recruit-stage/errors.js +65 -0
  113. package/dist/shortcuts/recruit-stage/host.js +109 -0
  114. package/dist/shortcuts/recruit-stage/index.js +115 -0
  115. package/dist/shortcuts/recruit-stage/manifest.js +29 -0
  116. package/dist/shortcuts/recruit-stage/operations/interview-arrange.js +722 -0
  117. package/dist/shortcuts/recruit-stage/operations/interview-feedback.js +269 -0
  118. package/dist/shortcuts/recruit-stage/operations/jd-create.js +630 -0
  119. package/dist/shortcuts/recruit-stage/operations/list.js +431 -0
  120. package/dist/shortcuts/recruit-stage/operations/registry.js +38 -0
  121. package/dist/shortcuts/recruit-stage/operations/resume-import.js +1198 -0
  122. package/dist/shortcuts/recruit-stage/operations/search.js +158 -0
  123. package/dist/shortcuts/recruit-stage/operations/types.js +25 -0
  124. package/dist/shortcuts/recruit-stage/school-tiers.json +318 -0
  125. package/dist/shortcuts/recruit-stage/shared.js +608 -0
  126. package/dist/shortcuts/workflow/operations/form.js +21 -2
  127. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupRules.js +52 -1
  128. package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +4 -2
  129. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +19 -11
  130. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +17 -24
  131. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +14 -9
  132. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +78 -10
  133. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +3 -1
  134. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +17 -11
  135. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +16 -40
  136. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +3 -2
  137. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +52 -15
  138. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +16 -1
  139. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +151 -63
  140. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.js +56 -0
  141. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +53 -16
  142. package/docs/e10-auth.md +22 -1
  143. package/docs/operation-manual.md +8 -0
  144. package/package.json +1 -1
  145. package/scripts/install-skill-to-xiaoe.mjs +105 -0
  146. package/scripts/mcp-meeting.mjs +234 -0
  147. package/scripts/package-skill.mjs +4 -2
  148. package/skill-template/business-info.json +24 -0
  149. package/skill-template/domains/recruit-stage.md +29 -0
  150. package/skills/weaver-e10-calendar/SKILL.md +2 -1
  151. package/skills/weaver-e10-calendar/references/calendar-write.md +54 -0
  152. package/skills/weaver-e10-cowork/SKILL.md +1 -1
  153. package/skills/weaver-e10-cowork/references/cowork-write.md +3 -1
  154. package/skills/weaver-e10-jucailin/SKILL.md +1 -1
  155. package/skills/weaver-e10-jucailin/references/attend-write.md +8 -0
  156. package/skills/weaver-e10-jucailin/references/hr-contact.md +8 -0
  157. package/skills/weaver-e10-jucailin/references/hr-report.md +8 -0
  158. package/skills/weaver-e10-jucailin/references/recruit-create.md +2 -2
  159. package/skills/weaver-e10-jucailin/references/recruit-read.md +1 -1
  160. package/skills/weaver-e10-jucailin/references/recruit-write.md +4 -3
  161. package/skills/weaver-e10-mail/SKILL.md +1 -1
  162. package/skills/weaver-e10-mail/references/mail-send.md +2 -0
  163. package/skills/weaver-e10-meeting/SKILL.md +119 -26
  164. package/skills/weaver-e10-meeting/references/meeting-minute-file.md +25 -11
  165. package/skills/weaver-e10-meeting.zip +0 -0
  166. package/skills/weaver-e10-recruit-stage/SKILL.md +226 -0
  167. package/skills/weaver-e10-recruit-stage/agents/openai.yaml +119 -0
  168. package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +188 -0
  169. package/skills/weaver-e10-recruit-stage/references/recruit-arrange-interview.md +322 -0
  170. package/skills/weaver-e10-recruit-stage/references/recruit-capability-check.md +127 -0
  171. package/skills/weaver-e10-recruit-stage/references/recruit-check-install.md +65 -0
  172. package/skills/weaver-e10-recruit-stage/references/recruit-detail-process.md +63 -0
  173. package/skills/weaver-e10-recruit-stage/references/recruit-edit-interview-feedback.md +142 -0
  174. package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +73 -0
  175. package/skills/weaver-e10-recruit-stage/references/recruit-jd-template.md +56 -0
  176. package/skills/weaver-e10-recruit-stage/references/recruit-list-candidate.md +101 -0
  177. package/skills/weaver-e10-recruit-stage/references/recruit-list-interview.md +148 -0
  178. package/skills/weaver-e10-recruit-stage/references/recruit-match-candidates.md +77 -0
  179. package/skills/weaver-e10-recruit-stage/references/recruit-output-links.md +59 -0
  180. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-creator.md +69 -0
  181. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-metadata.md +241 -0
  182. package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +438 -0
  183. package/skills/weaver-e10-recruit-stage/references/recruit-resume-parse.md +128 -0
  184. package/skills/weaver-e10-recruit-stage/references/recruit-search-candidate.md +146 -0
  185. package/skills/weaver-e10-recruit-stage/references/recruit-urge-feedback.md +69 -0
  186. package/skills/weaver-e10-shared/SKILL.md +2 -2
  187. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +4 -2
  188. package/skills/weaver-e10-shijingran/SKILL.md +3 -2
  189. package/skills/weaver-e10-shijingran/references/operations.md +3 -1
  190. package/skills/weaver-e10-shijingran/references/source-manifest.json +41 -40
  191. package/skills/weaver-e10-shijingran/references/write-operations.md +2 -0
  192. package/skills/weaver-e10-workflow/SKILL.md +7 -1
  193. package/skills/weaver-e10-workflow/aigroup/default.json +23 -9
  194. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +37 -21
  195. package/skills/weaver-e10-workflow/tools/todo-summary.cjs +135 -43
  196. package/skills/weaver-e10-yepiaotong/SKILL.md +9 -10
  197. package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +6 -3
@@ -24,7 +24,7 @@ import {
24
24
  createFetchTimingSink,
25
25
  hasXiaoEEnv,
26
26
  runWithFetchTiming
27
- } from "./chunk-XXJOSZTQ.js";
27
+ } from "./chunk-FOAA27U5.js";
28
28
 
29
29
  // src/shortcuts/workflow/operations/form.ts
30
30
  import { randomUUID } from "node:crypto";
@@ -5140,6 +5140,10 @@ var READONLY_COMPONENTS = /* @__PURE__ */ new Set([
5140
5140
  "subtablecontrol",
5141
5141
  "mobileinteraction"
5142
5142
  ]);
5143
+ function isBrowserLikeComponentKey(componentKey) {
5144
+ const normalized = String(componentKey ?? "").toLowerCase();
5145
+ return normalized === "einvoicecomponent" || normalized === "filecomponent";
5146
+ }
5143
5147
  var SYSTEM_FIELD_KEYS = {
5144
5148
  REQUEST_NAMEL: "\u6D41\u7A0B\u6807\u9898",
5145
5149
  REQUEST_LEVEL: "\u7D27\u6025\u7A0B\u5EA6",
@@ -6519,6 +6523,7 @@ async function buildCreateFormData(workflowId, env, options = {}) {
6519
6523
  for (const key of ["isBrowser", "isSelect", "isMultiple", "browserType", "browserModule"]) {
6520
6524
  if (field[key]) item[key] = field[key];
6521
6525
  }
6526
+ if (!item.isBrowser && isBrowserLikeComponentKey(field.componentKey)) item.isBrowser = true;
6522
6527
  if (String(field.componentKey ?? "").toLowerCase() === "employeescope") item.isEmployeeScope = true;
6523
6528
  if (String(field.componentKey ?? "").toLowerCase() === "einvoicecomponent") item.isEinvoice = true;
6524
6529
  if (String(field.componentKey ?? "").toLowerCase() === "filecomponent") {
@@ -8311,7 +8316,7 @@ function xiaoECustomParams(preview, fields) {
8311
8316
  const browserFieldIds = /* @__PURE__ */ new Set();
8312
8317
  for (const field of toArray(fields)) {
8313
8318
  const id = String(field?.id ?? "").trim();
8314
- if (id && field?.isBrowser) browserFieldIds.add(id);
8319
+ if (id && (field?.isBrowser || isBrowserLikeComponentKey(field?.componentKey))) browserFieldIds.add(id);
8315
8320
  }
8316
8321
  for (const item of toArray(preview)) {
8317
8322
  const fieldId = String(item?.fieldId ?? "").trim();
@@ -9963,6 +9968,7 @@ var STAGE_VALUES = [
9963
9968
  "smartGroup",
9964
9969
  "summaryContext",
9965
9970
  "summary",
9971
+ "subGroup",
9966
9972
  "groupSummaryContext",
9967
9973
  "groupSummary",
9968
9974
  "aggregate"
@@ -10077,6 +10083,7 @@ var ALLOWED_INPUT_KEYS = [
10077
10083
  "aiGroupSummaries",
10078
10084
  "withDetailContext",
10079
10085
  "withGroupSummaryContext",
10086
+ "withSubGroup",
10080
10087
  "detailPrefetch",
10081
10088
  "maxCharsPerBatch",
10082
10089
  "maxItemsPerBatch",
@@ -10094,6 +10101,7 @@ var ALLOWED_INPUT_KEYS = [
10094
10101
  "tabid",
10095
10102
  "tabName",
10096
10103
  "subCategory",
10104
+ "isremarks",
10097
10105
  "workflow",
10098
10106
  "creator",
10099
10107
  "requestName",
@@ -10394,8 +10402,8 @@ function promptTagOf(prompt) {
10394
10402
  return String(prompt ?? "").trim();
10395
10403
  }
10396
10404
  function entryMatches(entry, maxChars, pk, dv) {
10397
- if (maxChars !== void 0 && (entry.maxChars ?? 50) !== maxChars) return false;
10398
- if (pk !== void 0 && (entry.pk ?? "") !== pk) return false;
10405
+ if (pk !== void 0 && entry.pk !== pk) return false;
10406
+ if (maxChars !== void 0 && entry.maxChars !== void 0 && entry.maxChars !== maxChars) return false;
10399
10407
  if (entry.dv !== void 0 && entry.dv !== dv) return false;
10400
10408
  return true;
10401
10409
  }
@@ -10405,7 +10413,7 @@ function normalizeSummaryEntry(raw) {
10405
10413
  if (typeof entry.summary !== "string" || !entry.summary.trim()) return null;
10406
10414
  if (typeof entry.cachedAt !== "number" || !Number.isFinite(entry.cachedAt)) return null;
10407
10415
  const maxChars = typeof entry.maxChars === "number" && Number.isFinite(entry.maxChars) ? entry.maxChars : void 0;
10408
- const pk = typeof entry.pk === "string" && entry.pk !== "" ? entry.pk : void 0;
10416
+ const pk = typeof entry.pk === "string" ? entry.pk : void 0;
10409
10417
  const dv = typeof entry.dv === "string" && entry.dv !== "" ? entry.dv : void 0;
10410
10418
  return {
10411
10419
  summary: entry.summary,
@@ -10471,7 +10479,8 @@ async function openSummaryCache(ctx) {
10471
10479
  summary: text,
10472
10480
  cachedAt: Date.now(),
10473
10481
  ...maxChars === void 0 ? {} : { maxChars },
10474
- ...pk === void 0 || pk === "" ? {} : { pk },
10482
+ // 空串同样落库(见 entryMatches 注释):空口径与「缺 pk」必须能区分开。
10483
+ ...pk === void 0 ? {} : { pk },
10475
10484
  ...dv === void 0 || dv === "" ? {} : { dv }
10476
10485
  });
10477
10486
  dirty = true;
@@ -10576,6 +10585,39 @@ function validateRuleFile(raw) {
10576
10585
  errors.push("rules \u5FC5\u987B\u662F\u6570\u7EC4");
10577
10586
  return errors;
10578
10587
  }
10588
+ if (file.generalRules !== void 0) {
10589
+ if (!file.generalRules || typeof file.generalRules !== "object" || Array.isArray(file.generalRules)) {
10590
+ errors.push("generalRules \u5FC5\u987B\u662F\u5BF9\u8C61");
10591
+ } else {
10592
+ const identity = file.generalRules.identityFilter;
10593
+ if (identity !== void 0) {
10594
+ if (!identity || typeof identity !== "object" || Array.isArray(identity)) {
10595
+ errors.push("generalRules.identityFilter \u5FC5\u987B\u662F\u5BF9\u8C61");
10596
+ } else if (identity.defaultIsremarks !== void 0 && !/^\d+(,\d+)*$/.test(String(identity.defaultIsremarks).trim())) {
10597
+ errors.push("generalRules.identityFilter.defaultIsremarks \u5FC5\u987B\u662F\u300C\u6570\u5B57\u9017\u53F7\u62FC\u63A5\u300D\u683C\u5F0F\uFF0C\u5982 0,1,2");
10598
+ }
10599
+ if (identity?.excludedCodes !== void 0 && (!Array.isArray(identity.excludedCodes) || identity.excludedCodes.some((c) => !/^\d+$/.test(String(c))))) {
10600
+ errors.push("generalRules.identityFilter.excludedCodes \u5FC5\u987B\u662F\u6570\u5B57\u7801\u6570\u7EC4");
10601
+ }
10602
+ }
10603
+ const priority = file.generalRules.priorityGroup;
10604
+ if (priority !== void 0) {
10605
+ if (!priority || typeof priority !== "object" || Array.isArray(priority)) {
10606
+ errors.push("generalRules.priorityGroup \u5FC5\u987B\u662F\u5BF9\u8C61");
10607
+ } else {
10608
+ if (priority.title !== void 0 && (typeof priority.title !== "string" || !priority.title.trim())) {
10609
+ errors.push("generalRules.priorityGroup.title \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
10610
+ }
10611
+ if (priority.rules !== void 0) {
10612
+ const KNOWN_PRIORITY_RULES = ["overdue", "levelFallback"];
10613
+ if (!Array.isArray(priority.rules) || priority.rules.length === 0 || priority.rules.some((r) => !KNOWN_PRIORITY_RULES.includes(String(r)))) {
10614
+ errors.push(`generalRules.priorityGroup.rules \u53EA\u652F\u6301 ${KNOWN_PRIORITY_RULES.join("\u3001")}`);
10615
+ }
10616
+ }
10617
+ }
10618
+ }
10619
+ }
10620
+ }
10579
10621
  const defaultsExclude = validateExcludeFields(
10580
10622
  file.defaults?.excludeOriginFormDataFields,
10581
10623
  "defaults.excludeOriginFormDataFields"
@@ -10701,7 +10743,13 @@ function loadRules(options = {}) {
10701
10743
  }
10702
10744
  }
10703
10745
  return {
10704
- file: { schemaVersion: base.file.schemaVersion, defaults: { ...FALLBACK_DEFAULTS, ...base.file.defaults }, rules },
10746
+ file: {
10747
+ schemaVersion: base.file.schemaVersion,
10748
+ defaults: { ...FALLBACK_DEFAULTS, ...base.file.defaults },
10749
+ rules,
10750
+ // 通用规则区(2026-11-03):仅取 default.json 的定义;用户意图文件不参与通用规则
10751
+ ...base.file.generalRules ? { generalRules: base.file.generalRules } : {}
10752
+ },
10705
10753
  warnings,
10706
10754
  dir
10707
10755
  };
@@ -10874,6 +10922,9 @@ function activeRuleFor(workflowName) {
10874
10922
  if (!name) return null;
10875
10923
  return resolveRule(activeRules(), name)?.rule ?? null;
10876
10924
  }
10925
+ function generalRules() {
10926
+ return activeRules().generalRules ?? null;
10927
+ }
10877
10928
  function resetActiveRules() {
10878
10929
  activeFile = null;
10879
10930
  activeDir = null;
@@ -10888,6 +10939,11 @@ function excludeTagFor(workflowName) {
10888
10939
  return excludeTagOf(excludeFieldsFor(workflowName));
10889
10940
  }
10890
10941
 
10942
+ // src/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.ts
10943
+ import { writeFileSync } from "node:fs";
10944
+ import { tmpdir as tmpdir2 } from "node:os";
10945
+ import { join as join3 } from "node:path";
10946
+
10891
10947
  // src/shortcuts/workflow/operations/todoSmartConvert/todoListRows.ts
10892
10948
  var DISPLAY_ROW_FIELDS = [
10893
10949
  // 定位键
@@ -10951,18 +11007,15 @@ function projectDisplayRows(response) {
10951
11007
  var DETAIL_CACHE_FILE_NAME = "todo-detail-cache.json";
10952
11008
  var DETAIL_CACHE_TTL_MS = SUMMARY_CACHE_TTL_MS;
10953
11009
  var DETAIL_CACHE_PRUNE_INTERVAL_MS = SUMMARY_CACHE_PRUNE_INTERVAL_MS;
10954
- var DETAIL_CACHE_ENTRY_VERSION = 3;
11010
+ var DETAIL_CACHE_ENTRY_VERSION = 4;
10955
11011
  function detailCacheKey(requestId, lastFeedBackDateTime) {
10956
11012
  const stamp = String(lastFeedBackDateTime ?? "").trim();
10957
11013
  return `${requestId}__${stamp}`;
10958
11014
  }
10959
11015
  function detailMaterialTagOf(entry) {
10960
- const basic = entry.basicInfo ?? {};
10961
- const basicKeys = Object.keys(basic).sort();
10962
- const material = JSON.stringify([
10963
- basicKeys.map((key) => [key, basic[key]]),
11016
+ const material = JSON.stringify(
10964
11017
  (entry.fields ?? []).map((field) => [field.fieldName, field.value])
10965
- ]);
11018
+ );
10966
11019
  let hash = 5381;
10967
11020
  for (let i = 0; i < material.length; i += 1) hash = (hash << 5) + hash + material.charCodeAt(i) >>> 0;
10968
11021
  return hash.toString(16);
@@ -10973,17 +11026,12 @@ function normalizeEntry(raw) {
10973
11026
  if (value.v !== DETAIL_CACHE_ENTRY_VERSION) return null;
10974
11027
  if (typeof value.cachedAt !== "number" || !Number.isFinite(value.cachedAt)) return null;
10975
11028
  if (typeof value.excludeTag !== "string") return null;
10976
- const basicInfo = {};
10977
- if (value.basicInfo && typeof value.basicInfo === "object") {
10978
- for (const [key, item] of Object.entries(value.basicInfo)) {
10979
- if (typeof item === "string") basicInfo[key] = item;
10980
- }
10981
- }
11029
+ const workflowName = typeof value.workflowName === "string" ? value.workflowName : "";
10982
11030
  const fields = Array.isArray(value.fields) ? value.fields.filter((item) => Boolean(item) && typeof item.fieldName === "string" && typeof item.value === "string").map((item) => ({ fieldName: item.fieldName, value: item.value })) : [];
10983
11031
  const metrics = value.metrics && typeof value.metrics === "object" ? value.metrics : {};
10984
11032
  return {
10985
11033
  v: DETAIL_CACHE_ENTRY_VERSION,
10986
- basicInfo,
11034
+ workflowName,
10987
11035
  fields,
10988
11036
  metrics,
10989
11037
  excludeTag: value.excludeTag,
@@ -11076,13 +11124,13 @@ function pickInternalMessageContentField(fields) {
11076
11124
  const content = named.find((item) => item.name === "\u5185\u5BB9" || item.name.endsWith("\u5185\u5BB9"));
11077
11125
  return content?.field;
11078
11126
  }
11079
- function pickInternalMessageFieldPairs(fields, basicInfo = {}) {
11127
+ function pickInternalMessageFieldPairs(fields, basicInfo = {}, fallbackCreatorName) {
11080
11128
  const content = pickInternalMessageContentField(fields);
11081
11129
  const contentValue = String(content?.value ?? "").trim();
11082
11130
  if (!contentValue) return [];
11083
11131
  const name = normalizeDetailFieldName(content?.fieldName) || INTERNAL_MESSAGE_CONTENT_LABEL;
11084
11132
  const pairs = [{ fieldName: name, value: contentValue }];
11085
- const creatorName = String(basicInfo.creatorName ?? "").trim();
11133
+ const creatorName = String(basicInfo.creatorName ?? fallbackCreatorName ?? "").trim();
11086
11134
  if (creatorName) pairs.push({ fieldName: INTERNAL_MESSAGE_INITIATOR_LABEL, value: creatorName });
11087
11135
  const createdAt = String(basicInfo.createdAt ?? "").trim();
11088
11136
  if (createdAt) pairs.push({ fieldName: INTERNAL_MESSAGE_TIME_LABEL, value: createdAt });
@@ -11335,6 +11383,11 @@ function isRetryable(error) {
11335
11383
  if (structured?.type === "network") return true;
11336
11384
  return structured?.retryable === true && structured?.type !== "authentication";
11337
11385
  }
11386
+ function userIdToCreatorName(options, requestId) {
11387
+ const name = options.rowMeta?.get(requestId)?.createrName;
11388
+ const text = String(name ?? "").trim();
11389
+ return text === "" ? void 0 : text;
11390
+ }
11338
11391
  async function fetchOneDetail(env, requestId, userId, options) {
11339
11392
  const body = {
11340
11393
  requestId,
@@ -11355,28 +11408,26 @@ async function fetchOneDetail(env, requestId, userId, options) {
11355
11408
  const normalized = normalizeDetailResponse(response);
11356
11409
  const base = normalized?.basicInfo ?? {};
11357
11410
  const rawFields = Array.isArray(normalized?.formData?.fields) ? normalized.formData.fields : [];
11358
- const basicInfo = Object.fromEntries(
11359
- Object.entries(base).filter(([key]) => key !== "requestTitle" && key !== "flowName")
11360
- );
11411
+ const workflowName = String(base.workflowName ?? "").trim();
11361
11412
  const usableFields = dropDistributionDetailFields(rawFields);
11362
11413
  const internalMessage = isInternalMessageDetail(
11363
- base.workflowName,
11414
+ workflowName,
11364
11415
  usableFields.map((field) => field?.fieldName)
11365
11416
  );
11366
11417
  const cleanedFields = usableFields.map((field) => ({
11367
11418
  ...field,
11368
11419
  value: cleanFieldText(String(field?.value ?? ""))
11369
11420
  }));
11370
- const excludeFields = excludeFieldsFor(base.workflowName);
11421
+ const excludeFields = excludeFieldsFor(workflowName);
11371
11422
  const excludeSet = new Set(excludeFields.map((name) => normalizeDetailFieldName(name)));
11372
- const picked = (internalMessage ? pickInternalMessageFieldPairs(cleanedFields, base) : cleanedFields.filter((field) => !excludeSet.has(normalizeDetailFieldName(field?.fieldName)))).slice(0, DETAIL_MATERIAL_FIELD_LIMIT).map((field) => ({
11423
+ const picked = (internalMessage ? pickInternalMessageFieldPairs(cleanedFields, {}, userIdToCreatorName(options, requestId)) : cleanedFields.filter((field) => !excludeSet.has(normalizeDetailFieldName(field?.fieldName)))).slice(0, DETAIL_MATERIAL_FIELD_LIMIT).map((field) => ({
11373
11424
  fieldName: String(field?.fieldName ?? "").trim(),
11374
11425
  value: String(field?.value ?? "").slice(0, DETAIL_MATERIAL_VALUE_LIMIT)
11375
11426
  })).filter((field) => field.fieldName && field.value);
11376
11427
  const metrics = extractRowMetrics(usableFields);
11377
11428
  return {
11378
11429
  requestId,
11379
- basicInfo,
11430
+ workflowName,
11380
11431
  formFields: picked,
11381
11432
  contextAvailable: picked.length > 0,
11382
11433
  excludeTag: excludeTagOf(excludeFields),
@@ -11431,7 +11482,7 @@ async function fetchRequestDetailsBatch(env, requestIds, options = {}) {
11431
11482
  failures.push({ requestId, error: reason });
11432
11483
  details.set(requestId, {
11433
11484
  requestId,
11434
- basicInfo: {},
11485
+ workflowName: "",
11435
11486
  formFields: [],
11436
11487
  contextAvailable: false,
11437
11488
  excludeTag: "",
@@ -11459,9 +11510,7 @@ async function fetchRequestDetailsBatch(env, requestIds, options = {}) {
11459
11510
 
11460
11511
  // src/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.ts
11461
11512
  function contextOfDetail(detail) {
11462
- const basicLines = Object.entries(detail.basicInfo ?? {}).filter(([, value]) => String(value ?? "").trim() !== "").map(([key, value]) => `${key}:${String(value).trim()}`);
11463
- const fieldLines = (detail.formFields ?? []).map((field) => `${field.fieldName}:${field.value}`);
11464
- return [...basicLines, ...fieldLines].join("\n");
11513
+ return (detail.formFields ?? []).map((field) => `${field.fieldName}:${field.value}`).join("\n");
11465
11514
  }
11466
11515
  var EMPTY_DETAIL_STATS = {
11467
11516
  requested: 0,
@@ -11487,7 +11536,7 @@ function stampsOfRows(rows) {
11487
11536
  function materialFieldsOf(detail) {
11488
11537
  return detail.formFields.map((field) => ({ fieldName: field.fieldName, value: field.value }));
11489
11538
  }
11490
- async function fetchDetailFacts(env, requestIds, args, stamps) {
11539
+ async function fetchDetailFacts(env, requestIds, args, stamps, names, createrNames) {
11491
11540
  const unique = [...new Set(requestIds.filter(Boolean))];
11492
11541
  const facts = /* @__PURE__ */ new Map();
11493
11542
  const warnings = [];
@@ -11499,15 +11548,16 @@ async function fetchDetailFacts(env, requestIds, args, stamps) {
11499
11548
  const missing = [];
11500
11549
  for (const requestId of unique) {
11501
11550
  const hit = cache.get(requestId, stamps?.get(requestId));
11502
- if (!hit || hit.excludeTag !== excludeTagFor(hit.basicInfo.workflowName ?? "")) {
11551
+ if (!hit || hit.excludeTag !== excludeTagFor(hit.workflowName ?? names?.get(requestId) ?? "")) {
11503
11552
  missing.push(requestId);
11504
11553
  continue;
11505
11554
  }
11506
11555
  facts.set(requestId, {
11507
- context: contextOfDetail({ basicInfo: hit.basicInfo, formFields: hit.fields }),
11556
+ context: contextOfDetail({ formFields: hit.fields }),
11508
11557
  contextAvailable: hit.fields.length > 0,
11509
11558
  metrics: hit.metrics,
11510
- fields: hit.fields
11559
+ fields: hit.fields,
11560
+ workflowName: hit.workflowName || (names?.get(requestId) ?? "")
11511
11561
  });
11512
11562
  stats.cacheHit += 1;
11513
11563
  }
@@ -11516,7 +11566,8 @@ async function fetchDetailFacts(env, requestIds, args, stamps) {
11516
11566
  try {
11517
11567
  const { details, stats: fetchStats } = await fetchRequestDetailsBatch(env, missing, {
11518
11568
  concurrency: readBoundedInt(args.detailConcurrency, "detailConcurrency", 10, 1, 32),
11519
- timeoutMs: readBoundedInt(args.detailTimeoutMs, "detailTimeoutMs", 1e4, 1e3, 6e4)
11569
+ timeoutMs: readBoundedInt(args.detailTimeoutMs, "detailTimeoutMs", 1e4, 1e3, 6e4),
11570
+ ...createrNames ? { rowMeta: createrNames } : {}
11520
11571
  });
11521
11572
  stats.failed = fetchStats.failed;
11522
11573
  stats.concurrency = fetchStats.concurrency;
@@ -11525,7 +11576,8 @@ async function fetchDetailFacts(env, requestIds, args, stamps) {
11525
11576
  context: contextOfDetail(detail),
11526
11577
  contextAvailable: detail.formFields.length > 0,
11527
11578
  metrics: detail.metrics ?? {},
11528
- fields: materialFieldsOf(detail)
11579
+ fields: materialFieldsOf(detail),
11580
+ workflowName: detail.workflowName || (names?.get(requestId) ?? "")
11529
11581
  };
11530
11582
  facts.set(requestId, fact);
11531
11583
  stats.fetched += 1;
@@ -11533,7 +11585,7 @@ async function fetchDetailFacts(env, requestIds, args, stamps) {
11533
11585
  else stats.contextEmpty += 1;
11534
11586
  if (cache.set(requestId, stamps?.get(requestId), {
11535
11587
  v: DETAIL_CACHE_ENTRY_VERSION,
11536
- basicInfo: detail.basicInfo,
11588
+ workflowName: fact.workflowName,
11537
11589
  metrics: fact.metrics,
11538
11590
  fields: fact.fields,
11539
11591
  excludeTag: detail.excludeTag
@@ -11638,18 +11690,19 @@ function isExpiringTodayRow(row, now = Date.now()) {
11638
11690
  if (row.overTime) return false;
11639
11691
  return isExpiringTodayUserOverTime(row.userOverTime, now);
11640
11692
  }
11641
- function selectPriorityRows(rows) {
11693
+ function selectPriorityRows(rows, enabledRules) {
11694
+ const rules = enabledRules ?? /* @__PURE__ */ new Set(["overdue", "levelFallback"]);
11642
11695
  let maxLevel = 0;
11643
11696
  for (const row of rows) {
11644
11697
  if (row.requestLevel > maxLevel) maxLevel = row.requestLevel;
11645
11698
  }
11646
- const targetLevel = maxLevel >= 2 ? 2 : maxLevel >= 1 ? 1 : void 0;
11699
+ const targetLevel = rules.has("levelFallback") && maxLevel >= 2 ? 2 : rules.has("levelFallback") && maxLevel >= 1 ? 1 : void 0;
11647
11700
  const selected = [];
11648
11701
  let overdueCount = 0;
11649
11702
  let levelCount = 0;
11650
11703
  let bothCount = 0;
11651
11704
  for (const row of rows) {
11652
- const overdue = isOverdueRow(row);
11705
+ const overdue = rules.has("overdue") && isOverdueRow(row);
11653
11706
  const byLevel = targetLevel !== void 0 && row.requestLevel >= targetLevel;
11654
11707
  if (overdue) overdueCount += 1;
11655
11708
  if (byLevel) levelCount += 1;
@@ -11779,11 +11832,8 @@ function runGroup(args) {
11779
11832
  const { rawCount, rows, duplicateCount, unreadableCount } = readItems(args.items);
11780
11833
  const groupBy = readGroupBy(args.groupBy);
11781
11834
  const topN = readTopN(args.topN);
11782
- const priority = selectPriorityRows(rows);
11783
- const priorityRows = sortPriorityRows(priority.rows);
11784
- const restRows = rows;
11785
11835
  const buckets = /* @__PURE__ */ new Map();
11786
- for (const row of restRows) {
11836
+ for (const row of rows) {
11787
11837
  const key = groupKeyOf(row, groupBy);
11788
11838
  let bucket = buckets.get(key);
11789
11839
  if (!bucket) {
@@ -11806,16 +11856,8 @@ function runGroup(args) {
11806
11856
  stats: statsOf(bucket.rows),
11807
11857
  ...bucket.ids.length > 1 ? { workflowIds: bucket.ids } : {}
11808
11858
  }));
11809
- const groups = priorityRows.length > 0 && groupBy === "workflow" ? [{
11810
- id: PRIORITY_GROUP_ID,
11811
- topPriority: true,
11812
- title: PRIORITY_GROUP_TITLE,
11813
- count: priorityRows.length,
11814
- requestDatas: priorityRows.map((row) => toRequestData(row)),
11815
- stats: statsOf(priorityRows)
11816
- }, ...workflowGroups] : workflowGroups;
11817
- const displayedWorkflow = workflowGroups.slice(0, topN);
11818
- const displayed = priorityRows.length > 0 && groupBy === "workflow" ? [groups[0], ...displayedWorkflow] : displayedWorkflow;
11859
+ const groups = workflowGroups;
11860
+ const displayed = workflowGroups.slice(0, topN);
11819
11861
  const rest = workflowGroups.slice(topN);
11820
11862
  const restCount = rest.reduce((sum, group) => sum + group.count, 0);
11821
11863
  const overall = statsOf(rows);
@@ -11832,16 +11874,6 @@ function runGroup(args) {
11832
11874
  groupBy === "workflow" ? `\u6709 ${unknownGroupCount} \u6761\u7F3A\u5C11\u5DE5\u4F5C\u6D41\u540D\u79F0\uFF0C\u5DF2\u5F52\u5165\u300C${UNKNOWN_GROUP}\u300D` : `\u6709 ${unknownGroupCount} \u6761\u7F3A\u5C11\u5206\u7EC4\u5B57\u6BB5\uFF0C\u5DF2\u5F52\u5165\u300C${UNKNOWN_GROUP}\u300D`
11833
11875
  );
11834
11876
  }
11835
- if (priorityRows.length > 0 && groupBy === "workflow") {
11836
- const levelText = priority.targetLevel === 2 ? "\u7D27\u6025\uFF08requestLevel=2\uFF09" : priority.targetLevel === 1 ? "\u91CD\u8981\uFF08requestLevel=1\uFF1B\u672C\u6B21\u65E0 2 \u7EA7\u6570\u636E\uFF0C\u5DF2\u6309\u89C4\u5219\u964D\u7EA7\u53D6 1\uFF0C0 \u7EA7\u4E0D\u53D6\uFF09" : "\u65E0\u7B49\u7EA7\uFF08\u672C\u6B21\u6574\u6279\u6CA1\u6709 \u22651 \u7EA7\u7684\u6761\u76EE\uFF0C\u53EA\u6309\u8D85\u65F6\u7B5B\uFF09";
11837
- warnings.push(
11838
- `\u300C${PRIORITY_GROUP_TITLE}\u300D\u7B5B\u51FA ${priorityRows.length} \u6761\uFF1A\u8D85\u65F6 ${priority.overdueCount} \u6761 / \u7B49\u7EA7\u547D\u4E2D ${priority.levelCount} \u6761\uFF08\u4E24\u8005\u90FD\u6EE1\u8DB3 ${priority.bothCount} \u6761\uFF09\uFF0C\u7B49\u7EA7\u53E3\u5F84=${levelText}\uFF1B\u8FD9 ${priorityRows.length} \u6761\u540C\u65F6\u4FDD\u7559\u5728\u5404\u81EA\u5DE5\u4F5C\u6D41\u5206\u7EC4\u4E2D\uFF08\u53E0\u52A0\u89C6\u56FE\uFF1A\u03A3count \u4F1A\u5927\u4E8E totalCount\uFF0CtotalCount \u6309\u53BB\u91CD\u6761\u6570\u8BA1 = ${rows.length}\uFF09`
11839
- );
11840
- } else if (priorityRows.length === 0 && groupBy === "workflow") {
11841
- warnings.push(
11842
- `\u672C\u6B21\u6CA1\u6709\u8D85\u65F6\u6761\u76EE\uFF0C\u4E5F\u6CA1\u6709 requestLevel\u22651 \u7684\u6761\u76EE\uFF0C\u6545\u4E0D\u8F93\u51FA\u300C${PRIORITY_GROUP_TITLE}\u300D\u5206\u7EC4`
11843
- );
11844
- }
11845
11877
  if (rest.length > 0) {
11846
11878
  warnings.push(`markdown \u53EA\u5C55\u793A\u524D ${topN} \u4E2A\u5DE5\u4F5C\u6D41\u5206\u7EC4\uFF0C\u5176\u4F59 ${rest.length} \u7EC4\u5171 ${restCount} \u6761\u4ECD\u5728 wfIdGroup \u4E2D\uFF08\u672A\u622A\u65AD\uFF09`);
11847
11879
  }
@@ -11877,7 +11909,7 @@ function runGroup(args) {
11877
11909
  },
11878
11910
  wfIdGroup: groups,
11879
11911
  /** 第二部分(非优先组)的总条数与组数,前端折叠/分页直接用它,不用自己减 */
11880
- restTotal: restRows.length,
11912
+ restTotal: rows.length,
11881
11913
  restGroupCount: workflowGroups.length,
11882
11914
  restGroups: rest.length > 0 ? { groupCount: rest.length, count: restCount } : null,
11883
11915
  warnings,
@@ -11900,7 +11932,7 @@ async function collectRawTodos(args, env) {
11900
11932
  const plannedPages = Math.max(1, Math.min(Math.ceil(limit / pageSize), MAX_FETCH_PAGES));
11901
11933
  const listEnv = guardListOnlyHost(env);
11902
11934
  const searchArgs = { category };
11903
- for (const key of ["tabid", "tabName", "subCategory", "workflow", "creator", "requestName", "receiveTime", "requestLevel"]) {
11935
+ for (const key of ["tabid", "tabName", "subCategory", "isremarks", "workflow", "creator", "requestName", "receiveTime", "requestLevel"]) {
11904
11936
  const value = args[key];
11905
11937
  if (value !== void 0 && value !== null && value !== "") searchArgs[key] = value;
11906
11938
  }
@@ -11909,6 +11941,13 @@ async function collectRawTodos(args, env) {
11909
11941
  );
11910
11942
  if (!explicitTab) searchArgs.tabid = DEFAULT_TABID2;
11911
11943
  const warnings = [];
11944
+ if (searchArgs.isremarks === void 0) {
11945
+ const defaultIsremarks = generalRules()?.identityFilter?.defaultIsremarks?.trim();
11946
+ if (defaultIsremarks) {
11947
+ searchArgs.isremarks = defaultIsremarks;
11948
+ warnings.push(`\u5DF2\u6309\u901A\u7528\u89C4\u5219\u9ED8\u8BA4\u6392\u9664\u6284\u9001\u7C7B\u8EAB\u4EFD\uFF08isremarks=${defaultIsremarks}\uFF09\uFF1B\u5982\u9700\u5305\u542B\u6284\u9001\uFF0C\u8BF7\u5728\u63D0\u793A\u8BCD\u4E2D\u8BF4\u660E`);
11949
+ }
11950
+ }
11912
11951
  if (cappedFrom !== void 0) {
11913
11952
  warnings.push(
11914
11953
  `\u5355\u6B21\u6700\u591A\u53EA\u80FD\u53D6 ${MAX_FETCH_LIMIT} \u6761\uFF08${MAX_FETCH_PAGES} \u6B21\u8BF7\u6C42 \xD7 ${FETCH_PAGE_SIZE} \u6761\uFF09\uFF0C\u4F60\u8981\u6C42\u7684 ${cappedFrom} \u6761\u5DF2\u6309\u4E0A\u9650 ${MAX_FETCH_LIMIT} \u6761\u5904\u7406\uFF1B\u5982\u9700\u8986\u76D6\u66F4\u591A\uFF0C\u8BF7\u7F29\u5C0F\u7B5B\u9009\u6761\u4EF6\uFF08\u5982\u6309\u5DE5\u4F5C\u6D41\u3001\u65F6\u95F4\u8303\u56F4\u5206\u6279\uFF09\u540E\u518D\u6C47\u603B`
@@ -11933,6 +11972,19 @@ async function collectRawTodos(args, env) {
11933
11972
  { ...searchArgs, current: pageNo, pageSize },
11934
11973
  "list"
11935
11974
  );
11975
+ const isremarks = String(searchArgs.isremarks ?? "").trim();
11976
+ if (isremarks !== "") {
11977
+ query.params = { ...query.params || {}, isremarks };
11978
+ }
11979
+ if (process.env.WEAVER_WORK_CLI_DUMP_LIST_BODY) {
11980
+ try {
11981
+ writeFileSync(
11982
+ join3(tmpdir2(), `weaver-list-body-page${pageNo}.json`),
11983
+ JSON.stringify({ path: listPath, body: query }, null, 2)
11984
+ );
11985
+ } catch {
11986
+ }
11987
+ }
11936
11988
  const response = await listEnv.host.workflowRequest({
11937
11989
  method: "POST",
11938
11990
  path: listPath,
@@ -11972,6 +12024,46 @@ async function collectRawTodos(args, env) {
11972
12024
  if (items.length >= limit) break;
11973
12025
  if (pageRows.length < pageSize) break;
11974
12026
  }
12027
+ const workflowNames = /* @__PURE__ */ new Map();
12028
+ const createrNames = /* @__PURE__ */ new Map();
12029
+ for (const row of items) {
12030
+ if (!row.requestId) continue;
12031
+ const name = String(row.workflowName ?? "").trim();
12032
+ if (name) workflowNames.set(row.requestId, name);
12033
+ if (row.createrName) createrNames.set(row.requestId, { createrName: row.createrName });
12034
+ }
12035
+ const detailBackfill = { requested: 0, cacheHit: 0, fetched: 0, failed: 0, nameFilled: 0 };
12036
+ let allFacts = /* @__PURE__ */ new Map();
12037
+ if (items.length > 0) {
12038
+ const detailIds = [...new Set(items.map((row) => row.requestId).filter(Boolean))];
12039
+ const { facts, stats } = await fetchDetailFacts(
12040
+ env,
12041
+ detailIds,
12042
+ args,
12043
+ stampsOfRows(items),
12044
+ workflowNames,
12045
+ createrNames
12046
+ );
12047
+ allFacts = facts;
12048
+ detailBackfill.requested = stats.requested;
12049
+ detailBackfill.cacheHit = stats.cacheHit;
12050
+ detailBackfill.fetched = stats.fetched;
12051
+ detailBackfill.failed = stats.failed;
12052
+ for (const row of items) {
12053
+ const fact = facts.get(row.requestId);
12054
+ if (!fact) continue;
12055
+ if (!String(row.workflowName ?? "").trim() && fact.workflowName) {
12056
+ row.workflowName = fact.workflowName;
12057
+ workflowNames.set(row.requestId, fact.workflowName);
12058
+ detailBackfill.nameFilled += 1;
12059
+ }
12060
+ }
12061
+ if (detailBackfill.nameFilled > 0) {
12062
+ warnings.push(
12063
+ `\u6709 ${detailBackfill.nameFilled} \u6761\u5217\u8868\u6570\u636E\u7F3A\u5C11\u5DE5\u4F5C\u6D41\u540D\u79F0\uFF0C\u5DF2\u7528\u6D41\u7A0B\u8BE6\u60C5\u6570\u636E\uFF08basic.workflowName\uFF09\u56DE\u586B`
12064
+ );
12065
+ }
12066
+ }
11975
12067
  await saveSearchIndex(
11976
12068
  {
11977
12069
  items: items.map((row, index) => ({
@@ -12048,8 +12140,9 @@ async function collectRawTodos(args, env) {
12048
12140
  cachedSummaryIds.add(row.requestId);
12049
12141
  }
12050
12142
  detailStats = {
12051
- deferred: true,
12052
- note: "\u8BE6\u60C5\u4E0D\u9884\u53D6\uFF1AsmartGroup / summaryContext \u4F1A\u5728\u9700\u8981\u65F6\u73B0\u573A\u62C9\u53D6\uFF08\u8BE6\u60C5\u7F13\u5B58\u4F18\u5148\uFF09",
12143
+ deferred: false,
12144
+ note: "\u8BE6\u60C5\u5DF2\u5728 collect \u9636\u6BB5\u5168\u91CF\u56DE\u586B\uFF08\u7F13\u5B58\u4F18\u5148\uFF09\uFF1A\u4EC5 basic.workflowName \u4FDD\u7559\uFF0C\u5176\u4F59 basic \u5B57\u6BB5\u4E0E\u7D20\u6750\u65E0\u5173",
12145
+ detailBackfill,
12053
12146
  summaryCached: cachedSummaryIds.size,
12054
12147
  summaryCacheFile: summaryCache.file,
12055
12148
  summaryCachePruned: summaryCache.pruned
@@ -12060,15 +12153,15 @@ async function collectRawTodos(args, env) {
12060
12153
  const targetRows = wfIdGroup.filter((group) => !group.topPriority && activeRuleFor(group.title)?.aiGroup?.groupRule.aiContext === "\u6D41\u7A0B\u8BE6\u60C5").flatMap((group) => group.requestDatas ?? []);
12061
12154
  const targetIds = [...new Set(targetRows.map((row) => row.requestId).filter(Boolean))];
12062
12155
  if (targetIds.length > 0) {
12063
- const { facts, stats } = await fetchDetailFacts(env, targetIds, args, stampsOfRows(targetRows));
12064
- for (const [requestId, fact] of facts) {
12065
- if (fact.fields.length > 0) fieldsById.set(requestId, fact.fields);
12156
+ for (const requestId of targetIds) {
12157
+ const fact = allFacts.get(requestId);
12158
+ if (fact && fact.fields.length > 0) fieldsById.set(requestId, fact.fields);
12066
12159
  }
12067
12160
  detailStats.groupingMaterial = {
12068
12161
  requested: targetIds.length,
12069
- cacheHit: stats.cacheHit,
12070
- fetched: stats.fetched,
12071
- failed: stats.failed,
12162
+ cacheHit: detailBackfill.cacheHit,
12163
+ fetched: detailBackfill.fetched,
12164
+ failed: detailBackfill.failed,
12072
12165
  withFields: fieldsById.size
12073
12166
  };
12074
12167
  }
@@ -12240,7 +12333,17 @@ function inferStage(args) {
12240
12333
  if (!Array.isArray(args.wfIdGroup)) return "auto";
12241
12334
  if (Array.isArray(args.aiGroupSummaries)) return "groupSummary";
12242
12335
  if (Array.isArray(args.aiSummaries)) return "summary";
12243
- return hasAnyRequestSummary(args.wfIdGroup) ? "groupSummaryContext" : "summaryContext";
12336
+ if (hasAnyRequestSummary(args.wfIdGroup)) {
12337
+ return hasAnySubGroup(args.wfIdGroup) ? "groupSummaryContext" : "subGroup";
12338
+ }
12339
+ return "summaryContext";
12340
+ }
12341
+ function hasAnySubGroup(groups) {
12342
+ for (const raw of groups) {
12343
+ const items = raw?.displayItems;
12344
+ if (Array.isArray(items) && items.some((item) => item?.type === "group")) return true;
12345
+ }
12346
+ return false;
12244
12347
  }
12245
12348
  function rowsOfRawGroup(group) {
12246
12349
  if (!group) return [];
@@ -12275,6 +12378,34 @@ function rowsOfGroup(group) {
12275
12378
  function groupItemsOf(group) {
12276
12379
  return group.displayItems.filter((item) => item.type === "group");
12277
12380
  }
12381
+ function assemblePriorityGroup(groups) {
12382
+ const base = (groups ?? []).filter((group) => group.id !== PRIORITY_GROUP_ID && group.topPriority !== true);
12383
+ const pgConfig = generalRules()?.priorityGroup ?? null;
12384
+ const title = pgConfig?.title?.trim() || PRIORITY_GROUP_TITLE;
12385
+ const rules = new Set(pgConfig?.rules ?? ["overdue", "levelFallback"]);
12386
+ const rows = base.flatMap((group) => rowsOfGroup(group));
12387
+ if (rows.length === 0) return { groups: base };
12388
+ const selection = selectPriorityRows(rows, rules);
12389
+ const selected = sortPriorityRows(selection.rows);
12390
+ if (selected.length === 0) {
12391
+ return { groups: base, warning: `\u672C\u6B21\u6CA1\u6709\u8D85\u65F6\u6761\u76EE\uFF0C\u4E5F\u6CA1\u6709 requestLevel\u22651 \u7684\u6761\u76EE\uFF0C\u6545\u4E0D\u8F93\u51FA\u300C${title}\u300D\u5206\u7EC4` };
12392
+ }
12393
+ const levelText = selection.targetLevel === 2 ? "\u7D27\u6025\uFF08requestLevel=2\uFF09" : selection.targetLevel === 1 ? "\u91CD\u8981\uFF08requestLevel=1\uFF1B\u672C\u6B21\u65E0 2 \u7EA7\u6570\u636E\uFF0C\u5DF2\u6309\u89C4\u5219\u964D\u7EA7\u53D6 1\uFF0C0 \u7EA7\u4E0D\u53D6\uFF09" : "\u65E0\u7B49\u7EA7\uFF08\u672C\u6B21\u6574\u6279\u6CA1\u6709 \u22651 \u7EA7\u7684\u6761\u76EE\uFF0C\u53EA\u6309\u8D85\u65F6\u7B5B\uFF09";
12394
+ const priorityGroup = {
12395
+ id: PRIORITY_GROUP_ID,
12396
+ topPriority: true,
12397
+ title,
12398
+ count: selected.length,
12399
+ // 大分组(含优先组)默认展开;只有汇总项收缩
12400
+ defaultExpanded: true,
12401
+ // 复制一份:优先组是独立视图,确保两边互不影响
12402
+ displayItems: requestItemsOf(selected.map((row) => ({ ...row })))
12403
+ };
12404
+ return {
12405
+ groups: [priorityGroup, ...base],
12406
+ warning: `\u300C${title}\u300D\u7B5B\u51FA ${selected.length} \u6761\uFF1A\u8D85\u65F6 ${selection.overdueCount} \u6761 / \u7B49\u7EA7\u547D\u4E2D ${selection.levelCount} \u6761\uFF08\u4E24\u8005\u90FD\u6EE1\u8DB3 ${selection.bothCount} \u6761\uFF09\uFF0C\u7B49\u7EA7\u53E3\u5F84=${levelText}\uFF1B\u8FD9 ${selected.length} \u6761\u540C\u65F6\u4FDD\u7559\u5728\u5404\u81EA\u5DE5\u4F5C\u6D41\u5206\u7EC4\u4E2D\uFF08\u53E0\u52A0\u89C6\u56FE\uFF1A\u03A3count \u4F1A\u5927\u4E8E totalCount\uFF0CtotalCount \u6309\u53BB\u91CD\u6761\u6570\u8BA1\uFF09`
12407
+ };
12408
+ }
12278
12409
  function readAiGroups(value) {
12279
12410
  if (!Array.isArray(value)) {
12280
12411
  throw workflowValidationError(
@@ -12290,14 +12421,15 @@ function readAiGroups(value) {
12290
12421
  if (!record) {
12291
12422
  throw workflowValidationError("ai_groups_invalid", `${label} \u5FC5\u987B\u662F\u5BF9\u8C61 { groupId, title, requestIds }`, { retryAllowed: false });
12292
12423
  }
12293
- const unknownKeys = Object.keys(record).filter((key) => !["groupId", "title", "requestIds"].includes(key));
12424
+ const unknownKeys = Object.keys(record).filter((key) => !["groupId", "title", "requestIds", "summary"].includes(key));
12294
12425
  if (unknownKeys.length > 0) {
12295
12426
  throw workflowValidationError(
12296
12427
  "ai_groups_invalid",
12297
- `${label} \u4E0D\u63A5\u53D7\u5B57\u6BB5\uFF1A${unknownKeys.join(", ")}\uFF1B\u53EA\u652F\u6301 groupId / title / requestIds`,
12428
+ `${label} \u4E0D\u63A5\u53D7\u5B57\u6BB5\uFF1A${unknownKeys.join(", ")}\uFF1B\u53EA\u652F\u6301 groupId / title / requestIds / summary`,
12298
12429
  { retryAllowed: false, details: { unknownKeys } }
12299
12430
  );
12300
12431
  }
12432
+ const planSummary = typeof record.summary === "string" ? record.summary.trim() : "";
12301
12433
  const groupId = typeof record.groupId === "string" ? record.groupId.trim() : "";
12302
12434
  if (!groupId) {
12303
12435
  throw workflowValidationError(
@@ -12335,7 +12467,12 @@ function readAiGroups(value) {
12335
12467
  ids.push(id);
12336
12468
  }
12337
12469
  const bucket = map.get(groupId) ?? [];
12338
- bucket.push({ groupId, title, requestIds: [...new Set(ids)] });
12470
+ bucket.push({
12471
+ groupId,
12472
+ title,
12473
+ requestIds: [...new Set(ids)],
12474
+ ...planSummary ? { summary: planSummary } : {}
12475
+ });
12339
12476
  map.set(groupId, bucket);
12340
12477
  });
12341
12478
  return map;
@@ -12391,44 +12528,21 @@ function rowKeyForCount(row) {
12391
12528
  if (id) return `id:${id}`;
12392
12529
  return `tx:${row.requestNameTitle ?? ""}|${row.creater ?? ""}|${row.nodeId ?? ""}`;
12393
12530
  }
12394
- async function runSmartGroup(args, env, options = {}) {
12395
- const base = runGroup(args);
12396
- const groups = base.wfIdGroup ?? [];
12397
- const plans = args.aiGroups === void 0 || args.aiGroups === null ? void 0 : readAiGroups(args.aiGroups);
12398
- const groupFocus = typeof args.groupFocus === "string" ? args.groupFocus.trim() : "";
12399
- const hasFocus = groupFocus.length > 0;
12400
- const summaryMaxChars = readBoundedInt(
12401
- args.summaryMaxChars,
12402
- "summaryMaxChars",
12403
- DEFAULT_REQUEST_SUMMARY_MAX2,
12404
- 10,
12405
- 500
12406
- );
12407
- const skipDetail = args.withDetailContext === false;
12408
- const summaryCache = await openSummaryCache(env.ctx);
12409
- const detailCacheForTag = skipDetail ? null : await openDetailCache(env.ctx);
12410
- const materialTagOfRow = (requestId, stamp) => {
12411
- const entry = detailCacheForTag?.get(requestId, stamp);
12412
- return entry ? detailMaterialTagOf(entry) : void 0;
12413
- };
12414
- const cachedIds = /* @__PURE__ */ new Set();
12415
- const allRows = [];
12416
- for (const group of groups) {
12417
- for (const row of group.requestDatas ?? []) {
12418
- allRows.push(row);
12419
- if (summaryCache.get(
12420
- row.requestId,
12421
- row.lastFeedBackDateTime,
12422
- summaryMaxChars,
12423
- promptTagOf(activeRuleFor(group.title)?.requestSummaryPrompt ?? ""),
12424
- materialTagOfRow(row.requestId, row.lastFeedBackDateTime)
12425
- )) cachedIds.add(row.requestId);
12426
- }
12427
- }
12428
- const detailIds = [...new Set(allRows.map((row) => row.requestId).filter(Boolean))];
12429
- const stamps = stampsOfRows(allRows);
12430
- const facts = skipDetail ? /* @__PURE__ */ new Map() : options.facts ?? (await fetchDetailFacts(env, detailIds, args, stamps)).facts;
12431
- const metrics = skipDetail ? void 0 : options.metrics ?? metricsOfFacts(facts);
12531
+ function flattenFinalGroups(groups) {
12532
+ return groups.map((group) => ({
12533
+ id: group.id,
12534
+ topPriority: group.id === PRIORITY_GROUP_ID,
12535
+ title: group.title,
12536
+ count: group.count,
12537
+ defaultExpanded: true,
12538
+ displayItems: requestItemsOf(group.requestDatas)
12539
+ }));
12540
+ }
12541
+ function applySubGroups(groups, options) {
12542
+ const plans = options.plans;
12543
+ const facts = options.facts;
12544
+ const metrics = options.metrics;
12545
+ const warnings = options.warnings;
12432
12546
  const knownGroupIds = new Set(groups.map((group) => group.id));
12433
12547
  for (const groupId of plans?.keys() ?? []) {
12434
12548
  if (!knownGroupIds.has(groupId)) {
@@ -12446,15 +12560,6 @@ async function runSmartGroup(args, env, options = {}) {
12446
12560
  );
12447
12561
  }
12448
12562
  }
12449
- const warnings = (base.warnings ?? []).filter((text) => !text.startsWith("markdown \u53EA\u5C55\u793A\u524D"));
12450
- warnings.push(...primeRules(env.ctx).warnings);
12451
- if (skipDetail) {
12452
- warnings.push("withDetailContext=false\uFF1A\u672C\u6B21\u672A\u62C9\u53D6\u4EFB\u4F55\u8BE6\u60C5\u2014\u2014\u8BF7\u5047/\u8D22\u52A1\u9608\u503C\u6539\u4E3A\u6309\u6807\u9898\u8BC6\u522B\u3001\u8DF3\u8FC7\u6574\u7EC4\u7A7A\u5224\u5B9A\uFF0C\u4E5F\u4E0D\u4EA7 summaryBatches");
12453
- } else if (cachedIds.size > 0) {
12454
- warnings.push(
12455
- `\u6709 ${cachedIds.size} \u6761\u547D\u4E2D\u672C\u5730\u6458\u8981\u7F13\u5B58\uFF08\u8FD9\u4E9B\u6761\u76EE\u4E0D\u7528\u518D\u8C03 AI\uFF09\uFF1B\u8BE6\u60C5\u4ECD\u6309\u7F13\u5B58\u4F18\u5148\u53D6\u4E00\u6B21\u2014\u2014\u9608\u503C\u6307\u6807\u53EA\u8BA4\u6D41\u7A0B\u8BE6\u60C5\u6570\u636E\uFF0C\u8DF3\u8FC7\u8BE6\u60C5\u4F1A\u8BA9\u9608\u503C\u5206\u7EC4\u5931\u6548`
12456
- );
12457
- }
12458
12563
  const finalGroups = groups.map((group) => {
12459
12564
  if (group.id === PRIORITY_GROUP_ID) {
12460
12565
  return {
@@ -12580,7 +12685,11 @@ async function runSmartGroup(args, env, options = {}) {
12580
12685
  }
12581
12686
  groupRows = kept2;
12582
12687
  }
12583
- subGroups.push({ title: plan.title, requestDatas: groupRows });
12688
+ subGroups.push({
12689
+ title: plan.title,
12690
+ requestDatas: groupRows,
12691
+ ...plan.summary ? { summary: plan.summary } : {}
12692
+ });
12584
12693
  }
12585
12694
  const kept = subGroups.filter((sub) => sub.requestDatas.length >= 2);
12586
12695
  const dissolved = subGroups.length - kept.length;
@@ -12612,6 +12721,7 @@ async function runSmartGroup(args, env, options = {}) {
12612
12721
  }
12613
12722
  }
12614
12723
  const renderSubGroupSummary = (sub) => {
12724
+ if ((sub.summary ?? "").trim()) return sub.summary;
12615
12725
  const groupSummary = rule.aiGroup?.groupSummary;
12616
12726
  if (!groupSummary || groupSummary.needAI || !groupSummary.template) return "";
12617
12727
  if (groupRule.groupTitle && sub.title !== groupRule.groupTitle) return "";
@@ -12653,9 +12763,57 @@ async function runSmartGroup(args, env, options = {}) {
12653
12763
  displayItems: [...groupItems, ...requestItemsOf(singles)]
12654
12764
  };
12655
12765
  });
12656
- const orderedGroups = finalGroups;
12657
- if (plans === void 0) {
12658
- warnings.push("smartGroup \u672A\u6536\u5230 aiGroups\uFF1A\u5DF2\u6309\u4E1A\u52A1\u7C7B\u578B\u6267\u884C\u786E\u5B9A\u6027\u5206\u7EC4\uFF1B\u9700\u8981\u8BED\u4E49\u4FA7\u91CD\u70B9\u65F6\u518D\u4F20\u5165\u672C\u8F6E aiGroups");
12766
+ return finalGroups;
12767
+ }
12768
+ async function runSmartGroup(args, env, options = {}) {
12769
+ const base = runGroup(args);
12770
+ const groups = base.wfIdGroup ?? [];
12771
+ const plans = args.aiGroups === void 0 || args.aiGroups === null ? void 0 : readAiGroups(args.aiGroups);
12772
+ const groupFocus = typeof args.groupFocus === "string" ? args.groupFocus.trim() : "";
12773
+ const hasFocus = groupFocus.length > 0;
12774
+ const summaryMaxChars = readBoundedInt(
12775
+ args.summaryMaxChars,
12776
+ "summaryMaxChars",
12777
+ DEFAULT_REQUEST_SUMMARY_MAX2,
12778
+ 10,
12779
+ 500
12780
+ );
12781
+ const skipDetail = args.withDetailContext === false;
12782
+ const summaryCache = await openSummaryCache(env.ctx);
12783
+ const detailCacheForTag = skipDetail ? null : await openDetailCache(env.ctx);
12784
+ const materialTagOfRow = (requestId, stamp) => {
12785
+ const entry = detailCacheForTag?.get(requestId, stamp);
12786
+ return entry ? detailMaterialTagOf(entry) : void 0;
12787
+ };
12788
+ const cachedIds = /* @__PURE__ */ new Set();
12789
+ const allRows = [];
12790
+ for (const group of groups) {
12791
+ for (const row of group.requestDatas ?? []) {
12792
+ allRows.push(row);
12793
+ if (summaryCache.get(
12794
+ row.requestId,
12795
+ row.lastFeedBackDateTime,
12796
+ summaryMaxChars,
12797
+ promptTagOf(activeRuleFor(group.title)?.requestSummaryPrompt ?? ""),
12798
+ materialTagOfRow(row.requestId, row.lastFeedBackDateTime)
12799
+ )) cachedIds.add(row.requestId);
12800
+ }
12801
+ }
12802
+ const detailIds = [...new Set(allRows.map((row) => row.requestId).filter(Boolean))];
12803
+ const stamps = stampsOfRows(allRows);
12804
+ const facts = skipDetail ? /* @__PURE__ */ new Map() : options.facts ?? (await fetchDetailFacts(env, detailIds, args, stamps)).facts;
12805
+ const warnings = (base.warnings ?? []).filter((text) => !text.startsWith("markdown \u53EA\u5C55\u793A\u524D"));
12806
+ warnings.push(...primeRules(env.ctx).warnings);
12807
+ if (skipDetail) {
12808
+ warnings.push("withDetailContext=false\uFF1A\u672C\u6B21\u672A\u62C9\u53D6\u4EFB\u4F55\u8BE6\u60C5\u2014\u2014\u8BF7\u5047/\u8D22\u52A1\u9608\u503C\u6539\u4E3A\u6309\u6807\u9898\u8BC6\u522B\u3001\u8DF3\u8FC7\u6574\u7EC4\u7A7A\u5224\u5B9A\uFF0C\u4E5F\u4E0D\u4EA7 summaryBatches");
12809
+ } else if (cachedIds.size > 0) {
12810
+ warnings.push(
12811
+ `\u6709 ${cachedIds.size} \u6761\u547D\u4E2D\u672C\u5730\u6458\u8981\u7F13\u5B58\uFF08\u8FD9\u4E9B\u6761\u76EE\u4E0D\u7528\u518D\u8C03 AI\uFF09\uFF1B\u8BE6\u60C5\u4ECD\u6309\u7F13\u5B58\u4F18\u5148\u53D6\u4E00\u6B21\u2014\u2014\u9608\u503C\u6307\u6807\u53EA\u8BA4\u6D41\u7A0B\u8BE6\u60C5\u6570\u636E\uFF0C\u8DF3\u8FC7\u8BE6\u60C5\u4F1A\u8BA9\u9608\u503C\u5206\u7EC4\u5931\u6548`
12812
+ );
12813
+ }
12814
+ const orderedGroups = flattenFinalGroups(groups);
12815
+ if (plans !== void 0) {
12816
+ warnings.push("aiGroups \u5DF2\u6536\u5230\uFF0C\u4F46\u672C\u9636\u6BB5\u4E0D\u505A\u4E8C\u6B21\u5206\u7EC4\uFF1A\u7559\u5230 stage=subGroup \u5E94\u7528");
12659
12817
  }
12660
12818
  return {
12661
12819
  data: {
@@ -12681,6 +12839,11 @@ function requestMaxCharsFor(args, workflowName) {
12681
12839
  500
12682
12840
  );
12683
12841
  }
12842
+ function explicitMaxCharsFor(args, workflowName) {
12843
+ const explicit = args.summaryMaxChars;
12844
+ if (explicit === void 0 || explicit === null || String(explicit).trim() === "") return void 0;
12845
+ return requestMaxCharsFor(args, workflowName);
12846
+ }
12684
12847
  function requestPromptFor(workflowName) {
12685
12848
  return (activeRuleFor(workflowName)?.requestSummaryPrompt ?? "").trim();
12686
12849
  }
@@ -12827,7 +12990,7 @@ function collectSummaryUnits(groups) {
12827
12990
  continue;
12828
12991
  }
12829
12992
  const kind = detectBusinessKind(group.title);
12830
- if (!needsRequestSummary(kind)) continue;
12993
+ if (!needAiSummary(group.title) || !needsRequestSummary(kind)) continue;
12831
12994
  for (const item of group.displayItems) {
12832
12995
  if (item.type === "group") {
12833
12996
  units.push({
@@ -12867,11 +13030,11 @@ async function runSummaryContext(args, env, prefetched) {
12867
13030
  const prefilledIds = /* @__PURE__ */ new Set();
12868
13031
  const needsDetail = [];
12869
13032
  const workflowTitleByRequest = /* @__PURE__ */ new Map();
12870
- for (const unit of units) {
12871
- if (unit.groupId === "priority") continue;
12872
- for (const row of unit.rows) {
13033
+ for (const group of groups) {
13034
+ if (group.topPriority) continue;
13035
+ for (const row of rowsOfGroup(group)) {
12873
13036
  if (row.requestId && !workflowTitleByRequest.has(row.requestId)) {
12874
- workflowTitleByRequest.set(row.requestId, unit.groupTitle);
13037
+ workflowTitleByRequest.set(row.requestId, group.title);
12875
13038
  }
12876
13039
  }
12877
13040
  }
@@ -12879,10 +13042,11 @@ async function runSummaryContext(args, env, prefetched) {
12879
13042
  for (const unit of units) {
12880
13043
  for (const row of unit.rows) {
12881
13044
  const name = ruleNameForRow(unit, row);
13045
+ if (!needAiSummary(name)) continue;
12882
13046
  const cached = summaryCache.get(
12883
13047
  row.requestId,
12884
13048
  row.lastFeedBackDateTime,
12885
- requestMaxCharsFor(args, name),
13049
+ explicitMaxCharsFor(args, name),
12886
13050
  promptTagOf(requestPromptFor(name)),
12887
13051
  materialTagOfRow(row.requestId, row.lastFeedBackDateTime)
12888
13052
  );
@@ -12934,6 +13098,13 @@ async function runSummaryContext(args, env, prefetched) {
12934
13098
  };
12935
13099
  for (const row of unit.rows) {
12936
13100
  if (prefilledIds.has(row.requestId)) continue;
13101
+ if (!needAiSummary(ruleNameForRow(unit, row))) {
13102
+ if (!(row.summary ?? "").trim()) {
13103
+ row.summary = row.requestNameTitle ?? "";
13104
+ if ((row.summary ?? "").trim()) titleCopied += 1;
13105
+ }
13106
+ continue;
13107
+ }
12937
13108
  const { context, contextAvailable: available } = provider.get(row.requestId);
12938
13109
  if (!available) {
12939
13110
  const firstSeen = !row.requestId || !claimed.has(row.requestId);
@@ -13087,21 +13258,19 @@ async function runSummary(args, env) {
13087
13258
  }
13088
13259
  const ruleNameForGroup = (group, row) => group.topPriority ? wfTitleByRequest.get(row?.requestId ?? "") ?? group.title : group.title;
13089
13260
  for (const group of groups) {
13090
- if (!needAiSummary(group.title)) {
13091
- for (const row of rowsOfGroup(group)) {
13092
- if ((row.summary ?? "").trim()) continue;
13261
+ for (const row of rowsOfGroup(group)) {
13262
+ if ((row.summary ?? "").trim()) continue;
13263
+ const name = ruleNameForGroup(group, row);
13264
+ if (!needAiSummary(name)) {
13093
13265
  row.summary = row.requestNameTitle ?? "";
13094
13266
  if ((row.summary ?? "").trim()) titleSummary += 1;
13267
+ continue;
13095
13268
  }
13096
- continue;
13097
- }
13098
- for (const row of rowsOfGroup(group)) {
13099
- if (!row?.requestId || (row.summary ?? "").trim()) continue;
13100
- const name = ruleNameForGroup(group, row);
13269
+ if (!row?.requestId) continue;
13101
13270
  const cached = summaryCache.get(
13102
13271
  row.requestId,
13103
13272
  row.lastFeedBackDateTime,
13104
- maxCharsFor(name),
13273
+ explicitMaxCharsFor(args, name),
13105
13274
  promptTagOf(requestPromptFor(name)),
13106
13275
  materialTagOfRow(row.requestId, row.lastFeedBackDateTime)
13107
13276
  );
@@ -13230,6 +13399,41 @@ async function runSummary(args, env) {
13230
13399
  };
13231
13400
  }
13232
13401
 
13402
+ // src/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.ts
13403
+ async function runSubGroup(args, env) {
13404
+ const groups = await readFinalGroups(args, env);
13405
+ const warnings = [];
13406
+ const wfGroups = groups.filter((group) => !group.topPriority).map((group) => ({
13407
+ id: group.id,
13408
+ title: group.title,
13409
+ count: group.count,
13410
+ requestDatas: rowsOfGroup(group)
13411
+ }));
13412
+ const plans = args.aiGroups === void 0 || args.aiGroups === null ? void 0 : readAiGroups(args.aiGroups);
13413
+ const rows = wfGroups.flatMap((group) => group.requestDatas);
13414
+ const detailIds = [...new Set(rows.map((row) => row.requestId).filter(Boolean))];
13415
+ const facts = /* @__PURE__ */ new Map();
13416
+ let metrics;
13417
+ if (args.withDetailContext !== false && detailIds.length > 0) {
13418
+ const result = await fetchDetailFacts(env, detailIds, args, stampsOfRows(rows));
13419
+ for (const [requestId, fact] of result.facts) facts.set(requestId, fact);
13420
+ metrics = metricsOfFacts(facts);
13421
+ warnings.push(...result.warnings);
13422
+ }
13423
+ const finalGroups = applySubGroups(wfGroups, { plans, facts, metrics, warnings });
13424
+ return {
13425
+ data: {
13426
+ smartSummaryTitle: readSmartSummaryTitle(
13427
+ args,
13428
+ `\u60A8\u5F53\u524D\u6709 ${totalTodoCount(groups)} \u6761\u5F85\u529E\uFF0C\u6E05\u5355\u5982\u4E0B\uFF1A`
13429
+ ),
13430
+ totalCount: totalTodoCount(groups),
13431
+ wfIdGroup: finalGroups
13432
+ },
13433
+ warnings
13434
+ };
13435
+ }
13436
+
13233
13437
  // src/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.ts
13234
13438
  var INTERNAL_MESSAGE_SUMMARY_HINT2 = "\u5185\u90E8\u7559\u8A00\uFF1A\u53EA\u6309\u539F\u6587\u76F4\u63A5\u6982\u62EC\u300C\u8C01\u8BF4\u4E86\u4EC0\u4E48\u300D\uFF0C\u4E0D\u8981\u8FC7\u5EA6\u89E3\u8BFB\u3001\u4E0D\u8981\u63A8\u6D4B\u52A8\u673A\u6216\u5F71\u54CD\uFF0C\u4E25\u683C\u6309\u672C\u6279 suggestedMaxChars \u63A7\u5236\u5B57\u6570";
13235
13439
  var GROUP_SUMMARY_TAIL = GROUP_SUMMARY_TAIL_TEXT;
@@ -13274,7 +13478,7 @@ function collectGroupSummaryBatches(groups, isCtxEmpty, maxCharsFor = () => DEFA
13274
13478
  if (group.topPriority) continue;
13275
13479
  const kind = detectBusinessKind(group.title);
13276
13480
  for (const sub of groupItemsOf(group)) {
13277
- if (isDeterministicGroupKind(kind) && (sub.summary ?? "").trim() !== "") continue;
13481
+ if ((sub.summary ?? "").trim() !== "") continue;
13278
13482
  const allRows = Array.isArray(sub.requestDatas) ? sub.requestDatas : [];
13279
13483
  const rows = isCtxEmpty ? allRows.filter((row) => !isCtxEmpty(row.requestId)) : allRows;
13280
13484
  const emptySkipped = allRows.length - rows.length;
@@ -13579,6 +13783,7 @@ var inputSchema = schemaOf({
13579
13783
  }
13580
13784
  },
13581
13785
  withDetailContext: { type: "boolean", description: "smartGroup \u662F\u5426\u540C\u8FDB\u7A0B\u751F\u6210\u5355\u6761\u6458\u8981\u4E0A\u4E0B\u6587\u3002" },
13786
+ withSubGroup: { type: "boolean", description: "summary \u56DE\u586B\u540E\u662F\u5426\u540C\u8FDB\u7A0B\u63A5\u7740\u505A ai \u4E8C\u6B21\u5206\u7EC4\uFF08stage=subGroup \u7B49\u4EF7\uFF09\u3002" },
13582
13787
  withGroupSummaryContext: { type: "boolean", description: "summary \u662F\u5426\u540C\u8FDB\u7A0B\u751F\u6210\u7EC4\u6458\u8981\u4E0A\u4E0B\u6587\u3002" },
13583
13788
  detailPrefetch: { type: "boolean", description: "\u5E9F\u5F03\u517C\u5BB9\u53C2\u6570\uFF0C\u5DF2\u5FFD\u7565\uFF1Bcollect \u53EA\u5728\u7ED9\u4E86 groupFocus \u4E14\u610F\u56FE\u9002\u7528\u4E8E\u672C\u7EC4\u65F6\u6309\u9700\u9884\u53D6\u5206\u7EC4\u5B57\u6BB5\uFF08\u8D70\u8BE6\u60C5\u7F13\u5B58\uFF09\u3002" },
13584
13789
  groupBy: { type: "string", enum: [...GROUP_BY_VALUES], default: "workflow" },
@@ -13601,6 +13806,7 @@ var inputSchema = schemaOf({
13601
13806
  tabid: { type: "string" },
13602
13807
  tabName: { type: "string" },
13603
13808
  subCategory: { type: "string" },
13809
+ isremarks: { type: "string", description: "\u5907\u6CE8\u7B5B\u9009\uFF08getTodoListData params.isremarks\uFF09\uFF0C\u591A\u4E2A\u6570\u5B57\u7528\u82F1\u6587\u9017\u53F7\u62FC\u63A5\uFF0C\u4EC5\u4F5C\u7528\u4E8E\u672C\u6C47\u603B\u53D6\u6570" },
13604
13810
  workflow: { type: "array", items: { type: "string" } },
13605
13811
  creator: { type: "string" },
13606
13812
  requestName: { type: "string" },
@@ -13658,6 +13864,14 @@ var workflowTodoSmartConvertOperations = [{
13658
13864
  const stage = args.stage === void 0 || args.stage === null || args.stage === "" ? inferStage(args) : readStage(args.stage);
13659
13865
  const hasItems = Array.isArray(args.items);
13660
13866
  const resumed = stage === "collect" && hasItems;
13867
+ const withPriorityView = (data, extraWarnings) => {
13868
+ if ((args.groupBy ?? "workflow") !== "workflow") return { data, warnings: extraWarnings };
13869
+ const { groups, warning } = assemblePriorityGroup(data.wfIdGroup ?? []);
13870
+ return {
13871
+ data: { ...data, wfIdGroup: groups },
13872
+ warnings: warning ? [...extraWarnings, warning] : extraWarnings
13873
+ };
13874
+ };
13661
13875
  if ((stage === "group" || stage === "smartGroup" || stage === "aggregate") && !hasItems) {
13662
13876
  throw workflowValidationError(
13663
13877
  "items_required",
@@ -13711,39 +13925,62 @@ var workflowTodoSmartConvertOperations = [{
13711
13925
  );
13712
13926
  }
13713
13927
  const result = await runSummary(args, env);
13928
+ let baseData = result.data;
13929
+ let baseWarnings = result.warnings;
13930
+ let subGrouped = false;
13931
+ if (args.withSubGroup === true) {
13932
+ const sub = await runSubGroup({ ...args, wfIdGroup: baseData.wfIdGroup }, env);
13933
+ baseData = { ...baseData, wfIdGroup: sub.data.wfIdGroup };
13934
+ baseWarnings = [...baseWarnings, ...sub.warnings];
13935
+ subGrouped = true;
13936
+ }
13937
+ const final = withPriorityView(baseData, baseWarnings);
13714
13938
  if (args.withGroupSummaryContext === true) {
13715
13939
  const context = await runGroupSummaryContext({
13716
- wfIdGroup: result.data.wfIdGroup,
13717
- smartSummaryTitle: result.data.smartSummaryTitle,
13718
- totalCount: result.data.totalCount
13940
+ wfIdGroup: final.data.wfIdGroup,
13941
+ smartSummaryTitle: final.data.smartSummaryTitle,
13942
+ totalCount: final.data.totalCount
13719
13943
  }, env);
13720
13944
  if (Array.isArray(context.data.groupSummaryBatches) && context.data.groupSummaryBatches.length === 0) {
13721
- return finish(env, args, startedAt, stage, result.data, {
13945
+ return finish(env, args, startedAt, stage, final.data, {
13722
13946
  branch: "todo-smart-convert",
13723
13947
  stage,
13724
13948
  aiSummarized: true,
13949
+ subGrouped,
13725
13950
  withGroupSummaryContext: true,
13726
13951
  ...result.meta
13727
- }, result.warnings);
13952
+ }, final.warnings);
13728
13953
  }
13729
13954
  return finish(env, args, startedAt, stage, {
13730
- ...result.data,
13955
+ ...final.data,
13731
13956
  groupSummaryBatches: context.data.groupSummaryBatches,
13732
13957
  groupSummaryStats: context.data.groupSummaryStats
13733
13958
  }, {
13734
13959
  branch: "todo-smart-convert",
13735
13960
  stage,
13736
13961
  aiSummarized: true,
13962
+ subGrouped,
13737
13963
  withGroupSummaryContext: true,
13738
13964
  ...result.meta
13739
- }, [...result.warnings, ...context.warnings]);
13965
+ }, [...final.warnings, ...context.warnings]);
13740
13966
  }
13741
- return finish(env, args, startedAt, stage, result.data, {
13967
+ return finish(env, args, startedAt, stage, final.data, {
13742
13968
  branch: "todo-smart-convert",
13743
13969
  stage,
13744
13970
  aiSummarized: true,
13971
+ subGrouped,
13745
13972
  ...result.meta
13746
- }, result.warnings);
13973
+ }, final.warnings);
13974
+ }
13975
+ if (stage === "subGroup") {
13976
+ const result = await runSubGroup(args, env);
13977
+ const final = withPriorityView(result.data, result.warnings);
13978
+ return finish(env, args, startedAt, stage, final.data, {
13979
+ branch: "todo-smart-convert",
13980
+ stage,
13981
+ aiGrouped: Array.isArray(args.aiGroups),
13982
+ subGrouped: true
13983
+ }, final.warnings);
13747
13984
  }
13748
13985
  if (stage === "groupSummaryContext") {
13749
13986
  const result = await runGroupSummaryContext(args, env);
@@ -13762,12 +13999,13 @@ var workflowTodoSmartConvertOperations = [{
13762
13999
  );
13763
14000
  }
13764
14001
  const result = await runGroupSummary(args, env);
13765
- return finish(env, args, startedAt, stage, result.data, {
14002
+ const final = withPriorityView(result.data, result.warnings);
14003
+ return finish(env, args, startedAt, stage, final.data, {
13766
14004
  branch: "todo-smart-convert",
13767
14005
  stage,
13768
14006
  aiSummarized: true,
13769
14007
  ...result.meta
13770
- }, result.warnings);
14008
+ }, final.warnings);
13771
14009
  }
13772
14010
  if (stage === "group" || resumed) {
13773
14011
  return finish(env, args, startedAt, "group", runGroup(args), {