weaver-work-cli 0.1.8 → 0.1.20

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 (263) hide show
  1. package/README.md +11 -11
  2. package/dist/cmd/action.js +76 -0
  3. package/dist/cmd/index.js +2 -0
  4. package/dist/cmd/refs/index.js +103 -0
  5. package/dist/cmd/register.js +31 -0
  6. package/dist/cmd/root.js +1 -0
  7. package/dist/cmd/setup/index.js +25 -5
  8. package/dist/cmd/skills/index.js +37 -5
  9. package/dist/core/connector.js +54 -0
  10. package/dist/core/context.js +2 -1
  11. package/dist/core/input.js +48 -0
  12. package/dist/core/output.js +298 -3
  13. package/dist/core/refs.js +432 -0
  14. package/dist/core/state.js +26 -0
  15. package/dist/internal/e10/auth/commands.js +2 -2
  16. package/dist/internal/e10/auth/session.js +14 -0
  17. package/dist/internal/e10/auth/xiaoe.js +116 -51
  18. package/dist/internal/e10/request-runtime.js +5 -0
  19. package/dist/internal/skills/install.js +148 -28
  20. package/dist/internal/skills/reader.js +12 -9
  21. package/dist/shortcuts/blog/continuation.js +74 -0
  22. package/dist/shortcuts/blog/errors.js +60 -0
  23. package/dist/shortcuts/blog/host.js +175 -0
  24. package/dist/shortcuts/blog/index.js +324 -0
  25. package/dist/shortcuts/blog/manifest.js +415 -0
  26. package/dist/shortcuts/blog/operations/comment.js +125 -0
  27. package/dist/shortcuts/blog/operations/comments.js +31 -0
  28. package/dist/shortcuts/blog/operations/edit.js +131 -0
  29. package/dist/shortcuts/blog/operations/export.js +46 -0
  30. package/dist/shortcuts/blog/operations/like.js +80 -0
  31. package/dist/shortcuts/blog/operations/publish.js +157 -0
  32. package/dist/shortcuts/blog/operations/query-user.js +58 -0
  33. package/dist/shortcuts/blog/operations/query.js +96 -0
  34. package/dist/shortcuts/blog/operations/registry.js +54 -0
  35. package/dist/shortcuts/blog/operations/remind.js +176 -0
  36. package/dist/shortcuts/blog/operations/shared.js +330 -0
  37. package/dist/shortcuts/blog/operations/types.js +16 -0
  38. package/dist/shortcuts/blog/operations.js +9 -0
  39. package/dist/shortcuts/caizhilian/continuation.js +70 -0
  40. package/dist/shortcuts/caizhilian/errors.js +53 -0
  41. package/dist/shortcuts/caizhilian/host.js +190 -0
  42. package/dist/shortcuts/caizhilian/index.js +186 -0
  43. package/dist/shortcuts/caizhilian/manifest.js +42 -0
  44. package/dist/shortcuts/caizhilian/operations/api.js +801 -0
  45. package/dist/shortcuts/caizhilian/operations/confirm.js +75 -0
  46. package/dist/shortcuts/caizhilian/operations/files.js +306 -0
  47. package/dist/shortcuts/caizhilian/operations/form.js +170 -0
  48. package/dist/shortcuts/caizhilian/operations/handlers/collab.js +611 -0
  49. package/dist/shortcuts/caizhilian/operations/handlers/document.js +890 -0
  50. package/dist/shortcuts/caizhilian/operations/handlers/file-collection.js +346 -0
  51. package/dist/shortcuts/caizhilian/operations/handlers/file-upload.js +192 -0
  52. package/dist/shortcuts/caizhilian/operations/handlers/fileops.js +570 -0
  53. package/dist/shortcuts/caizhilian/operations/handlers/folder.js +969 -0
  54. package/dist/shortcuts/caizhilian/operations/handlers/search.js +318 -0
  55. package/dist/shortcuts/caizhilian/operations/handlers/setting-attach.js +294 -0
  56. package/dist/shortcuts/caizhilian/operations/handlers/setting-backup.js +423 -0
  57. package/dist/shortcuts/caizhilian/operations/handlers/setting-encrypt.js +238 -0
  58. package/dist/shortcuts/caizhilian/operations/handlers/setting-storage.js +364 -0
  59. package/dist/shortcuts/caizhilian/operations/handlers/system.js +106 -0
  60. package/dist/shortcuts/caizhilian/operations/registry.js +151 -0
  61. package/dist/shortcuts/caizhilian/operations/shared.js +408 -0
  62. package/dist/shortcuts/caizhilian/operations/specs.js +623 -0
  63. package/dist/shortcuts/caizhilian/operations/types.js +57 -0
  64. package/dist/shortcuts/caizhilian/operations.js +21 -0
  65. package/dist/shortcuts/contract/continuation.js +70 -0
  66. package/dist/shortcuts/contract/errors.js +62 -0
  67. package/dist/shortcuts/contract/host.js +205 -0
  68. package/dist/shortcuts/contract/index.js +318 -0
  69. package/dist/shortcuts/contract/manifest.js +596 -0
  70. package/dist/shortcuts/contract/operations/clause-reference.js +78 -0
  71. package/dist/shortcuts/contract/operations/form-info.js +371 -0
  72. package/dist/shortcuts/contract/operations/read.js +118 -0
  73. package/dist/shortcuts/contract/operations/registry.js +43 -0
  74. package/dist/shortcuts/contract/operations/request.js +300 -0
  75. package/dist/shortcuts/contract/operations/shared.js +133 -0
  76. package/dist/shortcuts/contract/operations/subject.js +157 -0
  77. package/dist/shortcuts/contract/operations/template.js +81 -0
  78. package/dist/shortcuts/contract/operations/types.js +7 -0
  79. package/dist/shortcuts/contract/operations/workflow.js +52 -0
  80. package/dist/shortcuts/contract/operations/write.js +131 -0
  81. package/dist/shortcuts/contract/operations.js +8 -0
  82. package/dist/shortcuts/hrm/index.js +83 -2
  83. package/dist/shortcuts/hrm/operations/employee.js +160 -30
  84. package/dist/shortcuts/hrm/operations/org.js +17 -3
  85. package/dist/shortcuts/hrm/operations/position.js +18 -2
  86. package/dist/shortcuts/index.js +5 -1
  87. package/dist/shortcuts/invoice/index.js +74 -36
  88. package/dist/shortcuts/invoice/manifest.js +674 -4
  89. package/dist/shortcuts/invoice/markdown.js +172 -0
  90. package/dist/shortcuts/invoice/operations/add.js +3 -3
  91. package/dist/shortcuts/invoice/operations/delete.js +2 -2
  92. package/dist/shortcuts/invoice/operations/get.js +10 -2
  93. package/dist/shortcuts/invoice/operations/import.js +2 -2
  94. package/dist/shortcuts/invoice/operations/registry.js +8 -1
  95. package/dist/shortcuts/invoice/operations/reim-auto.js +719 -0
  96. package/dist/shortcuts/invoice/operations/reim.js +85 -2
  97. package/dist/shortcuts/invoice/operations/shared.js +75 -8
  98. package/dist/shortcuts/invoice/operations/update.js +2 -2
  99. package/dist/shortcuts/invoice/operations/upload-and-validate.js +93 -0
  100. package/dist/shortcuts/invoice/operations/validate-preview.js +2 -1
  101. package/dist/shortcuts/invoice/projection.js +328 -0
  102. package/dist/shortcuts/meeting/host.js +18 -1
  103. package/dist/shortcuts/meeting/manifest.js +30 -18
  104. package/dist/shortcuts/meeting/operations/eb/catalog.js +390 -0
  105. package/dist/shortcuts/meeting/operations/eb/conflict.js +389 -0
  106. package/dist/shortcuts/meeting/operations/eb/factory.js +389 -0
  107. package/dist/shortcuts/meeting/operations/eb/index.js +22 -0
  108. package/dist/shortcuts/meeting/operations/env.js +8 -1
  109. package/dist/shortcuts/meeting/operations/registry.js +2 -0
  110. package/dist/shortcuts/meeting/operations/signs.js +216 -2
  111. package/dist/shortcuts/workflow/endpoints.js +2 -1
  112. package/dist/shortcuts/workflow/errors.js +8 -2
  113. package/dist/shortcuts/workflow/host.js +6 -3
  114. package/dist/shortcuts/workflow/operations/form.js +931 -589
  115. package/dist/shortcuts/workflow/operations/read.js +128 -205
  116. package/dist/shortcuts/workflow/operations/shared.js +21 -0
  117. package/dist/shortcuts/workflow/operations/write.js +750 -52
  118. package/dist/shortcuts/workflow/operations.js +36 -10
  119. package/docs/_catalog.md +6 -0
  120. package/docs/agent-invoice.md +5 -1
  121. package/docs/agent-io-channel-design.md +468 -0
  122. package/docs/agent-skill-install.md +9 -4
  123. package/docs/blog.md +123 -0
  124. package/docs/caizhilian.md +304 -0
  125. package/docs/contract.md +91 -0
  126. package/docs/e10-auth.md +2 -2
  127. package/docs/hrm.md +19 -9
  128. package/docs/invoice.md +5 -1
  129. package/docs/meeting.md +1 -1
  130. package/docs/operation-manual.md +15 -3
  131. package/docs/skill-review-2026-09-19.md +2 -2
  132. package/package.json +2 -2
  133. package/scripts/package-skill.mjs +32 -20
  134. package/skill-template/business-info.json +113 -14
  135. package/skill-template/domains/blog.md +24 -0
  136. package/skill-template/domains/caizhilian.md +22 -0
  137. package/skill-template/domains/jinchengda.md +23 -0
  138. package/skill-template/domains/meeting.md +1 -1
  139. package/skill-template/domains/workflow.md +1 -1
  140. package/skill-template/skill-template.md +1 -1
  141. package/skills/weaver-e10-blog/SKILL.md +111 -0
  142. package/skills/weaver-e10-blog/references/blog-comment.md +51 -0
  143. package/skills/weaver-e10-blog/references/blog-comments.md +39 -0
  144. package/skills/weaver-e10-blog/references/blog-default-permission.md +38 -0
  145. package/skills/weaver-e10-blog/references/blog-disabled-capabilities.md +11 -0
  146. package/skills/weaver-e10-blog/references/blog-edit.md +51 -0
  147. package/skills/weaver-e10-blog/references/blog-export.md +42 -0
  148. package/skills/weaver-e10-blog/references/blog-like.md +50 -0
  149. package/skills/weaver-e10-blog/references/blog-publish.md +52 -0
  150. package/skills/weaver-e10-blog/references/blog-query-user.md +45 -0
  151. package/skills/weaver-e10-blog/references/blog-query.md +49 -0
  152. package/skills/weaver-e10-blog/references/blog-remind.md +51 -0
  153. package/skills/weaver-e10-blog/references/blog-resolve-users.md +38 -0
  154. package/skills/weaver-e10-blog/references/source-manifest.json +1540 -0
  155. package/skills/weaver-e10-caizhilian/SKILL.md +216 -0
  156. package/skills/weaver-e10-caizhilian/references/agent-entry.md +106 -0
  157. package/skills/weaver-e10-caizhilian/references/collaboration.md +112 -0
  158. package/skills/weaver-e10-caizhilian/references/document.md +111 -0
  159. package/skills/weaver-e10-caizhilian/references/file-collection.md +136 -0
  160. package/skills/weaver-e10-caizhilian/references/file-upload.md +309 -0
  161. package/skills/weaver-e10-caizhilian/references/files.md +120 -0
  162. package/skills/weaver-e10-caizhilian/references/folder.md +118 -0
  163. package/skills/weaver-e10-caizhilian/references/org-browser.md +104 -0
  164. package/skills/weaver-e10-caizhilian/references/setting-attach.md +410 -0
  165. package/skills/weaver-e10-caizhilian/references/setting-backup.md +372 -0
  166. package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +399 -0
  167. package/skills/weaver-e10-caizhilian/references/setting-storage.md +603 -0
  168. package/skills/weaver-e10-caizhilian/references/source-manifest.json +5079 -0
  169. package/skills/weaver-e10-caizhilian/references/withheld.md +93 -0
  170. package/skills/weaver-e10-caizhilian/references/write-protocol.md +120 -0
  171. package/skills/weaver-e10-calendar/SKILL.md +4 -3
  172. package/skills/weaver-e10-ebuilder-form/SKILL.md +4 -9
  173. package/skills/weaver-e10-ebuilder-form/references/context-routing.md +0 -9
  174. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -5
  175. package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +1 -5
  176. package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +1 -5
  177. package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +1 -5
  178. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -5
  179. package/skills/weaver-e10-esb/SKILL.md +2 -2
  180. package/skills/weaver-e10-esb/references/source-manifest.json +9 -9
  181. package/skills/weaver-e10-hrm/SKILL.md +54 -6
  182. package/skills/weaver-e10-hrm/references/employee.md +89 -15
  183. package/skills/weaver-e10-hrm/references/org.md +7 -4
  184. package/skills/weaver-e10-hrm/references/position.md +14 -7
  185. package/skills/weaver-e10-hrm/references/source-manifest.json +1 -1
  186. package/skills/weaver-e10-jinchengda/SKILL.md +166 -0
  187. package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +82 -0
  188. package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +69 -0
  189. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +78 -0
  190. package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +27 -0
  191. package/skills/weaver-e10-jinchengda/references/contract-request-status.md +71 -0
  192. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +94 -0
  193. package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +89 -0
  194. package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +77 -0
  195. package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +66 -0
  196. package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +94 -0
  197. package/skills/weaver-e10-jinchengda/references/source-manifest.json +259 -0
  198. package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -11
  199. package/skills/weaver-e10-jucailin/SKILL.md +4 -3
  200. package/skills/weaver-e10-mail/SKILL.md +4 -11
  201. package/skills/weaver-e10-meeting/SKILL.md +66 -32
  202. package/skills/weaver-e10-meeting/references/meeting-change.md +5 -2
  203. package/skills/weaver-e10-meeting/references/meeting-create.md +2 -1
  204. package/skills/weaver-e10-meeting/references/meeting-eb.md +114 -0
  205. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +9 -8
  206. package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +35 -7
  207. package/skills/weaver-e10-meeting/references/meeting-update.md +1 -1
  208. package/skills/weaver-e10-okr/SKILL.md +6 -11
  209. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  210. package/skills/weaver-e10-plan/SKILL.md +3 -3
  211. package/skills/weaver-e10-plan/references/plan-collect-and-compose.md +1 -1
  212. package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +1 -1
  213. package/skills/weaver-e10-plan/references/source-manifest.json +13 -13
  214. package/skills/weaver-e10-qiyecheng/SKILL.md +4 -10
  215. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +9 -9
  216. package/skills/weaver-e10-shared/SKILL.md +36 -25
  217. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -31
  218. package/skills/weaver-e10-shared/references/json-output-contract.md +20 -11
  219. package/skills/weaver-e10-shijingran/SKILL.md +2 -1
  220. package/skills/weaver-e10-shijingran/references/source-manifest.json +9 -9
  221. package/skills/weaver-e10-skill-maker/SKILL.md +4 -10
  222. package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +5 -3
  223. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +12 -27
  224. package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +17 -5
  225. package/skills/weaver-e10-skill-maker/references/source-update-detection.md +4 -27
  226. package/skills/weaver-e10-wenshuding/SKILL.md +5 -16
  227. package/skills/weaver-e10-wenshuding/references/source-manifest.json +7 -7
  228. package/skills/weaver-e10-workflow/SKILL.md +32 -37
  229. package/skills/weaver-e10-workflow/references/source-manifest.json +39 -75
  230. package/skills/weaver-e10-workflow/references/workflow-batch.md +90 -29
  231. package/skills/weaver-e10-workflow/references/workflow-create.md +79 -109
  232. package/skills/weaver-e10-workflow/references/workflow-memory.md +19 -9
  233. package/skills/weaver-e10-workflow/references/workflow-operate.md +2 -2
  234. package/skills/weaver-e10-workflow/references/workflow-query.md +38 -20
  235. package/skills/weaver-e10-workflow/references/workflow-share.md +18 -2
  236. package/skills/weaver-e10-workflow/references/workflow-view.md +3 -4
  237. package/skills/weaver-e10-yepiaotong/SKILL.md +75 -39
  238. package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +22 -1
  239. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +3 -1
  240. package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +135 -0
  241. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +15 -3
  242. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +1 -1
  243. package/skills/weaver-e10-yepiaotong/references/invoice-summarize.py +217 -0
  244. package/skills/weaver-e10-yepiaotong/references/invoice-upload-and-validate.md +88 -0
  245. package/skills/weaver-e10-yepiaotong/references/invoice-validation-preview.md +7 -2
  246. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +89 -9
  247. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +1 -0
  248. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +70 -49
  249. package/skills/weaver-e10-yepiaotong/references/reim-fast-path.md +119 -0
  250. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +55 -36
  251. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +4 -0
  252. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +149 -0
  253. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +125 -5
  254. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +430 -63
  255. package/skills/weaver-e10-yimiaoban/SKILL.md +4 -12
  256. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
  257. package/skills/weaver-e10-ziguanjia/SKILL.md +2 -1
  258. package/skills/weaver-e10-ziguanjia/references/ziguanjia-agent-entry.md +3 -3
  259. package/tools/weaver-skill-detector-1.0.13/SKILL.md +9 -9
  260. package/tools/weaver-skill-detector-1.0.13/references/checklist.md +3 -3
  261. package/tools/weaver-skill-detector-1.0.13/scripts/__pycache__/validate_skill.cpython-313.pyc +0 -0
  262. package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +98 -91
  263. package/scripts/sync-connector-skills.mjs +0 -172
