weaver-work-cli 0.1.32 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +2 -2
  2. package/dist/chunks/{archive-UMGX72K6.js → archive-XBVH7JU7.js} +2 -2
  3. package/dist/chunks/{archive-oa-N2IYBLF3.js → archive-oa-MZM3EKFQ.js} +2 -2
  4. package/dist/chunks/{asset-GLEGKFG5.js → asset-4XO7UOUW.js} +2 -2
  5. package/dist/chunks/{attachment-content-AQNX5N3S.js → attachment-content-VXSWANAC.js} +3 -2
  6. package/dist/chunks/{blog-E44OTVDA.js → blog-PGZKOPSC.js} +2 -2
  7. package/dist/chunks/{caizhilian-DQUFZXZL.js → caizhilian-BH4ZVGUN.js} +2 -2
  8. package/dist/chunks/{calendar-JKPIRKFD.js → calendar-MXEMTIO4.js} +2 -2
  9. package/dist/chunks/{chunk-QWY6PGL6.js → chunk-2LV74IWP.js} +361 -56
  10. package/dist/chunks/chunk-3SO6QL6U.js +73 -0
  11. package/dist/chunks/chunk-5DQEEGCC.js +229 -0
  12. package/dist/chunks/{chunk-G3QJULO2.js → chunk-6LLJFKJE.js} +1 -1
  13. package/dist/chunks/{chunk-C6R3B2ML.js → chunk-BPE37FPB.js} +35 -7
  14. package/dist/chunks/chunk-BYATLLEF.js +68 -0
  15. package/dist/chunks/chunk-BYBSCN4X.js +932 -0
  16. package/dist/chunks/{chunk-CVZ2JOSW.js → chunk-F746NKNF.js} +1 -1
  17. package/dist/chunks/{chunk-GCG2NMWR.js → chunk-HXJQI5NM.js} +4 -2
  18. package/dist/chunks/{chunk-YRVDW4WN.js → chunk-I6QGIBDM.js} +2 -2
  19. package/dist/chunks/{chunk-H7J4DC5R.js → chunk-JCSN3JGM.js} +2 -2
  20. package/dist/chunks/{chunk-2GA5ZIQL.js → chunk-JNG42JKG.js} +30 -1
  21. package/dist/chunks/{chunk-DW6AUUKS.js → chunk-JUXVYKII.js} +9 -4
  22. package/dist/chunks/{chunk-6RKD4DRZ.js → chunk-JYKABYCV.js} +2 -2
  23. package/dist/chunks/{chunk-6EFWDL7Y.js → chunk-NCOVUAZK.js} +2 -2
  24. package/dist/chunks/{chunk-E4Z23GHM.js → chunk-QHFANTX7.js} +1114 -904
  25. package/dist/chunks/{ebuilder-form-V5FG2EHC.js → chunk-QYGO5EE2.js} +22 -1148
  26. package/dist/chunks/{chunk-IURUFGZK.js → chunk-T72N74ZT.js} +50 -33
  27. package/dist/chunks/{chunk-H6XSTSLM.js → chunk-TC6MZAO3.js} +137 -204
  28. package/dist/chunks/{chunk-WKI2FBIQ.js → chunk-VPUTVEMC.js} +737 -341
  29. package/dist/chunks/{chunk-WSKBSQ2U.js → chunk-VPXOPQJI.js} +2 -2
  30. package/dist/chunks/chunk-WXFPWCXG.js +774 -0
  31. package/dist/chunks/{chunk-4YC43QQ4.js → chunk-XMGSYD6S.js} +4 -4
  32. package/dist/chunks/conflict-JAB2LJEZ.js +21 -0
  33. package/dist/chunks/continuation-RN6PZN2M.js +11 -0
  34. package/dist/chunks/contract-XI2EEIZU.js +9110 -0
  35. package/dist/chunks/cowork-SCPGLBA4.js +2527 -0
  36. package/dist/chunks/ebuilder-form-EYLHNOTA.js +121 -0
  37. package/dist/chunks/{ehr-HMFY6VIL.js → ehr-EAP77IMT.js} +1344 -27
  38. package/dist/chunks/{esb-ZYSVB7SG.js → esb-2TGGXEE7.js} +4 -4
  39. package/dist/chunks/{fna-B7RKPAZD.js → fna-2X7ZE7BU.js} +13 -8
  40. package/dist/chunks/{host-OCH2BCCV.js → host-C6EL2RKL.js} +3 -3
  41. package/dist/chunks/{host-45WED2KK.js → host-I4NRK4MX.js} +3 -3
  42. package/dist/chunks/{host-I4Z6BFYX.js → host-Q4LZGCRU.js} +3 -3
  43. package/dist/chunks/host-UEI5FGDM.js +23 -0
  44. package/dist/chunks/{host-KNZ52LJZ.js → host-XCLDDXKQ.js} +3 -3
  45. package/dist/chunks/{hrm-2KAZGUHI.js → hrm-YXERJM76.js} +3 -3
  46. package/dist/chunks/{im-ACJJWH4U.js → im-A4VZN2TQ.js} +88 -12
  47. package/dist/chunks/{invoice-ZK3WCX2U.js → invoice-2Z6YPMIS.js} +3 -3
  48. package/dist/chunks/{jiuchuanhui-5PQD3IL2.js → jiuchuanhui-AR5GMKZB.js} +2 -2
  49. package/dist/chunks/{lazy-dispatch-JQXBW3GM.js → lazy-dispatch-QXW7P4X3.js} +4 -4
  50. package/dist/chunks/{mail-S2HDDXO2.js → mail-7GZ6CPBJ.js} +45 -24
  51. package/dist/chunks/{meeting-QVN3I37L.js → meeting-3NMGA3MB.js} +278 -43
  52. package/dist/chunks/{okr-QNG4VC2Q.js → okr-BZ6XUOAG.js} +2 -2
  53. package/dist/chunks/operations-5QL3AECO.js +11 -0
  54. package/dist/chunks/{plan-A25EMW6U.js → plan-DR5CMUYP.js} +2 -2
  55. package/dist/chunks/{project-G6XV66DZ.js → project-6J63MK33.js} +2 -2
  56. package/dist/chunks/{registry-DC6KR3NH.js → registry-KDD7DHNK.js} +4 -4
  57. package/dist/chunks/{registry-2VLUAESA.js → registry-OZSMDVPP.js} +2 -2
  58. package/dist/chunks/{registry-7C5UMIPL.js → registry-TKX2E7C7.js} +2 -2
  59. package/dist/chunks/{registry-TI3CIUXF.js → registry-VRTNC6UR.js} +8 -6
  60. package/dist/chunks/{room-recommend-WRTHO6Y2.js → room-recommend-XCWRMB5P.js} +4 -3
  61. package/dist/chunks/{schedule-KFIITGSK.js → schedule-IVBICP32.js} +4 -3
  62. package/dist/chunks/{workflow-DJ7SYWAF.js → workflow-D74NFK3C.js} +179 -6
  63. package/dist/index.js +35 -25
  64. package/dist/internal/e10/auth-recovery.js +14 -4
  65. package/dist/internal/e10/fetch-timing.js +31 -0
  66. package/dist/internal/e10/request-runtime.js +5 -0
  67. package/dist/shortcuts/contract/host.js +34 -59
  68. package/dist/shortcuts/cowork/continuation.js +70 -0
  69. package/dist/shortcuts/cowork/errors.js +59 -0
  70. package/dist/shortcuts/cowork/host.js +180 -0
  71. package/dist/shortcuts/cowork/index.js +166 -0
  72. package/dist/shortcuts/cowork/manifest.js +65 -0
  73. package/dist/shortcuts/cowork/operations/discuss-write.js +277 -0
  74. package/dist/shortcuts/cowork/operations/item-write.js +380 -0
  75. package/dist/shortcuts/cowork/operations/member-write.js +283 -0
  76. package/dist/shortcuts/cowork/operations/permission-write.js +286 -0
  77. package/dist/shortcuts/cowork/operations/read.js +423 -0
  78. package/dist/shortcuts/cowork/operations/registry.js +39 -0
  79. package/dist/shortcuts/cowork/operations/review-write.js +157 -0
  80. package/dist/shortcuts/cowork/operations/shared.js +215 -0
  81. package/dist/shortcuts/cowork/operations/types.js +39 -0
  82. package/dist/shortcuts/cowork/operations.js +19 -0
  83. package/dist/shortcuts/ehr/host.js +4 -1
  84. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +757 -0
  85. package/dist/shortcuts/ehr/operations/recruit-position.js +367 -0
  86. package/dist/shortcuts/ehr/operations/recruit-stats.js +133 -0
  87. package/dist/shortcuts/ehr/operations/recruit-write.js +43 -16
  88. package/dist/shortcuts/ehr/operations/recruit.js +182 -10
  89. package/dist/shortcuts/ehr/operations/registry.js +6 -0
  90. package/dist/shortcuts/fna/operations/expense-chart.js +19 -7
  91. package/dist/shortcuts/im/diagnostics.js +97 -0
  92. package/dist/shortcuts/im/host.js +58 -31
  93. package/dist/shortcuts/im/index.js +7 -2
  94. package/dist/shortcuts/im/operations/at-mention.js +127 -0
  95. package/dist/shortcuts/im/operations/file-user.js +10 -2
  96. package/dist/shortcuts/im/operations/group-read.js +26 -5
  97. package/dist/shortcuts/im/operations/group-write.js +35 -28
  98. package/dist/shortcuts/im/operations/msg-sync.js +7 -2
  99. package/dist/shortcuts/im/operations/msg-write.js +76 -10
  100. package/dist/shortcuts/im/operations/quote-mention.js +119 -0
  101. package/dist/shortcuts/im/operations/session.js +1 -1
  102. package/dist/shortcuts/im/operations/shared.js +10 -0
  103. package/dist/shortcuts/im/operations/types.js +13 -0
  104. package/dist/shortcuts/index.js +10 -0
  105. package/dist/shortcuts/mail/host.js +12 -1
  106. package/dist/shortcuts/mail/operations/types.js +17 -2
  107. package/dist/shortcuts/meeting/host.js +27 -34
  108. package/dist/shortcuts/meeting/index.js +79 -1
  109. package/dist/shortcuts/meeting/manifest.js +10 -0
  110. package/dist/shortcuts/meeting/operations/create.js +4 -1
  111. package/dist/shortcuts/meeting/operations/eb/catalog.js +10 -0
  112. package/dist/shortcuts/meeting/operations/eb/conflict.js +84 -8
  113. package/dist/shortcuts/meeting/operations/eb/create-flow.js +1195 -140
  114. package/dist/shortcuts/meeting/operations/eb/factory.js +170 -8
  115. package/dist/shortcuts/meeting/operations/eb/index.js +16 -3
  116. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +50 -5
  117. package/dist/shortcuts/meeting/operations/eb-fallback.js +163 -0
  118. package/dist/shortcuts/meeting/operations/env.js +99 -46
  119. package/dist/shortcuts/meeting/operations/form-fields.js +110 -0
  120. package/dist/shortcuts/meeting/operations/invitation.js +79 -20
  121. package/dist/shortcuts/meeting/operations/registry.js +2 -0
  122. package/dist/shortcuts/meeting/operations/standard-guard.js +71 -0
  123. package/dist/shortcuts/meeting/operations.js +16 -0
  124. package/dist/shortcuts/workflow/endpoints.js +8 -3
  125. package/dist/shortcuts/workflow/index.js +110 -1
  126. package/dist/shortcuts/workflow/operations/form.js +204 -36
  127. package/dist/shortcuts/workflow/operations/read.js +104 -23
  128. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupRules.js +448 -0
  129. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupStore.js +106 -0
  130. package/dist/shortcuts/workflow/operations/todoSmartConvert/businessRules.js +47 -0
  131. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +30 -23
  132. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +1 -0
  133. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +1 -0
  134. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +2 -1
  135. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +2 -4
  136. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +138 -181
  137. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +12 -7
  138. package/dist/shortcuts/workflow/operations.js +23 -1
  139. package/docs/e10-auth.md +1 -1
  140. package/docs/ehr.md +1 -1
  141. package/docs/fna.md +2 -1
  142. package/docs/im.md +8 -1
  143. package/docs/todo-smart-convert/README.md +1 -1
  144. package/docs/todo-smart-convert/data-contract.md +2 -2
  145. package/docs/todo-smart-convert/subgroup-rules.md +6 -0
  146. package/package.json +1 -1
  147. package/skill-template/business-info.json +18 -0
  148. package/skill-template/domains/cowork.md +14 -0
  149. package/skill-template/domains/yimiaoban.md +3 -3
  150. package/skill-template/skill-template.md +1 -1
  151. package/skills/weaver-e10-blog/SKILL.md +5 -5
  152. package/skills/weaver-e10-caizhilian/SKILL.md +5 -5
  153. package/skills/weaver-e10-calendar/SKILL.md +5 -5
  154. package/skills/weaver-e10-cowork/SKILL.md +101 -0
  155. package/skills/weaver-e10-cowork/references/cowork-read.md +90 -0
  156. package/skills/weaver-e10-cowork/references/cowork-write.md +131 -0
  157. package/skills/weaver-e10-cowork/references/safety-boundaries.md +45 -0
  158. package/skills/weaver-e10-esb/SKILL.md +5 -5
  159. package/skills/weaver-e10-hrm/SKILL.md +5 -5
  160. package/skills/weaver-e10-jinchengda/SKILL.md +2 -2
  161. package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -5
  162. package/skills/weaver-e10-jucailin/SKILL.md +38 -14
  163. package/skills/weaver-e10-jucailin/references/recruit-create.md +104 -0
  164. package/skills/weaver-e10-jucailin/references/recruit-read.md +25 -0
  165. package/skills/weaver-e10-jucailin/references/recruit-write.md +13 -0
  166. package/skills/weaver-e10-jucailin/references/salary.md +15 -11
  167. package/skills/weaver-e10-mail/SKILL.md +17 -14
  168. package/skills/weaver-e10-meeting/SKILL.md +442 -46
  169. package/skills/weaver-e10-meeting/references/meeting-eb.md +135 -3
  170. package/skills/weaver-e10-meeting/references/meeting-invitation.md +28 -2
  171. package/skills/weaver-e10-meeting/references/meeting-queries.md +9 -6
  172. package/skills/weaver-e10-meeting/references/meeting-verification.md +8 -6
  173. package/skills/weaver-e10-meeting.zip +0 -0
  174. package/skills/weaver-e10-okr/SKILL.md +5 -5
  175. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  176. package/skills/weaver-e10-plan/SKILL.md +5 -5
  177. package/skills/weaver-e10-qiyecheng/SKILL.md +5 -2
  178. package/skills/weaver-e10-qiyecheng/references/catalog.md +2 -2
  179. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +15 -1
  180. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +22 -21
  181. package/skills/weaver-e10-shared/SKILL.md +12 -12
  182. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +4 -4
  183. package/skills/weaver-e10-wenshuding/SKILL.md +5 -5
  184. package/skills/weaver-e10-workflow/SKILL.md +29 -5
  185. package/skills/weaver-e10-workflow/aigroup/default.json +88 -0
  186. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +66 -14
  187. package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +1 -1
  188. package/skills/weaver-e10-workflow/references/workflow-memory.md +1 -1
  189. package/skills/weaver-e10-workflow/references/workflow-query.md +12 -10
  190. package/skills/weaver-e10-workflow/references/workflow-view.md +2 -2
  191. package/skills/weaver-e10-workflow/tools/todo-serve.cjs +239 -0
  192. package/skills/weaver-e10-workflow/{scripts → tools}/todo-summary.cjs +218 -28
  193. package/skills/weaver-e10-yepiaotong/SKILL.md +10 -8
  194. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +7 -7
  195. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +10 -10
  196. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +40 -37
  197. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +4 -4
  198. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +27 -38
  199. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +4 -4
  200. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +37 -29
  201. package/skills/weaver-e10-yimiaoban/SKILL.md +156 -33
  202. package/skills/weaver-e10-yimiaoban/references/ding-write.md +1 -1
  203. package/skills/weaver-e10-yimiaoban/references/error-codes.md +5 -1
  204. package/skills/weaver-e10-yimiaoban/references/group-read.md +5 -1
  205. package/skills/weaver-e10-yimiaoban/references/group-write.md +6 -4
  206. package/skills/weaver-e10-yimiaoban/references/msg-read.md +1 -0
  207. package/skills/weaver-e10-yimiaoban/references/msg-write.md +34 -2
  208. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +5 -2
  209. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +79 -58
  210. package/skills/weaver-e10-yimiaoban/references/user-remind.md +2 -2
  211. package/skills/weaver-e10-ziguanjia/SKILL.md +5 -5
