weaver-work-cli 0.1.38 → 0.1.40

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 (166) hide show
  1. package/README.md +7 -3
  2. package/dist/chunks/{archive-PDV724YK.js → archive-JHTONRST.js} +556 -66
  3. package/dist/chunks/{archive-oa-4XE4MNXQ.js → archive-oa-FCHLCPHC.js} +2 -2
  4. package/dist/chunks/{asset-PDL2QE2N.js → asset-RLIHC7DB.js} +2 -2
  5. package/dist/chunks/asset-idle-KVOFTLCP.js +670 -0
  6. package/dist/chunks/{attachment-content-MDDGOE5E.js → attachment-content-RZYDB3MB.js} +3 -3
  7. package/dist/chunks/{blog-UYR3EUXW.js → blog-42OZTJNP.js} +2 -2
  8. package/dist/chunks/{caizhilian-LG2X5NMF.js → caizhilian-KRK547K5.js} +2 -2
  9. package/dist/chunks/{calendar-FG4BAZHE.js → calendar-RTWAMKHD.js} +2 -2
  10. package/dist/chunks/{chunk-J7USS3ED.js → chunk-4CTESSKI.js} +4 -4
  11. package/dist/chunks/{chunk-OJQUJZQF.js → chunk-4TEDNCON.js} +45 -5
  12. package/dist/chunks/chunk-57IECMWX.js +487 -0
  13. package/dist/chunks/{chunk-ELYDWBZJ.js → chunk-7BRU4EFH.js} +13 -7
  14. package/dist/chunks/{chunk-6LTFIFLM.js → chunk-7E6MUOEK.js} +2 -2
  15. package/dist/chunks/{chunk-KKRL3REV.js → chunk-7U577Q7U.js} +2 -2
  16. package/dist/chunks/{chunk-UJJD4QWF.js → chunk-CAQNBBQA.js} +2 -2
  17. package/dist/chunks/{chunk-CORFRD7Q.js → chunk-CXRQWOZ5.js} +2 -2
  18. package/dist/chunks/{chunk-GGJFMNJM.js → chunk-FLS4DPGP.js} +110 -16
  19. package/dist/chunks/{chunk-JSMFPO43.js → chunk-I566ZYNF.js} +1 -1
  20. package/dist/chunks/{chunk-6FTTSA45.js → chunk-IZSSVYAG.js} +2 -2
  21. package/dist/chunks/{chunk-XJY7G4DD.js → chunk-JWRZM2H2.js} +3 -3
  22. package/dist/chunks/{chunk-NI6GIPIM.js → chunk-LFMSDBZN.js} +529 -395
  23. package/dist/chunks/{chunk-VRYHGG6O.js → chunk-LN447PY2.js} +92 -51
  24. package/dist/chunks/{chunk-NR6RKXPA.js → chunk-NETCCARD.js} +4 -2
  25. package/dist/chunks/{chunk-Z32KWY6G.js → chunk-NJKREDA3.js} +1 -1
  26. package/dist/chunks/{chunk-FUWVHMVV.js → chunk-SPRHHSVC.js} +2 -2
  27. package/dist/chunks/{chunk-IZUDA353.js → chunk-T6EGVBKU.js} +1 -1
  28. package/dist/chunks/{chunk-DMV2TOMH.js → chunk-VNBU55SL.js} +428 -145
  29. package/dist/chunks/{chunk-UZZBA6PV.js → chunk-WFFNM65B.js} +47 -6
  30. package/dist/chunks/{chunk-EG6ZU444.js → chunk-ZUX3P6BQ.js} +10 -5
  31. package/dist/chunks/{conflict-BQZEQ4SP.js → conflict-VR55AOOO.js} +2 -2
  32. package/dist/chunks/{contract-XIRAFTEV.js → contract-HI4FNPYE.js} +2 -2
  33. package/dist/chunks/{cowork-BLG62BL2.js → cowork-HJLI353D.js} +12 -5
  34. package/dist/chunks/{ebuilder-form-NUKG5QW4.js → ebuilder-form-HTGI63UU.js} +3 -3
  35. package/dist/chunks/{ehr-2STW5ILH.js → ehr-GYXIYH3A.js} +2 -2
  36. package/dist/chunks/env-DW3G4HUO.js +19 -0
  37. package/dist/chunks/{esb-UUDQUNKY.js → esb-I5INCEFE.js} +4 -4
  38. package/dist/chunks/factory-TKXGXS6L.js +30 -0
  39. package/dist/chunks/{fna-6RCY4NU5.js → fna-K2MHTQ24.js} +2 -2
  40. package/dist/chunks/group-chat-VYBNMJLG.js +18 -0
  41. package/dist/chunks/{host-FWDOSRH5.js → host-256GVCAH.js} +3 -3
  42. package/dist/chunks/{host-EJZFROU3.js → host-D5SERMAJ.js} +3 -3
  43. package/dist/chunks/{host-RHM3NPXV.js → host-JM4YVHFM.js} +3 -3
  44. package/dist/chunks/{host-7RXEDMAH.js → host-L3VLITMT.js} +3 -3
  45. package/dist/chunks/{host-UFF33TWJ.js → host-ZUQTJYYK.js} +3 -3
  46. package/dist/chunks/{hrm-PKJ6ELSH.js → hrm-VLRBKTZB.js} +3 -3
  47. package/dist/chunks/{im-YJAXS7CO.js → im-QK3VTLXK.js} +8 -8
  48. package/dist/chunks/{invoice-HWVSXGX6.js → invoice-T5JTA32H.js} +3 -3
  49. package/dist/chunks/{jiuchuanhui-L7VKILZB.js → jiuchuanhui-P2FNEQVZ.js} +2 -2
  50. package/dist/chunks/{lazy-dispatch-NMYEIHRH.js → lazy-dispatch-XRRI46M6.js} +5 -5
  51. package/dist/chunks/{mail-B42RRU7G.js → mail-3Y7MJ6PS.js} +9 -4
  52. package/dist/chunks/{meeting-CFYVBJSS.js → meeting-M7LTXGJE.js} +11 -10
  53. package/dist/chunks/{okr-GCLF6V7W.js → okr-OBC6S67L.js} +2 -2
  54. package/dist/chunks/{plan-ZVL7GBRI.js → plan-5H6I53SK.js} +2 -2
  55. package/dist/chunks/{project-4YWAAE2K.js → project-L75QZV4S.js} +2 -2
  56. package/dist/chunks/{registry-EP4VTHZS.js → registry-KMHCPAAD.js} +9 -8
  57. package/dist/chunks/{registry-OZSMDVPP.js → registry-QGHFNUWS.js} +2 -2
  58. package/dist/chunks/{registry-FRJ6H7BT.js → registry-RXPN6BBT.js} +4 -4
  59. package/dist/chunks/{registry-SG2PGVCF.js → registry-UGRBCBHO.js} +3 -3
  60. package/dist/chunks/{room-recommend-R3JVUUAC.js → room-recommend-A3UDC3CA.js} +4 -4
  61. package/dist/chunks/{schedule-NIJBTYDO.js → schedule-5GCACCK7.js} +4 -4
  62. package/dist/chunks/{workflow-BB24DFBY.js → workflow-M5ZJ7DWF.js} +11 -8
  63. package/dist/core/output.js +16 -6
  64. package/dist/index.js +33 -28
  65. package/dist/internal/e10/auth/commands.js +109 -56
  66. package/dist/internal/e10/auth/messages.js +1 -0
  67. package/dist/internal/e10/auth/session.js +11 -1
  68. package/dist/internal/e10/auth/xiaoe.js +29 -4
  69. package/dist/internal/e10/auth-recovery.js +13 -6
  70. package/dist/internal/e10/client.js +13 -0
  71. package/dist/internal/e10/context.js +24 -3
  72. package/dist/internal/e10/request-runtime.js +12 -1
  73. package/dist/shortcuts/archive/host.js +2 -0
  74. package/dist/shortcuts/archive/manifest.js +1 -1
  75. package/dist/shortcuts/archive/operations/borrow-list.js +13 -1
  76. package/dist/shortcuts/archive/operations/flow-url.js +1 -1
  77. package/dist/shortcuts/archive/operations/prelib.js +472 -0
  78. package/dist/shortcuts/archive/operations/registry.js +2 -0
  79. package/dist/shortcuts/archive/operations/upload.js +1 -1
  80. package/dist/shortcuts/asset-idle/errors.js +44 -0
  81. package/dist/shortcuts/asset-idle/host.js +161 -0
  82. package/dist/shortcuts/asset-idle/index.js +114 -0
  83. package/dist/shortcuts/asset-idle/manifest.js +159 -0
  84. package/dist/shortcuts/asset-idle/operations/idle.js +47 -0
  85. package/dist/shortcuts/asset-idle/operations/registry.js +33 -0
  86. package/dist/shortcuts/asset-idle/operations/shared.js +142 -0
  87. package/dist/shortcuts/asset-idle/operations/types.js +9 -0
  88. package/dist/shortcuts/asset-idle/operations.js +15 -0
  89. package/dist/shortcuts/cowork/operations/item-write.js +10 -2
  90. package/dist/shortcuts/index.js +5 -0
  91. package/dist/shortcuts/mail/operations/mail-send.js +8 -2
  92. package/dist/shortcuts/meeting/operations/eb/catalog.js +5 -1
  93. package/dist/shortcuts/meeting/operations/eb/create-flow.js +381 -104
  94. package/dist/shortcuts/meeting/operations/eb/crm-search.js +87 -5
  95. package/dist/shortcuts/meeting/operations/eb/flow-memory.js +49 -0
  96. package/dist/shortcuts/meeting/operations/eb/group-chat.js +583 -0
  97. package/dist/shortcuts/meeting/operations/eb/index.js +2 -0
  98. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +19 -3
  99. package/dist/shortcuts/meeting/operations/eb/room-summary.js +2 -0
  100. package/dist/shortcuts/meeting/operations/eb/usage-cache.js +99 -0
  101. package/dist/shortcuts/meeting/operations/from-group-chat.js +35 -12
  102. package/dist/shortcuts/workflow/host.js +3 -0
  103. package/dist/shortcuts/workflow/index.js +1 -1
  104. package/dist/shortcuts/workflow/operations/form.js +65 -171
  105. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupRules.js +129 -27
  106. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupStore.js +6 -0
  107. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +60 -117
  108. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +44 -7
  109. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +37 -29
  110. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +48 -8
  111. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +1 -0
  112. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +22 -18
  113. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +17 -9
  114. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +34 -10
  115. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +5 -2
  116. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +9 -2
  117. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +122 -20
  118. package/docs/_catalog.md +3 -0
  119. package/docs/asset-idle.md +45 -0
  120. package/docs/e10-auth.md +16 -1
  121. package/docs/todo-smart-convert/subgroup-rules.md +1 -1
  122. package/package.json +1 -1
  123. package/scripts/mcp-meeting.mjs +234 -0
  124. package/scripts/package-skill.mjs +2 -0
  125. package/skill-template/business-info.json +14 -1
  126. package/skill-template/domains/asset-idle.md +13 -0
  127. package/skill-template/domains/wenshuding.md +3 -0
  128. package/skills/weaver-e10-archive-oa/SKILL.md +1 -0
  129. package/skills/weaver-e10-archive-oa/references/my-borrow.md +49 -0
  130. package/skills/weaver-e10-asset-idle/SKILL.md +73 -0
  131. package/skills/weaver-e10-asset-idle/references/idle-list.md +62 -0
  132. package/skills/weaver-e10-asset-idle/references/idle-stats-and-charts.md +65 -0
  133. package/skills/weaver-e10-asset-idle/references/source-manifest.json +193 -0
  134. package/skills/weaver-e10-asset-idle/references/widget-style.md +205 -0
  135. package/skills/weaver-e10-caizhilian/SKILL.md +29 -11
  136. package/skills/weaver-e10-caizhilian/references/auth-and-install.md +12 -0
  137. package/skills/weaver-e10-caizhilian/references/files.md +1 -1
  138. package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +1 -1
  139. package/skills/weaver-e10-caizhilian/references/source-manifest.json +45 -45
  140. package/skills/weaver-e10-cowork/SKILL.md +2 -0
  141. package/skills/weaver-e10-cowork/references/cowork-write.md +1 -1
  142. package/skills/weaver-e10-jucailin/SKILL.md +2 -0
  143. package/skills/weaver-e10-jucailin/references/recruit-read.md +2 -0
  144. package/skills/weaver-e10-jucailin/references/recruit-write.md +1 -1
  145. package/skills/weaver-e10-mail/SKILL.md +3 -0
  146. package/skills/weaver-e10-mail/references/mail-send.md +2 -0
  147. package/skills/weaver-e10-meeting/SKILL.md +88 -25
  148. package/skills/weaver-e10-meeting/references/meeting-minute-file.md +25 -11
  149. package/skills/weaver-e10-meeting.zip +0 -0
  150. package/skills/weaver-e10-shared/SKILL.md +5 -5
  151. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +3 -3
  152. package/skills/weaver-e10-wenshuding/SKILL.md +29 -6
  153. package/skills/weaver-e10-wenshuding/references/archive-borrow-list.md +14 -0
  154. package/skills/weaver-e10-wenshuding/references/archive-download.md +2 -0
  155. package/skills/weaver-e10-wenshuding/references/archive-flow.md +1 -1
  156. package/skills/weaver-e10-wenshuding/references/archive-prelib-arrange.md +76 -0
  157. package/skills/weaver-e10-wenshuding/references/archive-prelib-list.md +107 -0
  158. package/skills/weaver-e10-wenshuding/references/archive-prelib-open.md +59 -0
  159. package/skills/weaver-e10-wenshuding/references/archive-upload.md +4 -1
  160. package/skills/weaver-e10-wenshuding/references/source-manifest.json +108 -65
  161. package/skills/weaver-e10-workflow/SKILL.md +9 -2
  162. package/skills/weaver-e10-workflow/aigroup/default.json +166 -19
  163. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +72 -34
  164. package/skills/weaver-e10-workflow/tools/todo-serve.cjs +113 -25
  165. package/skills/weaver-e10-workflow/tools/todo-summary.cjs +350 -50
  166. package/dist/chunks/{chunk-2LV74IWP.js → chunk-E7OK5WD5.js} +5 -5
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-FMPJJYYI.js";
16
16
  import {
17
17
  stringifyForStdout
18
- } from "./chunk-EG6ZU444.js";
18
+ } from "./chunk-ZUX3P6BQ.js";
19
19
  import {
20
20
  stateRoot
21
21
  } from "./chunk-AJ62BGAW.js";