@@ -44,8 +44,8 @@ function idempotentReplayEnvelope(error, operation) {
44
44
  *
45
45
  * 形态对齐 V11.3:`e10_workflow.py:10356-10400` 与 `resolve_system_name_condition`(L8262)
46
46
  * 都返回 `success:true` + `needClarification:true`(多命中时带 `candidates` +
47
- * `clarificationType` + `clarificationKeyword`)。与 `workflow.createList` 已有的
48
- * `ok:true` + `status:NEEDS_SELECTION` 是同一套约定。
47
+ * `clarificationType` + `clarificationKeyword`)。发起侧(`form.ts` 的 `resolveCreateWorkflow`)
48
+ * 走的是**同一条通道**:工作流参数解析不出唯一目标时也抛这个错误,模型侧表现完全一致。
49
49
  *
50
50
  * 注意:这是「本次查询**未执行**」的语义,不是「查询已执行且结果为空」——
51
51
  * 文案必须让模型把候选原样摆给用户,而不是转述成「无匹配流程」。
@@ -58,23 +58,49 @@ function clarificationEnvelope(error, operation) {
58
58
  const question = typeof details.clarificationQuestion === 'string' && details.clarificationQuestion
59
59
  ? details.clarificationQuestion
60
60
  : error.message;
61
+ const reason = typeof details.clarificationReason === 'string' ? details.clarificationReason : '';
61
62
  return workflowSuccess(operation, {
62
63
  type: 'workflowClarification',
63
64
  status: 'NEEDS_CLARIFICATION',
64
65
  clarificationType: details.clarificationType ?? null,
65
66
  clarificationKeyword: details.clarificationKeyword ?? null,
66
67
  clarificationQuestion: question,
68
+ ...(reason ? { clarificationReason: reason } : {}),
67
69
  candidates,
68
70
  candidateCount: candidates.length,
69
- note: '这不是失败,也**不代表查询已执行**:本次查询已停止,没有返回任何流程数据。'
70
- + '请把澄清问题与候选**原样**交给用户确认(逐条列出「名称(ID)」),'
71
- + '拿到确认后用「名称(ID)」格式重发同一条命令。'
72
- + '**不要**把本次结果转述成「没有匹配的流程」「查询结果为 0 条」或自行挑一个候选继续查。'
73
- + (candidates.length === 0
74
- ? '当前没有任何候选——请让用户给出准确的完整名称(或纠正名称里的错别字)后重发。'
75
- : ''),
71
+ note: clarificationNote(reason, candidates.length),
76
72
  });
77
73
  }