@@ -0,0 +1,106 @@
1
+ /**
2
+ * 用户意图规则库(`aigroup/user-intents.json`,落在 **CLI 状态目录**,不写进 skill 目录)的读写。
3
+ *
4
+ * 为什么需要 CLI 入口:意图是模型用自然语言理解出来的,但**落盘必须结构化**。
5
+ * 让模型直接写文件,一旦字段拼错(`focus: true` 却没给 `focusKeyword`、`workflowName` 用了 `*`),
6
+ * 后续整轮分组都会走错分支且很难定位;所以由 CLI 统一做「校验 → 按 workflowName 整条覆盖 → 落盘」。
7
+ *
8
+ * 覆盖规则(2026-10-28 用户定):
9
+ * - 同一 `workflowName` **整条覆盖**(不是字段合并),缺的字段由 `default.json` 的 defaults 补;
10
+ * - **不允许覆盖通配条目 `*`**(系统默认的兜底规则不可被意图改掉);
11
+ * - 系统默认文件 `default.json` 永远只读。
12
+ */
13
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { workflowValidationError } from '../../errors.js';
16
+ import { aigroupUserDir, emptyRuleFile, loadRuleFile, validateRuleFile, USER_INTENT_RULE_FILE, } from './aigroupRules.js';
17
+ /** 把入参归一成规则条目数组:允许单条、数组、或 `{ rules: [...] }`。 */
18
+ export function normalizeIntentPayload(payload) {
19
+ if (Array.isArray(payload))
20
+ return payload;
21
+ if (payload && typeof payload === 'object') {
22
+ const record = payload;
23
+ if (Array.isArray(record.rules))
24
+ return record.rules;
25
+ if (record.workflowName !== undefined)
26
+ return [record];
27
+ }
28
+ throw workflowValidationError('aigroup_invalid', '入参必须是规则对象、规则数组,或 { rules: [...] }');
29
+ }
30
+ function namesOf(rule) {
31
+ const raw = rule?.workflowName;
32
+ if (typeof raw === 'string')
33
+ return [raw.trim()].filter(Boolean);
34
+ if (Array.isArray(raw))
35
+ return raw.map((item) => String(item ?? '').trim()).filter(Boolean);
36
+ return [];
37
+ }
38
+ /**
39
+ * 校验并落盘用户意图规则。
40
+ *
41
+ * 校验直接复用 `validateRuleFile`(包一层 `{ defaults, rules }`),
42
+ * 所以「focus=true 必须给 focusKeyword」「focus=false 不给 focusKeyword」「groupSummary 必须二选一」等
43
+ * 全部与默认文件同一套规则,不会出现两套标准。
44
+ */
45
+ export function saveUserIntents(payload, options = {}) {
46
+ const dir = options.dir ?? aigroupUserDir(options.ctx);
47
+ const warnings = [];
48
+ const entries = normalizeIntentPayload(payload);
49
+ if (entries.length === 0)
50
+ throw workflowValidationError('aigroup_invalid', '入参里没有规则条目');
51
+ const starred = entries.filter((rule) => namesOf(rule).includes('*'));
52
+ if (starred.length > 0) {
53
+ throw workflowValidationError('aigroup_wildcard_unsupported', '用户意图不能使用通配 workflowName「*」:兜底规则由 aigroup/default.json 决定');
54
+ }
55
+ const check = validateRuleFile({ schemaVersion: 2, defaults: {}, rules: entries });
56
+ if (check.length > 0) {
57
+ throw workflowValidationError('aigroup_invalid', `规则校验失败:${check.join(';')}`);
58
+ }
59
+ const file = join(dir, USER_INTENT_RULE_FILE);
60
+ const existing = existsSync(file) ? loadRuleFile(file) : emptyRuleFile();
61
+ if (existing.error) {
62
+ warnings.push(`${existing.error};本次将重建该文件`);
63
+ }
64
+ const byName = new Map();
65
+ const replaced = [];
66
+ for (const rule of existing.file.rules) {
67
+ for (const name of namesOf(rule))
68
+ byName.set(name, rule);
69
+ }
70
+ for (const rule of entries) {
71
+ const names = namesOf(rule);
72
+ for (const name of names) {
73
+ if (byName.has(name))
74
+ replaced.push(name);
75
+ byName.set(name, rule);
76
+ }
77
+ }
78
+ // 同一份规则可能有多个别名:按对象去重后落盘
79
+ const merged = [...new Set(byName.values())];
80
+ // 用户文件**不写 defaults**:缺省值统一由 default.json 提供,避免两份 defaults 打架
81
+ const text = `${JSON.stringify({ schemaVersion: 2, rules: merged }, null, 2)}\n`;
82
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
83
+ writeFileSync(file, text, { mode: 0o600 });
84
+ return { file, saved: entries.length, total: merged.length, replaced: [...new Set(replaced)], warnings };
85
+ }
86
+ /** 读用户意图文件(诊断/展示用)。 */
87
+ export function readUserIntents(options = {}) {
88
+ const dir = options.dir ?? aigroupUserDir(options.ctx);
89
+ const file = join(dir, USER_INTENT_RULE_FILE);
90
+ if (!existsSync(file))
91
+ return { dir, file, exists: false, error: null, rules: [] };
92
+ const loaded = loadRuleFile(file);
93
+ return { dir, file, exists: true, error: loaded.error, rules: loaded.file.rules };
94
+ }
95
+ /** 清空用户意图(只删内容、不删文件,保持目录结构)。 */
96
+ export function clearUserIntents(options = {}) {
97
+ const dir = options.dir ?? aigroupUserDir(options.ctx);
98
+ const file = join(dir, USER_INTENT_RULE_FILE);
99
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
100
+ writeFileSync(file, `${JSON.stringify({ schemaVersion: 2, rules: [] }, null, 2)}\n`, { mode: 0o600 });
101
+ return file;
102
+ }
103
+ /** 读原始文本(测试/排查用,避免被 loadRuleFile 的校验吞掉坏内容)。 */
104
+ export function readRawUserIntents(file) {
105
+ return readFileSync(file, 'utf8');
106
+ }
@@ -329,3 +329,50 @@ export function formatIssueSupportGroupSummary(input) {
329
329
  const restText = input.restCount > 0 ? `其余 ${input.restCount} 条按单条展示,` : '';
330
330
  return `含 ${input.count} 条已过期或今日到期的问题流程,${creatorText}${restText}${GROUP_SUMMARY_TAIL_TEXT}`;
331
331
  }