@@ -24,7 +24,7 @@ import {
24
24
  createFetchTimingSink,
25
25
  hasXiaoEEnv,
26
26
  runWithFetchTiming
27
- } from "./chunk-OJQUJZQF.js";
27
+ } from "./chunk-4TEDNCON.js";
28
28
 
29
29
  // src/shortcuts/workflow/operations/form.ts
30
30
  import { randomUUID } from "node:crypto";
@@ -5079,17 +5079,47 @@ async function runWorkflowSearch(args, env) {
5079
5079
  var TEXTAREA_COMPONENTS = /* @__PURE__ */ new Set(["textarea", "richtext", "editor", "html", "htmltext"]);
5080
5080
  var SELECT_COMPONENTS = /* @__PURE__ */ new Set(["select", "selectmultiple", "radiobox", "checkbox", "radio", "multiselect"]);
5081
5081
  var BROWSER_COMPONENTS = /* @__PURE__ */ new Set([
5082
+ // 人员 / 组织类
5082
5083
  "employee",
5083
5084
  "department",
5084
5085
  "subcompany",
5085
5086
  "jobtitle",
5086
5087
  "job",
5087
- "relatebrowser",
5088
- "browser",
5089
- "workflow",
5088
+ "employeeorganization",
5089
+ "employeeshare",
5090
+ "employeeauthshare",
5091
+ "odocreceivecomponent",
5092
+ // 关联类型(设计器「表单组件 / 关联类型」面板)
5090
5093
  "ebuilder",
5094
+ "mainline",
5095
+ "project",
5096
+ "task",
5097
+ "document",
5098
+ "workflow",
5099
+ "formcomponent",
5091
5100
  "customer",
5092
- "project"
5101
+ "customercomponent",
5102
+ "cluecomponent",
5103
+ "ordercomponent",
5104
+ "contactcomponent",
5105
+ "productioncomponent",
5106
+ "contractcomponent",
5107
+ "activitycomponent",
5108
+ "competitorcomponent",
5109
+ "kpiflowcomponent",
5110
+ "workreportcomponent",
5111
+ "attendcomponent",
5112
+ "agendacomponent",
5113
+ "chancecomponent",
5114
+ "relatebrowser",
5115
+ "relateodoc",
5116
+ "relatetag",
5117
+ "relateintegrate",
5118
+ "modulecomponent",
5119
+ "paas",
5120
+ "quotecomponent",
5121
+ "drivingrecord",
5122
+ "browser"
5093
5123
  ]);
5094
5124
  var NON_INPUT_COMPONENTS = /* @__PURE__ */ new Set([
5095
5125
  "paragraph",
@@ -5110,6 +5140,10 @@ var READONLY_COMPONENTS = /* @__PURE__ */ new Set([
5110
5140
  "subtablecontrol",
5111
5141
  "mobileinteraction"
5112
5142
  ]);
5143
+ function isBrowserLikeComponentKey(componentKey) {
5144
+ const normalized = String(componentKey ?? "").toLowerCase();
5145
+ return normalized === "einvoicecomponent" || normalized === "filecomponent";
5146
+ }
5113
5147
  var SYSTEM_FIELD_KEYS = {
5114
5148
  REQUEST_NAMEL: "\u6D41\u7A0B\u6807\u9898",
5115
5149
  REQUEST_LEVEL: "\u7D27\u6025\u7A0B\u5EA6",
@@ -5448,8 +5482,7 @@ function extractFields(layoutData, requiredMap, disableEditMap, displayMap) {
5448
5482
  const name = String(option.name ?? option.content ?? "").trim();
5449
5483
  if (optionId && name) options.push({ id: optionId, name });
5450
5484
  }
5451
- const componentBase = normalized.replace(/component$/, "");
5452
- const isBrowser = Object.keys(browserType).length > 0 || BROWSER_COMPONENTS.has(normalized) || BROWSER_COMPONENTS.has(componentBase);
5485
+ const isBrowser = Object.keys(browserType).length > 0 || BROWSER_COMPONENTS.has(normalized);
5453
5486
  const isSelect = SELECT_COMPONENTS.has(normalized) || options.length > 0;
5454
5487
  result.push({
5455
5488
  id: fieldId,
@@ -6379,24 +6412,6 @@ async function buildCreateFormData(workflowId, env, options = {}) {
6379
6412
  if (compsFieldIds.size && !String(f.subFormId ?? "").trim() && !compsFieldIds.has(fid)) continue;
6380
6413
  visibleFields.push(f);
6381
6414
  }
6382
- const hiddenBySubform = /* @__PURE__ */ new Map();
6383
- for (const f of fields) {
6384
- const fid = String(f.id ?? "");
6385
- const sid = String(f.subFormId ?? "").trim();
6386
- if (!sid || !hiddenCellIds.has(fid)) continue;
6387
- hiddenBySubform.set(sid, (hiddenBySubform.get(sid) || 0) + 1);
6388
- }
6389
- const survivingSubforms = new Set(
6390
- visibleFields.map((f) => String(f.subFormId ?? "").trim()).filter(Boolean)
6391
- );
6392
- const invisibleSubformWarnings = [];
6393
- for (const [sid, count] of hiddenBySubform) {
6394
- if (survivingSubforms.has(sid)) continue;
6395
- invisibleSubformWarnings.push(
6396
- `\u660E\u7EC6\u8868 ${sid} \u7684 ${count} \u4E2A\u5B57\u6BB5\u5168\u90E8\u88AB\u5224\u4E3A\u300C\u4E0D\u53EF\u89C1\u300D\uFF08\u8BE5\u660E\u7EC6\u8868\u6240\u5728\u7684\u884C/\u5217\u5728\u8868\u5355\u5E03\u5C40\u91CC\u662F\u9690\u85CF\u7684\uFF09\uFF0C\u56E0\u6B64\u6CA1\u6709\u51FA\u73B0\u5728\u5B57\u6BB5\u6E05\u5355\u91CC\u3002\u8981\u4E48\u5728\u8868\u5355\u8BBE\u8BA1\u5668\u91CC\u628A\u660E\u7EC6\u8868\u632A\u5230\u53EF\u89C1\u884C\uFF0C\u8981\u4E48\u53D6\u6D88\u9690\u85CF\u5B83\u6240\u5728\u7684\u884C/\u5217\uFF0C\u7136\u540E\u91CD\u65B0\u8F7D\u5165\u8868\u5355\u3002`
6397
- );
6398
- }
6399
- let layoutWarning = invisibleSubformWarnings.length ? invisibleSubformWarnings.join("\uFF1B") : null;
6400
6415
  const defaults = normalizeDefaults(layoutData.defaultDetails);
6401
6416
  const systemFieldValues = _normalizeSystemFieldValues(layoutData.businessOperatorObj);
6402
6417
  let linkageActions = Array.isArray(layoutData.linkageActions) ? layoutData.linkageActions : [];
@@ -6438,33 +6453,6 @@ async function buildCreateFormData(workflowId, env, options = {}) {
6438
6453
  }
6439
6454
  }
6440
6455
  const folderOptionValues = _mainValueMap(defaults);
6441
- const conditionalHiddenSubforms = /* @__PURE__ */ new Set();
6442
- const conditionalMainFields = /* @__PURE__ */ new Set();
6443
- const conditionalHints = collectDetailShowLinkages(layoutData.viewLinkages, fields);
6444
- const fieldShowIds = collectFieldShowLinkageIds(layoutData.viewLinkages);
6445
- for (const fid of Array.from(mainHidden)) {
6446
- if (!fieldShowIds.has(fid)) continue;
6447
- if (hiddenCellIds.has(fid)) continue;
6448
- const target = visibleFields.find((f) => String(f.id ?? "") === fid);
6449
- if (!target) continue;
6450
- conditionalMainFields.add(fid);
6451
- mainHidden.delete(fid);
6452
- invisibleSubformWarnings.push(
6453
- `\u5B57\u6BB5\u300C${target.name}\u300D(${fid}) \u56E0\u663E\u793A\u8054\u52A8\u9690\u85CF\uFF08\u8BE5\u5B57\u6BB5\u672C\u8EAB\u662F\u89E6\u53D1\u5B57\u6BB5\uFF09\uFF0C\u5DF2\u7167\u5E38\u4E0B\u53D1\u5E76\u6807 conditional: true`
6454
- );
6455
- }
6456
- for (const sid of Array.from(hiddenSubforms)) {
6457
- const hint = conditionalHints.get(sid);
6458
- if (!hint) continue;
6459
- const usable = visibleFields.some((f) => String(f.subFormId ?? "") === sid && !hiddenCellIds.has(String(f.id ?? "")));
6460
- if (!usable) continue;
6461
- conditionalHiddenSubforms.add(sid);
6462
- hiddenSubforms.delete(sid);
6463
- invisibleSubformWarnings.push(
6464
- `\u660E\u7EC6\u8868 ${sid}${hint.tableName ? `\uFF08${hint.tableName}\uFF09` : ""} \u56E0\u663E\u793A\u8054\u52A8\u9690\u85CF\uFF0C\u89E6\u53D1\u5B57\u6BB5\uFF1A${hint.triggerNames.join("\u3001") || hint.triggerIds.join("\u3001")}\u3002\u8BE5\u8868\u5B57\u6BB5\u5DF2\u7167\u5E38\u4E0B\u53D1\uFF08\u6807 conditional: true\uFF09\uFF0C\u628A\u89E6\u53D1\u5B57\u6BB5\u586B\u4E0A\u540E\u8868\u5355\u91CC\u5C31\u4F1A\u663E\u793A\uFF1B\u4E0D\u8981\u56DE\u300C\u8868\u5355\u91CC\u6CA1\u6709\u8FD9\u5F20\u660E\u7EC6\u8868\u300D\u3002`
6465
- );
6466
- }
6467
- layoutWarning = invisibleSubformWarnings.length ? invisibleSubformWarnings.join("\uFF1B") : null;
6468
6456
  for (const field of visibleFields) {
6469
6457
  const fieldId = String(field.id ?? "");
6470
6458
  const subFormId = String(field.subFormId ?? "");
@@ -6525,8 +6513,6 @@ async function buildCreateFormData(workflowId, env, options = {}) {
6525
6513
  } else if (slimSubFormId) {
6526
6514
  item.subFormId = slimSubFormId;
6527
6515
  }
6528
- if (slimSubFormId && conditionalHiddenSubforms.has(slimSubFormId)) item.conditional = true;
6529
- if (!slimSubFormId && conditionalMainFields.has(String(field.id ?? ""))) item.conditional = true;
6530
6516
  item.componentKey = field.componentKey;
6531
6517
  const initialValue = initialValueByFieldId.get(String(field.id ?? ""));
6532
6518
  if (initialValue !== void 0) item.initialValue = initialValue;
@@ -6537,6 +6523,7 @@ async function buildCreateFormData(workflowId, env, options = {}) {
6537
6523
  for (const key of ["isBrowser", "isSelect", "isMultiple", "browserType", "browserModule"]) {
6538
6524
  if (field[key]) item[key] = field[key];
6539
6525
  }
6526
+ if (!item.isBrowser && isBrowserLikeComponentKey(field.componentKey)) item.isBrowser = true;
6540
6527
  if (String(field.componentKey ?? "").toLowerCase() === "employeescope") item.isEmployeeScope = true;
6541
6528
  if (String(field.componentKey ?? "").toLowerCase() === "einvoicecomponent") item.isEinvoice = true;
6542
6529
  if (String(field.componentKey ?? "").toLowerCase() === "filecomponent") {
@@ -6660,8 +6647,6 @@ async function buildCreateFormData(workflowId, env, options = {}) {
6660
6647
  },
6661
6648
  systemFieldWarning: minorWarning,
6662
6649
  requiredInfoWarning: requiredInfoWarningText(context),
6663
- // 明细表整表不可见时的告警(见 layoutWarning 注释):有值时**不要**回"表单里没有这张明细表"。
6664
- layoutWarning,
6665
6650
  // 原 Python 把完整 context 落盘;此处通过 continuation 承载,返回结构保持文档契约。
6666
6651
  continuation: token
6667
6652
  }
@@ -7782,50 +7767,6 @@ function mergeLinkageDetails(merged, linkageDetails) {
7782
7767
  function emptyLinkageVisibility() {
7783
7768
  return [/* @__PURE__ */ new Set(), {}, {}, {}];
7784
7769
  }
7785
- function collectFieldShowLinkageIds(linkages) {
7786
- const out = /* @__PURE__ */ new Set();
7787
- if (!Array.isArray(linkages)) return out;
7788
- for (const rule of linkages) {
7789
- const details = Array.isArray(rule?.linkageDetails) ? rule.linkageDetails : [];
7790
- for (const detail of details) {
7791
- if (!detail || typeof detail !== "object") continue;
7792
- if (String(detail.linkageObj ?? "") !== "field") continue;
7793
- if (String(detail.linkageProp ?? "") !== "show") continue;
7794
- const fid = String(detail.linkageValue ?? "").trim();
7795
- if (fid) out.add(fid);
7796
- }
7797
- }
7798
- return out;
7799
- }
7800
- function collectDetailShowLinkages(linkages, fields) {
7801
- const out = /* @__PURE__ */ new Map();
7802
- if (!Array.isArray(linkages)) return out;
7803
- const list = Array.isArray(fields) ? fields : [];
7804
- const nameOf = (id) => {
7805
- for (const f of list) {
7806
- if (String(f?.id ?? "") === id) return String(f?.name ?? id);
7807
- }
7808
- return id;
7809
- };
7810
- for (const rule of linkages) {
7811
- const details = Array.isArray(rule?.linkageDetails) ? rule.linkageDetails : [];
7812
- for (const detail of details) {
7813
- if (!detail || typeof detail !== "object") continue;
7814
- if (String(detail.linkageObj ?? "") !== "detail") continue;
7815
- if (String(detail.linkageProp ?? "") !== "show") continue;
7816
- const sid = String(detail.linkageValue ?? "").trim();
7817
- if (!sid) continue;
7818
- const conds = Array.isArray(rule?.condition?.conditionDetails) ? rule.condition.conditionDetails : [];
7819
- const triggerIds = conds.map((c) => String(c?.targetId ?? "").trim()).filter(Boolean);
7820
- out.set(sid, {
7821
- triggerIds,
7822
- triggerNames: triggerIds.map(nameOf),
7823
- tableName: nameOf(sid) === sid ? "" : nameOf(sid)
7824
- });
7825
- }
7826
- }
7827
- return out;
7828
- }
7829
7770
  function computeLinkageVisibility(linkages, entries, defaults, linkageDetails, systemFieldValues, fields) {
7830
7771
  const hiddenSubforms = /* @__PURE__ */ new Set();
7831
7772
  const rowHidden = {};
@@ -8322,7 +8263,8 @@ var XIAOE_FILL_FORM_SDK_OPTIONS = {
8322
8263
  };
8323
8264
  var XIAOE_INITIAL_VALUES_MULTI_SEPARATOR = ",";
8324
8265
  var XIAOE_INITIAL_VALUES_ROW_SEPARATOR = ";";
8325
- function xiaoEUrlParamScalar(value) {
8266
+ var XIAOE_BROWSER_ID_PREFIX = "##";
8267
+ function xiaoEUrlParamScalar(value, prefixBrowserId = false) {
8326
8268
  if (value === null || value === void 0) return "";
8327
8269
  if (typeof value === "object") {
8328
8270
  const obj = value;
@@ -8330,18 +8272,19 @@ function xiaoEUrlParamScalar(value) {
8330
8272
  const picked = obj[key];
8331
8273
  if (picked === null || picked === void 0) continue;
8332
8274
  const text = String(picked).trim();
8333
- if (text) return text;
8275
+ if (!text) continue;
8276
+ return prefixBrowserId ? `${XIAOE_BROWSER_ID_PREFIX}${text}` : text;
8334
8277
  }
8335
8278
  return "";
8336
8279
  }
8337
8280
  return String(value).trim();
8338
8281
  }
8339
- function xiaoEUrlParamValue(value) {
8282
+ function xiaoEUrlParamValue(value, prefixBrowserId = false) {
8340
8283
  if (value === null || value === void 0) return "";
8341
8284
  if (Array.isArray(value)) {
8342
- return value.map((item) => xiaoEUrlParamScalar(item)).filter(Boolean).join(XIAOE_INITIAL_VALUES_MULTI_SEPARATOR);
8285
+ return value.map((item) => xiaoEUrlParamScalar(item, prefixBrowserId)).filter(Boolean).join(XIAOE_INITIAL_VALUES_MULTI_SEPARATOR);
8343
8286
  }
8344
- return xiaoEUrlParamScalar(value);
8287
+ return xiaoEUrlParamScalar(value, prefixBrowserId);
8345
8288
  }
8346
8289
  function editablePreviewForXiaoE(preview, fields, visibility) {
8347
8290
  const fieldById = /* @__PURE__ */ new Map();
@@ -8366,14 +8309,19 @@ function editablePreviewForXiaoE(preview, fields, visibility) {
8366
8309
  }
8367
8310
  return kept;
8368
8311
  }
8369
- function xiaoECustomParams(preview) {
8312
+ function xiaoECustomParams(preview, fields) {
8370
8313
  const ordered = [];
8371
8314
  const mainValues = /* @__PURE__ */ new Map();
8372
8315
  const detailValues = /* @__PURE__ */ new Map();
8316
+ const browserFieldIds = /* @__PURE__ */ new Set();
8317
+ for (const field of toArray(fields)) {
8318
+ const id = String(field?.id ?? "").trim();
8319
+ if (id && (field?.isBrowser || isBrowserLikeComponentKey(field?.componentKey))) browserFieldIds.add(id);
8320
+ }
8373
8321
  for (const item of toArray(preview)) {
8374
8322
  const fieldId = String(item?.fieldId ?? "").trim();
8375
8323
  if (!fieldId) continue;
8376
- const text = xiaoEUrlParamValue(item?.value);
8324
+ const text = xiaoEUrlParamValue(item?.value, browserFieldIds.has(fieldId));
8377
8325
  if (!text) continue;
8378
8326
  const isDetail = item?.dataIndex !== void 0 && item?.dataIndex !== null;
8379
8327
  if (!isDetail) {
@@ -8528,8 +8476,7 @@ async function runCreateRequest(args, env, options = {}) {
8528
8476
  }
8529
8477
  const [details, valueAmbiguities, preview] = await resolveEntryValues(env, entries, context.layout.form_id);
8530
8478
  const merged = mergeDetails(context.defaults || [], details);
8531
- const forceServerSubmit = args.forceServerSubmit === true;
8532
- const isXiaoE = forceServerSubmit ? false : hasXiaoEEnv(env.ctx.env, env.ctx.getGlobalOptions?.());
8479
+ const isXiaoE = hasXiaoEEnv(env.ctx.env, env.ctx.getGlobalOptions?.());
8533
8480
  const linkageDetails = isXiaoE ? [] : await runFieldLinkage(env, linkageContextFromPayload(context), entries, null, merged, false, context.defaults || []);
8534
8481
  const merged2 = fillDetailDefaultsByRow(
8535
8482
  mergeLinkageDetails(merged, linkageDetails),
@@ -8658,7 +8605,7 @@ async function runCreateRequest(args, env, options = {}) {
8658
8605
  baseUrl: xiaoEBaseUrl,
8659
8606
  title: String(context.workflow?.name ?? ""),
8660
8607
  workflowId: String(context.workflow?.id ?? context.runtime?.workflow_id ?? ""),
8661
- customParams: xiaoECustomParams(fillPreview)
8608
+ customParams: xiaoECustomParams(fillPreview, fields)
8662
8609
  })
8663
8610
  });
8664
8611
  }
@@ -10152,6 +10099,7 @@ var ALLOWED_INPUT_KEYS = [
10152
10099
  "tabid",
10153
10100
  "tabName",
10154
10101
  "subCategory",
10102
+ "isremarks",
10155
10103
  "workflow",
10156
10104
  "creator",
10157
10105
  "requestName",
@@ -10392,90 +10340,30 @@ import { existsSync as existsSync3, readFileSync } from "node:fs";
10392
10340
  import { join as join2 } from "node:path";
10393
10341
 
10394
10342
  // src/shortcuts/workflow/operations/todoSmartConvert/summaryCache.ts
10395
- import { existsSync as existsSync2, readdirSync, statSync } from "node:fs";
10343
+ import { existsSync as existsSync2 } from "node:fs";
10396
10344
  import { chmod as chmod2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
10397
- import { homedir as homedir2 } from "node:os";
10398
10345
  import { join, resolve as resolve2 } from "node:path";
10399
- var SKILL_DIR_NAME = "weaver-e10-workflow";
10400
10346
  var CACHE_DIR_NAME = "cache";
10401
- var AGENT_HOME_DIRS = [".workbuddy", ".claude", ".codebuddy", ".codex", ".cursor", ".gemini"];
10402
10347
  var SUMMARY_CACHE_FILE_NAME = "todo-summary-cache.json";
10403
10348
  var SUMMARY_CACHE_VERSION = 2;
10404
10349
  function uniqueDirs(dirs) {
10405
- return [...new Set(dirs.filter(Boolean))];
10350
+ return [...new Set(dirs.filter((dir) => Boolean(dir)))];
10406
10351
  }
10407
- function stateCacheDir(ctx) {
10408
- return resolve2(stateRoot(ctx), CACHE_DIR_NAME);
10409
- }
10410
- function discoverThisSkillDirs(home) {
10411
- const marker = join("references", "todo-smart-convert.md");
10412
- const found = [];
10413
- for (const agent of AGENT_HOME_DIRS) {
10414
- const root = join(home, agent, "skills");
10415
- const entries = (() => {
10416
- try {
10417
- return readdirSync(root, { withFileTypes: true });
10418
- } catch {
10419
- return [];
10420
- }
10421
- })();
10422
- for (const entry of entries) {
10423
- if (!entry.isDirectory()) continue;
10424
- const dir = join(root, entry.name);
10425
- if (existsSync2(join(dir, marker))) found.push(dir);
10426
- }
10427
- }
10428
- return found;
10429
- }
10430
- function mtimeOf(file) {
10431
- try {
10432
- return statSync(file).mtimeMs;
10433
- } catch {
10434
- return 0;
10435
- }
10436
- }
10437
- function rankSkillDirs(dirs) {
10438
- const scored = dirs.map((dir, index) => ({
10439
- dir,
10440
- index,
10441
- hasCache: existsSync2(join(dir, CACHE_DIR_NAME, SUMMARY_CACHE_FILE_NAME)) ? 1 : 0,
10442
- cacheMtime: mtimeOf(join(dir, CACHE_DIR_NAME, SUMMARY_CACHE_FILE_NAME)),
10443
- hasMarker: existsSync2(join(dir, "references", "todo-smart-convert.md")) ? 1 : 0,
10444
- skillMtime: mtimeOf(join(dir, "SKILL.md"))
10445
- }));
10446
- scored.sort(
10447
- (a, b) => b.hasCache - a.hasCache || b.cacheMtime - a.cacheMtime || b.hasMarker - a.hasMarker || b.skillMtime - a.skillMtime || a.index - b.index
10448
- );
10449
- return scored.map((item) => item.dir);
10352
+ function resolveSkillDir() {
10353
+ const explicit = process.env.WEAVER_WORK_CLI_SKILL_DIR?.trim();
10354
+ return explicit ? resolve2(explicit) : null;
10450
10355
  }
10451
10356
  function cacheRoots(ctx) {
10452
- const fallback = stateCacheDir(ctx);
10453
- const explicitCache = process.env.WEAVER_WORK_CLI_CACHE_DIR?.trim();
10454
- if (explicitCache) {
10455
- const dir = resolve2(explicitCache);
10456
- return { preferred: dir, fallback: dir, inSkillDir: false, skillDir: null };
10457
- }
10458
- const home = homedir2();
10459
- const explicitSkill = process.env.WEAVER_WORK_CLI_SKILL_DIR?.trim();
10460
- const candidates = [];
10461
- if (explicitSkill) candidates.push(resolve2(explicitSkill));
10462
- for (const agent of AGENT_HOME_DIRS) {
10463
- candidates.push(join(home, agent, "skills", SKILL_DIR_NAME));
10464
- }
10465
- candidates.push(...discoverThisSkillDirs(home));
10466
- const installed = uniqueDirs(candidates).filter((dir) => existsSync2(join(dir, "SKILL.md")));
10467
- const [skillDir] = rankSkillDirs(installed);
10468
- if (skillDir) {
10469
- return {
10470
- preferred: join(skillDir, CACHE_DIR_NAME),
10471
- fallback,
10472
- inSkillDir: true,
10473
- skillDir
10474
- };
10357
+ void ctx;
10358
+ const skillDir = resolveSkillDir();
10359
+ if (!skillDir) {
10360
+ return { preferred: null, fallback: null, inSkillDir: false, skillDir: null, refused: true };
10475
10361
  }
10476
- return { preferred: fallback, fallback, inSkillDir: false, skillDir: null };
10362
+ const cacheDir = join(skillDir, CACHE_DIR_NAME);
10363
+ return { preferred: cacheDir, fallback: cacheDir, inSkillDir: true, skillDir, refused: false };
10477
10364
  }
10478
10365
  async function readCacheFile(roots, fileName) {
10366
+ if (roots.refused || !roots.preferred) return null;
10479
10367
  for (const dir of uniqueDirs([roots.preferred, roots.fallback])) {
10480
10368
  const file = join(dir, fileName);
10481
10369
  if (!existsSync2(file)) continue;
@@ -10488,6 +10376,7 @@ async function readCacheFile(roots, fileName) {
10488
10376
  return null;
10489
10377
  }
10490
10378
  async function writeCacheFile(roots, fileName, payload) {
10379
+ if (roots.refused || !roots.preferred) return null;
10491
10380
  for (const dir of uniqueDirs([roots.preferred, roots.fallback])) {
10492
10381
  const file = join(dir, fileName);
10493
10382
  try {
@@ -10507,9 +10396,14 @@ function summaryCacheKey(requestId, lastFeedBackDateTime) {
10507
10396
  const stamp = String(lastFeedBackDateTime ?? "").trim();
10508
10397
  return `${requestId}__${stamp}`;
10509
10398
  }
10510
- function entryMatchesMaxChars(entry, maxChars) {
10511
- if (maxChars === void 0) return true;
10512
- return (entry.maxChars ?? 50) === maxChars;
10399
+ function promptTagOf(prompt) {
10400
+ return String(prompt ?? "").trim();
10401
+ }
10402
+ function entryMatches(entry, maxChars, pk, dv) {
10403
+ if (pk !== void 0 && entry.pk !== void 0 && entry.pk !== pk) return false;
10404
+ if (maxChars !== void 0 && entry.maxChars !== void 0 && entry.maxChars !== maxChars) return false;
10405
+ if (entry.dv !== void 0 && entry.dv !== dv) return false;
10406
+ return true;
10513
10407
  }
10514
10408
  function normalizeSummaryEntry(raw) {
10515
10409
  if (!raw || typeof raw !== "object") return null;
@@ -10517,7 +10411,15 @@ function normalizeSummaryEntry(raw) {
10517
10411
  if (typeof entry.summary !== "string" || !entry.summary.trim()) return null;
10518
10412
  if (typeof entry.cachedAt !== "number" || !Number.isFinite(entry.cachedAt)) return null;
10519
10413
  const maxChars = typeof entry.maxChars === "number" && Number.isFinite(entry.maxChars) ? entry.maxChars : void 0;
10520
- return { summary: entry.summary, cachedAt: entry.cachedAt, ...maxChars === void 0 ? {} : { maxChars } };
10414
+ const pk = typeof entry.pk === "string" && entry.pk !== "" ? entry.pk : void 0;
10415
+ const dv = typeof entry.dv === "string" && entry.dv !== "" ? entry.dv : void 0;
10416
+ return {
10417
+ summary: entry.summary,
10418
+ cachedAt: entry.cachedAt,
10419
+ ...maxChars === void 0 ? {} : { maxChars },
10420
+ ...pk === void 0 ? {} : { pk },
10421
+ ...dv === void 0 ? {} : { dv }
10422
+ };
10521
10423
  }
10522
10424
  async function openSummaryCache(ctx) {
10523
10425
  const roots = cacheRoots(ctx);
@@ -10554,27 +10456,29 @@ async function openSummaryCache(ctx) {
10554
10456
  misses: 0,
10555
10457
  pruned,
10556
10458
  dirty: false,
10557
- get(requestId, lastFeedBackDateTime, maxChars) {
10459
+ get(requestId, lastFeedBackDateTime, maxChars, pk, dv) {
10558
10460
  const key = summaryCacheKey(requestId, lastFeedBackDateTime);
10559
10461
  const entry = entries.get(key);
10560
- if (entry && now - entry.cachedAt <= SUMMARY_CACHE_TTL_MS && entryMatchesMaxChars(entry, maxChars)) {
10462
+ if (entry && now - entry.cachedAt <= SUMMARY_CACHE_TTL_MS && entryMatches(entry, maxChars, pk, dv)) {
10561
10463
  cache.hits += 1;
10562
10464
  return entry.summary;
10563
10465
  }
10564
10466
  cache.misses += 1;
10565
10467
  return null;
10566
10468
  },
10567
- has(requestId, lastFeedBackDateTime, maxChars) {
10469
+ has(requestId, lastFeedBackDateTime, maxChars, pk, dv) {
10568
10470
  const entry = entries.get(summaryCacheKey(requestId, lastFeedBackDateTime));
10569
- return entry !== void 0 && entryMatchesMaxChars(entry, maxChars);
10471
+ return entry !== void 0 && entryMatches(entry, maxChars, pk, dv);
10570
10472
  },
10571
- set(requestId, lastFeedBackDateTime, summary, maxChars) {
10473
+ set(requestId, lastFeedBackDateTime, summary, maxChars, pk, dv) {
10572
10474
  const text = String(summary ?? "").trim();
10573
10475
  if (!requestId || !text) return false;
10574
10476
  entries.set(summaryCacheKey(requestId, lastFeedBackDateTime), {
10575
10477
  summary: text,
10576
10478
  cachedAt: Date.now(),
10577
- ...maxChars === void 0 ? {} : { maxChars }
10479
+ ...maxChars === void 0 ? {} : { maxChars },
10480
+ ...pk === void 0 || pk === "" ? {} : { pk },
10481
+ ...dv === void 0 || dv === "" ? {} : { dv }
10578
10482
  });
10579
10483
  dirty = true;
10580
10484
  cache.dirty = true;
@@ -10626,7 +10530,8 @@ var FALLBACK_DEFAULTS = {
10626
10530
  requestSummaryPrompt: "",
10627
10531
  summaryMaxChars: 150,
10628
10532
  groupSummaryMaxChars: 100,
10629
- groupSummaryTail: "\u53EF\u5C55\u5F00\u9010\u6761\u67E5\u770B\u6216\u76F4\u63A5\u6C47\u603B\u5904\u7406"
10533
+ groupSummaryTail: "\u53EF\u5C55\u5F00\u9010\u6761\u67E5\u770B\u6216\u76F4\u63A5\u6C47\u603B\u5904\u7406",
10534
+ excludeOriginFormDataFields: []
10630
10535
  };
10631
10536
  function emptyRuleFile(error = null) {
10632
10537
  return {
@@ -10655,14 +10560,66 @@ function validateFocusKeyword(raw, index) {
10655
10560
  if (raw.length !== 3) return `focusKeyword[${index}] \u5FC5\u987B\u662F [\u6307\u6807, \u7B97\u5B50, \u503C] \u4E09\u5143\u7EC4`;
10656
10561
  return null;
10657
10562
  }
10563
+ function validateExcludeFields(raw, where) {
10564
+ if (raw === void 0) return null;
10565
+ if (typeof raw === "string") {
10566
+ return raw.trim() === "" ? `${where} \u4E0D\u80FD\u662F\u7A7A\u5B57\u7B26\u4E32\uFF08\u4E0D\u6392\u9664\u5C31\u522B\u7ED9\u8FD9\u4E2A\u952E\uFF09` : null;
10567
+ }
10568
+ if (!Array.isArray(raw)) return `${where} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4`;
10569
+ for (const item of raw) {
10570
+ if (typeof item !== "string" || item.trim() === "") return `${where} \u7684\u6BCF\u4E00\u9879\u90FD\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`;
10571
+ }
10572
+ return null;
10573
+ }
10658
10574
  function validateRuleFile(raw) {
10659
10575
  const errors = [];
10660
10576
  const file = raw;
10661
10577
  if (!file || typeof file !== "object") return ["\u89C4\u5219\u6587\u4EF6\u5FC5\u987B\u662F JSON \u5BF9\u8C61"];
10578
+ if (file.schemaVersion !== void 0 && file.schemaVersion !== 2 && file.schemaVersion !== 3) {
10579
+ errors.push(`schemaVersion \u53EA\u652F\u6301 2 \u6216 3\uFF0C\u6536\u5230 ${JSON.stringify(file.schemaVersion ?? null)}`);
10580
+ }
10662
10581
  if (!Array.isArray(file.rules)) {
10663
10582
  errors.push("rules \u5FC5\u987B\u662F\u6570\u7EC4");
10664
10583
  return errors;
10665
10584
  }
10585
+ if (file.generalRules !== void 0) {
10586
+ if (!file.generalRules || typeof file.generalRules !== "object" || Array.isArray(file.generalRules)) {
10587
+ errors.push("generalRules \u5FC5\u987B\u662F\u5BF9\u8C61");
10588
+ } else {
10589
+ const identity = file.generalRules.identityFilter;
10590
+ if (identity !== void 0) {
10591
+ if (!identity || typeof identity !== "object" || Array.isArray(identity)) {
10592
+ errors.push("generalRules.identityFilter \u5FC5\u987B\u662F\u5BF9\u8C61");
10593
+ } else if (identity.defaultIsremarks !== void 0 && !/^\d+(,\d+)*$/.test(String(identity.defaultIsremarks).trim())) {
10594
+ errors.push("generalRules.identityFilter.defaultIsremarks \u5FC5\u987B\u662F\u300C\u6570\u5B57\u9017\u53F7\u62FC\u63A5\u300D\u683C\u5F0F\uFF0C\u5982 0,1,2");
10595
+ }
10596
+ if (identity?.excludedCodes !== void 0 && (!Array.isArray(identity.excludedCodes) || identity.excludedCodes.some((c) => !/^\d+$/.test(String(c))))) {
10597
+ errors.push("generalRules.identityFilter.excludedCodes \u5FC5\u987B\u662F\u6570\u5B57\u7801\u6570\u7EC4");
10598
+ }
10599
+ }
10600
+ const priority = file.generalRules.priorityGroup;
10601
+ if (priority !== void 0) {
10602
+ if (!priority || typeof priority !== "object" || Array.isArray(priority)) {
10603
+ errors.push("generalRules.priorityGroup \u5FC5\u987B\u662F\u5BF9\u8C61");
10604
+ } else {
10605
+ if (priority.title !== void 0 && (typeof priority.title !== "string" || !priority.title.trim())) {
10606
+ errors.push("generalRules.priorityGroup.title \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
10607
+ }
10608
+ if (priority.rules !== void 0) {
10609
+ const KNOWN_PRIORITY_RULES = ["overdue", "levelFallback"];
10610
+ if (!Array.isArray(priority.rules) || priority.rules.length === 0 || priority.rules.some((r) => !KNOWN_PRIORITY_RULES.includes(String(r)))) {
10611
+ errors.push(`generalRules.priorityGroup.rules \u53EA\u652F\u6301 ${KNOWN_PRIORITY_RULES.join("\u3001")}`);
10612
+ }
10613
+ }
10614
+ }
10615
+ }
10616
+ }
10617
+ }
10618
+ const defaultsExclude = validateExcludeFields(
10619
+ file.defaults?.excludeOriginFormDataFields,
10620
+ "defaults.excludeOriginFormDataFields"
10621
+ );
10622
+ if (defaultsExclude) errors.push(defaultsExclude);
10666
10623
  const seen = /* @__PURE__ */ new Set();
10667
10624
  file.rules.forEach((rule, index) => {
10668
10625
  if (!rule || typeof rule !== "object") {
@@ -10684,6 +10641,13 @@ function validateRuleFile(raw) {
10684
10641
  if (rule.summaryMaxChars !== void 0 && (typeof rule.summaryMaxChars !== "number" || rule.summaryMaxChars <= 0)) {
10685
10642
  errors.push(`rules[${index}].summaryMaxChars \u5FC5\u987B\u662F\u6B63\u6570`);
10686
10643
  }
10644
+ const excludeReason = validateExcludeFields(rule.excludeOriginFormDataFields, `rules[${index}].excludeOriginFormDataFields`);
10645
+ if (excludeReason) errors.push(excludeReason);
10646
+ if (rule.summaryRequiredFields !== void 0) {
10647
+ if (!Array.isArray(rule.summaryRequiredFields) || rule.summaryRequiredFields.length === 0 || rule.summaryRequiredFields.some((f) => typeof f !== "string" || !f.trim() || f.trim().length > 50) || rule.summaryRequiredFields.length > 20) {
10648
+ errors.push(`rules[${index}].summaryRequiredFields \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u6570\u7EC4\uFF081~20 \u9879\u3001\u6BCF\u9879 1~50 \u5B57\uFF09`);
10649
+ }
10650
+ }
10687
10651
  const groupRule = rule.aiGroup?.groupRule;
10688
10652
  if (groupRule) {
10689
10653
  if (typeof groupRule.focus !== "boolean") errors.push(`rules[${index}].aiGroup.groupRule.focus \u5FC5\u987B\u662F\u5E03\u5C14`);
@@ -10737,29 +10701,28 @@ function loadRuleFile(file) {
10737
10701
  return { file: parsed, error: null };
10738
10702
  }
10739
10703
  function aigroupDir(ctx) {
10740
- const explicit = process.env.WEAVER_WORK_CLI_AIGROUP_DIR?.trim();
10741
- if (explicit) return join2(explicit);
10742
- const roots = cacheRoots(ctx);
10743
- return roots.skillDir ? join2(roots.skillDir, AIGROUP_DIR_NAME) : join2(stateRoot(ctx), AIGROUP_DIR_NAME);
10704
+ const skillDir = resolveSkillDir();
10705
+ return skillDir ? join2(skillDir, AIGROUP_DIR_NAME) : null;
10744
10706
  }
10745
10707
  function aigroupUserDir(ctx) {
10746
- const explicit = process.env.WEAVER_WORK_CLI_AIGROUP_DIR?.trim();
10747
- if (explicit) return join2(explicit);
10748
- return join2(stateRoot(ctx), AIGROUP_DIR_NAME);
10708
+ return aigroupDir(ctx);
10749
10709
  }
10750
10710
  function loadRules(options = {}) {
10751
- const dir = options.dir ?? aigroupDir(options.ctx);
10752
- const userDir = options.dir ?? aigroupUserDir(options.ctx);
10753
10711
  const warnings = [];
10712
+ const dir = options.dir ?? aigroupDir(options.ctx);
10713
+ if (!dir) {
10714
+ warnings.push("\u65E0\u5F53\u524D skill \u4E0A\u4E0B\u6587\uFF08WEAVER_WORK_CLI_SKILL_DIR \u672A\u8BBE\u7F6E\uFF09\uFF1Aaigroup \u89C4\u5219\u672A\u52A0\u8F7D\uFF0C\u6309\u65E0\u89C4\u5219\u5904\u7406");
10715
+ return { file: emptyRuleFile(null).file, warnings, dir: null };
10716
+ }
10754
10717
  const base = loadRuleFile(join2(dir, DEFAULT_RULE_FILE));
10755
10718
  if (base.error) warnings.push(base.error);
10756
10719
  const rules = [...base.file.rules];
10757
- const userIntentFile = join2(userDir, USER_INTENT_RULE_FILE);
10758
- const legacyIntentFile = join2(dir, USER_INTENT_RULE_FILE);
10720
+ const userIntentFile = join2(dir, USER_INTENT_RULE_FILE);
10721
+ const legacyIntentFile = join2(stateRoot(options.ctx), AIGROUP_DIR_NAME, USER_INTENT_RULE_FILE);
10759
10722
  let intentFile = userIntentFile;
10760
10723
  if (!options.dir && !existsSync3(userIntentFile) && existsSync3(legacyIntentFile)) {
10761
10724
  intentFile = legacyIntentFile;
10762
- warnings.push(`\u7528\u6237\u610F\u56FE\u4ECD\u8BFB\u81EA skill \u76EE\u5F55\uFF08${legacyIntentFile}\uFF09\uFF1A\u65B0\u4F4D\u7F6E\u662F ${userIntentFile}\uFF0C\u91CD\u65B0\u6267\u884C aigroup set \u5373\u53EF\u8FC1\u79FB`);
10725
+ warnings.push(`\u7528\u6237\u610F\u56FE\u4ECD\u8BFB\u81EA CLI \u72B6\u6001\u76EE\u5F55\uFF08${legacyIntentFile}\uFF09\uFF1A\u65B0\u4F4D\u7F6E\u662F ${userIntentFile}\uFF0C\u91CD\u65B0\u6267\u884C aigroup set \u5373\u53EF\u8FC1\u79FB`);
10763
10726
  }
10764
10727
  const intent = loadRuleFile(intentFile);
10765
10728
  if (intent.error) {
@@ -10777,7 +10740,13 @@ function loadRules(options = {}) {
10777
10740
  }
10778
10741
  }
10779
10742
  return {
10780
- file: { schemaVersion: base.file.schemaVersion, defaults: { ...FALLBACK_DEFAULTS, ...base.file.defaults }, rules },
10743
+ file: {
10744
+ schemaVersion: base.file.schemaVersion,
10745
+ defaults: { ...FALLBACK_DEFAULTS, ...base.file.defaults },
10746
+ rules,
10747
+ // 通用规则区(2026-11-03):仅取 default.json 的定义;用户意图文件不参与通用规则
10748
+ ...base.file.generalRules ? { generalRules: base.file.generalRules } : {}
10749
+ },
10781
10750
  warnings,
10782
10751
  dir
10783
10752
  };
@@ -10821,12 +10790,13 @@ function resolveRule(file, workflowName) {
10821
10790
  summaryMaxChars: raw.summaryMaxChars ?? defaults.summaryMaxChars,
10822
10791
  groupSummaryMaxChars: defaults.groupSummaryMaxChars,
10823
10792
  groupSummaryTail: defaults.groupSummaryTail,
10793
+ // 显式给 `[]` = 规则级覆盖(清空 defaults 的清单);未给才落 defaults
10794
+ excludeOriginFormDataFields: raw.excludeOriginFormDataFields === void 0 ? defaults.excludeOriginFormDataFields : asStringArray3(raw.excludeOriginFormDataFields) ?? [],
10824
10795
  aiGroup: raw.aiGroup ? {
10825
10796
  groupSummary: {
10826
10797
  needAI: groupSummary?.needAI ?? false,
10827
10798
  ...groupSummary?.prompt === void 0 ? {} : { prompt: groupSummary.prompt },
10828
10799
  ...groupSummary?.template === void 0 ? {} : { template: groupSummary.template },
10829
- maxChars: defaults.groupSummaryMaxChars,
10830
10800
  tail: defaults.groupSummaryTail
10831
10801
  },
10832
10802
  groupRule: groupRule ?? EMPTY_GROUP_RULE
@@ -10949,10 +10919,27 @@ function activeRuleFor(workflowName) {
10949
10919
  if (!name) return null;
10950
10920
  return resolveRule(activeRules(), name)?.rule ?? null;
10951
10921
  }
10922
+ function generalRules() {
10923
+ return activeRules().generalRules ?? null;
10924
+ }
10952
10925
  function resetActiveRules() {
10953
10926
  activeFile = null;
10954
10927
  activeDir = null;
10955
10928
  }
10929
+ function excludeFieldsFor(workflowName) {
10930
+ return activeRuleFor(workflowName)?.excludeOriginFormDataFields ?? [];
10931
+ }
10932
+ function excludeTagOf(fields) {
10933
+ return [...fields].join("");
10934
+ }
10935
+ function excludeTagFor(workflowName) {
10936
+ return excludeTagOf(excludeFieldsFor(workflowName));
10937
+ }
10938
+
10939
+ // src/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.ts
10940
+ import { writeFileSync } from "node:fs";
10941
+ import { tmpdir as tmpdir2 } from "node:os";
10942
+ import { join as join3 } from "node:path";
10956
10943
 
10957
10944
  // src/shortcuts/workflow/operations/todoSmartConvert/todoListRows.ts
10958
10945
  var DISPLAY_ROW_FIELDS = [
@@ -11013,6 +11000,107 @@ function projectDisplayRows(response) {
11013
11000
  return projected;
11014
11001
  }
11015
11002
 
11003
+ // src/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.ts
11004
+ var DETAIL_CACHE_FILE_NAME = "todo-detail-cache.json";
11005
+ var DETAIL_CACHE_TTL_MS = SUMMARY_CACHE_TTL_MS;
11006
+ var DETAIL_CACHE_PRUNE_INTERVAL_MS = SUMMARY_CACHE_PRUNE_INTERVAL_MS;
11007
+ var DETAIL_CACHE_ENTRY_VERSION = 3;
11008
+ function detailCacheKey(requestId, lastFeedBackDateTime) {
11009
+ const stamp = String(lastFeedBackDateTime ?? "").trim();
11010
+ return `${requestId}__${stamp}`;
11011
+ }
11012
+ function detailMaterialTagOf(entry) {
11013
+ const basic = entry.basicInfo ?? {};
11014
+ const basicKeys = Object.keys(basic).sort();
11015
+ const material = JSON.stringify([
11016
+ basicKeys.map((key) => [key, basic[key]]),
11017
+ (entry.fields ?? []).map((field) => [field.fieldName, field.value])
11018
+ ]);
11019
+ let hash = 5381;
11020
+ for (let i = 0; i < material.length; i += 1) hash = (hash << 5) + hash + material.charCodeAt(i) >>> 0;
11021
+ return hash.toString(16);
11022
+ }
11023
+ function normalizeEntry(raw) {
11024
+ if (!raw || typeof raw !== "object") return null;
11025
+ const value = raw;
11026
+ if (value.v !== DETAIL_CACHE_ENTRY_VERSION) return null;
11027
+ if (typeof value.cachedAt !== "number" || !Number.isFinite(value.cachedAt)) return null;
11028
+ if (typeof value.excludeTag !== "string") return null;
11029
+ const basicInfo = {};
11030
+ if (value.basicInfo && typeof value.basicInfo === "object") {
11031
+ for (const [key, item] of Object.entries(value.basicInfo)) {
11032
+ if (typeof item === "string") basicInfo[key] = item;
11033
+ }
11034
+ }
11035
+ 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 })) : [];
11036
+ const metrics = value.metrics && typeof value.metrics === "object" ? value.metrics : {};
11037
+ return {
11038
+ v: DETAIL_CACHE_ENTRY_VERSION,
11039
+ basicInfo,
11040
+ fields,
11041
+ metrics,
11042
+ excludeTag: value.excludeTag,
11043
+ cachedAt: value.cachedAt
11044
+ };
11045
+ }
11046
+ async function openDetailCache(ctx) {
11047
+ const roots = cacheRoots(ctx);
11048
+ const stored = await readCacheFile(roots, DETAIL_CACHE_FILE_NAME);
11049
+ const now = Date.now();
11050
+ const entries = /* @__PURE__ */ new Map();
11051
+ let prunedAt = 0;
11052
+ let loaded = 0;
11053
+ let pruned = 0;
11054
+ if (stored) {
11055
+ try {
11056
+ const parsed = JSON.parse(stored.text);
11057
+ prunedAt = typeof parsed.prunedAt === "number" ? parsed.prunedAt : 0;
11058
+ for (const [key, raw] of Object.entries(parsed.entries ?? {})) {
11059
+ const entry = normalizeEntry(raw);
11060
+ if (!entry) continue;
11061
+ if (now - entry.cachedAt > DETAIL_CACHE_TTL_MS) {
11062
+ pruned += 1;
11063
+ continue;
11064
+ }
11065
+ entries.set(key, entry);
11066
+ loaded += 1;
11067
+ }
11068
+ } catch {
11069
+ }
11070
+ }
11071
+ const cache = {
11072
+ file: stored?.file ?? null,
11073
+ pruned: 0,
11074
+ loaded,
11075
+ get(requestId, lastFeedBackDateTime) {
11076
+ const entry = entries.get(detailCacheKey(requestId, lastFeedBackDateTime));
11077
+ if (!entry) return null;
11078
+ if (Date.now() - entry.cachedAt > DETAIL_CACHE_TTL_MS) return null;
11079
+ return entry;
11080
+ },
11081
+ has(requestId, lastFeedBackDateTime) {
11082
+ return cache.get(requestId, lastFeedBackDateTime) !== null;
11083
+ },
11084
+ set(requestId, lastFeedBackDateTime, entry) {
11085
+ if (!requestId) return false;
11086
+ entries.set(detailCacheKey(requestId, lastFeedBackDateTime), { ...entry, cachedAt: Date.now() });
11087
+ return true;
11088
+ },
11089
+ async save() {
11090
+ const shouldPrune = pruned > 0 && Date.now() - prunedAt > DETAIL_CACHE_PRUNE_INTERVAL_MS;
11091
+ const payload = {
11092
+ prunedAt: shouldPrune ? Date.now() : prunedAt,
11093
+ entries: Object.fromEntries(entries)
11094
+ };
11095
+ const file = await writeCacheFile(roots, DETAIL_CACHE_FILE_NAME, JSON.stringify(payload));
11096
+ if (file) cache.file = file;
11097
+ if (shouldPrune) cache.pruned = pruned;
11098
+ return file;
11099
+ }
11100
+ };
11101
+ return cache;
11102
+ }
11103
+
11016
11104
  // src/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.ts
11017
11105
  function normalizeDetailFieldName(raw) {
11018
11106
  return String(raw ?? "").replace(/<[^>]*>/g, " ").replace(/[【】[\]()()]/g, "").replace(/\s+/g, "").trim();
@@ -11230,7 +11318,8 @@ function renderGroupSummaryTemplate(input) {
11230
11318
  var DETAIL_BATCH_CONCURRENCY = 10;
11231
11319
  var DETAIL_BATCH_TIMEOUT_MS = 1e4;
11232
11320
  var DETAIL_BATCH_RETRIES = 1;
11233
- var DETAIL_BATCH_FIELD_LIMIT = 12;
11321
+ var DETAIL_MATERIAL_FIELD_LIMIT = 200;
11322
+ var DETAIL_MATERIAL_VALUE_LIMIT = 500;
11234
11323
  var HTML_ENTITIES = {
11235
11324
  amp: "&",
11236
11325
  lt: "<",
@@ -11319,6 +11408,9 @@ async function fetchOneDetail(env, requestId, userId, options) {
11319
11408
  const normalized = normalizeDetailResponse(response);
11320
11409
  const base = normalized?.basicInfo ?? {};
11321
11410
  const rawFields = Array.isArray(normalized?.formData?.fields) ? normalized.formData.fields : [];
11411
+ const basicInfo = Object.fromEntries(
11412
+ Object.entries(base).filter(([key]) => key !== "requestTitle" && key !== "flowName")
11413
+ );
11322
11414
  const usableFields = dropDistributionDetailFields(rawFields);
11323
11415
  const internalMessage = isInternalMessageDetail(
11324
11416
  base.workflowName,
@@ -11328,25 +11420,19 @@ async function fetchOneDetail(env, requestId, userId, options) {
11328
11420
  ...field,
11329
11421
  value: cleanFieldText(String(field?.value ?? ""))
11330
11422
  }));
11331
- const picked = internalMessage ? pickInternalMessageFieldPairs(cleanedFields, { creatorName: base.creatorName, createdAt: base.createdAt }) : selectSummaryFields(cleanedFields, options.fieldLimit ?? DETAIL_BATCH_FIELD_LIMIT, void 0, { fullValue: true });
11332
- const summaryFields = picked.map((field) => ({
11423
+ const excludeFields = excludeFieldsFor(base.workflowName);
11424
+ const excludeSet = new Set(excludeFields.map((name) => normalizeDetailFieldName(name)));
11425
+ const picked = (internalMessage ? pickInternalMessageFieldPairs(cleanedFields, base) : cleanedFields.filter((field) => !excludeSet.has(normalizeDetailFieldName(field?.fieldName)))).slice(0, DETAIL_MATERIAL_FIELD_LIMIT).map((field) => ({
11333
11426
  fieldName: String(field?.fieldName ?? "").trim(),
11334
- value: String(field?.value ?? "")
11427
+ value: String(field?.value ?? "").slice(0, DETAIL_MATERIAL_VALUE_LIMIT)
11335
11428
  })).filter((field) => field.fieldName && field.value);
11336
11429
  const metrics = extractRowMetrics(usableFields);
11337
11430
  return {
11338
11431
  requestId,
11339
- basicInfo: {
11340
- requestTitle: String(base.requestTitle ?? ""),
11341
- workflowName: String(base.workflowName ?? ""),
11342
- creatorName: String(base.creatorName ?? ""),
11343
- createdAt: String(base.createdAt ?? ""),
11344
- currentNode: String(base.currentNode ?? ""),
11345
- requestLevel: String(base.requestLevel ?? ""),
11346
- flowStatus: String(base.flowStatus ?? "")
11347
- },
11348
- summaryFields,
11349
- contextAvailable: summaryFields.length > 0,
11432
+ basicInfo,
11433
+ formFields: picked,
11434
+ contextAvailable: picked.length > 0,
11435
+ excludeTag: excludeTagOf(excludeFields),
11350
11436
  metrics
11351
11437
  };
11352
11438
  }
@@ -11398,17 +11484,10 @@ async function fetchRequestDetailsBatch(env, requestIds, options = {}) {
11398
11484
  failures.push({ requestId, error: reason });
11399
11485
  details.set(requestId, {
11400
11486
  requestId,
11401
- basicInfo: {
11402
- requestTitle: "",
11403
- workflowName: "",
11404
- creatorName: "",
11405
- createdAt: "",
11406
- currentNode: "",
11407
- requestLevel: "",
11408
- flowStatus: ""
11409
- },
11410
- summaryFields: [],
11487
+ basicInfo: {},
11488
+ formFields: [],
11411
11489
  contextAvailable: false,
11490
+ excludeTag: "",
11412
11491
  metrics: {},
11413
11492
  error: reason
11414
11493
  });
@@ -11431,90 +11510,11 @@ async function fetchRequestDetailsBatch(env, requestIds, options = {}) {
11431
11510
  };
11432
11511
  }
11433
11512
 
11434
- // src/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.ts
11435
- var DETAIL_CACHE_FILE_NAME = "todo-detail-cache.json";
11436
- var DETAIL_CACHE_TTL_MS = SUMMARY_CACHE_TTL_MS;
11437
- var DETAIL_CACHE_PRUNE_INTERVAL_MS = SUMMARY_CACHE_PRUNE_INTERVAL_MS;
11438
- function detailCacheKey(requestId, lastFeedBackDateTime) {
11439
- const stamp = String(lastFeedBackDateTime ?? "").trim();
11440
- return `${requestId}__${stamp}`;
11441
- }
11442
- function normalizeEntry(raw) {
11443
- if (!raw || typeof raw !== "object") return null;
11444
- const value = raw;
11445
- if (typeof value.cachedAt !== "number" || !Number.isFinite(value.cachedAt)) return null;
11446
- if (typeof value.context !== "string") return null;
11447
- 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 })) : [];
11448
- const metrics = value.metrics && typeof value.metrics === "object" ? value.metrics : {};
11449
- return {
11450
- context: value.context,
11451
- contextAvailable: value.contextAvailable === true,
11452
- metrics,
11453
- fields,
11454
- cachedAt: value.cachedAt
11455
- };
11456
- }
11457
- async function openDetailCache(ctx) {
11458
- const roots = cacheRoots(ctx);
11459
- const stored = await readCacheFile(roots, DETAIL_CACHE_FILE_NAME);
11460
- const now = Date.now();
11461
- const entries = /* @__PURE__ */ new Map();
11462
- let prunedAt = 0;
11463
- let loaded = 0;
11464
- let pruned = 0;
11465
- if (stored) {
11466
- try {
11467
- const parsed = JSON.parse(stored.text);
11468
- prunedAt = typeof parsed.prunedAt === "number" ? parsed.prunedAt : 0;
11469
- for (const [key, raw] of Object.entries(parsed.entries ?? {})) {
11470
- const entry = normalizeEntry(raw);
11471
- if (!entry) continue;
11472
- if (now - entry.cachedAt > DETAIL_CACHE_TTL_MS) {
11473
- pruned += 1;
11474
- continue;
11475
- }
11476
- entries.set(key, entry);
11477
- loaded += 1;
11478
- }
11479
- } catch {
11480
- }
11481
- }
11482
- const cache = {
11483
- file: stored?.file ?? null,
11484
- pruned: 0,
11485
- loaded,
11486
- get(requestId, lastFeedBackDateTime) {
11487
- const entry = entries.get(detailCacheKey(requestId, lastFeedBackDateTime));
11488
- if (!entry) return null;
11489
- if (Date.now() - entry.cachedAt > DETAIL_CACHE_TTL_MS) return null;
11490
- return entry;
11491
- },
11492
- has(requestId, lastFeedBackDateTime) {
11493
- return cache.get(requestId, lastFeedBackDateTime) !== null;
11494
- },
11495
- set(requestId, lastFeedBackDateTime, entry) {
11496
- if (!requestId) return false;
11497
- entries.set(detailCacheKey(requestId, lastFeedBackDateTime), { ...entry, cachedAt: Date.now() });
11498
- return true;
11499
- },
11500
- async save() {
11501
- const shouldPrune = pruned > 0 && Date.now() - prunedAt > DETAIL_CACHE_PRUNE_INTERVAL_MS;
11502
- const payload = {
11503
- prunedAt: shouldPrune ? Date.now() : prunedAt,
11504
- entries: Object.fromEntries(entries)
11505
- };
11506
- const file = await writeCacheFile(roots, DETAIL_CACHE_FILE_NAME, JSON.stringify(payload));
11507
- if (file) cache.file = file;
11508
- if (shouldPrune) cache.pruned = pruned;
11509
- return file;
11510
- }
11511
- };
11512
- return cache;
11513
- }
11514
-
11515
11513
  // src/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.ts
11516
11514
  function contextOfDetail(detail) {
11517
- return detail.summaryFields.map((field) => `${field.fieldName}\uFF1A${field.value}`).join("\uFF1B");
11515
+ const basicLines = Object.entries(detail.basicInfo ?? {}).filter(([, value]) => String(value ?? "").trim() !== "").map(([key, value]) => `${key}:${String(value).trim()}`);
11516
+ const fieldLines = (detail.formFields ?? []).map((field) => `${field.fieldName}:${field.value}`);
11517
+ return [...basicLines, ...fieldLines].join("\n");
11518
11518
  }
11519
11519
  var EMPTY_DETAIL_STATS = {
11520
11520
  requested: 0,
@@ -11526,8 +11526,6 @@ var EMPTY_DETAIL_STATS = {
11526
11526
  concurrency: 0,
11527
11527
  durationMs: 0
11528
11528
  };
11529
- var DETAIL_MATERIAL_FIELD_LIMIT = 8;
11530
- var DETAIL_MATERIAL_VALUE_LIMIT = 80;
11531
11529
  function stampsOfRows(rows) {
11532
11530
  const stamps = /* @__PURE__ */ new Map();
11533
11531
  for (const row of rows) {
@@ -11540,7 +11538,7 @@ function stampsOfRows(rows) {
11540
11538
  return stamps;
11541
11539
  }
11542
11540
  function materialFieldsOf(detail) {
11543
- return detail.summaryFields.filter((field) => field.value.length <= 200).slice(0, DETAIL_MATERIAL_FIELD_LIMIT).map((field) => ({ fieldName: field.fieldName, value: field.value.slice(0, DETAIL_MATERIAL_VALUE_LIMIT) }));
11541
+ return detail.formFields.map((field) => ({ fieldName: field.fieldName, value: field.value }));
11544
11542
  }
11545
11543
  async function fetchDetailFacts(env, requestIds, args, stamps) {
11546
11544
  const unique = [...new Set(requestIds.filter(Boolean))];
@@ -11554,13 +11552,13 @@ async function fetchDetailFacts(env, requestIds, args, stamps) {
11554
11552
  const missing = [];
11555
11553
  for (const requestId of unique) {
11556
11554
  const hit = cache.get(requestId, stamps?.get(requestId));
11557
- if (!hit) {
11555
+ if (!hit || hit.excludeTag !== excludeTagFor(hit.basicInfo.workflowName ?? "")) {
11558
11556
  missing.push(requestId);
11559
11557
  continue;
11560
11558
  }
11561
11559
  facts.set(requestId, {
11562
- context: hit.context,
11563
- contextAvailable: hit.contextAvailable,
11560
+ context: contextOfDetail({ basicInfo: hit.basicInfo, formFields: hit.fields }),
11561
+ contextAvailable: hit.fields.length > 0,
11564
11562
  metrics: hit.metrics,
11565
11563
  fields: hit.fields
11566
11564
  });
@@ -11578,7 +11576,7 @@ async function fetchDetailFacts(env, requestIds, args, stamps) {
11578
11576
  for (const [requestId, detail] of details) {
11579
11577
  const fact = {
11580
11578
  context: contextOfDetail(detail),
11581
- contextAvailable: detail.summaryFields.length > 0,
11579
+ contextAvailable: detail.formFields.length > 0,
11582
11580
  metrics: detail.metrics ?? {},
11583
11581
  fields: materialFieldsOf(detail)
11584
11582
  };
@@ -11587,10 +11585,11 @@ async function fetchDetailFacts(env, requestIds, args, stamps) {
11587
11585
  if (fact.contextAvailable) stats.contextAvailable += 1;
11588
11586
  else stats.contextEmpty += 1;
11589
11587
  if (cache.set(requestId, stamps?.get(requestId), {
11590
- context: fact.context,
11591
- contextAvailable: fact.contextAvailable,
11588
+ v: DETAIL_CACHE_ENTRY_VERSION,
11589
+ basicInfo: detail.basicInfo,
11592
11590
  metrics: fact.metrics,
11593
- fields: fact.fields
11591
+ fields: fact.fields,
11592
+ excludeTag: detail.excludeTag
11594
11593
  })) written += 1;
11595
11594
  }
11596
11595
  } catch (error) {
@@ -11692,18 +11691,19 @@ function isExpiringTodayRow(row, now = Date.now()) {
11692
11691
  if (row.overTime) return false;
11693
11692
  return isExpiringTodayUserOverTime(row.userOverTime, now);
11694
11693
  }
11695
- function selectPriorityRows(rows) {
11694
+ function selectPriorityRows(rows, enabledRules) {
11695
+ const rules = enabledRules ?? /* @__PURE__ */ new Set(["overdue", "levelFallback"]);
11696
11696
  let maxLevel = 0;
11697
11697
  for (const row of rows) {
11698
11698
  if (row.requestLevel > maxLevel) maxLevel = row.requestLevel;
11699
11699
  }
11700
- const targetLevel = maxLevel >= 2 ? 2 : maxLevel >= 1 ? 1 : void 0;
11700
+ const targetLevel = rules.has("levelFallback") && maxLevel >= 2 ? 2 : rules.has("levelFallback") && maxLevel >= 1 ? 1 : void 0;
11701
11701
  const selected = [];
11702
11702
  let overdueCount = 0;
11703
11703
  let levelCount = 0;
11704
11704
  let bothCount = 0;
11705
11705
  for (const row of rows) {
11706
- const overdue = isOverdueRow(row);
11706
+ const overdue = rules.has("overdue") && isOverdueRow(row);
11707
11707
  const byLevel = targetLevel !== void 0 && row.requestLevel >= targetLevel;
11708
11708
  if (overdue) overdueCount += 1;
11709
11709
  if (byLevel) levelCount += 1;
@@ -11833,7 +11833,10 @@ function runGroup(args) {
11833
11833
  const { rawCount, rows, duplicateCount, unreadableCount } = readItems(args.items);
11834
11834
  const groupBy = readGroupBy(args.groupBy);
11835
11835
  const topN = readTopN(args.topN);
11836
- const priority = selectPriorityRows(rows);
11836
+ const pgConfig = generalRules()?.priorityGroup ?? null;
11837
+ const pgTitle = pgConfig?.title?.trim() || PRIORITY_GROUP_TITLE;
11838
+ const pgRules = new Set(pgConfig?.rules ?? ["overdue", "levelFallback"]);
11839
+ const priority = selectPriorityRows(rows, pgRules);
11837
11840
  const priorityRows = sortPriorityRows(priority.rows);
11838
11841
  const restRows = rows;
11839
11842
  const buckets = /* @__PURE__ */ new Map();
@@ -11863,7 +11866,7 @@ function runGroup(args) {
11863
11866
  const groups = priorityRows.length > 0 && groupBy === "workflow" ? [{
11864
11867
  id: PRIORITY_GROUP_ID,
11865
11868
  topPriority: true,
11866
- title: PRIORITY_GROUP_TITLE,
11869
+ title: pgTitle,
11867
11870
  count: priorityRows.length,
11868
11871
  requestDatas: priorityRows.map((row) => toRequestData(row)),
11869
11872
  stats: statsOf(priorityRows)
@@ -11889,7 +11892,7 @@ function runGroup(args) {
11889
11892
  if (priorityRows.length > 0 && groupBy === "workflow") {
11890
11893
  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";
11891
11894
  warnings.push(
11892
- `\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`
11895
+ `\u300C${pgTitle}\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`
11893
11896
  );
11894
11897
  } else if (priorityRows.length === 0 && groupBy === "workflow") {
11895
11898
  warnings.push(
@@ -11954,7 +11957,7 @@ async function collectRawTodos(args, env) {
11954
11957
  const plannedPages = Math.max(1, Math.min(Math.ceil(limit / pageSize), MAX_FETCH_PAGES));
11955
11958
  const listEnv = guardListOnlyHost(env);
11956
11959
  const searchArgs = { category };
11957
- for (const key of ["tabid", "tabName", "subCategory", "workflow", "creator", "requestName", "receiveTime", "requestLevel"]) {
11960
+ for (const key of ["tabid", "tabName", "subCategory", "isremarks", "workflow", "creator", "requestName", "receiveTime", "requestLevel"]) {
11958
11961
  const value = args[key];
11959
11962
  if (value !== void 0 && value !== null && value !== "") searchArgs[key] = value;
11960
11963
  }
@@ -11963,6 +11966,13 @@ async function collectRawTodos(args, env) {
11963
11966
  );
11964
11967
  if (!explicitTab) searchArgs.tabid = DEFAULT_TABID2;
11965
11968
  const warnings = [];
11969
+ if (searchArgs.isremarks === void 0) {
11970
+ const defaultIsremarks = generalRules()?.identityFilter?.defaultIsremarks?.trim();
11971
+ if (defaultIsremarks) {
11972
+ searchArgs.isremarks = defaultIsremarks;
11973
+ 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`);
11974
+ }
11975
+ }
11966
11976
  if (cappedFrom !== void 0) {
11967
11977
  warnings.push(
11968
11978
  `\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`
@@ -11987,6 +11997,19 @@ async function collectRawTodos(args, env) {
11987
11997
  { ...searchArgs, current: pageNo, pageSize },
11988
11998
  "list"
11989
11999
  );
12000
+ const isremarks = String(searchArgs.isremarks ?? "").trim();
12001
+ if (isremarks !== "") {
12002
+ query.params = { ...query.params || {}, isremarks };
12003
+ }
12004
+ if (process.env.WEAVER_WORK_CLI_DUMP_LIST_BODY) {
12005
+ try {
12006
+ writeFileSync(
12007
+ join3(tmpdir2(), `weaver-list-body-page${pageNo}.json`),
12008
+ JSON.stringify({ path: listPath, body: query }, null, 2)
12009
+ );
12010
+ } catch {
12011
+ }
12012
+ }
11990
12013
  const response = await listEnv.host.workflowRequest({
11991
12014
  method: "POST",
11992
12015
  path: listPath,
@@ -12071,16 +12094,32 @@ async function collectRawTodos(args, env) {
12071
12094
  });
12072
12095
  wfIdGroup = grouped.wfIdGroup ?? [];
12073
12096
  const summaryCache = await openSummaryCache(env.ctx);
12074
- const collectSummaryMaxChars = readBoundedInt(
12075
- args.summaryMaxChars,
12076
- "summaryMaxChars",
12077
- DEFAULT_REQUEST_SUMMARY_MAX,
12078
- 10,
12079
- 500
12080
- );
12097
+ const collectMaxCharsByGroup = /* @__PURE__ */ new Map();
12098
+ const collectMaxCharsFor = (workflowName) => {
12099
+ const key = workflowName ?? "";
12100
+ const hit = collectMaxCharsByGroup.get(key);
12101
+ if (hit !== void 0) return hit;
12102
+ const value = readBoundedInt(
12103
+ args.summaryMaxChars ?? activeRuleFor(key)?.summaryMaxChars,
12104
+ "summaryMaxChars",
12105
+ DEFAULT_REQUEST_SUMMARY_MAX,
12106
+ 10,
12107
+ 500
12108
+ );
12109
+ collectMaxCharsByGroup.set(key, value);
12110
+ return value;
12111
+ };
12081
12112
  const cachedSummaryIds = /* @__PURE__ */ new Set();
12113
+ const detailCacheForTag = await openDetailCache(env.ctx);
12082
12114
  for (const row of items) {
12083
- const cached = summaryCache.get(row.requestId, row.lastFeedBackDateTime, collectSummaryMaxChars);
12115
+ const detailEntry = detailCacheForTag.get(row.requestId, row.lastFeedBackDateTime);
12116
+ const cached = summaryCache.get(
12117
+ row.requestId,
12118
+ row.lastFeedBackDateTime,
12119
+ collectMaxCharsFor(row.workflowName),
12120
+ promptTagOf(activeRuleFor(row.workflowName ?? "")?.requestSummaryPrompt ?? ""),
12121
+ detailEntry ? detailMaterialTagOf(detailEntry) : void 0
12122
+ );
12084
12123
  if (!cached) continue;
12085
12124
  row.summary = cached;
12086
12125
  cachedSummaryIds.add(row.requestId);
@@ -12157,7 +12196,7 @@ async function collectRawTodos(args, env) {
12157
12196
  }
12158
12197
  if (!summaryCache.inSkillDir) {
12159
12198
  warnings.push(
12160
- "\u6CA1\u6709\u627E\u5230\u672C\u673A Agent \u7684 weaver-e10-workflow skill \u76EE\u5F55\uFF0C\u6458\u8981\u7F13\u5B58\u5DF2\u9000\u56DE CLI \u72B6\u6001\u76EE\u5F55\uFF1B\u5982\u9700\u7F13\u5B58\u843D\u5728 skill \u76EE\u5F55\uFF0C\u53EF\u7528 WEAVER_WORK_CLI_SKILL_DIR \u6307\u5B9A"
12199
+ "\u65E0\u5F53\u524D skill \u4E0A\u4E0B\u6587\uFF08WEAVER_WORK_CLI_SKILL_DIR \u672A\u8BBE\u7F6E\uFF09\uFF1A\u6458\u8981\u7F13\u5B58\u4E0E aigroup \u89C4\u5219\u5747\u672A\u8BFB\u5199\uFF0C\u672C\u6B21\u6309\u300C\u4ECE\u672A\u751F\u6210\u8FC7\u300D\u8D70\u5B9E\u65F6\u903B\u8F91\uFF1B\u8BF7\u7ECF skill \u7684 tools \u811A\u672C\u8C03\u7528"
12161
12200
  );
12162
12201
  }
12163
12202
  }
@@ -12444,12 +12483,23 @@ async function runSmartGroup(args, env, options = {}) {
12444
12483
  );
12445
12484
  const skipDetail = args.withDetailContext === false;
12446
12485
  const summaryCache = await openSummaryCache(env.ctx);
12486
+ const detailCacheForTag = skipDetail ? null : await openDetailCache(env.ctx);
12487
+ const materialTagOfRow = (requestId, stamp) => {
12488
+ const entry = detailCacheForTag?.get(requestId, stamp);
12489
+ return entry ? detailMaterialTagOf(entry) : void 0;
12490
+ };
12447
12491
  const cachedIds = /* @__PURE__ */ new Set();
12448
12492
  const allRows = [];
12449
12493
  for (const group of groups) {
12450
12494
  for (const row of group.requestDatas ?? []) {
12451
12495
  allRows.push(row);
12452
- if (summaryCache.get(row.requestId, row.lastFeedBackDateTime, summaryMaxChars)) cachedIds.add(row.requestId);
12496
+ if (summaryCache.get(
12497
+ row.requestId,
12498
+ row.lastFeedBackDateTime,
12499
+ summaryMaxChars,
12500
+ promptTagOf(activeRuleFor(group.title)?.requestSummaryPrompt ?? ""),
12501
+ materialTagOfRow(row.requestId, row.lastFeedBackDateTime)
12502
+ )) cachedIds.add(row.requestId);
12453
12503
  }
12454
12504
  }
12455
12505
  const detailIds = [...new Set(allRows.map((row) => row.requestId).filter(Boolean))];
@@ -12699,6 +12749,26 @@ async function runSmartGroup(args, env, options = {}) {
12699
12749
  function needAiSummary(workflowName) {
12700
12750
  return activeRuleFor(workflowName)?.needSummary ?? true;
12701
12751
  }
12752
+ function requestMaxCharsFor(args, workflowName) {
12753
+ return readBoundedInt(
12754
+ args.summaryMaxChars ?? activeRuleFor(workflowName)?.summaryMaxChars,
12755
+ "summaryMaxChars",
12756
+ DEFAULT_REQUEST_SUMMARY_MAX3,
12757
+ 10,
12758
+ 500
12759
+ );
12760
+ }
12761
+ function explicitMaxCharsFor(args, workflowName) {
12762
+ const explicit = args.summaryMaxChars;
12763
+ if (explicit === void 0 || explicit === null || String(explicit).trim() === "") return void 0;
12764
+ return requestMaxCharsFor(args, workflowName);
12765
+ }
12766
+ function requestPromptFor(workflowName) {
12767
+ return (activeRuleFor(workflowName)?.requestSummaryPrompt ?? "").trim();
12768
+ }
12769
+ function distinctBatchMaxChars(batches) {
12770
+ return [...new Set(batches.map((batch) => batch.suggestedMaxChars))].sort((left, right) => left - right);
12771
+ }
12702
12772
  var DEFAULT_MAX_CHARS_PER_BATCH = 24e3;
12703
12773
  var DEFAULT_MAX_ITEMS_PER_BATCH = 100;
12704
12774
  var DEFAULT_REQUEST_SUMMARY_MAX3 = 50;
@@ -12869,20 +12939,35 @@ async function runSummaryContext(args, env, prefetched) {
12869
12939
  const units = collectSummaryUnits(groups);
12870
12940
  const skippedSatisfaction = groups.filter((group) => !needAiSummary(group.title)).reduce((sum, group) => sum + rowsOfGroup(group).length, 0);
12871
12941
  const requestIds = [...new Set(units.flatMap((unit) => unit.rows.map((row) => row.requestId)))].filter(Boolean);
12872
- const summaryMaxChars = readBoundedInt(
12873
- args.summaryMaxChars,
12874
- "summaryMaxChars",
12875
- DEFAULT_REQUEST_SUMMARY_MAX3,
12876
- 10,
12877
- 500
12878
- );
12879
12942
  const summaryCache = await openSummaryCache(env.ctx);
12943
+ const detailCacheForTag = await openDetailCache(env.ctx);
12944
+ const materialTagOfRow = (requestId, stamp) => {
12945
+ const entry = detailCacheForTag.get(requestId, stamp);
12946
+ return entry ? detailMaterialTagOf(entry) : void 0;
12947
+ };
12880
12948
  let prefilled = 0;
12881
12949
  const prefilledIds = /* @__PURE__ */ new Set();
12882
12950
  const needsDetail = [];
12951
+ const workflowTitleByRequest = /* @__PURE__ */ new Map();
12952
+ for (const unit of units) {
12953
+ if (unit.groupId === "priority") continue;
12954
+ for (const row of unit.rows) {
12955
+ if (row.requestId && !workflowTitleByRequest.has(row.requestId)) {
12956
+ workflowTitleByRequest.set(row.requestId, unit.groupTitle);
12957
+ }
12958
+ }
12959
+ }
12960
+ const ruleNameForRow = (unit, row) => unit.groupId === "priority" ? workflowTitleByRequest.get(row.requestId ?? "") ?? unit.groupTitle : unit.groupTitle;
12883
12961
  for (const unit of units) {
12884
12962
  for (const row of unit.rows) {
12885
- const cached = summaryCache.get(row.requestId, row.lastFeedBackDateTime, summaryMaxChars);
12963
+ const name = ruleNameForRow(unit, row);
12964
+ const cached = summaryCache.get(
12965
+ row.requestId,
12966
+ row.lastFeedBackDateTime,
12967
+ explicitMaxCharsFor(args, name),
12968
+ promptTagOf(requestPromptFor(name)),
12969
+ materialTagOfRow(row.requestId, row.lastFeedBackDateTime)
12970
+ );
12886
12971
  if (cached) {
12887
12972
  row.summary = cached;
12888
12973
  prefilled += 1;
@@ -12901,13 +12986,17 @@ async function runSummaryContext(args, env, prefetched) {
12901
12986
  let contextEmpty = 0;
12902
12987
  let titleCopied = 0;
12903
12988
  const claimed = /* @__PURE__ */ new Set();
12904
- for (const unit of units) {
12989
+ const orderedUnits = [...units].sort(
12990
+ (a, b) => Number(a.groupId === "priority") - Number(b.groupId === "priority")
12991
+ );
12992
+ for (const unit of orderedUnits) {
12905
12993
  let bucket = [];
12906
12994
  let chars = 0;
12907
12995
  let seq = 0;
12908
12996
  const flush = () => {
12909
12997
  if (bucket.length === 0) return;
12910
12998
  seq += 1;
12999
+ const firstName = ruleNameForRow(unit, { requestId: bucket[0].requestId });
12911
13000
  batches.push({
12912
13001
  batchId: `${unit.subGroupId}#${seq}`,
12913
13002
  groupId: unit.groupId,
@@ -12918,7 +13007,8 @@ async function runSummaryContext(args, env, prefetched) {
12918
13007
  charCount: chars,
12919
13008
  kind: unit.kind,
12920
13009
  ...unit.kind === "internal-message" ? { hint: INTERNAL_MESSAGE_SUMMARY_HINT } : {},
12921
- suggestedMaxChars: summaryMaxChars,
13010
+ ...requestPromptFor(firstName) ? { prompt: requestPromptFor(firstName) } : {},
13011
+ suggestedMaxChars: requestMaxCharsFor(args, firstName),
12922
13012
  items: bucket
12923
13013
  });
12924
13014
  bucket = [];
@@ -12989,8 +13079,8 @@ async function runSummaryContext(args, env, prefetched) {
12989
13079
  titleCopied,
12990
13080
  /** 本地摘要命中、跳过 AI 的条数 */
12991
13081
  prefilled,
12992
- /** 单条摘要的目标字数(默认 50,可由 summaryMaxChars 覆盖) */
12993
- suggestedMaxChars: summaryMaxChars,
13082
+ /** 单条摘要的目标字数:口径一致时给数字,各组口径不同时给 distinct 列表 */
13083
+ ...distinctBatchMaxChars(batches).length === 1 ? { suggestedMaxChars: distinctBatchMaxChars(batches)[0] } : { suggestedMaxCharsList: distinctBatchMaxChars(batches) },
12994
13084
  /** 内部留言类批次:摘要要按「最低推理强度」写 */
12995
13085
  internalMessageBatches: batches.filter((batch) => batch.kind === "internal-message").length,
12996
13086
  skippedSatisfaction,
@@ -13054,16 +13144,30 @@ function readAiSummaries(value) {
13054
13144
  async function runSummary(args, env) {
13055
13145
  const groups = await readFinalGroups(args, env);
13056
13146
  const summaries = readAiSummaries(args.aiSummaries);
13057
- const summaryMaxChars = readBoundedInt(
13058
- args.summaryMaxChars,
13059
- "summaryMaxChars",
13060
- DEFAULT_REQUEST_SUMMARY_MAX3,
13061
- 10,
13062
- 500
13063
- );
13147
+ const maxCharsByGroup = /* @__PURE__ */ new Map();
13148
+ const maxCharsFor = (workflowName) => {
13149
+ const hit = maxCharsByGroup.get(workflowName);
13150
+ if (hit !== void 0) return hit;
13151
+ const value = requestMaxCharsFor(args, workflowName);
13152
+ maxCharsByGroup.set(workflowName, value);
13153
+ return value;
13154
+ };
13064
13155
  const summaryCache = await openSummaryCache(env.ctx);
13156
+ const detailCacheForTag = await openDetailCache(env.ctx);
13157
+ const materialTagOfRow = (requestId, stamp) => {
13158
+ const entry = detailCacheForTag.get(requestId, stamp);
13159
+ return entry ? detailMaterialTagOf(entry) : void 0;
13160
+ };
13065
13161
  let cacheWritten = 0;
13066
13162
  let titleSummary = 0;
13163
+ const wfTitleByRequest = /* @__PURE__ */ new Map();
13164
+ for (const group of groups) {
13165
+ if (group.topPriority) continue;
13166
+ for (const row of rowsOfGroup(group)) {
13167
+ if (row?.requestId && !wfTitleByRequest.has(row.requestId)) wfTitleByRequest.set(row.requestId, group.title);
13168
+ }
13169
+ }
13170
+ const ruleNameForGroup = (group, row) => group.topPriority ? wfTitleByRequest.get(row?.requestId ?? "") ?? group.title : group.title;
13067
13171
  for (const group of groups) {
13068
13172
  if (!needAiSummary(group.title)) {
13069
13173
  for (const row of rowsOfGroup(group)) {
@@ -13075,7 +13179,14 @@ async function runSummary(args, env) {
13075
13179
  }
13076
13180
  for (const row of rowsOfGroup(group)) {
13077
13181
  if (!row?.requestId || (row.summary ?? "").trim()) continue;
13078
- const cached = summaryCache.get(row.requestId, row.lastFeedBackDateTime, summaryMaxChars);
13182
+ const name = ruleNameForGroup(group, row);
13183
+ const cached = summaryCache.get(
13184
+ row.requestId,
13185
+ row.lastFeedBackDateTime,
13186
+ explicitMaxCharsFor(args, name),
13187
+ promptTagOf(requestPromptFor(name)),
13188
+ materialTagOfRow(row.requestId, row.lastFeedBackDateTime)
13189
+ );
13079
13190
  if (cached) {
13080
13191
  row.summary = cached;
13081
13192
  }
@@ -13103,7 +13214,7 @@ async function runSummary(args, env) {
13103
13214
  let titleKept = 0;
13104
13215
  let prefilledKept = 0;
13105
13216
  const countedIds = /* @__PURE__ */ new Set();
13106
- const applyAll = (rows) => {
13217
+ const applyAll = (rows, meta) => {
13107
13218
  for (const row of rows) {
13108
13219
  const summary = summaries.get(row.requestId) ?? "";
13109
13220
  const firstTime = !row.requestId || !countedIds.has(row.requestId);
@@ -13118,9 +13229,9 @@ async function runSummary(args, env) {
13118
13229
  if (summary) {
13119
13230
  if (firstTime) {
13120
13231
  filled += 1;
13121
- if (summary.length > summaryMaxChars) tooLong += 1;
13232
+ if (summary.length > meta(row).maxChars) tooLong += 1;
13122
13233
  }
13123
- if (summaryCache.set(row.requestId, row.lastFeedBackDateTime, summary, summaryMaxChars)) cacheWritten += 1;
13234
+ if (summaryCache.set(row.requestId, row.lastFeedBackDateTime, summary, meta(row).maxChars, meta(row).pk, materialTagOfRow(row.requestId, row.lastFeedBackDateTime))) cacheWritten += 1;
13124
13235
  } else if (firstTime) {
13125
13236
  empty += 1;
13126
13237
  }
@@ -13130,17 +13241,28 @@ async function runSummary(args, env) {
13130
13241
  for (const group of groups) {
13131
13242
  if (!needAiSummary(group.title)) continue;
13132
13243
  if (group.topPriority) {
13133
- applyAll(rowsOfGroup(group));
13244
+ applyAll(rowsOfGroup(group), (row) => {
13245
+ const name = ruleNameForGroup(group, row);
13246
+ return { maxChars: maxCharsFor(name), pk: promptTagOf(requestPromptFor(name)) };
13247
+ });
13134
13248
  continue;
13135
13249
  }
13136
13250
  for (const item of group.displayItems) {
13137
13251
  if (item.type === "group") {
13138
- applyAll(item.requestDatas);
13252
+ applyAll(item.requestDatas, (row) => {
13253
+ const name = ruleNameForGroup(group, row);
13254
+ return { maxChars: maxCharsFor(name), pk: promptTagOf(requestPromptFor(name)) };
13255
+ });
13139
13256
  continue;
13140
13257
  }
13141
- applyAll([item.requestData]);
13258
+ applyAll([item.requestData], (row) => {
13259
+ const name = ruleNameForGroup(group, row);
13260
+ return { maxChars: maxCharsFor(name), pk: promptTagOf(requestPromptFor(name)) };
13261
+ });
13142
13262
  }
13143
13263
  }
13264
+ const usedMaxChars = [...new Set(maxCharsByGroup.values())].sort((left, right) => left - right);
13265
+ const maxCharsHint = usedMaxChars.length > 0 ? usedMaxChars.join("/") : String(DEFAULT_REQUEST_SUMMARY_MAX3);
13144
13266
  if (empty > 0) {
13145
13267
  warnings.push(`\u6709 ${empty} \u6761\u6CA1\u6709\u62FF\u5230 AI \u6458\u8981\uFF0Csummary \u4FDD\u6301\u7A7A\u4E32\uFF08\u672A\u7528\u6807\u9898\u515C\u5E95\u3001\u672A\u7F16\u9020\uFF09`);
13146
13268
  }
@@ -13149,7 +13271,7 @@ async function runSummary(args, env) {
13149
13271
  }
13150
13272
  if (tooLong > 0) {
13151
13273
  warnings.push(
13152
- `\u6709 ${tooLong} \u6761\u6458\u8981\u8D85\u8FC7\u76EE\u6807\u957F\u5EA6 ${summaryMaxChars} \u5B57\uFF08\u53EF\u6309\u7528\u6237\u53E3\u5F84\u8C03\u6574\uFF09\uFF0C\u5DF2\u539F\u6837\u4FDD\u7559\uFF1B\u5982\u9700\u63A7\u5236\u957F\u5EA6\u8BF7\u91CD\u8DD1\u6A21\u578B\u4FA7\uFF08CLI \u4E0D\u6539\u5199\u6587\u6848\uFF09`
13274
+ `\u6709 ${tooLong} \u6761\u6458\u8981\u8D85\u8FC7\u76EE\u6807\u957F\u5EA6 ${maxCharsHint} \u5B57\uFF08\u53EF\u6309\u7528\u6237\u53E3\u5F84\u8C03\u6574\uFF09\uFF0C\u5DF2\u539F\u6837\u4FDD\u7559\uFF1B\u5982\u9700\u63A7\u5236\u957F\u5EA6\u8BF7\u91CD\u8DD1\u6A21\u578B\u4FA7\uFF08CLI \u4E0D\u6539\u5199\u6587\u6848\uFF09`
13153
13275
  );
13154
13276
  }
13155
13277
  if (prefilledKept > 0) {
@@ -13174,8 +13296,8 @@ async function runSummary(args, env) {
13174
13296
  meta: {
13175
13297
  summarized: filled,
13176
13298
  empty,
13177
- /** 单条摘要的目标字数(默认 50,可由 summaryMaxChars 覆盖) */
13178
- suggestedMaxChars: summaryMaxChars,
13299
+ /** 单条摘要的目标字数:各组口径一致时给数字,不一致时给 distinct 列表 */
13300
+ ...usedMaxChars.length === 1 ? { suggestedMaxChars: usedMaxChars[0] } : { suggestedMaxCharsList: usedMaxChars },
13179
13301
  titleCopied: titleKept,
13180
13302
  /** 本地摘要缓存命中、未重新生成的条数 */
13181
13303
  prefilled: prefilledKept,
@@ -13194,6 +13316,22 @@ async function runSummary(args, env) {
13194
13316
  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";
13195
13317
  var GROUP_SUMMARY_TAIL = GROUP_SUMMARY_TAIL_TEXT;
13196
13318
  var DEFAULT_GROUP_SUMMARY_MAX = 100;
13319
+ function makeGroupMaxCharsResolver(args) {
13320
+ const cache = /* @__PURE__ */ new Map();
13321
+ return (workflowName) => {
13322
+ const hit = cache.get(workflowName);
13323
+ if (hit !== void 0) return hit;
13324
+ const value = readBoundedInt(
13325
+ args.groupSummaryMaxChars ?? activeRuleFor(workflowName)?.groupSummaryMaxChars,
13326
+ "groupSummaryMaxChars",
13327
+ DEFAULT_GROUP_SUMMARY_MAX,
13328
+ 20,
13329
+ 1e3
13330
+ );
13331
+ cache.set(workflowName, value);
13332
+ return value;
13333
+ };
13334
+ }
13197
13335
  var GROUP_AMOUNT_PATTERNS = [
13198
13336
  /[¥¥]\s*(\d[\d,]*(?:\.\d{1,2})?)/u,
13199
13337
  /(\d[\d,]*(?:\.\d{1,2})?)\s*元/u
@@ -13212,7 +13350,7 @@ function createrPhraseOf(creators) {
13212
13350
  if (creators.length <= 3) return `\u7531${creators.join("\u3001")} \u53D1\u8D77`;
13213
13351
  return `\u7531${creators.slice(0, 3).join("\u3001")} \u7B49 ${creators.length} \u4EBA\u53D1\u8D77`;
13214
13352
  }
13215
- function collectGroupSummaryBatches(groups, isCtxEmpty, maxChars = DEFAULT_GROUP_SUMMARY_MAX) {
13353
+ function collectGroupSummaryBatches(groups, isCtxEmpty, maxCharsFor = () => DEFAULT_GROUP_SUMMARY_MAX) {
13216
13354
  const batches = [];
13217
13355
  for (const group of groups) {
13218
13356
  if (group.topPriority) continue;
@@ -13241,6 +13379,7 @@ function collectGroupSummaryBatches(groups, isCtxEmpty, maxChars = DEFAULT_GROUP
13241
13379
  if (amount !== null) amounts.push(amount);
13242
13380
  }
13243
13381
  const amountReliable = items.length >= 2 && amounts.length === items.length;
13382
+ const groupPrompt = (activeRuleFor(group.title)?.aiGroup?.groupSummary?.prompt ?? "").trim();
13244
13383
  batches.push({
13245
13384
  groupId: sub.id,
13246
13385
  parentGroupId: group.id,
@@ -13250,7 +13389,8 @@ function collectGroupSummaryBatches(groups, isCtxEmpty, maxChars = DEFAULT_GROUP
13250
13389
  totalCount: allRows.length,
13251
13390
  kind,
13252
13391
  ...kind === "internal-message" ? { hint: INTERNAL_MESSAGE_SUMMARY_HINT2 } : {},
13253
- suggestedMaxChars: maxChars,
13392
+ ...groupPrompt ? { prompt: groupPrompt } : {},
13393
+ suggestedMaxChars: maxCharsFor(group.title),
13254
13394
  ...emptySkipped > 0 ? { emptySkipped } : {},
13255
13395
  items,
13256
13396
  stats: {
@@ -13295,14 +13435,9 @@ async function loadCtxEmptyPredicate(env, groups, args = {}) {
13295
13435
  async function runGroupSummaryContext(args, env) {
13296
13436
  const groups = await readFinalGroups(args, env);
13297
13437
  const { isCtxEmpty, warnings: emptyWarnings } = await loadCtxEmptyPredicate(env, groups, args);
13298
- const groupSummaryMaxChars = readBoundedInt(
13299
- args.groupSummaryMaxChars,
13300
- "groupSummaryMaxChars",
13301
- DEFAULT_GROUP_SUMMARY_MAX,
13302
- 20,
13303
- 1e3
13304
- );
13305
- const batches = collectGroupSummaryBatches(groups, isCtxEmpty, groupSummaryMaxChars);
13438
+ const groupMaxCharsFor = makeGroupMaxCharsResolver(args);
13439
+ const batches = collectGroupSummaryBatches(groups, isCtxEmpty, groupMaxCharsFor);
13440
+ const distinctChars = [...new Set(batches.map((batch) => batch.suggestedMaxChars))].sort((left, right) => left - right);
13306
13441
  const totalCount = totalTodoCount(groups);
13307
13442
  const warnings = [...emptyWarnings];
13308
13443
  const skippedEmpty = batches.reduce((sum, batch) => sum + (batch.emptySkipped ?? 0), 0);
@@ -13338,7 +13473,7 @@ async function runGroupSummaryContext(args, env) {
13338
13473
  /** CLI 固定文案的汇总项个数(不进批次,`smartGroup` 阶段已写好) */
13339
13474
  deterministicGroups,
13340
13475
  tail: GROUP_SUMMARY_TAIL,
13341
- suggestedMaxChars: groupSummaryMaxChars
13476
+ ...distinctChars.length === 1 ? { suggestedMaxChars: distinctChars[0] } : { suggestedMaxCharsList: distinctChars }
13342
13477
  }
13343
13478
  },
13344
13479
  warnings
@@ -13389,14 +13524,9 @@ async function runGroupSummary(args, env) {
13389
13524
  const groups = await readFinalGroups(args, env);
13390
13525
  const summaries = readAiGroupSummaries(args.aiGroupSummaries);
13391
13526
  const { isCtxEmpty, warnings: emptyWarnings } = await loadCtxEmptyPredicate(env, groups, args);
13392
- const groupSummaryMaxChars = readBoundedInt(
13393
- args.groupSummaryMaxChars,
13394
- "groupSummaryMaxChars",
13395
- DEFAULT_GROUP_SUMMARY_MAX,
13396
- 20,
13397
- 1e3
13398
- );
13399
- const batches = collectGroupSummaryBatches(groups, isCtxEmpty, groupSummaryMaxChars);
13527
+ const groupMaxCharsFor = makeGroupMaxCharsResolver(args);
13528
+ const batches = collectGroupSummaryBatches(groups, isCtxEmpty, groupMaxCharsFor);
13529
+ const distinctChars = [...new Set(batches.map((batch) => batch.suggestedMaxChars))].sort((left, right) => left - right);
13400
13530
  const knownGroupIds = new Set(batches.map((batch) => batch.groupId));
13401
13531
  for (const groupId of summaries.keys()) {
13402
13532
  if (!knownGroupIds.has(groupId)) {
@@ -13417,6 +13547,7 @@ async function runGroupSummary(args, env) {
13417
13547
  for (const group of groups) {
13418
13548
  if (group.topPriority) continue;
13419
13549
  const kind = detectBusinessKind(group.title);
13550
+ const groupMaxChars = groupMaxCharsFor(group.title);
13420
13551
  for (const sub of groupItemsOf(group)) {
13421
13552
  if (isDeterministicGroupKind(kind)) {
13422
13553
  if ((sub.summary ?? "").trim() === "") {
@@ -13428,7 +13559,7 @@ async function runGroupSummary(args, env) {
13428
13559
  }
13429
13560
  filled += 1;
13430
13561
  summarizedGroupCount += 1;
13431
- if (summary2.length > groupSummaryMaxChars) tooLong += 1;
13562
+ if (summary2.length > groupMaxChars) tooLong += 1;
13432
13563
  const batch2 = batches.find((item) => item.groupId === sub.id);
13433
13564
  if (batch2 && batch2.stats.createrPhrase && !summary2.includes(batch2.stats.createrPhrase)) {
13434
13565
  missingCreater += 1;
@@ -13447,7 +13578,7 @@ async function runGroupSummary(args, env) {
13447
13578
  }
13448
13579
  filled += 1;
13449
13580
  summarizedGroupCount += 1;
13450
- if (summary.length > groupSummaryMaxChars) tooLong += 1;
13581
+ if (summary.length > groupMaxChars) tooLong += 1;
13451
13582
  const batch = batches.find((item) => item.groupId === sub.id);
13452
13583
  if (batch && batch.stats.createrPhrase && !summary.includes(batch.stats.createrPhrase)) {
13453
13584
  missingCreater += 1;
@@ -13456,7 +13587,7 @@ async function runGroupSummary(args, env) {
13456
13587
  }
13457
13588
  if (empty > 0) warnings.push(`\u6709 ${empty} \u4E2A\u6C47\u603B\u9879\u6CA1\u6709\u62FF\u5230\u7EC4\u6458\u8981\uFF0Csummary \u4FDD\u6301\u7A7A\u4E32\uFF08\u672A\u7F16\u9020\uFF09`);
13458
13589
  if (tooLong > 0) {
13459
- warnings.push(`\u6709 ${tooLong} \u4E2A\u7EC4\u6458\u8981\u8D85\u8FC7\u5EFA\u8BAE\u7684 ${groupSummaryMaxChars} \u5B57\uFF0C\u5DF2\u539F\u6837\u4FDD\u7559\uFF08CLI \u4E0D\u6539\u5199\u6587\u6848\uFF09`);
13590
+ warnings.push(`\u6709 ${tooLong} \u4E2A\u7EC4\u6458\u8981\u8D85\u8FC7\u5EFA\u8BAE\u7684 ${distinctChars.length > 0 ? distinctChars.join("/") : DEFAULT_GROUP_SUMMARY_MAX} \u5B57\uFF0C\u5DF2\u539F\u6837\u4FDD\u7559\uFF08CLI \u4E0D\u6539\u5199\u6587\u6848\uFF09`);
13460
13591
  }
13461
13592
  if (missingCreater > 0) {
13462
13593
  warnings.push(
@@ -13552,6 +13683,7 @@ var inputSchema = schemaOf({
13552
13683
  tabid: { type: "string" },
13553
13684
  tabName: { type: "string" },
13554
13685
  subCategory: { type: "string" },
13686
+ 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" },
13555
13687
  workflow: { type: "array", items: { type: "string" } },
13556
13688
  creator: { type: "string" },
13557
13689
  requestName: { type: "string" },
@@ -13560,8 +13692,10 @@ var inputSchema = schemaOf({
13560
13692
  groupFocus: { type: "string" },
13561
13693
  maxCharsPerBatch: { type: "integer", minimum: 500, maximum: 2e5, default: 24e3 },
13562
13694
  maxItemsPerBatch: { type: "integer", minimum: 1, maximum: 500, default: 100 },
13563
- summaryMaxChars: { type: "integer", minimum: 10, maximum: 500, default: 50 },
13564
- groupSummaryMaxChars: { type: "integer", minimum: 20, maximum: 1e3, default: 100 },
13695
+ // 字数口径不设 schema 默认:默认值来自 aigroup 规则(default.json 的 defaults),
13696
+ // 入参只在用户当轮明确给口径时覆盖规则(2026-10-30 用户要求「摘要规则必须从 JSON 取」)。
13697
+ summaryMaxChars: { type: "integer", minimum: 10, maximum: 500 },
13698
+ groupSummaryMaxChars: { type: "integer", minimum: 20, maximum: 1e3 },
13565
13699
  detailConcurrency: { type: "integer", minimum: 1, maximum: 32, default: 10 },
13566
13700
  detailTimeoutMs: { type: "integer", minimum: 1e3, maximum: 6e4, default: 1e4 },
13567
13701
  skillTiming: { type: "object" },