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
@@ -2,15 +2,22 @@ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
4
  createWorkflowHost
5
- } from "./chunk-WSKBSQ2U.js";
5
+ } from "./chunk-VPXOPQJI.js";
6
6
  import {
7
+ USER_INTENT_RULE_FILE,
8
+ aigroupUserDir,
7
9
  asObject,
8
10
  assertNoForbiddenKeys,
9
11
  compactStdoutPaths,
12
+ emptyRuleFile,
10
13
  getWorkflowOperation,
14
+ loadRuleFile,
15
+ loadRules,
16
+ resetActiveRules,
17
+ validateRuleFile,
11
18
  workflowOperationDefinitions,
12
19
  workflowSuccess
13
- } from "./chunk-WKI2FBIQ.js";
20
+ } from "./chunk-VPUTVEMC.js";
14
21
  import {
15
22
  createWorkflowContinuationSigner
16
23
  } from "./chunk-EZALDOQH.js";
@@ -21,8 +28,8 @@ import {
21
28
  } from "./chunk-FMPJJYYI.js";
22
29
  import "./chunk-EG6ZU444.js";
23
30
  import "./chunk-AJ62BGAW.js";
24
- import "./chunk-DW6AUUKS.js";
25
- import "./chunk-2GA5ZIQL.js";
31
+ import "./chunk-JUXVYKII.js";
32
+ import "./chunk-JNG42JKG.js";
26
33
  import {
27
34
  isCliError,
28
35
  toErrorEnvelope
@@ -82,6 +89,8 @@ function clarificationEnvelope(error, operation) {
82
89
  const candidates = Array.isArray(details.candidates) ? details.candidates : [];
83
90
  const question = typeof details.clarificationQuestion === "string" && details.clarificationQuestion ? details.clarificationQuestion : error.message;
84
91
  const reason = typeof details.clarificationReason === "string" ? details.clarificationReason : "";
92
+ const missingInput = Array.isArray(details.missingInput) ? details.missingInput.map(String) : [];
93
+ const requiredInput = details.requiredInput && typeof details.requiredInput === "object" ? details.requiredInput : null;
85
94
  return workflowSuccess(operation, {
86
95
  type: "workflowClarification",
87
96
  status: "NEEDS_CLARIFICATION",
@@ -89,6 +98,8 @@ function clarificationEnvelope(error, operation) {
89
98
  clarificationKeyword: details.clarificationKeyword ?? null,
90
99
  clarificationQuestion: question,
91
100
  ...reason ? { clarificationReason: reason } : {},
101
+ ...missingInput.length ? { missingInput } : {},
102
+ ...missingInput.length && requiredInput ? { requiredInput } : {},
92
103
  candidates,
93
104
  candidateCount: candidates.length,
94
105
  note: clarificationNote(reason, candidates.length)
@@ -96,6 +107,9 @@ function clarificationEnvelope(error, operation) {
96
107
  }
97
108
  function clarificationNote(reason, candidateCount) {
98
109
  const base = "\u8FD9\u4E0D\u662F\u5931\u8D25\uFF0C\u4E5F**\u4E0D\u4EE3\u8868\u67E5\u8BE2\u5DF2\u6267\u884C**\uFF1A\u672C\u6B21\u67E5\u8BE2\u5DF2\u505C\u6B62\uFF0C\u6CA1\u6709\u8FD4\u56DE\u4EFB\u4F55\u6D41\u7A0B\u6570\u636E\u3002";
110
+ if (reason === "workflow_required") {
111
+ return "\u672C\u6B21\u547D\u4EE4**\u6CA1\u6709\u62FF\u5230\u5FC5\u586B\u5165\u53C2 `workflow`**\uFF08\u6CA1\u5199\u8FD9\u4E2A\u952E\u3001\u7A7A\u6570\u7EC4\u3001\u7A7A\u5B57\u7B26\u4E32\u90FD\u7B97\u6CA1\u7ED9\uFF09\u2014\u2014\u547D\u4EE4\u505C\u5728\u4E86\u67E5\u8BE2\u4E4B\u524D\uFF1A**\u6CA1\u6709\u53D1\u8D77\u4EFB\u4F55\u6D41\u7A0B**\uFF0C\u4E5F\u6CA1\u6709\u53BB\u67E5\u53EF\u53D1\u8D77\u5217\u8868\uFF0C\u8FD9\u65E2\u4E0D\u662F\u6267\u884C\u5931\u8D25\uFF0C\u4E5F\u4E0D\u4EE3\u8868\u300C\u6CA1\u6709\u5339\u914D\u7684\u6D41\u7A0B\u300D\u3002\u8BF7\u5148\u5411\u7528\u6237\u786E\u8BA4\u8981\u53D1\u8D77\u54EA\u4E2A\u6D41\u7A0B\uFF08**\u5FC5\u987B\u95EE\uFF0C\u4E0D\u8981\u81EA\u5DF1\u731C\uFF0C\u4E5F\u4E0D\u8981\u62FF\u76F8\u4F3C\u7684\u540D\u5B57\u4EE3\u66FF**\uFF09\uFF0C\u518D\u6309 `requiredInput.workflow` \u7ED9\u51FA\u7684\u5F62\u6001\u628A\u5165\u53C2\u8865\u4E0A\u3001\u91CD\u53D1\u540C\u4E00\u6761\u547D\u4EE4\u3002\u6CE8\u610F `--input` \u63A5\u6536\u7684\u662F**\u6587\u4EF6\u8DEF\u5F84**\uFF08`-` \u8868\u793A\u6807\u51C6\u8F93\u5165\uFF09\uFF0C\u5185\u8054 JSON \u8981\u7528 `--input-json`\u3002";
112
+ }
99
113
  if (reason === "workflow_not_exist") {
100
114
  return base + '\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\uFF1A\u8BE5\u5DE5\u4F5C\u6D41\u4E0D\u5B58\u5728\uFF08\u53EF\u80FD\u5DF2\u5220\u9664\u6216\u88AB\u505C\u7528\uFF09\uFF0C\u8BF7\u7528\u6237\u6539\u7528\u8BE5\u6D41\u7A0B\u7684\u5B8C\u6574\u540D\u79F0\uFF08\u6216\u5176\u5B83\u53EF\u7528\u4E8E\u68C0\u7D22\u7684\u5173\u952E\u8BCD\uFF09\u91CD\u65B0\u6307\u5B9A\u2014\u2014**\u4E0D\u8981\u5411\u7528\u6237\u7D22\u53D6 ID**\u3002**\u4E0D\u8981**\u8BF4\u6210"\u6CA1\u6709\u53EF\u53D1\u8D77\u7684\u5DE5\u4F5C\u6D41"\u8FD9\u7C7B\u6A21\u7CCA\u8BF4\u6CD5\u2014\u2014\u95EE\u9898\u5C31\u51FA\u5728\u8FD9\u4E2A\u76EE\u6807\u4E0A\u3002';
101
115
  }
@@ -129,6 +143,86 @@ async function executeWorkflowOperation(operation, rawInput, context) {
129
143
  return result;
130
144
  }
131
145
 
146
+ // src/shortcuts/workflow/index.ts
147
+ import { join as join2 } from "node:path";
148
+
149
+ // src/shortcuts/workflow/operations/todoSmartConvert/aigroupStore.ts
150
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
151
+ import { join } from "node:path";
152
+ function normalizeIntentPayload(payload) {
153
+ if (Array.isArray(payload)) return payload;
154
+ if (payload && typeof payload === "object") {
155
+ const record = payload;
156
+ if (Array.isArray(record.rules)) return record.rules;
157
+ if (record.workflowName !== void 0) return [record];
158
+ }
159
+ throw workflowValidationError("aigroup_invalid", "\u5165\u53C2\u5FC5\u987B\u662F\u89C4\u5219\u5BF9\u8C61\u3001\u89C4\u5219\u6570\u7EC4\uFF0C\u6216 { rules: [...] }");
160
+ }
161
+ function namesOf(rule) {
162
+ const raw = rule?.workflowName;
163
+ if (typeof raw === "string") return [raw.trim()].filter(Boolean);
164
+ if (Array.isArray(raw)) return raw.map((item) => String(item ?? "").trim()).filter(Boolean);
165
+ return [];
166
+ }
167
+ function saveUserIntents(payload, options = {}) {
168
+ const dir = options.dir ?? aigroupUserDir(options.ctx);
169
+ const warnings = [];
170
+ const entries = normalizeIntentPayload(payload);
171
+ if (entries.length === 0) throw workflowValidationError("aigroup_invalid", "\u5165\u53C2\u91CC\u6CA1\u6709\u89C4\u5219\u6761\u76EE");
172
+ const starred = entries.filter((rule) => namesOf(rule).includes("*"));
173
+ if (starred.length > 0) {
174
+ throw workflowValidationError(
175
+ "aigroup_wildcard_unsupported",
176
+ "\u7528\u6237\u610F\u56FE\u4E0D\u80FD\u4F7F\u7528\u901A\u914D workflowName\u300C*\u300D\uFF1A\u515C\u5E95\u89C4\u5219\u7531 aigroup/default.json \u51B3\u5B9A"
177
+ );
178
+ }
179
+ const check = validateRuleFile({ schemaVersion: 2, defaults: {}, rules: entries });
180
+ if (check.length > 0) {
181
+ throw workflowValidationError("aigroup_invalid", `\u89C4\u5219\u6821\u9A8C\u5931\u8D25\uFF1A${check.join("\uFF1B")}`);
182
+ }
183
+ const file = join(dir, USER_INTENT_RULE_FILE);
184
+ const existing = existsSync(file) ? loadRuleFile(file) : emptyRuleFile();
185
+ if (existing.error) {
186
+ warnings.push(`${existing.error}\uFF1B\u672C\u6B21\u5C06\u91CD\u5EFA\u8BE5\u6587\u4EF6`);
187
+ }
188
+ const byName = /* @__PURE__ */ new Map();
189
+ const replaced = [];
190
+ for (const rule of existing.file.rules) {
191
+ for (const name of namesOf(rule)) byName.set(name, rule);
192
+ }
193
+ for (const rule of entries) {
194
+ const names = namesOf(rule);
195
+ for (const name of names) {
196
+ if (byName.has(name)) replaced.push(name);
197
+ byName.set(name, rule);
198
+ }
199
+ }
200
+ const merged = [...new Set(byName.values())];
201
+ const text = `${JSON.stringify({ schemaVersion: 2, rules: merged }, null, 2)}
202
+ `;
203
+ mkdirSync(dir, { recursive: true, mode: 448 });
204
+ writeFileSync(file, text, { mode: 384 });
205
+ return { file, saved: entries.length, total: merged.length, replaced: [...new Set(replaced)], warnings };
206
+ }
207
+ function readUserIntents(options = {}) {
208
+ const dir = options.dir ?? aigroupUserDir(options.ctx);
209
+ const file = join(dir, USER_INTENT_RULE_FILE);
210
+ if (!existsSync(file)) return { dir, file, exists: false, error: null, rules: [] };
211
+ const loaded = loadRuleFile(file);
212
+ return { dir, file, exists: true, error: loaded.error, rules: loaded.file.rules };
213
+ }
214
+ function clearUserIntents(options = {}) {
215
+ const dir = options.dir ?? aigroupUserDir(options.ctx);
216
+ const file = join(dir, USER_INTENT_RULE_FILE);
217
+ mkdirSync(dir, { recursive: true, mode: 448 });
218
+ writeFileSync(file, `${JSON.stringify({ schemaVersion: 2, rules: [] }, null, 2)}
219
+ `, { mode: 384 });
220
+ return file;
221
+ }
222
+ function readRawUserIntents(file) {
223
+ return readFileSync(file, "utf8");
224
+ }
225
+
132
226
  // src/shortcuts/workflow/index.ts
133
227
  function asOptions(value) {
134
228
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
@@ -218,6 +312,43 @@ async function executeAndPrint(ctx, operation, input) {
218
312
  process.exitCode = isCliError(error) ? error.exitCode : 1 /* GeneralError */;
219
313
  }
220
314
  }
315
+ function fieldNamesOf(inputSchema) {
316
+ const properties = inputSchema.properties;
317
+ if (!properties || typeof properties !== "object" || Array.isArray(properties)) return [];
318
+ return Object.keys(properties);
319
+ }
320
+ function manifestIndex() {
321
+ return {
322
+ schemaVersion: workflowManifest.schemaVersion,
323
+ name: workflowManifest.name,
324
+ title: workflowManifest.title,
325
+ version: workflowManifest.version,
326
+ host: workflowManifest.host,
327
+ status: workflowManifest.status,
328
+ sourceSkill: workflowManifest.sourceSkill,
329
+ capabilities: workflowManifest.capabilities,
330
+ operationCount: workflowManifest.operations.length,
331
+ operations: workflowManifest.operations.map((definition) => ({
332
+ name: definition.name,
333
+ resource: definition.resource,
334
+ summary: definition.summary,
335
+ ...definition.capability ? { capability: definition.capability } : {},
336
+ risk: definition.risk,
337
+ ...definition.requiresConfirmation ? { requiresConfirmation: true } : {},
338
+ fields: fieldNamesOf(definition.inputSchema)
339
+ })),
340
+ withheldOperations: workflowManifest.withheldOperations,
341
+ operationsHint: "\u9ED8\u8BA4\u53EA\u5217 operation \u4E0E\u5B57\u6BB5\u540D\uFF1B\u5B57\u6BB5\u7C7B\u578B\u3001\u679A\u4E3E\u548C\u586B\u5199\u53E3\u5F84\u7528 `workflow schema --operation <name>` \u5355\u53D6\uFF0C\u6574\u4EFD\u5B8C\u6574 manifest \u7528 `workflow schema --full`\u3002"
342
+ };
343
+ }
344
+ function findOperationContract(name) {
345
+ const full = name.startsWith("workflow.") ? name : `workflow.${name}`;
346
+ const matched = workflowManifest.operations.find((definition) => definition.name === full);
347
+ if (!matched) {
348
+ throw workflowValidationError("operation_unknown", `\u6D41\u7A0B\u6A21\u5757\u4E0D\u652F\u6301\u64CD\u4F5C\uFF1A${name}`);
349
+ }
350
+ return matched;
351
+ }
221
352
  function withJsonInputOptions(command) {
222
353
  command.option("--input <path>", "JSON input file, or - for stdin").option("--input-json <json>", "inline JSON input object");
223
354
  return command;
@@ -228,8 +359,50 @@ var workflowShortcut = {
228
359
  category: "shortcut",
229
360
  register({ program, action }) {
230
361
  const workflow = program.command("workflow").description("\u6CDB\u5FAEE10\u6D41\u7A0B\u667A\u80FD\u52A9\u624B\uFF08\u5F85\u529E/\u5DF2\u529E/\u6211\u53D1\u8D77/\u5168\u90E8\u3001\u8BE6\u60C5\u3001\u64CD\u4F5C\u3001\u6279\u91CF\u3001\u53D1\u8D77\u3001\u4FEE\u6539\uFF09");
231
- workflow.command("schema").description("Print workflow operation manifest for agents").action(action((ctx) => {
232
- ctx.output.write(workflowManifest, { json: true });
362
+ workflow.command("schema").description("Print workflow operation manifest for agents").option("--operation <name>", "print one operation with its full inputSchema").option("--full", "print the whole manifest (about 65 KB; stdout may be trimmed)").action(action((ctx, options) => {
363
+ const opts = asOptions(options);
364
+ const requested = String(opts.operation ?? "").trim();
365
+ if (requested && opts.full === true) {
366
+ throw workflowValidationError("option_conflict", "\u4E0D\u80FD\u540C\u65F6\u4F20 --operation \u548C --full");
367
+ }
368
+ if (opts.full === true) {
369
+ ctx.output.write(workflowManifest, { json: true });
370
+ return;
371
+ }
372
+ if (requested) {
373
+ ctx.output.write(findOperationContract(requested), { json: true });
374
+ return;
375
+ }
376
+ ctx.output.write(manifestIndex(), { json: true });
377
+ }));
378
+ const aigroup = workflow.command("aigroup").description("ai\u4E8C\u6B21\u5206\u7EC4\u89C4\u5219\u5E93\uFF08\u9ED8\u8BA4\u89C4\u5219 + \u7528\u6237\u610F\u56FE\uFF09");
379
+ aigroup.command("show").description("Print effective ai-group rules (default merged with user intents)").option("--raw", "also print user-intents.json as stored on disk").action(action((ctx, options) => {
380
+ const opts = asOptions(options);
381
+ const loaded = loadRules({ ctx });
382
+ const user = readUserIntents({ ctx });
383
+ ctx.output.write({
384
+ dir: loaded.dir,
385
+ defaultFile: join2(loaded.dir, "default.json"),
386
+ userIntentFile: user.file,
387
+ userIntentExists: user.exists,
388
+ userIntentError: user.error,
389
+ defaults: loaded.file.defaults,
390
+ rules: loaded.file.rules,
391
+ userRules: user.rules,
392
+ warnings: loaded.warnings,
393
+ ...opts.raw === true && user.exists ? { rawUserIntents: readRawUserIntents(user.file) } : {}
394
+ }, { json: true });
395
+ }));
396
+ withJsonInputOptions(aigroup.command("set").description("Save user-intent rules: validated, whole-entry replace by workflowName").action(action(async (ctx, options) => {
397
+ const payload = await inputFrom(options);
398
+ const result = saveUserIntents(payload, { ctx });
399
+ resetActiveRules();
400
+ ctx.output.write(result, { json: true });
401
+ })));
402
+ aigroup.command("clear").description("Empty user-intent rules (default.json is never touched)").action(action((ctx) => {
403
+ const file = clearUserIntents({ ctx });
404
+ resetActiveRules();
405
+ ctx.output.write({ cleared: true, file }, { json: true });
233
406
  }));
234
407
  withJsonInputOptions(workflow.command("run").description("Run a workflow operation with JSON input").argument("<operation>", "operation name, e.g. workflow.search")).action(action(async (ctx, operation, options) => {
235
408
  await executeAndPrint(ctx, String(operation), await inputFrom(options));
package/dist/index.js CHANGED
@@ -7,12 +7,12 @@ import {
7
7
  firstPositionalToken,
8
8
  registerCommands,
9
9
  toCommandMetadata
10
- } from "./chunks/chunk-6RKD4DRZ.js";
10
+ } from "./chunks/chunk-JYKABYCV.js";
11
11
  import "./chunks/chunk-EG6ZU444.js";
12
12
  import "./chunks/chunk-AJ62BGAW.js";
13
- import "./chunks/chunk-H7J4DC5R.js";
14
- import "./chunks/chunk-DW6AUUKS.js";
15
- import "./chunks/chunk-2GA5ZIQL.js";
13
+ import "./chunks/chunk-JCSN3JGM.js";
14
+ import "./chunks/chunk-JUXVYKII.js";
15
+ import "./chunks/chunk-JNG42JKG.js";
16
16
  import "./chunks/chunk-LUSPKZKY.js";
17
17
  import "./chunks/chunk-BUSC6UAE.js";
18
18
 
@@ -29,7 +29,7 @@ function lazyShortcut(definition) {
29
29
  placeholder.allowExcessArguments(true);
30
30
  placeholder.helpOption(false);
31
31
  placeholder.action(async () => {
32
- const { dispatchLazyShortcut } = await import("./chunks/lazy-dispatch-JQXBW3GM.js");
32
+ const { dispatchLazyShortcut } = await import("./chunks/lazy-dispatch-QXW7P4X3.js");
33
33
  await dispatchLazyShortcut(definition, shortcutMetadata());
34
34
  });
35
35
  }
@@ -39,102 +39,112 @@ var builtinShortcuts = [
39
39
  lazyShortcut({
40
40
  name: "invoice",
41
41
  description: "E10 \u4E1A\u7968\u901A\u53D1\u7968\u7BA1\u7406 CLI",
42
- load: async () => (await import("./chunks/invoice-ZK3WCX2U.js")).invoiceShortcut
42
+ load: async () => (await import("./chunks/invoice-2Z6YPMIS.js")).invoiceShortcut
43
43
  }),
44
44
  lazyShortcut({
45
45
  name: "ehr",
46
46
  description: "\u6CDB\u5FAEE10\u805A\u624D\u6797\uFF08\u4EBA\u4E8B/\u51FA\u52E4/\u85AA\u916C\uFF09CLI",
47
- load: async () => (await import("./chunks/ehr-HMFY6VIL.js")).ehrShortcut
47
+ load: async () => (await import("./chunks/ehr-EAP77IMT.js")).ehrShortcut
48
+ }),
49
+ lazyShortcut({
50
+ name: "cowork",
51
+ description: "\u6CDB\u5FAEE10\u534F\u4F5C\u533A\uFF08\u534F\u4F5C\u4E8B\u9879/\u8BA8\u8BBA/\u5BA1\u6279/\u5171\u4EAB\u6743\u9650\uFF09CLI",
52
+ load: async () => (await import("./chunks/cowork-SCPGLBA4.js")).coworkShortcut
48
53
  }),
49
54
  lazyShortcut({
50
55
  name: "archive",
51
56
  description: "E10 \u6587\u4E66\u5B9A\u6863\u6848\u7BA1\u7406 CLI",
52
- load: async () => (await import("./chunks/archive-UMGX72K6.js")).archiveShortcut
57
+ load: async () => (await import("./chunks/archive-XBVH7JU7.js")).archiveShortcut
53
58
  }),
54
59
  lazyShortcut({
55
60
  name: "archive-oa",
56
61
  description: "E10 \u6863\u6848\u5B9A\u4F4D\u4E0E OA \u5546\u52A1\u5408\u540C\u501F\u9605 CLI",
57
- load: async () => (await import("./chunks/archive-oa-N2IYBLF3.js")).archiveOaShortcut
62
+ load: async () => (await import("./chunks/archive-oa-MZM3EKFQ.js")).archiveOaShortcut
58
63
  }),
59
64
  lazyShortcut({
60
65
  name: "calendar",
61
66
  description: "\u6CDB\u5FAEE10\u65E5\u7A0B\u7BA1\u7406 CLI\uFF08\u521B\u5EFA/\u67E5\u8BE2/\u66F4\u65B0/\u5220\u9664/\u5B57\u5178\uFF09",
62
- load: async () => (await import("./chunks/calendar-JKPIRKFD.js")).calendarShortcut
67
+ load: async () => (await import("./chunks/calendar-MXEMTIO4.js")).calendarShortcut
63
68
  }),
64
69
  lazyShortcut({
65
70
  name: "fna",
66
71
  description: "\u6CDB\u5FAEE10\u9F50\u4E1A\u6210\u8D39\u63A7\u4E2D\u5FC3\uFF08\u9884\u7B97/\u8D39\u7528\u4E2D\u5FC3/\u501F\u6B3E\u7BA1\u7406/\u53D1\u7968\u6838\u9500\uFF09CLI",
67
- load: async () => (await import("./chunks/fna-B7RKPAZD.js")).fnaShortcut
72
+ load: async () => (await import("./chunks/fna-2X7ZE7BU.js")).fnaShortcut
68
73
  }),
69
74
  lazyShortcut({
70
75
  name: "hrm",
71
76
  description: "\u6CDB\u5FAEE10\u7EC4\u7EC7\u7BA1\u7406\uFF08\u5458\u5DE5/\u7EC4\u7EC7/\u5C97\u4F4D\u67E5\u8BE2\uFF09CLI",
72
- load: async () => (await import("./chunks/hrm-2KAZGUHI.js")).hrmShortcut
77
+ load: async () => (await import("./chunks/hrm-YXERJM76.js")).hrmShortcut
73
78
  }),
74
79
  lazyShortcut({
75
80
  name: "mail",
76
81
  description: "\u6CDB\u5FAEE10\u90AE\u4EF6\u7BA1\u7406 CLI",
77
- load: async () => (await import("./chunks/mail-S2HDDXO2.js")).mailShortcut
82
+ load: async () => (await import("./chunks/mail-7GZ6CPBJ.js")).mailShortcut
78
83
  }),
79
84
  lazyShortcut({
80
85
  name: "meeting",
81
86
  description: "\u6CDB\u5FAEE10\u4F1A\u8BAE\u7BA1\u7406 CLI\uFF08\u6807\u51C6\u7248\uFF1A\u67E5\u8BE2/\u51B2\u7A81/\u9884\u7EA6/\u56DE\u6267/\u7B7E\u5230\uFF09",
82
- load: async () => (await import("./chunks/meeting-QVN3I37L.js")).meetingShortcut
87
+ load: async () => (await import("./chunks/meeting-3NMGA3MB.js")).meetingShortcut
83
88
  }),
84
89
  lazyShortcut({
85
90
  name: "okr",
86
91
  description: "\u6CDB\u5FAEE10 OKR \u76EE\u6807\u7BA1\u7406 CLI\uFF08\u76EE\u6807\u67E5\u8BE2/\u65B0\u5EFA/\u7F16\u8F91\u3001\u5173\u952E\u6210\u679C\u3001\u76EE\u6807\u5BF9\u9F50\u3001\u8BC4\u8BBA\uFF09",
87
- load: async () => (await import("./chunks/okr-QNG4VC2Q.js")).okrShortcut
92
+ load: async () => (await import("./chunks/okr-BZ6XUOAG.js")).okrShortcut
88
93
  }),
89
94
  lazyShortcut({
90
95
  name: "plan",
91
96
  description: "\u6CDB\u5FAEE10\u8BA1\u5212\u62A5\u544A CLI\uFF08\u67E5\u8BE2/\u65B0\u5EFA/\u4FEE\u6539/\u53D1\u5E03/\u64A4\u56DE/\u63D0\u4EA4\u63D0\u9192/\u8BC4\u8BBA\uFF09",
92
- load: async () => (await import("./chunks/plan-A25EMW6U.js")).planShortcut
97
+ load: async () => (await import("./chunks/plan-DR5CMUYP.js")).planShortcut
93
98
  }),
94
99
  lazyShortcut({
95
100
  name: "esb",
96
101
  description: "\u6CDB\u5FAEE10 ESB \u4E2D\u5FC3\u81EA\u5B9A\u4E49\u89E6\u53D1\u52A8\u4F5C\u6D41 CLI",
97
- load: async () => (await import("./chunks/esb-ZYSVB7SG.js")).esbShortcut
102
+ load: async () => (await import("./chunks/esb-2TGGXEE7.js")).esbShortcut
98
103
  }),
99
104
  lazyShortcut({
100
105
  name: "ebuilder-form",
101
106
  description: "\u6CDB\u5FAEE10 eBuilder \u8868\u5355\u83DC\u5355\u3001\u5217\u8868\u548C\u8868\u5355\u6570\u636E CLI",
102
- load: async () => (await import("./chunks/ebuilder-form-V5FG2EHC.js")).ebuilderFormShortcut
107
+ load: async () => (await import("./chunks/ebuilder-form-EYLHNOTA.js")).ebuilderFormShortcut
103
108
  }),
104
109
  lazyShortcut({
105
110
  name: "jiuchuanhui",
106
111
  description: "\u6CDB\u5FAEE10\u4E5D\u6C1A\u6C47\u8425\u9500\u7BA1\u7406 CLI\uFF08\u5BA2\u6237/\u8054\u7CFB\u4EBA/\u5546\u673A/\u7EBF\u7D22/\u8054\u7CFB\u8BA1\u5212/\u516C\u6D77\uFF09",
107
- load: async () => (await import("./chunks/jiuchuanhui-5PQD3IL2.js")).jiuchuanhuiShortcut
112
+ load: async () => (await import("./chunks/jiuchuanhui-AR5GMKZB.js")).jiuchuanhuiShortcut
108
113
  }),
109
114
  lazyShortcut({
110
115
  name: "asset",
111
116
  description: "E10 \u8D44\u4EA7\u7BA1\u7406\uFF08\u8D44\u7BA1\u5BB6\uFF09CLI",
112
- load: async () => (await import("./chunks/asset-GLEGKFG5.js")).assetShortcut
117
+ load: async () => (await import("./chunks/asset-4XO7UOUW.js")).assetShortcut
113
118
  }),
114
119
  lazyShortcut({
115
120
  name: "im",
116
121
  description: "\u6CDB\u5FAEE10\u6613\u79D2\u529E\uFF08\u5373\u65F6\u901A\u8BAF\uFF09CLI",
117
- load: async () => (await import("./chunks/im-ACJJWH4U.js")).imShortcut
122
+ load: async () => (await import("./chunks/im-A4VZN2TQ.js")).imShortcut
118
123
  }),
119
124
  lazyShortcut({
120
125
  name: "project",
121
126
  description: "\u6CDB\u5FAEE10\u4E8B\u4E95\u7136\u9879\u76EE\u7BA1\u7406 CLI\uFF08\u9879\u76EE/\u4EFB\u52A1\u67E5\u8BE2\u4E0E\u786E\u8BA4\u5199\u5165\uFF09",
122
- load: async () => (await import("./chunks/project-G6XV66DZ.js")).projectShortcut
127
+ load: async () => (await import("./chunks/project-6J63MK33.js")).projectShortcut
123
128
  }),
124
129
  lazyShortcut({
125
130
  name: "workflow",
126
131
  description: "\u6CDB\u5FAEE10\u6D41\u7A0B\u667A\u80FD\u52A9\u624B CLI\uFF08\u67E5\u8BE2/\u67E5\u770B/\u64CD\u4F5C/\u6279\u91CF/\u53D1\u8D77/\u4FEE\u6539\uFF09",
127
- load: async () => (await import("./chunks/workflow-DJ7SYWAF.js")).workflowShortcut
132
+ load: async () => (await import("./chunks/workflow-D74NFK3C.js")).workflowShortcut
128
133
  }),
129
134
  lazyShortcut({
130
135
  name: "blog",
131
136
  description: "\u6CDB\u5FAEE10\u5DE5\u4F5C\u65E5\u62A5 CLI\uFF08\u67E5\u8BE2/\u53D1\u5E03/\u7F16\u8F91/\u8BC4\u8BBA/\u70B9\u8D5E/\u63D0\u9192/\u5BFC\u51FA\uFF09",
132
- load: async () => (await import("./chunks/blog-E44OTVDA.js")).blogShortcut
137
+ load: async () => (await import("./chunks/blog-PGZKOPSC.js")).blogShortcut
133
138
  }),
134
139
  lazyShortcut({
135
140
  name: "caizhilian",
136
141
  description: "\u6CDB\u5FAEE10\u91C7\u77E5\u8FDE\uFF08\u6587\u6863\u4E2D\u5FC3\uFF09CLI",
137
- load: async () => (await import("./chunks/caizhilian-DQUFZXZL.js")).caizhilianShortcut
142
+ load: async () => (await import("./chunks/caizhilian-BH4ZVGUN.js")).caizhilianShortcut
143
+ }),
144
+ lazyShortcut({
145
+ name: "contract",
146
+ description: "\u6CDB\u5FAEE10\u4ECA\u627F\u8FBE\u5408\u540C\u7BA1\u7406 CLI",
147
+ load: async () => (await import("./chunks/contract-XI2EEIZU.js")).contractShortcut
138
148
  })
139
149
  ];
140
150
  function shortcutMetadata() {
@@ -1,3 +1,4 @@
1
+ import { isXiaoERuntimeAgent } from '../../core/runtime-agent.js';
1
2
  import { getActiveProfile } from './auth/session.js';
2
3
  import { hasXiaoEEnv, tryXiaoEUnifiedLogin } from './auth/xiaoe.js';
3
4
  const AUTH_REQUIRED_CODES = new Set(['-2', '401']);
@@ -94,12 +95,21 @@ export function isE10AuthenticationRequired(response) {
94
95
  function globalOptions(ctx) {
95
96
  return typeof ctx.getGlobalOptions === 'function' ? ctx.getGlobalOptions() : {};
96
97
  }
97
- /** XiaoE automatic recovery is opt-in through explicit runtime evidence. */
98
- export function canAutomaticallyRecoverXiaoE(ctx) {
98
+ /**
99
+ * Decide whether an expired session can be recovered through XiaoE without
100
+ * involving the caller/Agent. Runtime evidence is preferred, but a persisted
101
+ * XiaoE login is also authoritative: business commands often run in a fresh
102
+ * process where the host no longer injects its original XIAOE_* markers.
103
+ */
104
+ export function canAutomaticallyRecoverXiaoE(ctx, currentSession) {
99
105
  const options = globalOptions(ctx);
100
106
  // An explicitly supplied auth file is caller-owned and must not be replaced
101
107
  // by a profile-backed XiaoE session behind the caller's back.
102
- return !options.auth && hasXiaoEEnv(ctx.env || process.env, options);
108
+ if (options.auth)
109
+ return false;
110
+ return hasXiaoEEnv(ctx.env || process.env, options)
111
+ || currentSession?.loginSource === 'xiaoe-unified'
112
+ || isXiaoERuntimeAgent(currentSession?.agentType);
103
113
  }
104
114
  /**
105
115
  * Silently refresh a stale XiaoE session. Concurrent requests for the same
@@ -107,7 +117,7 @@ export function canAutomaticallyRecoverXiaoE(ctx) {
107
117
  * does not start a burst of login attempts.
108
118
  */
109
119
  export async function recoverXiaoEAuthSession(ctx, currentSession) {
110
- if (!canAutomaticallyRecoverXiaoE(ctx))
120
+ if (!canAutomaticallyRecoverXiaoE(ctx, currentSession))
111
121
  return null;
112
122
  const options = globalOptions(ctx);
113
123
  const profile = options.profile || getActiveProfile();
@@ -0,0 +1,31 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ const storage = new AsyncLocalStorage();
3
+ export function createFetchTimingSink() {
4
+ return { fetchMs: 0, fetchCount: 0, fetchStart: null, fetchEnd: null };
5
+ }
6
+ /** 在 `sink` 的上下文里执行 `fn`:期间发生的 fetch 都会记到它上面。 */
7
+ export function runWithFetchTiming(sink, fn) {
8
+ return storage.run(sink, fn);
9
+ }
10
+ /**
11
+ * fetch 前调一次,拿到的结束函数在 fetch 落定(成功或失败)时调一次。
12
+ * 返回 `null` 表示当前没有 sink(非计时路径)⇒ 调用方跳过全部计时动作。
13
+ */
14
+ export function startFetchTiming() {
15
+ const sink = storage.getStore();
16
+ if (!sink)
17
+ return null;
18
+ const startedAt = Date.now();
19
+ let finished = false;
20
+ return () => {
21
+ if (finished)
22
+ return;
23
+ finished = true;
24
+ const endedAt = Date.now();
25
+ sink.fetchMs += Math.max(0, endedAt - startedAt);
26
+ sink.fetchCount += 1;
27
+ // 重试会有多次 fetch:起点取最早、终点取最晚,中间的空档(如换票据)不计入 fetchCost。
28
+ sink.fetchStart = sink.fetchStart === null ? startedAt : Math.min(sink.fetchStart, startedAt);
29
+ sink.fetchEnd = sink.fetchEnd === null ? endedAt : Math.max(sink.fetchEnd, endedAt);
30
+ };
31
+ }
@@ -1,5 +1,6 @@
1
1
  import { CliError, ExitCode } from '../../core/errors.js';
2
2
  import { isE10AuthenticationRequired, recoverXiaoEAuthSession, sameE10SessionIdentity, } from './auth-recovery.js';
3
+ import { startFetchTiming } from './fetch-timing.js';
3
4
  const DEFAULT_TIMEOUT_MS = 30_000;
4
5
  const DEFAULT_BIG_INT_STRINGS = true;
5
6
  const RESERVED_HEADERS = [
@@ -220,6 +221,9 @@ export class E10RequestRuntime {
220
221
  async fetchWithTimeout(url, init, timeoutMs) {
221
222
  const controller = new AbortController();
222
223
  const timer = setTimeout(() => controller.abort(), timeoutMs);
224
+ // 「纯 fetch」= 发出请求 → 收到响应头(`fetch` 落定那一刻,不含读响应体/解析)。没有计时上下文
225
+ // (`startFetchTiming()` 返回 `null`)时它什么都不做,非计时路径零开销。
226
+ const stopFetchTiming = startFetchTiming();
223
227
  try {
224
228
  return await this.fetchFn(url, { ...init, signal: controller.signal });
225
229
  }
@@ -238,6 +242,7 @@ export class E10RequestRuntime {
238
242
  }
239
243
  finally {
240
244
  clearTimeout(timer);
245
+ stopFetchTiming?.();
241
246
  }
242
247
  }
243
248
  async readResponse(response, responseType, bigIntStrings = DEFAULT_BIG_INT_STRINGS, maxResponseBytes, timeoutMs = DEFAULT_TIMEOUT_MS) {
@@ -3,6 +3,7 @@ import { basename } from 'node:path';
3
3
  import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js';
4
4
  import { requireE10Session } from '../../internal/e10/context.js';
5
5
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
6
+ import { E10ApiError, createE10RequestRuntime, } from '../../internal/e10/request-runtime.js';
6
7
  import { ContractCliError, contractAuthError, contractNetworkError, contractValidationError, } from './errors.js';
7
8
  const DEFAULT_TIMEOUT_MS = 30_000;
8
9
  function assertPath(requestPath) {
@@ -16,38 +17,6 @@ function assertPath(requestPath) {
16
17
  throw contractValidationError('path_not_allowed', '今承达合同管理只能调用 /api/ 路径');
17
18
  }
18
19
  }
19
- function withQuery(baseUrl, requestPath, query = {}) {
20
- const url = new URL(`${baseUrl}${requestPath}`);
21
- for (const [key, value] of Object.entries(query)) {
22
- if (value === undefined || value === null || value === '')
23
- continue;
24
- if (Array.isArray(value)) {
25
- for (const item of value)
26
- url.searchParams.append(key, String(item));
27
- }
28
- else {
29
- url.searchParams.set(key, String(value));
30
- }
31
- }
32
- return url;
33
- }
34
- async function fetchWithTimeout(url, options, timeoutMs) {
35
- const controller = new AbortController();
36
- const timer = setTimeout(() => controller.abort(), timeoutMs);
37
- try {
38
- return await fetch(url, { ...options, signal: controller.signal, redirect: 'manual' });
39
- }
40
- catch (error) {
41
- if (error instanceof Error && error.name === 'AbortError') {
42
- throw contractNetworkError('timeout', `请求超时(${timeoutMs}ms)`, { retryable: false });
43
- }
44
- const message = error instanceof Error ? error.message : String(error);
45
- throw contractNetworkError('transport', `请求失败:${message}`, { retryable: true });
46
- }
47
- finally {
48
- clearTimeout(timer);
49
- }
50
- }
51
20
  function textOf(value, keys) {
52
21
  for (const key of keys) {
53
22
  const candidate = value?.[key];
@@ -131,15 +100,6 @@ function inferProfile(ctx) {
131
100
  const options = ctx.getGlobalOptions();
132
101
  return options.profile || getActiveProfile();
133
102
  }
134
- function requestHeaders(session) {
135
- return {
136
- Accept: 'application/json, text/plain, */*',
137
- Cookie: session.cookieHeader(),
138
- eteamsid: session.eteamsId,
139
- 'User-Agent': session.uaHeader(),
140
- Origin: session.getBaseUrl(),
141
- };
142
- }
143
103
  export function createContractHost(ctx, dependencies = {}) {
144
104
  let e10Session = null;
145
105
  let sessionContext = null;
@@ -164,10 +124,9 @@ export function createContractHost(ctx, dependencies = {}) {
164
124
  assertPath(path);
165
125
  const session = await ensureSession();
166
126
  const context = await getSession();
167
- const headers = { ...requestHeaders(session), ...(extraHeaders ?? {}) };
168
- const finalQuery = { ...query };
127
+ const finalQuery = Object.fromEntries(Object.entries(query).filter(([, value]) => value !== undefined && value !== null && value !== ''));
169
128
  let finalBody = body;
170
- const init = { method, headers };
129
+ let formData;
171
130
  if (userIdField) {
172
131
  if (!context.userId) {
173
132
  throw contractAuthError('user_id_missing', '当前会话没有可用的用户 ID,请确认 E10 登录态');
@@ -178,9 +137,9 @@ export function createContractHost(ctx, dependencies = {}) {
178
137
  finalBody = { ...finalBody, [userIdField]: context.userId };
179
138
  }
180
139
  if (form || file) {
181
- const data = new FormData();
140
+ formData = new FormData();
182
141
  for (const [key, value] of Object.entries(form ?? {}))
183
- data.append(key, value);
142
+ formData.append(key, value);
184
143
  if (file) {
185
144
  let buffer;
186
145
  try {
@@ -190,25 +149,41 @@ export function createContractHost(ctx, dependencies = {}) {
190
149
  throw contractValidationError('file_unreadable', `无法读取文件:${file.path}`);
191
150
  }
192
151
  const filename = file.filename ?? basename(file.path);
193
- data.append(file.field ?? 'file', new Blob([new Uint8Array(buffer)], { type: file.contentType ?? 'application/octet-stream' }), filename);
152
+ formData.append(file.field ?? 'file', new Blob([new Uint8Array(buffer)], { type: file.contentType ?? 'application/octet-stream' }), filename);
194
153
  }
195
- init.body = data;
196
154
  }
197
- else if (finalBody !== undefined) {
198
- headers['Content-Type'] = 'application/json;charset=UTF-8';
199
- init.body = JSON.stringify(finalBody);
155
+ const runtime = createE10RequestRuntime(ctx, session, {
156
+ interceptors: dependencies.interceptors,
157
+ fetch: dependencies.fetch,
158
+ recoverAuthentication: dependencies.recoverAuthentication,
159
+ });
160
+ let response;
161
+ try {
162
+ response = await runtime.requestJson({
163
+ module: 'contract',
164
+ method,
165
+ path,
166
+ query: finalQuery,
167
+ body: formData ? undefined : finalBody,
168
+ formData,
169
+ headers: extraHeaders,
170
+ timeoutMs,
171
+ });
172
+ }
173
+ catch (error) {
174
+ if (error instanceof E10ApiError && error.type === 'network') {
175
+ throw contractNetworkError(error.subtype, error.message, {
176
+ retryable: error.retryable,
177
+ details: error.details,
178
+ });
179
+ }
180
+ throw error;
200
181
  }
201
- const url = withQuery(context.baseUrl, path, finalQuery);
202
- const response = await fetchWithTimeout(url, init, timeoutMs);
203
182
  if (response.status === 401 || response.status === 302) {
204
183
  throw contractAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status, path });
205
184
  }
206
- const text = await response.text();
207
- let value = {};
208
- try {
209
- value = text ? JSON.parse(text) : {};
210
- }
211
- catch {
185
+ const { text, value } = response;
186
+ if (response.parseError) {
212
187
  throw contractNetworkError('protocol', `接口返回不是合法 JSON(HTTP ${response.status})`, {
213
188
  retryable: false,
214
189
  details: { path, status: response.status },