332
+ /**
333
+ * 用 JSON 里的模板渲染组摘要(2026-10-28 用户定:文案从 `aigroup/default.json` 的 `template` 读)。
334
+ *
335
+ * 支持占位符:`{{count}}` `{{restCount}}` `{{categoryCount}}` `{{categories}}` `{{min}}` `{{max}}`
336
+ * `{{sum}}` `{{creators}}` `{{tail}}` `{{maxChars}}`。
337
+ *
338
+ * 两条防空规则(不产生 `()` / `发起。` 这类残句):
339
+ * - 没有类别 ⇒ 整段 `({{categories}})` 删掉,`{{categoryCount}}` 至少为 1;
340
+ * - 没有发起人 ⇒ 整段 `{{creators}}发起。` / `{{creators}}发起,` 删掉。
341
+ */
342
+ export function renderGroupSummaryTemplate(input) {
343
+ let text = String(input.template ?? '');
344
+ if (!text.trim())
345
+ return '';
346
+ const allCategories = uniqueTexts(input.categories ?? []);
347
+ const shownCategories = allCategories.slice(0, 3);
348
+ const categoryCount = allCategories.length > 0 ? allCategories.length : 1;
349
+ const categories = shownCategories.length > 0
350
+ ? `${shownCategories.join('、')}${allCategories.length > shownCategories.length ? '等' : ''}`
351
+ : '';
352
+ const allCreators = normalizeCreators(input.creators ?? []);
353
+ const shownCreators = allCreators.slice(0, 3);
354
+ const creators = shownCreators.length > 0
355
+ ? `由${shownCreators.join('、')}${allCreators.length > 2 ? '等' : ''}`
356
+ : '';
357
+ if (!creators) {
358
+ text = text.replace(/\{\{creators\}\}发起[。,]/gu, '');
359
+ }
360
+ if (!categories) {
361
+ text = text.replace(/(\{\{categories\}\})/gu, '');
362
+ }
363
+ const amounts = (input.amounts ?? []).filter((value) => typeof value === 'number' && Number.isFinite(value));
364
+ const replaced = text
365
+ .replace(/\{\{count\}\}/gu, String(input.count))
366
+ .replace(/\{\{restCount\}\}/gu, String(input.restCount ?? 0))
367
+ .replace(/\{\{categoryCount\}\}/gu, String(categoryCount))
368
+ .replace(/\{\{categories\}\}/gu, categories)
369
+ .replace(/\{\{min\}\}/gu, amounts.length > 0 ? formatNumber(Math.min(...amounts)) : '')
370
+ .replace(/\{\{max\}\}/gu, amounts.length > 0 ? formatNumber(Math.max(...amounts)) : '')
371
+ .replace(/\{\{sum\}\}/gu, amounts.length > 0
372
+ ? formatNumber(Number(amounts.reduce((total, value) => total + value, 0).toFixed(2)))
373
+ : '')
374
+ .replace(/\{\{creators\}\}/gu, creators)
375
+ .replace(/\{\{tail\}\}/gu, input.tail);
376
+ // 空占位没有可填内容时,别把 `¥` / 逗号留在句子里
377
+ return replaced.replace(/¥(\s*)/gu, '').replace(/\s*,\s*,/gu, ',').trim();
378
+ }
@@ -1,12 +1,12 @@
1
+ import { activeRuleFor } from './aigroupRules.js';
1
2
  import { WORKFLOW_ENDPOINTS } from '../../endpoints.js';