74
+ /**
75
+ * 澄清随附文案——按**原因**分叉,避免把性质完全不同的"进不去"混成同一句话。
76
+ *
77
+ * 2026-09-22:自带显式 ID 时不再请求「可发起工作流列表」,改由 `loadBaseParam` 的
78
+ * `authInfo.verifyRight` 判定,于是出现了两种**必须分开说**的情形:
79
+ * - `workflow_not_exist` —— 该 ID 在系统里不存在,正确说法就是"这个 ID 不存在";
80
+ * - `no_create_right` —— 流程**存在**但当前账号没有发起权限,**绝不能**说成"不存在"
81
+ * (那正是把"没权限"伪装成"没有这条流程",与项目纪律相反)。
82
+ *
83
+ * 无 `reason` 时(名称解析 0 / 多命中)保持原文案不变。
84
+ */
85
+ function clarificationNote(reason, candidateCount) {
86
+ const base = '这不是失败,也**不代表查询已执行**:本次查询已停止,没有返回任何流程数据。';
87
+ if (reason === 'workflow_not_exist') {
88
+ return base + '请如实告知用户:该工作流 ID 不存在(可能已删除或被停用),'
89
+ + '让用户核对 ID 或改用流程名称重新指定。**不要**说成"没有可发起的工作流"这类模糊说法——'
90
+ + '用户给的是一个具体 ID,问题就出在这个 ID 上。';
91
+ }
92
+ if (reason === 'no_create_right') {
93
+ return base + '请如实告知用户:该流程**存在**,但当前账号**没有发起权限**。'
94
+ + '**必须明确说出「存在但没有发起权限」**,绝不能转述成"流程不存在";'
95
+ + '并给出下一步:改用其他可发起的流程,或联系管理员为该流程授予发起权限。';
96
+ }
97
+ return base + '请把澄清问题与候选**原样**交给用户确认(逐条列出「名称(ID)」),'
98
+ + '拿到确认后用「名称(ID)」格式重发同一条命令。'
99
+ + '**不要**把本次结果转述成「没有匹配的流程」「查询结果为 0 条」或自行挑一个候选继续查。'
100
+ + (candidateCount === 0
101
+ ? '当前没有任何候选——请让用户给出准确的完整名称(或纠正名称里的错别字)后重发。'
102
+ : '');
103
+ }
78
104
  /**
79
105
  * 写入成功后回写 continuation 的执行结果(best-effort),使重复执行能回报「上一次已成功」,
80
106
  * 而不是一句无法分辨的「已使用」。
@@ -85,7 +111,7 @@ function clarificationEnvelope(error, operation) {
85
111
  async function settleAppliedContinuation(input, result, context, definition) {
86
112
  if (definition.risk !== 'high-risk-write')
87
113
  return;
88
- // 单条/批量/共享的句柄入参叫 `continuation`;发起(createApply)与修改(editApply)的句柄
114
+ // 单条/批量/共享的句柄入参叫 `continuation`;发起(createRequest)与修改(editApply)的句柄
89
115
  // 从 createForm/editLoad 一路传下来,入参名是 `context`(同一个本机托管句柄)。
90
116
  // 原先只认 `continuation` ⇒ 发起/修改成功后从不回写结果,重放只能报"已使用",
91
117
  // 模型被迫反查 OA 才能确认到底有没有发起(2026-09-16 线上)。
package/docs/_catalog.md CHANGED
@@ -42,4 +42,10 @@
42
42
  | Agent 调用易秒办 CLI 的具体 reference | `skills/weaver-e10-yimiaoban/references/` |
43
43
  | Agent 调用事井然项目管理 CLI 的入口路由 | `skills/weaver-e10-shijingran/SKILL.md` |
44
44
  | Agent 调用事井然项目管理 CLI 的具体 reference | `skills/weaver-e10-shijingran/references/` |
45
+ | 工作日报(下属/关注查询、单人查询、补交判定、发布、编辑、评论、点赞、提醒、导出 xlsx)、blog operation、写操作 prepare/apply | `docs/blog.md` |
46
+ | Agent 调用工作日报 CLI 的入口路由 | `skills/weaver-e10-blog/SKILL.md` |
47
+ | Agent 调用工作日报 CLI 的具体 reference | `skills/weaver-e10-blog/references/` |
48
+ | 采知连文档中心(文档/文件夹/权限共享/标签/参与人/附件/封面/文档比对)、caizhilian operation、写操作 prepare/apply | `docs/caizhilian.md` |
49
+ | Agent 调用采知连文档中心 CLI 的入口路由 | `skills/weaver-e10-caizhilian/SKILL.md` |
50
+ | Agent 调用采知连文档中心 CLI 的具体 reference | `skills/weaver-e10-caizhilian/references/` |
45
51
  | 将新业务模块文档或代码同步转换为 weaver-work-cli 业务 CLI 与 Skill、检测源资料更新 | `skills/weaver-e10-skill-maker/SKILL.md` |
@@ -42,8 +42,12 @@ weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"s
42
42
 
43
43
  ## 输出与大数据处理
44
44
 
45
- 当前项目的输出方式是 JSON envelope 直接写 stdout,失败 envelope 写 stderr;不像飞书 CLI 已内置 `--format table/pretty/ndjson`、`--jq` 和通用翻页参数。因此 Agent 调用时要主动控量:
45
+ 输出方式是 JSON envelope 直接写 stdout,失败 envelope 写 stderr;不像飞书 CLI 已内置 `--format table/pretty/ndjson`、`--jq` 和通用翻页参数。因此 Agent 调用时要主动控量:
46
46
 
47
+ - **列表类查询优先加 `--view summary`(0.1.17 起)**:一次调用得到语义平表,省略空值字段,10 条发票从约 35KB 降到约 3KB,不必再写脚本解析完整 envelope。仅 `invoice.list` / `invoice.enterprise.list` 支持,其他 operation 传该参数返回 `validation/view_unsupported`。
48
+ - 需要精确字段时用 `--fields number,detailUrl`:点路径按原始 JSON 结构投影,`data.items` 逐项裁剪、列表级汇总字段保留。**不要用裸 `total` 取金额**——发票顶层 `total` 是 E10 的独立字段(实测恒为 `0`),价税合计在 `comm_info.price.total`。未命中的路径出现在 `meta.projection.missingFields`,全部未命中返回 `validation/field_not_found`。
49
+ - `--view` 与 `--fields` 互斥(同时传返回 `validation/input_conflict`),两者都只裁剪输出、不改变请求参数,因此不受列表查询字段白名单限制。
50
+ - CLI 版本低于 0.1.17 时没有这两个参数,可用 `skills/weaver-e10-yepiaotong/references/invoice-summarize.py` 兜底,字段口径一致。
47
51
  - 列表默认 `page_size=10`,需要更多时再按 `start_pos` 分页。
48
52
  - 回复用户时只展示结论、数量、关键字段和下一步,不要原样粘完整 stdout JSON。
49
53
  - 发票列表/详情优先展示 `fid`、代码/号码、购销方、金额、日期、查验/报销状态和附件摘要。
@@ -0,0 +1,468 @@
1
+ # 操作间数据传递去文件化方案
2
+
3
+ ## 1. 问题边界:CLI 拦不住 Agent 写文件
4
+
5
+ 宿主(WorkBuddy)在 Windows 上通过 PowerShell 调 CLI,典型写法:
6
+
7
+ ```powershell
8
+ & $cli @a 2>&1 | Out-File "...\.wb_tmp\inv_raw.json" -Encoding UTF8
9
+ (Get-Item "...\inv_raw.json").Length | Out-File "...\size.txt" -Encoding UTF8
10
+ ```
11
+
12
+ 落盘发生在 **CLI 进程之外**,CLI 感知不到,也无法阻止。所以「从底层限制」必须拆成两个战场:
13
+
14
+ | 战场 | 手段 | 能做什么 |
15
+ | --- | --- | --- |
16
+ | CLI 侧 | 关闭「文件输入」这条路的可用性 | Agent 写了文件也喂不进来,被迫改道 |
17
+ | CLI 侧 | 提供比文件更好的替代通道 | 让文件变得不必要(疏导) |
18
+ | Skill 侧 | 在共享契约里写死红线 + 正确模板 | Agent 行为由 skill 文本驱动,这是唯一能直接约束它的地方 |
19
+
20
+ 只做 CLI 侧会导致 Agent 报错后重试;只做 Skill 侧没有强制力。两者必须同时做。
21
+
22
+ ## 2. 现状代码事实(2026-09-21)
23
+
24
+ - `--input <path>` 的解析**被复制进了 20 个业务模块**:34 处 `option('--input <path>')` 声明,每个模块自带 `inputFrom()` + `readStdin()` + `stripBom()`(`src/shortcuts/*/index.ts`)。
25
+ - `src/core/` 只有 `output.ts`,**没有对应的 `input.ts`**,因此不存在可以一刀切的开关点。
26
+ - 已具备的基础能力:`--input-json <json>`(内联)与 `--input -`(stdin)在所有模块都已实现;`--json` 输出 envelope 走 stdout,错误 envelope 走 stderr,退出码语义完整(`src/core/errors.ts`,含 `ExitCode.PolicyError = 6`)。
27
+ - `invoice` 已有 continuation 机制(HMAC 签名 token,`src/shortcuts/invoice/continuation.ts`),是「句柄代替数据」的现成雏形,但只用于 prepare/apply 写流程。
28
+
29
+ ## 3. 目标通道模型
30
+
31
+ 按优先级,Agent 应依次尝试:
32
+
33
+ 1. **内联**(`--input-json`)——首选,跨 Windows/macOS 无差异。
34
+ 2. **stdin**(`--input -`)——次选,需要 shell 能稳定传管道。
35
+ 3. **引用句柄**(`--input-ref <id>`)——大结果专用,见 P1。
36
+ 4. **文件**(`--input <path>`)——仅保留给豁免场景,默认告警,strict 下拒绝。
37
+
38
+ ⚠️ **通道 1/2 的前提修正(2026-09-22 补充)**:宿主对 stdout 有截断行为——实测完整内联上限约 24-32 KB,超线后会被截成约 2048 B 预览,且截断是静默的(调用方不知道丢了什么)。这意味着超线结果「写 stdout 直传」这个选项实际上不存在;P1 的句柄化不是可选优化,而是大结果唯一可靠的通道。因此 P1 envelope 的设计必须满足:句柄与摘要控制在截断预算内自解释,且一次性读完(详见 5.1)。
39
+
40
+ ## 4. P0:收口 + 硬开关(唯一能真正"限制"的一步)
41
+
42
+ ### 4.1 新增 `src/core/input.ts`
43
+
44
+ ```ts
45
+ export type FileInputPolicy = 'allow' | 'warn' | 'deny';
46
+
47
+ // 策略优先级:CLI flag > 环境变量 > config > 默认 warn
48
+ export function resolveFileInputPolicy(ctx: CliContext, opts: Record<string, any>): FileInputPolicy;
49
+ export function guardFileInput(ctx: CliContext, opts: Record<string, any>): void;
50
+ ```
51
+
52
+ 策略解析顺序:
53
+
54
+ 1. `--allow-file-input` / `--no-file-input`(显式 flag 最高)
55
+ 2. `WEAVER_WORK_CLI_FILE_INPUT=allow|warn|deny`
56
+ 3. config `io.fileInput`(`ConfigStore` 已支持任意 key,`~/.weaver-work-cli/config.json`)
57
+ 4. 默认 `warn`
58
+
59
+ ### 4.2 行为定义
60
+
61
+ | 策略 | `--input <path>` 行为 |
62
+ | --- | --- |
63
+ | `allow` | 照旧 |
64
+ | `warn` | 正常执行,stderr 输出一行提示(不污染 stdout):建议改用 `--input-json` 或 `--input -` |
65
+ | `deny` | 抛错,退出码 `6`(PolicyError),envelope `type=policy` / `subtype=file_input_denied` / `retryable=false`,message 给出可直接复制的改法 |
66
+
67
+ `deny` 的错误对象在 core 内统一构造为 structured error(`{ type:'policy', subtype:'file_input_denied', message, retryable:false }`),这样各模块 `toErrorEnvelope()` 无需改动即可识别,不依赖每个模块自己的 `xxxValidationError`。
68
+
69
+ BOM 处理要保留并统一:Windows `Set-Content -Encoding UTF8` 会写 BOM,`JSON.parse` 不接受前导 BOM,`ehr` 模块的 `stripBom()` 是正确的,收口后所有模块共享这一份。
70
+
71
+ ### 4.3 输入策略接入
72
+
73
+ 当前先在 `createAction` 统一检查 `--input <path>`,不改各业务模块自己的 JSON 解析逻辑:
74
+
75
+ - 所有叶子命令统一注册 `--allow-file-input` / `--no-file-input`。
76
+ - action 在业务 handler 运行前执行 `guardFileInput()`;`--input -` 和业务附件 `--file` 不受影响。
77
+ - 默认 `warn` 先兼容旧调用;用户可用 config 或环境变量设为 `deny`,确认迁移完成后再考虑改变默认值。
78
+
79
+ ### 4.4 灰度节奏
80
+
81
+ 1. 第一版默认 `warn`,观察一轮 Agent 实际行为与告警命中率。
82
+ 2. 确认主流路径都能走内联后,在 skill 安装/初始化时把 `io.fileInput: "deny"` 写进 config。
83
+ 3. 保留 `allow` 作为显式逃生阀:`--allow-file-input`。
84
+
85
+ ## 5. P1:结果引用(ref store)——让大结果不需要落盘
86
+
87
+ 当单次 JSON 输出超过阈值(默认 24 KB,可用 `WEAVER_WORK_CLI_REF_THRESHOLD` 覆盖):
88
+
89
+ - 完整数据写入 `~/.weaver-work-cli/state/refs/<date>/<id>.json`(CLI 自己的 state 目录,不在工作区、不进 Agent 上下文;权限限当前用户)
90
+ - stdout 只返回摘要 + 句柄:
91
+
92
+ ```json
93
+ {
94
+ "schemaVersion": 1,
95
+ "ok": true,
96
+ "operation": "invoice.list",
97
+ "refId": "20260922-105401-invoice-list-a1b2c3d4",
98
+ "resultPersisted": true,
99
+ "outputBytes": 128743,
100
+ "expiresAt": "2026-09-22T11:24:01.000Z",
101
+ "previewTruncated": true,
102
+ "largeOutputNotice": "结果已暂存……",
103
+ "data": { "items": [ /* 压缩预览 */ ], "count": 137 }
104
+ }
105
+ ```
106
+
107
+ - 下游用 `--input-ref <refId>` 消费;选单个值时加 `--pick-as <输入字段>`,例如 `--pick items[0].fid --pick-as fid`。CLI 从 state 目录读回(这是 CLI 内部 IO,不经过 Agent)
108
+ - ref 带 TTL 过期清理,不长期占用磁盘
109
+
110
+ 结果引用独立使用 `src/core/refs.ts` 保存 SHA-256 校验、TTL 和容量索引;不复用 invoice/workflow 的 continuation,因为结果句柄用于读取业务结果,生命周期和用途不同。
111
+
112
+ 可用 `refs show <refId>` 查看完整小结果;大结果请用 `refs get <refId> <json-path>` 读取需要的字段,避免再次触发宿主 stdout 截断。
113
+
114
+ ### 5.1 落盘必须配「够用的精简版」(2026-09-22 补充,来自宿主截断实测)
115
+
116
+ 只回指针是次优解(模型要多一次工具调用);最优解是「落盘 + stdout 回精简版和前置索引」,让 90% 场景不需要读文件:
117
+
118
+ - **渲染层留在 stdout**:`finalMarkdown` 等模型唯一必须渲染的东西(通常几 KB)不落盘,移出的只是结构化明细。
119
+ - **移出清单时附紧凑索引**:字段清单被移出时,附一份 `writableFields` 紧凑索引(278 字段表单实测仅 3.7 KB),模型能直接构造 `data` 的键,不用读文件。
120
+ - **句柄前置(withLeadingMeta 思想)**:`refId` 排到 JSON 最前面——宿主截断只保留前 2048 B,排在后面等于没有。stdout 不返回绝对文件路径,避免 Agent 直接读取暂存文件。
121
+ - **契约明令一次读完、禁用 head/tail**:截断会破坏 JSON 结构,还会导致重复执行同一条命令。
122
+
123
+ 据此 P1 的输出处理规则:
124
+
125
+ | 档位 | 条件 | 行为 |
126
+ | --- | --- | --- |
127
+ | 档 0 | ≤ 24 KB | 原样返回全量,不落盘 |
128
+ | 档 1 | > 24 KB | 完整结果落盘 + stdout 回前置 `refId` + 尽量压缩的原结构预览 |
129
+ | 档 2 | 压缩后仍超线 | stdout 回可解析的最小摘要和 `refId`,通过 `--input-ref` 或 `refs get` 取回数据 |
130
+
131
+ 统一口径:`stdoutBytesOf(v) = JSON.stringify(v, null, 2)` 的 UTF-8 字节数,与 CLI 实际打印一致。
132
+
133
+ ### 5.2 改造面:业务模块基本不用改
134
+
135
+ **关键代码事实(2026-09-22 核实)**:19 个业务模块的成功输出**全部**经过 `ctx.output.write(...)`(共 41 处调用),失败 envelope 走 `console.error`(stderr,体积小,不受影响)。也就是说输出只有一个出口——`src/core/output.ts` 的 `Output.write`。
136
+
137
+ 因此 P1 **输出侧**的通用档可以做到 **零业务模块改动**:
138
+
139
+ | # | 文件 | 改动 | 是否碰业务模块 |
140
+ | --- | --- | --- | --- |
141
+ | 1 | `src/core/output.ts` | 主改动:阈值判断 → 精简/落盘 → 重建 envelope(句柄前置)→ 注入 `refId` / `outputBytes` / `largeOutputNotice` | 否 |
142
+ | 2 | 新增 `src/core/state.ts` | 统一 `stateRoot()`(现状:19 个模块各写一份)+ refs 目录 + TTL 清理,可复用现有 `continuation.ts` 的实现 | 否 |
143
+ | 3 | 阈值配置 | 复用 `ConfigStore`:`io.resultThreshold`(默认 24576)、`io.refTtlMs`;支持 env 覆盖 | 否 |
144
+ | 4 | 新增 `src/core/compact.ts`(可选) | 通用列式压缩 + 模块 `compact` 钩子注册表 | 否 |
145
+ | 5 | `src/core/output.ts` 内最终预算检查 | **必须做**:对附加 ref 信息后的整个 envelope 重新计字节;超限时继续精简,保证返回完整、可解析的 JSON | 否 |
146
+
147
+ **输入侧**(`--input-ref`)由注册层给叶子命令统一加选项,再在 action 入口转换成现有 `--input-json`,业务模块不需要逐个改动。`--pick` 选单个值时还要用 `--pick-as <字段名>` 映射成业务输入对象,例如 `{ "fid": "123" }`。
148
+
149
+ ### 5.3 通用档与精品档
150
+
151
+ | 档 | 谁实现 | 效果 | 适用 |
152
+ | --- | --- | --- | --- |
153
+ | 通用档 | core 自动 | 落盘 + refId + 通用压缩 + refId 前置,零模块改动 | 全部 19 个模块,一次性生效 |
154
+ | 精品档 | 模块实现 `compact(operation, data)` 钩子 | 按业务语义压出「够用的精简版」(如 278 字段表单压到 3.7 KB 的字段索引) | 先给 invoice / workflow / ebuilder-form 等高频模块 |
155
+
156
+ 建议先上通用档拿到全局收益,再给高频模块补精品档钩子。`finalMarkdown` / 字段索引这类精简版本质上依赖业务语义,core 只能做通用压缩,做不出「够用」的效果。
157
+
158
+ ### 5.4 风险与回归
159
+
160
+ - **落盘位置必须是 CLI state 目录**(`~/.weaver-work-cli/state/...`),绝不能写 cwd、工作区或自定义 `--config` 文件旁。POSIX 文件权限设为当前用户私有;理由见 5.6。
161
+ - **回归开关**:提供 `WEAVER_WORK_CLI_REF_THRESHOLD=0`(或设为极大值)关闭落盘,用于对照回归。小结果(≤ 24 KB)走原路径不受影响,回归风险集中在有大结果的用例。
162
+ - 落盘文件需 TTL 清理,避免 state 目录无限增长。
163
+
164
+ ### 5.5 会不会丢内容、能不能追溯、TTL 怎么清
165
+
166
+ #### 会不会丢:成功落盘时完整结果可取回;写盘失败会明确告知不可恢复
167
+
168
+ P1 的落盘发生在**写 stdout 之前**——写入成功时完整数据先落 state 目录,stdout 只回指针 + 精简版,因此完整数据不会被宿主截断。若暂存目录写入失败,CLI 会在 stderr 明确告警,并在 stdout 标记 `resultPersisted: false`;此时只有精简预览,完整结果不可恢复。
169
+
170
+ 但仍有以下边界,必须逐个处理,否则会变成新的丢数据点:
171
+
172
+ | 风险 | 处理 |
173
+ | --- | --- |
174
+ | 精简版本身仍超输出预算 | 对最终 envelope(包含句柄、摘要和 warnings)计字节数,逐档精简;超预算时返回可解析的最小 envelope |
175
+ | 写盘失败(磁盘满 / 权限) | 必须显式报错或降级为「尽力压缩后全量输出 + `degraded` 标记」,**绝不静默截断** |
176
+ | ref id 冲突覆盖 | 用时间戳 + 随机串生成唯一 id,禁止按 operation 名复用固定文件名 |
177
+ | 模型读完整文件时被 Read 工具截断 | **模型不应直接读文件**。应提供 `--input-ref <id> --pick <jsonpath>` 让 CLI 代劳取子集,避免大文件读回时再次被截 |
178
+ | TTL 过期后引用 | 返回明确 `ref_expired` 错误(复用 continuation 的 `*_expired` 语义),而不是「文件不存在」 |
179
+
180
+ 结论:完整数据不丢;模型"看不到"的只是明细,且可用 `--pick` 按需取回。相比现状的静默截断,可观测性大幅提升。
181
+
182
+ #### 追溯:必须建索引,否则比 `.wb_tmp` 还难查
183
+
184
+ 现状的 `.wb_tmp/时间戳/inv_raw.json` 散落在工作区,事后无法对应到具体哪次调用、什么入参。P1 必须配套可追溯设计:
185
+
186
+ - **ref id 自带语义**:`20260922-104135-invoice.list-a1b2c3.json`,按日期分目录 `refs/2026-09-22/`
187
+ - **索引** `refs/index.jsonl`:保存 `{ refId, operation, createdAt, expiresAt, bytes, sha256 }`;不保存业务入参,避免把敏感信息复制进索引
188
+ - **envelope 内自证**:`refId`、`outputBytes`、`sha256`——拿到 stdout 就能定位与校验;绝对路径只由显式的 `refs path` 管理命令显示,不进入业务结果
189
+ - **查询命令**:`weaver-work-cli refs list` / `refs show <refId>` / `refs get <refId> <json-path>` / `refs prune ...`;大结果只能用 `refs get` 按需查看
190
+
191
+ 这样追溯链路是:命令输出 → `refId` → `refs show` 查看小结果或 `refs get` 查看子集。索引和业务输出中都不暴露暂存文件的绝对路径。
192
+
193
+ #### TTL 清理:自动为主,手动为辅,不引入后台进程
194
+
195
+ CLI 是「一次一进程」模型,没有常驻进程可跑定时任务,因此用**惰性 GC**:
196
+
197
+ | 机制 | 做法 |
198
+ | --- | --- |
199
+ | 惰性清理 | 每次 CLI 命令开始时扫描 refs 目录,清理过期项。成本仅一次 `readdir` + 时间戳比较 |
200
+ | 容量上限 | 除时间维度外加容量维度:保留最近 N 个(默认 50)或总大小上限(默认 200 MB),新结果写入后再清理旧项;若单个新结果已超过上限,保留本次结果并在 envelope 明确告警 |
201
+ | 手动命令 | `refs prune --older-than 7d` / `refs prune --all`,用于用户主动清理 |
202
+ | 不要引入 daemon / cron | Windows 无 cron,跨平台成本高。惰性 GC 与 CLI 的进程模型天然契合 |
203
+
204
+ 实现注意:
205
+
206
+ - **并发安全**:CLI 可能被并行调用。删除用 `unlink`;索引追加一行,重建索引时用「临时文件 + rename」;不要引入锁文件(跨平台问题多)。
207
+ - **Windows 占用**:文件被占用时删除会失败,`catch` 忽略即可,下次 GC 再清。
208
+ - **过期时间要告诉模型**:envelope 顶层带 `expiresAt`,让模型知道句柄的大致可用窗口,避免隔很久再用已过期的 ref。
209
+
210
+ 结果引用独立实现 TTL(默认 30 分钟)与 `ref_expired` 错误,不复用 invoice/workflow 的 continuation;两者语义和生命周期不同。
211
+
212
+ ### 5.6 为什么必须落 CLI state 目录,不能落工作区
213
+
214
+ 不是「不能」,而是工作区落盘会让 P1 的多项收益同时失效。五条理由按重要性排序:
215
+
216
+ | # | 理由 | 说明 |
217
+ | --- | --- | --- |
218
+ | 1 | **GC 直接失效(决定性)** | 惰性 GC 只能扫当前 cwd。调用①在 A 目录写了文件,调用②的 cwd 变成 B,GC 永远扫不到 A 的文件 → 只能永久残留。state 目录是固定路径,任何 cwd 下都能命中 |
219
+ | 2 | **跨调用不可达** | 工作区路径绑定 cwd,换一次目录 ref 就找不到;`--input-ref <id>` 要求在任何目录都能解析,只有固定 state 目录能满足 |
220
+ | 3 | **敏感数据有入库风险** | 工作区常常是 git 仓库、网盘同步目录或备份范围内。发票数据、OCR 原文、E10 业务明细落在那里,可能被误提交或同步出去。state 目录在用户主目录;POSIX 系统设置为当前用户可读写,Windows 继承用户目录 ACL |
221
+ | 4 | **污染用户工作区** | 写文件会让 `git status` 变脏、触发 IDE 文件监听与构建工具 watch 重启;工作区还可能只读或权限受限,写盘失败率更高,一旦失败就触发降级分支 |
222
+ | 5 | **会重新打开要关闭的通道** | 工作区路径对 Agent 是可见的、可直接 Read 的。落盘到工作区等于把「直接读文件」这条便捷通道又打开了,P1 想要的「模型不读文件、用 `--input-ref` 按需取」会被绕过。业务 envelope 只返回 `refId`,不暴露 state 文件路径 |
223
+
224
+ **判据**:文件的所有权归谁?
225
+
226
+ - **临时传递介质**(上一步的输出、给下一步的输入)→ 归 CLI → state 目录 → 可 GC、全局可达、强制走句柄
227
+ - **交付给用户的产物**(下载附件、导出报表、生成的文件)→ 归用户 → 工作区或用户指定路径
228
+
229
+ 后者正是 5.4 与第 10 节的豁免场景(`invoice.download --output`、`export`、用户提供的 `--file` 入参),两者不矛盾。
230
+
231
+ ## 6. P2:进程内 pipeline
232
+
233
+ ```bash
234
+ weaver-work-cli chain --steps '[
235
+ {"op":"invoice.list","input":{"page_size":10}},
236
+ {"op":"invoice.get","input":{"fid":"$.steps[0].data.items[0].fid"}}
237
+ ]'
238
+ ```
239
+
240
+ 多步在单个 Node 进程内执行,中间数据是内存里的 JS 对象,只输出最后一步结果。附带收益:省掉每次调用重复的 auth 解析与会话建立(现在每次 CLI 调用都要重走一遍)。
241
+
242
+ ## 7. P3:MCP stdio server(2026-09-22 细化)
243
+
244
+ `weaver-work-cli mcp serve` 把 operations 暴露为 MCP tools,输入输出走 JSON-RPC over stdio,协议层天然无文件。
245
+
246
+ ### 7.1 为什么现在不做(六条理由)
247
+
248
+ 1. **MCP 只换管道,不换数据量问题。** 工具返回值照样进上下文,超线照样被截断或撑爆上下文。P1 的精简版 + 句柄是任何管道都需要的地基。没解决「传多少」就先换「怎么传」,等于白改一轮。
249
+ 2. **P1 的产物是 P3 的原材料。** 统一 envelope(`refId` / `outputBytes` / `largeOutputNotice` / `persistedResult`)就是 MCP tool 返回值的形状,`--input-ref` 句柄就是大入参的引用方式。契约定稿后 MCP 只是换个出口;反过来先做 MCP,契约一改工具定义全部返工。
250
+ 3. **常驻进程引入新的风险面。** 要处理 E10 会话生命周期(token 过期/刷新)、并发、错误隔离(单个 operation 崩溃不能拖垮 server)。CLI 现有「一次一进程」模型下,这些问题被进程退出天然兜住。
251
+ 4. **宿主依赖不在我们手里。** 需要宿主支持配置 stdio server、Windows 下正确 spawn、用户手动 Trust。P1 纯在本仓库内,收益确定、不依赖外部排期。
252
+ 5. **提速收益被高估。** MCP 省的是每次调用的固定开销(Node 启动 + E10 鉴权,百毫秒级),而 E10 业务网络往返通常才是主导。业务请求 500 ms 时约省 30%,2 s 时只省约 10%;相比之下 P1 省的是整轮 LLM(数秒级)。
253
+ 6. **验证成本更高。** MCP 调试链路长(握手 → 工具发现 → 宿主集成),CLI 直接跑命令即可验证。
254
+
255
+ ### 7.2 项目特有的约束:tool 数量与体积
256
+
257
+ 当前全仓 **136 个 operation**,每个 manifest 已自带完整 JSON Schema(`inputSchema` / `outputSchema` / `risk`)。全量暴露的后果:
258
+
259
+ - `tools/list` 响应达数百 KB
260
+ - 136 个 tool 描述长期占据上下文,严重拖慢工具选择
261
+
262
+ 所以 MCP 必须先解决「按需暴露」,而这依赖的是 P1 的控量思想,不是协议本身能给的。
263
+
264
+ ### 7.3 实现清单
265
+
266
+ **利好**:tool 的 `inputSchema` 可以直接复用 manifest 的 `inputSchema`(已是标准 JSON Schema,含 `type`/`enum`/`description`/`default`/`pattern`),`risk` 可映射为 MCP annotation(`readOnlyHint` / `destructiveHint`)。不需要手写 136 份 schema。
267
+
268
+ | # | 事项 | 说明 | 预估 |
269
+ | --- | --- | --- | --- |
270
+ | 1 | 传输层 | stdio + JSON-RPC 2.0。建议引 `@modelcontextprotocol/sdk`(`Server` + `StdioServerTransport`),手写协议易漏 initialize 协商/capabilities/cancellation 等细节 | 0.5-1 天 |
271
+ | 2 | 协议方法 | 最小集:`initialize`、`tools/list`、`tools/call`;可选 `resources/list`(通过 P1 的 refId 按需读取) | 含在上项 |
272
+ | 3 | 模块 dispatcher | 需要一个可枚举的模块注册表(manifest + execute + host + continuation 四件套),当前 20 个模块入口分散,`src/shortcuts/index.ts` 仅 42 行不足以支撑 | 1-2 天 |
273
+ | 4 | tools 生成 | manifest → tool;**必须按需暴露**:方案 A 启动时指定 `--modules invoice,workflow`;方案 B 暴露 3 个 meta-tool(`list_operations` / `describe_operation` / `run_operation`),tool 数恒定、体积可控,且与现有 `weaver-work-cli invoice schema` 的心智一致 | 0.5-1 天 |
274
+ | 5 | 认证常驻化 | 缓存 E10 凭据与会话;401/会话过期要有刷新或结构化错误(复用 `ExitCode.AuthError=3` 语义);`--profile` / `--is-connector` 在 serve 启动时固定;token 不得出现在任何输出中 | 1-2 天 |
275
+ | 6 | 输出侧 | **直接复用 P1 的 envelope**,CLI 与 MCP 两条通道行为一致,测试与文档只写一份 | 依赖 P1 |
276
+ | 7 | 宿主配置 | `~/.workbuddy/mcp.json` 增加 `mcpServers.weaver-e10`,`command` 为 CLI 可执行文件(Windows 下注意 `.cmd` 与 PATH),随后需用户在连接器管理页手动 Trust 才生效 | 1 天+(外部依赖) |
277
+ | 8 | 测试 | MCP inspector 或自写 stdio 客户端,跑 initialize → tools/list → tools/call 三轮;补一个大结果走 `refId` 的用例 | 0.5 天 |
278
+
279
+ 合计约 1 周,第 3、5 项不确定性最大。
280
+
281
+ ### 7.4 启动 P3 的判据(需同时满足)
282
+
283
+ - P1 输出侧已稳定:envelope 契约定稿、阈值与精简版跑通
284
+ - 宿主明确支持 MCP stdio server(可配置 + Trust + Windows spawn 正常)
285
+ - 有明确的高频多步场景,且**实测**瓶颈确实在进程启动/鉴权而非网络往返
286
+
287
+ 第三条若不成立(大概率不成立),MCP 的价值就只剩「更结构化」,优先级应继续后移。
288
+
289
+ ## 8. 便宜但关键:envelope 自带 next 指引
290
+
291
+ 在成功 envelope 的 `meta` 里返回下一步建议:
292
+
293
+ ```json
294
+ "meta": {
295
+ "status": "COMPLETE",
296
+ "next": [
297
+ { "op": "invoice.get", "input": { "fid": "12345" }, "why": "查看详情" }
298
+ ]
299
+ }
300
+ ```
301
+
302
+ Agent 之所以要暂存中间结果,多半是因为不确定下一步怎么接。给出 `next` 能显著减少自发的落盘行为,且实现成本极低。
303
+
304
+ ## 9. Skill 文档侧改造(必须同步)
305
+
306
+ `skills/weaver-e10-shared/references/json-output-contract.md` 现在第 79-93 行**主动教 Agent 写临时文件**,且第 113 行、120 行鼓励「超长 JSON 先落盘」。需要:
307
+
308
+ 1. 把「复杂 JSON 用临时文件」降级为最后手段,主推 `--input-json` 与 `--input -`。
309
+ 2. 新增红线:**禁止把上一步的 stdout 落盘再喂回下一个 operation**;要用变量传递。
310
+ 3. 给出 Windows PowerShell 正确模板:
311
+
312
+ ```powershell
313
+ [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
314
+ $out = (& $cli --json invoice run invoice.list --input-json '{"page_size":10}') -join "`n"
315
+ if ($LASTEXITCODE -ne 0) { throw $out } # 判退出码,不判文件大小
316
+ $fid = ($out | ConvertFrom-Json).data.items[0].fid # 数据留在变量里
317
+ & $cli --json invoice run invoice.get --input-json "{""fid"":""$fid""}"
318
+ ```
319
+
320
+ 要点:不要用 `2>&1`(会把 stderr 混进 JSON);`Out-File -Encoding UTF8` 在 PS 5.1 会加 BOM,导致下游 `JSON.parse` 失败;`&` 返回的是行数组,`ConvertFrom-Json` 前需要 `-join`。
321
+
322
+ ### 9.1 结果超过预算时:Windows PowerShell 与 macOS/Linux 两套写法
323
+
324
+ 大结果会返回 `refId`,下游直接引用,不必落盘中转。Windows PowerShell:
325
+
326
+ ```powershell
327
+ $out = (& $cli --json invoice run invoice.list --input-json '{"page_size":200}') -join "`n"
328
+ if ($LASTEXITCODE -ne 0) { throw $out }
329
+ $refId = ($out | ConvertFrom-Json).refId
330
+ & $cli --json invoice run invoice.get --input-ref $refId --pick items[0].fid --pick-as fid
331
+ ```
332
+
333
+ macOS/Linux(bash/zsh):
334
+
335
+ ```bash
336
+ out="$(weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":200}')"
337
+ ref_id="$(node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const j=JSON.parse(s);process.stdout.write(j.refId||"")})' <<<"$out")"
338
+ weaver-work-cli --json invoice run invoice.get --input-ref "$ref_id" --pick items[0].fid --pick-as fid
339
+ ```
340
+
341
+ 两套示例都必须给出:Windows PowerShell 用 `Get-ChildItem` 而非 `ls`;macOS/Linux 侧才使用 `printf`、`mktemp` 等写法。
342
+
343
+ shared 的 SKILL.md / references 不属于各业务模块 source manifest 的源资料或产物基线;只有某个 manifest 明确列入这些文件时,才需要更新对应指纹。
344
+
345
+ ## 10. 必须保留的文件 IO 豁免
346
+
347
+ 以下场景文件是业务产物而非传递介质,不受限制:
348
+
349
+ - `invoice.download` 的 `--output <path>`(附件下载)
350
+ - `invoice.upload` / `invoice.import.prepare` 的 `--file <path>`(本地发票文件是真实输入源,不是上一步的输出)
351
+ - 导出类 operation(blog export、报表导出)
352
+
353
+ 判断标准:**文件是用户提供的输入或交付给用户的产物 → 放行;文件是上一步 CLI 的输出 → 限制。**
354
+
355
+ ### 5.7 实现状态(2026-09-22 已落地)
356
+
357
+ P1 输出侧与引用输入、P0 文件输入策略已接入共享 action 层,业务模块零改动;文件输入默认 `warn`,严格拒绝需显式设置 `deny`。
358
+
359
+ | 文件 | 状态 | 说明 |
360
+ | --- | --- | --- |
361
+ | `src/core/input.ts` | 新增 | `--input <path>` 策略解析与告警/拒绝;不替换业务模块内的 JSON 解析 |
362
+ | `src/core/state.ts` | 新增 | `stateRoot` / `refsDir` / `refsIndexPath`;自定义 `--config` 不会把业务结果改存到项目目录 |
363
+ | `src/core/refs.ts` | 新增 | 写入 / 校验 / 读取 / 列表 / 惰性 GC / `--pick` 与 `--pick-as` / `RefError` |
364
+ | `src/core/output.ts` | 改造 | 阈值判断 → 精简 → 落盘 → refId 前置并限制最终 envelope 大小;`persist:false` 逃逸开关 |
365
+ | `src/cmd/action.ts` | 改造 | 每条命令开始时 GC;`--input-ref` + `--pick` / `--pick-as` 翻译成等价 `--input-json` |
366
+ | `src/cmd/register.ts` | 改造 | 递归给**叶子命令**注入引用参数与 `--allow-file-input` / `--no-file-input` |
367
+ | `src/cmd/refs/index.ts` | 新增 | `refs path` / `list` / `show` / `get` / `prune` |
368
+ | `test/core/refs.test.ts` | 新增 | 24 个用例,含 Windows 文件名安全与防回归用例 |
369
+
370
+ 可调参数(env > config `io.*` > 默认值):
371
+
372
+ | 变量 | config 键 | 默认 |
373
+ | --- | --- | --- |
374
+ | `WEAVER_WORK_CLI_REF_THRESHOLD` | `io.resultThreshold` | 24576(0 表示关闭落盘) |
375
+ | `WEAVER_WORK_CLI_REF_TTL_MS` | `io.refTtlMs` | 30 分钟 |
376
+ | `WEAVER_WORK_CLI_REF_MAX_COUNT` | `io.refMaxCount` | 50 |
377
+ | `WEAVER_WORK_CLI_REF_MAX_BYTES` | `io.refMaxBytes` | 200 MB(新结果优先保留;单个结果超限时会明确告警) |
378
+
379
+ 超预算时 stdout 的 envelope(句柄在最前,整个 envelope 会保持在输出预算内):
380
+
381
+ ```json
382
+ {
383
+ "refId": "20260922-111549-result-e71c6a88",
384
+ "resultPersisted": true,
385
+ "outputBytes": 174055,
386
+ "sha256": "cd97...",
387
+ "expiresAt": "2026-09-22T03:45:49.855Z",
388
+ "previewTruncated": true,
389
+ "largeOutputNotice": "结果已暂存。使用 --input-ref ... 引用…",
390
+ "schemaVersion": 1,
391
+ "ok": true,
392
+ "operation": "invoice.list",
393
+ "data": { "…": "精简版,结构不变、明细裁剪" },
394
+ "warnings": []
395
+ }
396
+ ```
397
+
398
+ 实现中踩到并已修掉的两个坑:
399
+
400
+ 1. **只压 `data` 不够**:`invoice schema` 这类命令的 envelope 没有 `data` 键,大字段是 `operations`,只压 data 等于没压。按 envelope 字段通用压缩后,再计算包含 refId 和提示的最终 JSON 字节数;仍超预算时降级为可解析的最小 envelope。
401
+ 2. **父命令会吃掉子命令的选项**:给中间命令(如 `invoice`)也加 `--input-ref` 时,Commander 的 `parseOptions` 会先把它当自己的选项消费,叶子命令 `run` 的 `opts()` 为空。改为只给叶子命令注入。
402
+
403
+ 已知限制:
404
+
405
+ - 阈值只按序列化后的字节数判断,不做业务语义压缩(精品档的 `compact` 钩子尚未实现,见 5.3)。
406
+ - 索引 `refs/index.jsonl` 只记录元信息,不记录入参(避免 OCR 原文等敏感数据入索引)。
407
+
408
+ ## 11. 选型结论(2026-09-22)
409
+
410
+ ### 11.1 先纠正直觉:真正的瓶颈不是磁盘 IO
411
+
412
+ 按成本从高到低,Agent 多步任务的耗时构成是:
413
+
414
+ 1. **额外的模型轮次**(读一次文件 = 一轮 LLM,数秒级)
415
+ 2. **因截断丢数据导致的重跑**(一次完整业务请求 + 一轮 LLM,最贵)
416
+ 3. **上下文膨胀**(大 JSON 进上下文后每轮推理都变慢,且持续到任务结束)
417
+ 4. 进程启动 + E10 鉴权解析(百毫秒级)
418
+ 5. 磁盘 IO(毫秒级)
419
+
420
+ 所以「提升速度」的主战场是**减少模型轮次与重跑**,不是消灭文件 IO 本身。相应地,「保证完整」的最大威胁也不是数据没存下来,而是**静默截断 + 部分读取**(`head/tail` 会破坏 JSON 结构)。
421
+
422
+ 这两点恰好都被 P1 直接命中,因此:
423
+
424
+ ### 11.2 结论:以 P1 为主轴,P0 配套,P2 限场景,P3 暂缓
425
+
426
+ | 方案 | 速度 | 完整 | 成本 | 结论 |
427
+ | --- | --- | --- | --- | --- |
428
+ | **P1 句柄 + 精简版** | 高 | 高 | 中 | **主轴**,必须做 |
429
+ | P0 strict IO | 无提升(短期可能因重试略降) | 间接 | 极低 | 配套做,用于封死工作区落盘 |
430
+ | P2 进程内 chain | 最高 | 中 | 中高 | 限确定性链路,锦上添花 |
431
+ | P3 MCP | 最高 | 高 | 极高 | 暂缓,P1 的 envelope 契约是它的前置 |
432
+
433
+ **P2 的隐藏代价**:把多步塞进一个进程后,模型看不到中间结果,动态决策链路("先看列表再决定看哪条")用不了——而 Agent 场景大量是动态决策。它只对确定性链路(`prepare → apply`、固定组合)有效,且最终输出超线时仍需 P1 兜底。
434
+
435
+ **P1 必须对称做完整**:只做输出侧落盘而不做 `--input-ref`,模型要把大载荷回传给下一步时,仍会撞上命令行长度上限(Windows 约 8 KB)或退回落盘到工作区——半套方案会退化回原问题。
436
+
437
+ ### 11.3 落地顺序
438
+
439
+ 1. **P1 输出侧**(1-2 天):统一 envelope + 24 KB 阈值分级 + 落盘配精简版(5.1 四条规则),提进 `src/core/output.ts`。直接消灭截断丢数据与重跑。
440
+ 2. **P1 输入侧**(0.5-1 天):`--input-ref` 消费句柄,让大载荷回传不必内联。
441
+ 3. **P0**(收口时顺手做):`src/core/input.ts` + `warn/deny` 策略,默认 `warn` 观察一轮。
442
+ 4. **P2**(按需):仅对高频确定性链路加 `chain`。
443
+ 5. **P3**:待前四步稳定、宿主 MCP 支持明确后再评估。
444
+
445
+ ### 11.4 不该做的事
446
+
447
+ - 不要让模型自己筛字段来规避超线——会漏字段,且要多轮试错。
448
+ - 不要默认全量落盘——多一次读文件轮次,比内联更慢。精简版是关键。
449
+ - 不要先做 P3——P1 定义的 envelope 契约是 P3 的前置,跳过会让 MCP 的工具定义反复返工。
450
+
451
+ ### 11.5 验收指标(可度量)
452
+
453
+ 取「多步任务」样本,改造前后对比:
454
+
455
+ - 平均模型轮次数(目标:多步任务减少 1-2 轮)
456
+ - 因截断导致的命令重跑率(目标:降到 0)
457
+ - 工作区 `.wb_tmp` 临时文件产生次数(目标:降到 0)
458
+ - 单次任务上下文 token 峰值(目标:大结果场景显著下降)
459
+
460
+ ## 12. 验收清单
461
+
462
+ - [ ] `src/core/input.ts` 的策略已由 action 入口统一接入,叶子命令有策略选项
463
+ - [ ] `WEAVER_WORK_CLI_FILE_INPUT=deny` 下,`--input <path>` 退出码 6 且 envelope subtype 为 `file_input_denied`
464
+ - [ ] `warn` 模式下提示只写 stderr,不影响 stdout 的 `JSON.parse`
465
+ - [ ] stdout 在 `--json` 下保持无 BOM、无额外日志
466
+ - [ ] 下载/上传/导出类 operation 不受策略影响
467
+ - [ ] shared 文档红线已更新
468
+ - [ ] `npm run build` 与 `npm test` 通过
@@ -88,7 +88,10 @@ weaver-work-cli skills install yepiaotong --target-dir "$AGENT_SKILLS_ROOT"
88
88
 
89
89
  - Agent 代装业务 Skill 时,必须先判断目标目录里的 `weaver-e10-shared/SKILL.md` 是否存在;未安装时先执行 `weaver-work-cli skills install shared --target-dir "<agent-skills-root>"`,再安装业务 Skill。
90
90
  - `skills install yepiaotong` 的 CLI 层会同时安装 `weaver-e10-shared` 与 `weaver-e10-yepiaotong`,用于命令兜底;但提示词和自动安装流程仍需显式展示 shared 前置检查。
91
- - 默认目标优先使用环境变量 `CODEX_HOME` 下的 `skills` 子目录;未设置时使用用户主目录下的 `.codex/skills`。其它目录必须用 `--target-dir` 显式指定。
91
+ - 安装目录优先级为:`--target-dir` → 通用环境变量 `WEAVER_SKILLS_ROOT` → 当前进程明确识别出的 Codex/WorkBuddy 宿主 → 当前用户目录下唯一已存在的已知 skills 目录。
92
+ - `WEAVER_AGENT_TYPE=codex|workbuddy` 可明确当前宿主;未设置时,CLI 优先比较当前进程中的 `CODEX_*` / `WORKBUDDY_*` 运行时信号,再参考可能被长期配置的 `CODEX_HOME` / `WORKBUDDY_HOME`。两个 `*_HOME` 表示宿主主目录,CLI 会追加 `skills`;`WEAVER_SKILLS_ROOT` 则直接表示最终的 skills 根目录。
93
+ - 两个已知宿主目录都存在、完全没有可靠信号,或检测到其它智能体但没有取得其 skills 路径时,CLI 不会猜测或写入,而是要求使用 `--target-dir` 或 `WEAVER_SKILLS_ROOT` 后重试。
94
+ - Agent 在业务 Skill 内自行推断目标目录时,取**当前这份 SKILL.md 所在目录的上一级绝对目录**(即与本技能同级的 skills 根目录),不要省略 `--target-dir`——省略后若宿主信号不足,CLI 会拒绝安装;仅靠已有目录推断也可能不是当前宿主。
92
95
  - 安装是文件拷贝,不需要 E10 登录;登录只在执行业务命令(`invoice run ...`)前需要。
93
96
  - 名称支持短名(如 `skill-maker`)、全名 `weaver-e10-skill-maker` 和旧前缀 `weaver-work-cli-skill-maker`;旧前缀会转换为当前名称。建议使用短名,避免不同版本的前缀差异。
94
97
  - Skill 生成器拼写为 `maker`,不是 `marker`。名称不存在时会提示相近名称和查询命令,不会自动安装猜测的 Skill。
@@ -103,9 +106,11 @@ weaver-work-cli skills install skill-maker --target-dir "$HOME/.workbuddy/skills
103
106
 
104
107
  | Agent 环境 | skill 根目录 | 安装方式 |
105
108
  | --- | --- | --- |
106
- | Codex CLI | `CODEX_HOME` 下的 `skills`;默认用户主目录下的 `.codex/skills` | `skills install yepiaotong`(默认目标) |
107
- | WorkBuddy(桌面端) | 用户主目录下的 `.workbuddy/skills`(用户级) | Windows:`skills install yepiaotong --target-dir "$env:USERPROFILE\.workbuddy\skills"`;macOS/Linux:`skills install yepiaotong --target-dir "$HOME/.workbuddy/skills"` |
108
- | 其它 Agent | 由 Agent 配置决定 | `skills install yepiaotong --target-dir <path>` |
109
+ | Codex CLI | `CODEX_HOME` 下的 `skills`;默认当前用户主目录下的 `.codex/skills` | 当前进程带有 Codex 环境信号时可直接执行 `skills install yepiaotong`;否则显式指定目录 |
110
+ | WorkBuddy(桌面端) | `WORKBUDDY_HOME` 下的 `skills`;默认当前用户主目录下的 `.workbuddy/skills` | 当前进程带有 WorkBuddy 环境信号时可直接执行;否则用 `--target-dir` 或 `WEAVER_SKILLS_ROOT` |
111
+ | 其它 Agent | 由 Agent 配置决定 | `skills install yepiaotong --target-dir <path>`,或先把 `WEAVER_SKILLS_ROOT` 设置为该路径 |
112
+
113
+ 安装输出的第一行会写明实际使用的目标目录与判定来源。Windows 可执行 `$env:WEAVER_SKILLS_ROOT = "$env:USERPROFILE\.<agent>\skills"`;macOS/Linux 可执行 `export WEAVER_SKILLS_ROOT="$HOME/.<agent>/skills"`。这里只读取当前登录用户的主目录,不扫描其它用户目录。
109
114
 
110
115
  不确定 Agent 读哪个目录时先问用户,不要盲目同时安装到多个目录。装到用户主目录下的 `.workbuddy/skills` 不会同步 `.codex/skills`,反之亦然。
111
116