2
3
  import { saveSearchIndex } from '../../state.js';
3
4
  import { buildSearchQuery } from '../read.js';
4
5
  import { projectDisplayRows } from './todoListRows.js';
5
6
  import { responseData } from '../shared.js';
6
7
  import { openSummaryCache, SUMMARY_CACHE_FILE_NAME } from './summaryCache.js';
7
- import { detectBusinessKind } from './businessRules.js';
8
8
  import { fetchDetailFacts, stampsOfRows } from './todoSmartConvert.detail.js';
9
- import { focusAppliesToKind, GROUP_MIN_ITEMS_FOR_SUBGROUP, isExpiringTodayRow, isOverdueRow, runGroup, } from './todoSmartConvert.group.js';
9
+ import { GROUP_MIN_ITEMS_FOR_SUBGROUP, isExpiringTodayRow, isOverdueRow, runGroup, } from './todoSmartConvert.group.js';
10
10
  import { DEFAULT_TABID, FETCH_PAGE_SIZE, LIST_ENDPOINT_BY_CATEGORY, MAX_FETCH_LIMIT, MAX_FETCH_PAGES, guardListOnlyHost, readBoundedInt, readCategory, readFetchLimit, readPageSize, rowFromAny, } from './todoSmartConvert.core.js';
11
11
  const DEFAULT_REQUEST_SUMMARY_MAX = 50;
12
12
  export async function collectRawTodos(args, env) {
@@ -170,7 +170,7 @@ export async function collectRawTodos(args, env) {
170
170
  const fieldsById = new Map();
171
171
  if (focusText) {
172
172
  const targetRows = wfIdGroup
173
- .filter((group) => !group.topPriority && focusAppliesToKind(focusText, detectBusinessKind(group.title)))
173
+ .filter((group) => !group.topPriority && activeRuleFor(group.title)?.aiGroup?.groupRule.aiContext === '流程详情')
174
174
  .flatMap((group) => group.requestDatas ?? []);
175
175
  const targetIds = [...new Set(targetRows.map((row) => row.requestId).filter(Boolean))];
176
176
  if (targetIds.length > 0) {
@@ -189,26 +189,33 @@ export async function collectRawTodos(args, env) {
189
189
  }
190
190
  }
191
191
  // 给模型的紧凑视图使用组内序号,aiGroups 可用 seq 引用。
192
- groupingBrief = wfIdGroup.map((group) => ({
193
- groupId: group.id,
194
- title: group.title,
195
- count: group.count,
196
- topPriority: group.topPriority,
197
- items: (group.requestDatas ?? []).map((row, index) => ({
198
- idx: index + 1,
199
- requestId: row.requestId,
200
- title: row.requestNameTitle ?? '',
201
- // 客户问题支持类无侧重点时按这两个布尔分组(模型不用自己解析日期文案)
202
- overdue: isOverdueRow(row),
203
- expiringToday: isExpiringTodayRow(row),
204
- ...(row.userOverTime ? { userOverTime: row.userOverTime } : {}),
205
- ...(row.summary ? { summary: row.summary } : {}),
206
- // `summaryCached:true` = 这条已有本地摘要(按 requestId__lastFeedBackDateTime 命中),
207
- // 分组仍要做(聚类看标题),但**不要再给它写摘要**。
208
- ...(cachedSummaryIds.has(row.requestId) ? { summaryCached: true } : {}),
209
- ...(fieldsById.has(row.requestId) ? { fields: fieldsById.get(row.requestId) } : {}),
210
- })),
211
- }));
192
+ groupingBrief = wfIdGroup.map((group) => {
193
+ const groupRule = activeRuleFor(group.title)?.aiGroup?.groupRule;
194
+ // 分组口径随素材一起下发:模型生成 aiGroups 时必须遵循(只有 focus=false 的语义分组才有意义)
195
+ const groupingPrompt = groupRule && groupRule.focus === false
196
+ && typeof groupRule.groupingPrompt === 'string' ? groupRule.groupingPrompt.trim() : '';
197
+ return {
198
+ groupId: group.id,
199
+ title: group.title,
200
+ count: group.count,
201
+ topPriority: group.topPriority,
202
+ ...(groupingPrompt ? { groupingPrompt } : {}),
203
+ items: (group.requestDatas ?? []).map((row, index) => ({
204
+ idx: index + 1,
205
+ requestId: row.requestId,
206
+ title: row.requestNameTitle ?? '',
207
+ // 客户问题支持类无侧重点时按这两个布尔分组(模型不用自己解析日期文案)
208
+ overdue: isOverdueRow(row),
209
+ expiringToday: isExpiringTodayRow(row),
210
+ ...(row.userOverTime ? { userOverTime: row.userOverTime } : {}),
211
+ ...(row.summary ? { summary: row.summary } : {}),
212
+ // `summaryCached:true` = 这条已有本地摘要(按 requestId__lastFeedBackDateTime 命中),
213
+ // 分组仍要做(聚类看标题),但**不要再给它写摘要**。
214
+ ...(cachedSummaryIds.has(row.requestId) ? { summaryCached: true } : {}),
215
+ ...(fieldsById.has(row.requestId) ? { fields: fieldsById.get(row.requestId) } : {}),
216
+ })),
217
+ };
218
+ });
212
219
  // 用户侧重点原样回显:分组/排序都按「标题语义 + 侧重点」,模型照它决定子组与顺序。
213
220
  const groupingFocus = typeof args.groupFocus === 'string' ? args.groupFocus.trim() : '';
214
221
  groupInfo = {
@@ -331,6 +331,7 @@ export function rowFromAny(raw) {
331
331
  lastFeedBackDateTime: pick([
332
332
  'lastFeedBackDateTime', 'lastfeedbackdatetime', 'lastFeedbackDateTime', 'lastfeedbacktime', 'lastFeedbackTime',
333
333
  ]) ?? '',
334
+ ...(pick(['planFinishDatetime', 'planfinishdatetime']) ? { planFinishDatetime: pick(['planFinishDatetime', 'planfinishdatetime']) } : {}),
334
335
  summary: pick(['summary']),
335
336
  workflowName: pick(['workflowName', 'workflowname', 'workflowTypeName'], true),
336
337
  receivedTime: pick(['receivedTime', 'receivedtime', 'receivedatetime', 'operatedatetime', 'stayStartAt']),
@@ -196,6 +196,7 @@ export function toRequestData(row) {
196
196
  creater: row.creater,
197
197
  createrName: row.createrName,
198
198
  lastFeedBackDateTime: row.lastFeedBackDateTime,
199
+ ...(row.planFinishDatetime ? { planFinishDatetime: row.planFinishDatetime } : {}),
199
200
  summary: row.summary ?? '',
200
201
  };
201
202
  }
@@ -1,3 +1,4 @@
1
+ import { activeRuleFor } from './aigroupRules.js';
1
2
  import { workflowValidationError } from '../../errors.js';
2
3
  import { asRecord, readBoundedInt } from './todoSmartConvert.core.js';
3
4
  import { detectBusinessKind, isDeterministicGroupKind, GROUP_SUMMARY_TAIL_TEXT, } from './businessRules.js';
@@ -191,7 +192,7 @@ export async function runGroupSummaryContext(args, env) {
191
192
  }
192
193
  const deterministicGroups = groups
193
194
  .filter((group) => !group.topPriority
194
- && isDeterministicGroupKind(detectBusinessKind(group.title)))
195
+ && activeRuleFor(group.title)?.aiGroup?.groupSummary.needAI === false)
195
196
  .reduce((sum, group) => sum + groupItemsOf(group).length, 0);
196
197
  return {
197
198
  data: {
@@ -25,7 +25,7 @@ const inputSchema = schemaOf({
25
25
  },
26
26
  aiGroups: {
27
27
  type: 'array',
28
- description: 'smartGroup 的二次分组计划。每项必须提供 groupId、title,以及 requestIds 与 seq 二选一。',
28
+ description: 'smartGroup 的二次分组计划。每项必须提供 groupId、title、requestIds。',
29
29
  items: {
30
30
  type: 'object',
31
31
  additionalProperties: false,
@@ -33,10 +33,8 @@ const inputSchema = schemaOf({
33
33
  groupId: { type: 'string' },
34
34
  title: { type: 'string' },
35
35
  requestIds: { type: 'array', minItems: 1, items: { type: 'string' } },
36
- seq: { type: 'array', minItems: 1, items: { type: 'integer', minimum: 1 } },
37
36
  },
38
- required: ['groupId', 'title'],
39
- oneOf: [{ required: ['requestIds'] }, { required: ['seq'] }],
37
+ required: ['groupId', 'title', 'requestIds'],
40
38
  },
41
39
  },
42
40
  aiSummaries: {