weaver-work-cli 0.1.1 → 0.1.4

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 (351) hide show
  1. package/README.md +187 -76
  2. package/dist/cmd/setup/index.js +5 -5
  3. package/dist/cmd/skills/index.js +1 -1
  4. package/dist/core/hooks.js +7 -0
  5. package/dist/index.js +0 -0
  6. package/dist/internal/e10/auth/commands.js +160 -55
  7. package/dist/internal/e10/auth/crypto.js +7 -22
  8. package/dist/internal/e10/auth/session.js +1 -1
  9. package/dist/internal/e10/auth/xiaoe.js +268 -0
  10. package/dist/internal/e10/context.js +16 -2
  11. package/dist/internal/e10/index.js +1 -0
  12. package/dist/internal/e10/request-runtime.js +344 -0
  13. package/dist/internal/skills/install.js +48 -6
  14. package/dist/internal/skills/reader.js +27 -0
  15. package/dist/shortcuts/archive/continuation.js +70 -0
  16. package/dist/shortcuts/archive/errors.js +53 -0
  17. package/dist/shortcuts/archive/host.js +197 -0
  18. package/dist/shortcuts/archive/index.js +363 -0
  19. package/dist/shortcuts/archive/manifest.js +45 -0
  20. package/dist/shortcuts/archive/operations/archive-info.js +55 -0
  21. package/dist/shortcuts/archive/operations/borrow-car.js +146 -0
  22. package/dist/shortcuts/archive/operations/borrow-list.js +200 -0
  23. package/dist/shortcuts/archive/operations/confirm.js +46 -0
  24. package/dist/shortcuts/archive/operations/download.js +238 -0
  25. package/dist/shortcuts/archive/operations/flow-url.js +240 -0
  26. package/dist/shortcuts/archive/operations/fonds.js +95 -0
  27. package/dist/shortcuts/archive/operations/getPageUrl.js +137 -0
  28. package/dist/shortcuts/archive/operations/registry.js +43 -0
  29. package/dist/shortcuts/archive/operations/search.js +88 -0
  30. package/dist/shortcuts/archive/operations/shared.js +120 -0
  31. package/dist/shortcuts/archive/operations/types.js +23 -0
  32. package/dist/shortcuts/archive/operations/upload.js +182 -0
  33. package/dist/shortcuts/archive/operations.js +13 -0
  34. package/dist/shortcuts/archive/render/search-format.js +276 -0
  35. package/dist/shortcuts/archive/render/search-view.js +125 -0
  36. package/dist/shortcuts/asset/continuation.js +70 -0
  37. package/dist/shortcuts/asset/errors.js +67 -0
  38. package/dist/shortcuts/asset/host.js +438 -0
  39. package/dist/shortcuts/asset/index.js +255 -0
  40. package/dist/shortcuts/asset/manifest.js +471 -0
  41. package/dist/shortcuts/asset/operations/query.js +249 -0
  42. package/dist/shortcuts/asset/operations/registry.js +85 -0
  43. package/dist/shortcuts/asset/operations/shared.js +100 -0
  44. package/dist/shortcuts/asset/operations/type-cache.js +49 -0
  45. package/dist/shortcuts/asset/operations/types.js +1 -0
  46. package/dist/shortcuts/asset/operations/viewlink.js +117 -0
  47. package/dist/shortcuts/asset/operations/write.js +435 -0
  48. package/dist/shortcuts/asset/operations.js +9 -0
  49. package/dist/shortcuts/calendar/continuation.js +70 -0
  50. package/dist/shortcuts/calendar/errors.js +53 -0
  51. package/dist/shortcuts/calendar/host.js +148 -0
  52. package/dist/shortcuts/calendar/index.js +125 -0
  53. package/dist/shortcuts/calendar/manifest.js +26 -0
  54. package/dist/shortcuts/calendar/operations/read.js +259 -0
  55. package/dist/shortcuts/calendar/operations/registry.js +31 -0
  56. package/dist/shortcuts/calendar/operations/shared.js +132 -0
  57. package/dist/shortcuts/calendar/operations/types.js +25 -0
  58. package/dist/shortcuts/calendar/operations/write.js +439 -0
  59. package/dist/shortcuts/calendar/operations.js +8 -0
  60. package/dist/shortcuts/ehr/continuation.js +70 -0
  61. package/dist/shortcuts/ehr/errors.js +53 -0
  62. package/dist/shortcuts/ehr/host.js +213 -0
  63. package/dist/shortcuts/ehr/index.js +205 -0
  64. package/dist/shortcuts/ehr/manifest.js +47 -0
  65. package/dist/shortcuts/ehr/operations/attend-read.js +373 -0
  66. package/dist/shortcuts/ehr/operations/attend-write.js +514 -0
  67. package/dist/shortcuts/ehr/operations/hr-contact.js +363 -0
  68. package/dist/shortcuts/ehr/operations/hr-ds.js +298 -0
  69. package/dist/shortcuts/ehr/operations/hr-report.js +386 -0
  70. package/dist/shortcuts/ehr/operations/recruit-write.js +1629 -0
  71. package/dist/shortcuts/ehr/operations/recruit.js +803 -0
  72. package/dist/shortcuts/ehr/operations/registry.js +43 -0
  73. package/dist/shortcuts/ehr/operations/salary.js +319 -0
  74. package/dist/shortcuts/ehr/operations/shared.js +246 -0
  75. package/dist/shortcuts/ehr/operations/types.js +25 -0
  76. package/dist/shortcuts/ehr/operations.js +25 -0
  77. package/dist/shortcuts/esb/continuation.js +70 -0
  78. package/dist/shortcuts/esb/errors.js +65 -0
  79. package/dist/shortcuts/esb/host.js +187 -0
  80. package/dist/shortcuts/esb/index.js +112 -0
  81. package/dist/shortcuts/esb/manifest.js +91 -0
  82. package/dist/shortcuts/esb/operations/input-format.js +31 -0
  83. package/dist/shortcuts/esb/operations/registry.js +48 -0
  84. package/dist/shortcuts/esb/operations/shared.js +152 -0
  85. package/dist/shortcuts/esb/operations/trigger.js +76 -0
  86. package/dist/shortcuts/esb/operations/types.js +21 -0
  87. package/dist/shortcuts/esb/operations.js +15 -0
  88. package/dist/shortcuts/fna/continuation.js +70 -0
  89. package/dist/shortcuts/fna/errors.js +59 -0
  90. package/dist/shortcuts/fna/host.js +146 -0
  91. package/dist/shortcuts/fna/index.js +111 -0
  92. package/dist/shortcuts/fna/manifest.js +41 -0
  93. package/dist/shortcuts/fna/operations/budget.js +124 -0
  94. package/dist/shortcuts/fna/operations/expense-center.js +148 -0
  95. package/dist/shortcuts/fna/operations/invoice-writeoff.js +212 -0
  96. package/dist/shortcuts/fna/operations/loan.js +195 -0
  97. package/dist/shortcuts/fna/operations/registry.js +35 -0
  98. package/dist/shortcuts/fna/operations/shared.js +210 -0
  99. package/dist/shortcuts/fna/operations/types.js +25 -0
  100. package/dist/shortcuts/fna/operations.js +19 -0
  101. package/dist/shortcuts/hrm/errors.js +38 -0
  102. package/dist/shortcuts/hrm/host.js +156 -0
  103. package/dist/shortcuts/hrm/index.js +111 -0
  104. package/dist/shortcuts/hrm/manifest.js +32 -0
  105. package/dist/shortcuts/hrm/operations/employee.js +338 -0
  106. package/dist/shortcuts/hrm/operations/org.js +110 -0
  107. package/dist/shortcuts/hrm/operations/position.js +176 -0
  108. package/dist/shortcuts/hrm/operations/registry.js +33 -0
  109. package/dist/shortcuts/hrm/operations/shared.js +143 -0
  110. package/dist/shortcuts/hrm/operations/types.js +23 -0
  111. package/dist/shortcuts/hrm/operations.js +19 -0
  112. package/dist/shortcuts/index.js +20 -0
  113. package/dist/shortcuts/invoice/host.js +99 -94
  114. package/dist/shortcuts/invoice/index.js +65 -61
  115. package/dist/shortcuts/invoice/manifest.js +222 -14
  116. package/dist/shortcuts/invoice/operations/browse-field.js +17 -0
  117. package/dist/shortcuts/invoice/operations/issuing.js +198 -0
  118. package/dist/shortcuts/invoice/operations/ocr-preview.js +6 -3
  119. package/dist/shortcuts/invoice/operations/registry.js +17 -0
  120. package/dist/shortcuts/invoice/operations/reim.js +401 -0
  121. package/dist/shortcuts/invoice/operations/shared.js +271 -6
  122. package/dist/shortcuts/invoice/operations/validate-preview.js +1 -1
  123. package/dist/shortcuts/jiuchuanhui/cache.js +441 -0
  124. package/dist/shortcuts/jiuchuanhui/continuation.js +70 -0
  125. package/dist/shortcuts/jiuchuanhui/errors.js +59 -0
  126. package/dist/shortcuts/jiuchuanhui/host.js +159 -0
  127. package/dist/shortcuts/jiuchuanhui/index.js +109 -0
  128. package/dist/shortcuts/jiuchuanhui/manifest.js +469 -0
  129. package/dist/shortcuts/jiuchuanhui/operations/datajson.js +214 -0
  130. package/dist/shortcuts/jiuchuanhui/operations/esb.js +157 -0
  131. package/dist/shortcuts/jiuchuanhui/operations/generic.js +146 -0
  132. package/dist/shortcuts/jiuchuanhui/operations/registry.js +133 -0
  133. package/dist/shortcuts/jiuchuanhui/operations/shared.js +158 -0
  134. package/dist/shortcuts/jiuchuanhui/operations/types.js +1 -0
  135. package/dist/shortcuts/jiuchuanhui/operations.js +8 -0
  136. package/dist/shortcuts/mail/continuation.js +70 -0
  137. package/dist/shortcuts/mail/errors.js +53 -0
  138. package/dist/shortcuts/mail/host.js +182 -0
  139. package/dist/shortcuts/mail/index.js +519 -0
  140. package/dist/shortcuts/mail/manifest.js +38 -0
  141. package/dist/shortcuts/mail/operations/mail-blacklist.js +79 -0
  142. package/dist/shortcuts/mail/operations/mail-contacts.js +195 -0
  143. package/dist/shortcuts/mail/operations/mail-manage.js +335 -0
  144. package/dist/shortcuts/mail/operations/mail-read.js +508 -0
  145. package/dist/shortcuts/mail/operations/mail-send.js +474 -0
  146. package/dist/shortcuts/mail/operations/mail-sign.js +203 -0
  147. package/dist/shortcuts/mail/operations/mail-template.js +170 -0
  148. package/dist/shortcuts/mail/operations/registry.js +41 -0
  149. package/dist/shortcuts/mail/operations/shared.js +64 -0
  150. package/dist/shortcuts/mail/operations/types.js +27 -0
  151. package/dist/shortcuts/mail/operations.js +19 -0
  152. package/dist/shortcuts/plan/continuation.js +70 -0
  153. package/dist/shortcuts/plan/errors.js +70 -0
  154. package/dist/shortcuts/plan/host.js +180 -0
  155. package/dist/shortcuts/plan/index.js +150 -0
  156. package/dist/shortcuts/plan/manifest.js +53 -0
  157. package/dist/shortcuts/plan/operations/link.js +256 -0
  158. package/dist/shortcuts/plan/operations/read.js +259 -0
  159. package/dist/shortcuts/plan/operations/registry.js +33 -0
  160. package/dist/shortcuts/plan/operations/shared.js +246 -0
  161. package/dist/shortcuts/plan/operations/types.js +49 -0
  162. package/dist/shortcuts/plan/operations/version.js +49 -0
  163. package/dist/shortcuts/plan/operations/write.js +710 -0
  164. package/dist/shortcuts/plan/operations.js +8 -0
  165. package/docs/SKILL.md +11 -7
  166. package/docs/_catalog.md +23 -5
  167. package/docs/agent-invoice.md +31 -10
  168. package/docs/agent-skill-install.md +211 -0
  169. package/docs/calendar.md +87 -0
  170. package/docs/e10-auth.md +28 -9
  171. package/docs/ehr.md +186 -0
  172. package/docs/esb.md +64 -0
  173. package/docs/fna.md +72 -0
  174. package/docs/hrm.md +89 -0
  175. package/docs/invoice.md +66 -20
  176. package/docs/jiuchuanhui.md +131 -0
  177. package/docs/operation-manual.md +443 -0
  178. package/docs/plan.md +82 -0
  179. package/docs/wenshuding.md +129 -0
  180. package/docs/ziguanjia.md +89 -0
  181. package/package.json +4 -4
  182. package/scripts/package-skill.mjs +127 -34
  183. package/scripts/postbuild.mjs +13 -0
  184. package/skill-template/business-info.json +13 -2
  185. package/skill-template/domains/calendar.md +15 -0
  186. package/skill-template/domains/esb.md +13 -0
  187. package/skill-template/domains/hrm.md +16 -0
  188. package/skill-template/domains/jiuchuanhui.md +23 -0
  189. package/skill-template/domains/jucailin.md +22 -0
  190. package/skill-template/domains/mail.md +21 -0
  191. package/skill-template/domains/plan.md +17 -0
  192. package/skill-template/domains/qiyecheng.md +17 -0
  193. package/skill-template/domains/shared.md +9 -3
  194. package/skill-template/domains/skill-maker.md +10 -0
  195. package/skill-template/domains/wenshuding.md +22 -0
  196. package/skill-template/domains/{invoice.md → yepiaotong.md} +4 -0
  197. package/skill-template/domains/ziguanjia.md +21 -0
  198. package/skill-template/master-skill-template.md +12 -6
  199. package/skill-template/skill-template.md +40 -9
  200. package/skills/weaver-e10-calendar/SKILL.md +101 -0
  201. package/skills/weaver-e10-calendar/product.json +8 -0
  202. package/skills/weaver-e10-calendar/references/calendar-app-check.md +65 -0
  203. package/skills/weaver-e10-calendar/references/calendar-dict.md +55 -0
  204. package/skills/weaver-e10-calendar/references/calendar-query.md +70 -0
  205. package/skills/weaver-e10-calendar/references/calendar-write.md +97 -0
  206. package/skills/weaver-e10-calendar/references/source-manifest.json +54 -0
  207. package/skills/weaver-e10-esb/SKILL.md +102 -0
  208. package/skills/weaver-e10-esb/product.json +8 -0
  209. package/skills/weaver-e10-esb/references/input-format.md +52 -0
  210. package/skills/weaver-e10-esb/references/source-manifest.json +242 -0
  211. package/skills/weaver-e10-esb/references/trigger.md +99 -0
  212. package/skills/weaver-e10-hrm/SKILL.md +87 -0
  213. package/skills/weaver-e10-hrm/product.json +8 -0
  214. package/skills/weaver-e10-hrm/references/employee.md +109 -0
  215. package/skills/weaver-e10-hrm/references/org.md +95 -0
  216. package/skills/weaver-e10-hrm/references/position.md +95 -0
  217. package/skills/weaver-e10-hrm/references/source-manifest.json +121 -0
  218. package/skills/weaver-e10-jiuchuanhui/SKILL.md +174 -0
  219. package/skills/weaver-e10-jiuchuanhui/product.json +8 -0
  220. package/skills/weaver-e10-jiuchuanhui/references/cache.md +110 -0
  221. package/skills/weaver-e10-jiuchuanhui/references/clue.md +61 -0
  222. package/skills/weaver-e10-jiuchuanhui/references/contact-plan.md +56 -0
  223. package/skills/weaver-e10-jiuchuanhui/references/contact-records.md +48 -0
  224. package/skills/weaver-e10-jiuchuanhui/references/contact.md +56 -0
  225. package/skills/weaver-e10-jiuchuanhui/references/customer.md +69 -0
  226. package/skills/weaver-e10-jiuchuanhui/references/disabled-capabilities.md +24 -0
  227. package/skills/weaver-e10-jiuchuanhui/references/discovery-config.md +60 -0
  228. package/skills/weaver-e10-jiuchuanhui/references/general-helpers.md +59 -0
  229. package/skills/weaver-e10-jiuchuanhui/references/jiuchuanhui-entry.md +60 -0
  230. package/skills/weaver-e10-jiuchuanhui/references/sale.md +72 -0
  231. package/skills/weaver-e10-jiuchuanhui/references/source-manifest.json +2632 -0
  232. package/skills/weaver-e10-jucailin/SKILL.md +101 -0
  233. package/skills/weaver-e10-jucailin/product.json +8 -0
  234. package/skills/weaver-e10-jucailin/references/attend-read.md +73 -0
  235. package/skills/weaver-e10-jucailin/references/attend-write.md +82 -0
  236. package/skills/weaver-e10-jucailin/references/hr-contact.md +92 -0
  237. package/skills/weaver-e10-jucailin/references/hr-datasource.md +104 -0
  238. package/skills/weaver-e10-jucailin/references/hr-report.md +76 -0
  239. package/skills/weaver-e10-jucailin/references/recruit-read.md +76 -0
  240. package/skills/weaver-e10-jucailin/references/recruit-write.md +70 -0
  241. package/skills/weaver-e10-jucailin/references/safety-boundaries.md +35 -0
  242. package/skills/weaver-e10-jucailin/references/salary.md +110 -0
  243. package/skills/weaver-e10-jucailin/references/source-manifest.json +152 -0
  244. package/skills/weaver-e10-mail/SKILL.md +151 -0
  245. package/skills/weaver-e10-mail/product.json +8 -0
  246. package/skills/weaver-e10-mail/references/mail-agent-entry.md +47 -0
  247. package/skills/weaver-e10-mail/references/mail-attachment.md +30 -0
  248. package/skills/weaver-e10-mail/references/mail-blacklist.md +27 -0
  249. package/skills/weaver-e10-mail/references/mail-contacts.md +33 -0
  250. package/skills/weaver-e10-mail/references/mail-manage.md +44 -0
  251. package/skills/weaver-e10-mail/references/mail-read.md +76 -0
  252. package/skills/weaver-e10-mail/references/mail-send.md +43 -0
  253. package/skills/weaver-e10-mail/references/mail-sign.md +33 -0
  254. package/skills/weaver-e10-mail/references/mail-template.md +31 -0
  255. package/skills/weaver-e10-mail/references/safety-boundaries.md +32 -0
  256. package/skills/weaver-e10-plan/SKILL.md +139 -0
  257. package/skills/weaver-e10-plan/product.json +8 -0
  258. package/skills/weaver-e10-plan/references/plan-collect-and-compose.md +123 -0
  259. package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +138 -0
  260. package/skills/weaver-e10-plan/references/plan-report-query.md +154 -0
  261. package/skills/weaver-e10-plan/references/plan-report-remind.md +104 -0
  262. package/skills/weaver-e10-plan/references/plan-report-write.md +162 -0
  263. package/skills/weaver-e10-plan/references/source-manifest.json +858 -0
  264. package/skills/weaver-e10-qiyecheng/SKILL.md +118 -0
  265. package/skills/weaver-e10-qiyecheng/product.json +8 -0
  266. package/skills/weaver-e10-qiyecheng/references/budget.md +65 -0
  267. package/skills/weaver-e10-qiyecheng/references/catalog.md +56 -0
  268. package/skills/weaver-e10-qiyecheng/references/expense-center.md +51 -0
  269. package/skills/weaver-e10-qiyecheng/references/invoice-writeoff.md +57 -0
  270. package/skills/weaver-e10-qiyecheng/references/loan-management.md +59 -0
  271. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +698 -0
  272. package/skills/weaver-e10-shared/SKILL.md +86 -0
  273. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +127 -0
  274. package/skills/weaver-e10-shared/references/json-output-contract.md +120 -0
  275. package/skills/weaver-e10-shared/references/weaver-e10-installation.md +110 -0
  276. package/skills/weaver-e10-skill-maker/SKILL.md +77 -0
  277. package/skills/weaver-e10-skill-maker/product.json +8 -0
  278. package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +124 -0
  279. package/skills/weaver-e10-skill-maker/references/detector-validation.md +101 -0
  280. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +230 -0
  281. package/skills/weaver-e10-skill-maker/references/post-generation-install.md +105 -0
  282. package/skills/weaver-e10-skill-maker/references/source-update-detection.md +261 -0
  283. package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +141 -0
  284. package/skills/weaver-e10-wenshuding/SKILL.md +157 -0
  285. package/skills/weaver-e10-wenshuding/product.json +8 -0
  286. package/skills/weaver-e10-wenshuding/references/archive-agent-entry.md +63 -0
  287. package/skills/weaver-e10-wenshuding/references/archive-borrow-car.md +52 -0
  288. package/skills/weaver-e10-wenshuding/references/archive-borrow-list.md +52 -0
  289. package/skills/weaver-e10-wenshuding/references/archive-disabled-capabilities.md +22 -0
  290. package/skills/weaver-e10-wenshuding/references/archive-download.md +48 -0
  291. package/skills/weaver-e10-wenshuding/references/archive-flow.md +46 -0
  292. package/skills/weaver-e10-wenshuding/references/archive-fonds.md +34 -0
  293. package/skills/weaver-e10-wenshuding/references/archive-info.md +33 -0
  294. package/skills/weaver-e10-wenshuding/references/archive-search.md +52 -0
  295. package/skills/weaver-e10-wenshuding/references/archive-upload.md +41 -0
  296. package/skills/weaver-e10-wenshuding/references/source-manifest.json +517 -0
  297. package/skills/weaver-e10-yepiaotong/SKILL.md +184 -0
  298. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-add.md +1 -1
  299. package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +47 -0
  300. package/skills/weaver-e10-yepiaotong/references/invoice-browse-field-data.md +204 -0
  301. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-delete.md +1 -1
  302. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-detail.md +13 -5
  303. package/skills/weaver-e10-yepiaotong/references/invoice-disabled-capabilities.md +28 -0
  304. package/skills/weaver-e10-yepiaotong/references/invoice-download.md +31 -0
  305. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +45 -0
  306. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-file-upload.md +15 -4
  307. package/skills/weaver-e10-yepiaotong/references/invoice-import.md +45 -0
  308. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +120 -0
  309. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-field-rules.md +161 -0
  310. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +99 -0
  311. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-ocr-preview.md +14 -4
  312. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +58 -0
  313. package/skills/weaver-e10-yepiaotong/references/invoice-red.md +261 -0
  314. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +97 -0
  315. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-update.md +1 -1
  316. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-validation-preview.md +10 -3
  317. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +1340 -0
  318. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +845 -0
  319. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +94 -0
  320. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +449 -0
  321. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +266 -0
  322. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +494 -0
  323. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +1103 -0
  324. package/skills/weaver-e10-ziguanjia/SKILL.md +162 -0
  325. package/skills/weaver-e10-ziguanjia/product.json +8 -0
  326. package/skills/weaver-e10-ziguanjia/references/source-manifest.json +147 -0
  327. package/skills/weaver-e10-ziguanjia/references/ziguanjia-agent-entry.md +65 -0
  328. package/skills/weaver-e10-ziguanjia/references/ziguanjia-create.md +45 -0
  329. package/skills/weaver-e10-ziguanjia/references/ziguanjia-depre.md +48 -0
  330. package/skills/weaver-e10-ziguanjia/references/ziguanjia-disabled-capabilities.md +22 -0
  331. package/skills/weaver-e10-ziguanjia/references/ziguanjia-purch.md +57 -0
  332. package/skills/weaver-e10-ziguanjia/references/ziguanjia-query.md +62 -0
  333. package/skills/weaver-e10-ziguanjia/references/ziguanjia-repair.md +83 -0
  334. package/skills/weaver-e10-ziguanjia/references/ziguanjia-resolve.md +49 -0
  335. package/skills/weaver-e10-ziguanjia/references/ziguanjia-return.md +70 -0
  336. package/skills/weaver-e10-ziguanjia/references/ziguanjia-update.md +45 -0
  337. package/skills/weaver-e10-ziguanjia/references/ziguanjia-use.md +60 -0
  338. package/skills/weaver-e10-ziguanjia/references/ziguanjia-viewlink.md +81 -0
  339. package/skills/weaver-work-cli-invoice/SKILL.md +0 -103
  340. package/skills/weaver-work-cli-invoice/references/invoice-agent-entry.md +0 -38
  341. package/skills/weaver-work-cli-invoice/references/invoice-disabled-capabilities.md +0 -26
  342. package/skills/weaver-work-cli-invoice/references/invoice-download.md +0 -22
  343. package/skills/weaver-work-cli-invoice/references/invoice-enterprise-list.md +0 -35
  344. package/skills/weaver-work-cli-invoice/references/invoice-import.md +0 -28
  345. package/skills/weaver-work-cli-invoice/references/invoice-personal-list.md +0 -47
  346. package/skills/weaver-work-cli-shared/SKILL.md +0 -53
  347. package/skills/weaver-work-cli-shared/references/e10-auth-and-session.md +0 -83
  348. package/skills/weaver-work-cli-shared/references/json-output-contract.md +0 -61
  349. package/skills/weaver-work-cli-shared/references/weaver-work-cli-installation.md +0 -61
  350. /package/skills/{weaver-work-cli-shared → weaver-e10-shared}/references/high-risk-write.md +0 -0
  351. /package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/product.json +0 -0
@@ -0,0 +1,152 @@
1
+ import { esbValidationError } from '../errors.js';
2
+ /** 原型污染防护:禁止出现在输入对象中的键。 */
3
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
4
+ export function asObject(value, field = 'input') {
5
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
6
+ throw esbValidationError('input_not_object', `${field} 必须是 JSON 对象`);
7
+ }
8
+ return value;
9
+ }
10
+ export function assertNoForbiddenKeys(input) {
11
+ for (const key of Object.keys(input)) {
12
+ if (FORBIDDEN_KEYS.has(key)) {
13
+ throw esbValidationError('forbidden_key', `输入包含非法字段:${key}`);
14
+ }
15
+ }
16
+ }
17
+ /** 顶层输入严格白名单:schema 已声明 additionalProperties: false,运行时同样拒绝未知字段。 */
18
+ export function assertKnownKeys(input, allowed, operation) {
19
+ const unknown = Object.keys(input).filter((key) => !allowed.includes(key));
20
+ if (unknown.length > 0) {
21
+ throw esbValidationError('unknown_field', `${operation} 不支持字段:${unknown.join('、')}`, { unknown });
22
+ }
23
+ }
24
+ function isFilled(value) {
25
+ return value !== undefined && value !== null && value !== '';
26
+ }
27
+ export function requiredString(value, field) {
28
+ if (!isFilled(value)) {
29
+ throw esbValidationError('field_required', `${field} 必填`);
30
+ }
31
+ if (typeof value === 'object') {
32
+ throw esbValidationError('field_invalid', `${field} 必须是字符串`);
33
+ }
34
+ return String(value);
35
+ }
36
+ /** 动作流 ID / applicationId:源资料中为长整型数字串,按字符串传递避免精度丢失。 */
37
+ export function flowIdString(value, field) {
38
+ const text = requiredString(value, field);
39
+ if (!/^\d+$/.test(text)) {
40
+ throw esbValidationError('field_invalid', `${field} 必须是数字 ID(长整型按字符串传递)`);
41
+ }
42
+ return text;
43
+ }
44
+ export const TRIGGER_INPUT_KEYS = ['esbFlowId', 'uniqueIndent', 'employeeId', 'customParams', 'moduleSource'];
45
+ /**
46
+ * 触发入参归一化。esbFlowId / uniqueIndent 二选一:都缺或多传均为结构化校验错误,
47
+ * 不做静默回退,避免把「唯一值触发」误当「普通触发」发出。
48
+ */
49
+ export function normalizeTriggerInput(input) {
50
+ const hasFlowId = isFilled(input.esbFlowId);
51
+ const hasUniqueIndent = isFilled(input.uniqueIndent);
52
+ if (!hasFlowId && !hasUniqueIndent) {
53
+ throw esbValidationError('trigger_target_missing', 'esbFlowId 与 uniqueIndent 二选一必填:普通触发传 esbFlowId,唯一值触发传 uniqueIndent');
54
+ }
55
+ if (hasFlowId && hasUniqueIndent) {
56
+ throw esbValidationError('trigger_target_conflict', 'esbFlowId 与 uniqueIndent 不能同时传入,请二选一');
57
+ }
58
+ const employeeId = requiredString(input.employeeId, 'employeeId');
59
+ const customParams = asObject(input.customParams, 'customParams');
60
+ const mainTable = customParams.mainTable;
61
+ if (!mainTable || typeof mainTable !== 'object' || Array.isArray(mainTable)) {
62
+ throw esbValidationError('custom_params_invalid', 'customParams.mainTable 必须是 JSON 对象');
63
+ }
64
+ const moduleSource = isFilled(input.moduleSource) ? requiredString(input.moduleSource, 'moduleSource') : undefined;
65
+ return {
66
+ mode: hasFlowId ? 'esbFlowId' : 'uniqueIndent',
67
+ ...(hasFlowId ? { esbFlowId: flowIdString(input.esbFlowId, 'esbFlowId') } : {}),
68
+ ...(hasUniqueIndent ? { uniqueIndent: requiredString(input.uniqueIndent, 'uniqueIndent') } : {}),
69
+ employeeId,
70
+ customParams,
71
+ ...(moduleSource === undefined ? {} : { moduleSource }),
72
+ };
73
+ }
74
+ /** 触发接口请求体:与源接口文档的字段命名保持一致。 */
75
+ export function buildTriggerPayload(target) {
76
+ return {
77
+ customParams: target.customParams,
78
+ ...(target.moduleSource === undefined ? {} : { moduleSource: target.moduleSource }),
79
+ ...(target.esbFlowId === undefined ? {} : { esbFlowId: target.esbFlowId }),
80
+ ...(target.uniqueIndent === undefined ? {} : { uniqueIndent: target.uniqueIndent }),
81
+ employeeId: target.employeeId,
82
+ };
83
+ }
84
+ const MAX_PLACEHOLDERS = 100;
85
+ /** 收集模板中的 `#可选` 占位路径,告诉 Agent 哪些字段可以删或替换。 */
86
+ export function collectPlaceholders(value, prefix = '', collected = []) {
87
+ if (collected.length >= MAX_PLACEHOLDERS)
88
+ return collected;
89
+ if (Array.isArray(value)) {
90
+ value.forEach((item, index) => collectPlaceholders(item, `${prefix}[${index}]`, collected));
91
+ return collected;
92
+ }
93
+ if (value && typeof value === 'object') {
94
+ for (const [key, item] of Object.entries(value)) {
95
+ collectPlaceholders(item, prefix ? `${prefix}.${key}` : key, collected);
96
+ if (collected.length >= MAX_PLACEHOLDERS)
97
+ break;
98
+ }
99
+ return collected;
100
+ }
101
+ if (typeof value === 'string' && value.trim() === '#可选')
102
+ collected.push(prefix);
103
+ return collected;
104
+ }
105
+ const PAGE_ACTIONS = {
106
+ 0: '无需页面操作',
107
+ 1: '刷新页面',
108
+ 2: '关闭页面',
109
+ 3: '跳转页面',
110
+ };
111
+ const REMINDERS = {
112
+ 0: '无提醒',
113
+ 1: '提醒',
114
+ 2: '确认',
115
+ 3: '警告',
116
+ 4: '错误',
117
+ };
118
+ function asRecord(value) {
119
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
120
+ }
121
+ /**
122
+ * 触发结果归一化:resultCode 200 已在 host 层校验,这里只做 actionData 解读与后续动作摘要,
123
+ * 枚举含义取自源接口文档,不新增服务端未返回的字段。
124
+ */
125
+ export function summarizeTriggerResult(value) {
126
+ const record = asRecord(value);
127
+ const actionData = asRecord(record.actionData);
128
+ const pageAction = Number(actionData.pageAction ?? 0);
129
+ const reminder = Number(actionData.reminder ?? 0);
130
+ const hasData = Number(actionData.hasData ?? 0);
131
+ const followUp = [];
132
+ if (pageAction !== 0)
133
+ followUp.push(PAGE_ACTIONS[pageAction] || `页面动作 ${pageAction}`);
134
+ if (reminder !== 0) {
135
+ const reminderMsg = typeof actionData.reminderMsg === 'string' && actionData.reminderMsg.trim()
136
+ ? actionData.reminderMsg.trim()
137
+ : undefined;
138
+ followUp.push(`${REMINDERS[reminder] || `提醒 ${reminder}`}${reminderMsg ? `:${reminderMsg}` : ''}`);
139
+ }
140
+ if (hasData === 1)
141
+ followUp.push('动作流返回了业务数据,见 actionData.responseData');
142
+ if (followUp.length === 0)
143
+ followUp.push('动作流已执行完成,无需额外页面动作');
144
+ return {
145
+ resultCode: 200,
146
+ resultMsg: typeof record.resultMsg === 'string' ? record.resultMsg : '',
147
+ ...(record.resultData === undefined ? {} : { resultData: record.resultData }),
148
+ ...(record.nextAction === undefined ? {} : { nextAction: record.nextAction }),
149
+ actionData,
150
+ followUp,
151
+ };
152
+ }
@@ -0,0 +1,76 @@
1
+ import { esbSuccess } from './types.js';
2
+ import { esbValidationError } from '../errors.js';
3
+ import { isEsbFlowUnavailable } from '../host.js';
4
+ import { asObject, buildTriggerPayload, collectPlaceholders, normalizeTriggerInput, requiredString, summarizeTriggerResult, } from './shared.js';
5
+ /** prepare 阶段回查失败的提示文案:只暴露分类,不泄漏请求细节。 */
6
+ function describeLookupFailure(error) {
7
+ if (error && typeof error === 'object') {
8
+ const structured = error;
9
+ const subtype = typeof structured.subtype === 'string' ? structured.subtype : 'unknown';
10
+ return `subtype=${subtype}`;
11
+ }
12
+ return 'cause=unknown';
13
+ }
14
+ export const esbTriggerHandlers = {
15
+ 'esb.trigger.prepare': async (input, { host, continuation }) => {
16
+ const target = normalizeTriggerInput(input);
17
+ const warnings = [];
18
+ let templateFields = null;
19
+ if (target.mode === 'esbFlowId') {
20
+ const esbFlowId = target.esbFlowId;
21
+ try {
22
+ const raw = await host.inputFormat(esbFlowId);
23
+ const record = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
24
+ templateFields = collectPlaceholders(record.customParams ?? null);
25
+ }
26
+ catch (error) {
27
+ // 目标动作流本身不可用(不存在/未绑定/未启用/回收站)时阻断;其余问题只降级为警告。
28
+ if (isEsbFlowUnavailable(error))
29
+ throw error;
30
+ warnings.push(`目标动作流入参模板回查未成功(${describeLookupFailure(error)}),已跳过回查;触发是否可用以 apply 返回为准`);
31
+ }
32
+ }
33
+ else {
34
+ warnings.push('唯一值触发无法按 applicationId 回查:同一租户下存在相同唯一值的多条动作流时,系统只执行 create_time 最新的一条');
35
+ }
36
+ const payload = buildTriggerPayload(target);
37
+ const session = await host.getSession();
38
+ const token = await continuation.issue({
39
+ operation: 'esb.trigger.apply',
40
+ target: { mode: target.mode, value: target.esbFlowId ?? target.uniqueIndent },
41
+ actor: { userId: session.userId, tenantKey: session.tenantKey, profile: session.profile },
42
+ payload,
43
+ });
44
+ return esbSuccess('esb.trigger.prepare', {
45
+ target: {
46
+ mode: target.mode,
47
+ esbFlowId: target.esbFlowId ?? null,
48
+ uniqueIndent: target.uniqueIndent ?? null,
49
+ employeeId: target.employeeId,
50
+ },
51
+ requestPreview: payload,
52
+ templateFields,
53
+ continuation: token,
54
+ expiresInSeconds: 600,
55
+ }, { status: 'PREPARED' }, warnings);
56
+ },
57
+ 'esb.trigger.apply': async (input, { host, continuation }) => {
58
+ if (input.confirm !== true) {
59
+ throw esbValidationError('confirm_required', '触发动作流是高风险写操作:必须显式传 confirm: true 表示用户已确认执行');
60
+ }
61
+ const record = await continuation.verify(requiredString(input.continuation, 'continuation'), 'esb.trigger.apply');
62
+ const session = await host.getSession();
63
+ const actor = record.actor && typeof record.actor === 'object' ? record.actor : {};
64
+ if (actor.userId !== session.userId || actor.tenantKey !== session.tenantKey) {
65
+ throw esbValidationError('continuation_actor_changed', 'continuation 签发时的登录身份与当前会话不一致,请重新执行 esb.trigger.prepare 后再确认');
66
+ }
67
+ const payload = asObject(record.payload, 'continuation.payload');
68
+ // 防御性复核:continuation 由 CLI 签发,但仍校验请求体形状未被破坏。
69
+ const mainTable = payload.customParams?.mainTable;
70
+ if (!mainTable || typeof mainTable !== 'object' || Array.isArray(mainTable)) {
71
+ throw esbValidationError('continuation_payload_invalid', 'continuation 中的 customParams.mainTable 缺失,请重新执行 esb.trigger.prepare');
72
+ }
73
+ const result = await host.trigger(payload);
74
+ return esbSuccess('esb.trigger.apply', summarizeTriggerResult(result), { status: 'COMPLETE' });
75
+ },
76
+ };
@@ -0,0 +1,21 @@
1
+ export const READ = 'read';
2
+ export const READ_BEFORE_WRITE = 'read-before-write';
3
+ export const HIGH_RISK_WRITE = 'high-risk-write';
4
+ export function esbSuccess(action, data, meta, warnings = []) {
5
+ const payload = { ok: true, action, data };
6
+ if (meta && Object.keys(meta).length > 0)
7
+ payload.meta = meta;
8
+ if (warnings.length > 0)
9
+ payload.warnings = warnings;
10
+ return payload;
11
+ }
12
+ /** 构造「对象类型 + 严格禁止额外字段」的 JSON Schema。 */
13
+ export function schemaOf(properties, options = {}) {
14
+ return {
15
+ type: 'object',
16
+ additionalProperties: false,
17
+ properties,
18
+ ...(options.required?.length ? { required: options.required } : {}),
19
+ ...(options.description ? { description: options.description } : {}),
20
+ };
21
+ }
@@ -0,0 +1,15 @@
1
+ import { esbManifest } from './manifest.js';
2
+ import { getEsbOperation } from './operations/registry.js';
3
+ import { assertKnownKeys, assertNoForbiddenKeys, asObject } from './operations/shared.js';
4
+ /** 顶层输入白名单直接取自 manifest:schema 即运行时约束,避免两处规则漂移。 */
5
+ const ALLOWED_KEYS = Object.fromEntries(esbManifest.operations.map((operation) => [
6
+ operation.name,
7
+ Object.keys(operation.inputSchema.properties ?? {}),
8
+ ]));
9
+ export async function executeEsbOperation(operation, rawInput, context) {
10
+ const definition = getEsbOperation(operation);
11
+ const input = asObject(rawInput);
12
+ assertNoForbiddenKeys(input);
13
+ assertKnownKeys(input, ALLOWED_KEYS[operation] ?? [], operation);
14
+ return definition.handler(input, context);
15
+ }
@@ -0,0 +1,70 @@
1
+ import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
2
+ import { existsSync } from 'node:fs';
3
+ import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
4
+ import { homedir } from 'node:os';
5
+ import { resolve } from 'node:path';
6
+ import { fnaValidationError } from './errors.js';
7
+ function stateRoot(ctx) {
8
+ const configured = ctx?.config?.path();
9
+ if (configured)
10
+ return resolve(configured, '..');
11
+ return process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve(homedir(), '.weaver-work-cli');
12
+ }
13
+ async function loadKey(ctx) {
14
+ const keysDir = resolve(stateRoot(ctx), 'keys');
15
+ const filename = resolve(keysDir, 'fna-continuation.key');
16
+ await mkdir(keysDir, { recursive: true, mode: 0o700 });
17
+ if (existsSync(filename))
18
+ return readFile(filename);
19
+ const key = randomBytes(32);
20
+ try {
21
+ await writeFile(filename, key, { flag: 'wx', mode: 0o600 });
22
+ if (process.platform !== 'win32')
23
+ await chmod(filename, 0o600).catch(() => undefined);
24
+ return key;
25
+ }
26
+ catch {
27
+ return readFile(filename);
28
+ }
29
+ }
30
+ function encode(value) {
31
+ return Buffer.from(JSON.stringify(value)).toString('base64url');
32
+ }
33
+ function signature(payload, key) {
34
+ return createHmac('sha256', key).update(payload).digest('base64url');
35
+ }
36
+ export function createFnaContinuationSigner(ctx) {
37
+ return {
38
+ async issue(payload, ttlMs = 10 * 60_000) {
39
+ const issuedAt = Date.now();
40
+ const body = encode({ ...payload, issuedAt, expiresAt: issuedAt + ttlMs });
41
+ const sig = signature(body, await loadKey(ctx));
42
+ return `${body}.${sig}`;
43
+ },
44
+ async verify(token, expectedOperation) {
45
+ if (typeof token !== 'string' || !token.includes('.')) {
46
+ throw fnaValidationError('continuation_invalid', 'continuation 无效');
47
+ }
48
+ const [body, provided] = token.split('.');
49
+ const expected = signature(body, await loadKey(ctx));
50
+ const valid = provided.length === expected.length
51
+ && timingSafeEqual(Buffer.from(provided), Buffer.from(expected));
52
+ if (!valid)
53
+ throw fnaValidationError('continuation_invalid', 'continuation 签名校验失败');
54
+ let value;
55
+ try {
56
+ value = JSON.parse(Buffer.from(body, 'base64url').toString('utf8'));
57
+ }
58
+ catch {
59
+ throw fnaValidationError('continuation_invalid', 'continuation 内容无法解析');
60
+ }
61
+ if (value.operation !== expectedOperation) {
62
+ throw fnaValidationError('continuation_mismatch', 'continuation 不属于当前操作');
63
+ }
64
+ if (!Number.isSafeInteger(value.expiresAt) || value.expiresAt < Date.now()) {
65
+ throw fnaValidationError('continuation_expired', 'continuation 已过期');
66
+ }
67
+ return value;
68
+ },
69
+ };
70
+ }
@@ -0,0 +1,59 @@
1
+ import { CliError, ExitCode } from '../../core/errors.js';
2
+ export class FnaCliError extends CliError {
3
+ type;
4
+ subtype;
5
+ code;
6
+ retryable;
7
+ stage;
8
+ details;
9
+ partialData;
10
+ constructor(type, subtype, message, options = {}) {
11
+ super(message, options.exitCode ?? ExitCode.InternalError);
12
+ this.name = 'FnaCliError';
13
+ this.type = type;
14
+ this.subtype = subtype;
15
+ this.code = options.code;
16
+ this.retryable = options.retryable ?? false;
17
+ this.stage = options.stage;
18
+ this.details = options.details;
19
+ this.partialData = options.partialData;
20
+ }
21
+ }
22
+ export function fnaValidationError(subtype, message, details) {
23
+ return new FnaCliError('validation', subtype, message, {
24
+ details,
25
+ exitCode: ExitCode.UsageError,
26
+ });
27
+ }
28
+ export function fnaAuthError(subtype, message, details) {
29
+ return new FnaCliError('authentication', subtype, message, {
30
+ details,
31
+ exitCode: ExitCode.AuthError,
32
+ });
33
+ }
34
+ export function fnaNetworkError(subtype, message, options = {}) {
35
+ return new FnaCliError('network', subtype, message, {
36
+ ...options,
37
+ retryable: options.retryable ?? true,
38
+ exitCode: ExitCode.NetworkError,
39
+ });
40
+ }
41
+ export function fnaConfirmationError(action, details) {
42
+ return new FnaCliError('confirmation', 'required', '该操作需要明确确认', {
43
+ details: { action, ...details },
44
+ exitCode: ExitCode.ConfirmationRequired,
45
+ });
46
+ }
47
+ export function fnaPartialError(message, partialData, details) {
48
+ return new FnaCliError('partial', 'write_uncertain', message, {
49
+ details,
50
+ partialData,
51
+ exitCode: ExitCode.Partial,
52
+ });
53
+ }
54
+ export function isFnaNetworkError(error) {
55
+ return Boolean(error
56
+ && typeof error === 'object'
57
+ && 'type' in error
58
+ && error.type === 'network');
59
+ }
@@ -0,0 +1,146 @@
1
+ import { requireE10Session } from '../../internal/e10/context.js';
2
+ import { getActiveProfile } from '../../internal/e10/auth/session.js';
3
+ import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
4
+ import { FnaCliError, fnaAuthError, fnaNetworkError, fnaValidationError } from './errors.js';
5
+ function inferProfile(ctx) {
6
+ const options = ctx.getGlobalOptions();
7
+ return options.profile || getActiveProfile();
8
+ }
9
+ /**
10
+ * FNA 费控中心返回 WeaResult 外层,但子模块成功字段不统一:
11
+ * - 费用中心 AI 查询:{ code, msg, success, data }
12
+ * - 预算 / 借款管理 / 发票核销:{ code, msg, status, fail, data }
13
+ * 均以 code == 200 为业务成功。
14
+ */
15
+ export function isBusinessSuccess(value) {
16
+ if (!value || typeof value !== 'object')
17
+ return false;
18
+ if (typeof value.success === 'boolean')
19
+ return value.success;
20
+ if (typeof value.status === 'boolean')
21
+ return value.status;
22
+ if (value.code !== undefined && value.code !== null)
23
+ return Number(value.code) === 200;
24
+ return false;
25
+ }
26
+ export function businessMessage(value) {
27
+ if (!value || typeof value !== 'object')
28
+ return '泛微接口返回业务失败';
29
+ const candidates = [value.msg, value.message, value.data?.message];
30
+ for (const item of candidates) {
31
+ if (typeof item === 'string' && item.trim())
32
+ return item;
33
+ }
34
+ return '泛微接口返回业务失败';
35
+ }
36
+ function businessCode(value) {
37
+ if (!value || typeof value !== 'object')
38
+ return undefined;
39
+ const code = value.code ?? value.status;
40
+ if (typeof code === 'string' || typeof code === 'number')
41
+ return code;
42
+ return undefined;
43
+ }
44
+ export function assertPath(requestPath) {
45
+ if (typeof requestPath !== 'string' || !requestPath.startsWith('/') || requestPath.startsWith('//')) {
46
+ throw fnaValidationError('path_invalid', '请求路径必须是相对绝对路径');
47
+ }
48
+ if (/^https?:/i.test(requestPath) || /[\r\n]/.test(requestPath) || requestPath.includes('/../')) {
49
+ throw fnaValidationError('path_invalid', '请求路径不允许跨域或路径逃逸');
50
+ }
51
+ if (!requestPath.startsWith('/api/fna/') && !requestPath.startsWith('/api/app/fna/')) {
52
+ throw fnaValidationError('path_not_allowed', 'FNA 费控中心只能调用 /api/fna/ 或 /api/app/fna/ 路径');
53
+ }
54
+ }
55
+ function omitEmptyQueryValues(query) {
56
+ if (!query)
57
+ return undefined;
58
+ return Object.fromEntries(Object.entries(query).filter(([, value]) => value !== ''));
59
+ }
60
+ function mapRuntimeNetworkError(error) {
61
+ if (error instanceof E10ApiError && error.type === 'network') {
62
+ throw fnaNetworkError(error.subtype, error.message, {
63
+ retryable: error.retryable,
64
+ details: error.details,
65
+ });
66
+ }
67
+ throw error;
68
+ }
69
+ export function createFnaHost(ctx, dependencies = {}) {
70
+ let e10Session = null;
71
+ let sessionContext = null;
72
+ const requireSession = dependencies.requireSession || requireE10Session;
73
+ async function ensureSession() {
74
+ if (!e10Session) {
75
+ e10Session = await requireSession(ctx);
76
+ sessionContext = {
77
+ baseUrl: e10Session.getBaseUrl(),
78
+ profile: inferProfile(ctx),
79
+ userId: e10Session.userId,
80
+ tenantKey: e10Session.tenantKey,
81
+ eteamsId: e10Session.eteamsId,
82
+ };
83
+ }
84
+ return e10Session;
85
+ }
86
+ async function getSession() {
87
+ await ensureSession();
88
+ return sessionContext;
89
+ }
90
+ async function runtime() {
91
+ return createE10RequestRuntime(ctx, await ensureSession(), {
92
+ interceptors: dependencies.interceptors,
93
+ fetch: dependencies.fetch,
94
+ });
95
+ }
96
+ async function request(request) {
97
+ const { method, path, query, body, operation, headers: extraHeaders = {}, timeoutMs = 30_000, } = request;
98
+ assertPath(path);
99
+ const resolvedMethod = method || (body === undefined ? 'GET' : 'POST');
100
+ let response;
101
+ try {
102
+ response = await (await runtime()).requestJson({
103
+ module: 'fna',
104
+ operation,
105
+ method: resolvedMethod,
106
+ path,
107
+ query: omitEmptyQueryValues(query),
108
+ body,
109
+ headers: { 'X-Requested-With': 'XMLHttpRequest', ...extraHeaders },
110
+ timeoutMs,
111
+ });
112
+ }
113
+ catch (error) {
114
+ mapRuntimeNetworkError(error);
115
+ }
116
+ if (response.status === 401 || response.status === 302) {
117
+ throw fnaAuthError('session_expired', 'E10 登录态已失效,请先向用户确认 E10 登录域名,再运行 weaver-work-cli auth login --base-url <域名> 完成登录', { httpStatus: response.status });
118
+ }
119
+ if (response.parseError) {
120
+ if (response.status < 200 || response.status >= 300) {
121
+ throw new FnaCliError('api', 'http_error', `泛微接口 HTTP ${response.status}`, {
122
+ code: response.status,
123
+ details: { status: response.status },
124
+ exitCode: 1,
125
+ });
126
+ }
127
+ throw fnaNetworkError('protocol', `接口返回不是合法 JSON(HTTP ${response.status})`, { retryable: false });
128
+ }
129
+ if (response.status < 200 || response.status >= 300) {
130
+ throw new FnaCliError('api', 'http_error', `泛微接口 HTTP ${response.status}`, {
131
+ code: response.status,
132
+ details: { status: response.status, message: businessMessage(response.value) },
133
+ exitCode: 1,
134
+ });
135
+ }
136
+ if (!isBusinessSuccess(response.value)) {
137
+ throw new FnaCliError('api', 'business_error', businessMessage(response.value), {
138
+ code: businessCode(response.value),
139
+ details: { code: businessCode(response.value), message: businessMessage(response.value) },
140
+ exitCode: 1,
141
+ });
142
+ }
143
+ return response.value;
144
+ }
145
+ return { request, getSession };
146
+ }
@@ -0,0 +1,111 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { ExitCode, isCliError, toErrorEnvelope } from '../../core/errors.js';
3
+ import { createFnaContinuationSigner } from './continuation.js';
4
+ import { createFnaHost } from './host.js';
5
+ import { fnaManifest } from './manifest.js';
6
+ import { executeFnaOperation } from './operations.js';
7
+ import { fnaValidationError } from './errors.js';
8
+ function asOptions(value) {
9
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
10
+ }
11
+ async function readStdin() {
12
+ const chunks = [];
13
+ for await (const chunk of process.stdin) {
14
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
15
+ }
16
+ return Buffer.concat(chunks).toString('utf8');
17
+ }
18
+ /** Windows PowerShell 管道/Set-Content 会写入 UTF-8 BOM,JSON.parse 前必须剥离。 */
19
+ function stripBom(value) {
20
+ return value.replace(/^\uFEFF+/, '');
21
+ }
22
+ export async function inputFrom(options, extra = {}) {
23
+ const opts = asOptions(options);
24
+ let input = {};
25
+ if (opts.input && opts.inputJson) {
26
+ throw fnaValidationError('input_conflict', '不能同时传 --input 和 --input-json');
27
+ }
28
+ if (opts.inputJson) {
29
+ input = parseJsonInput(String(opts.inputJson), '--input-json');
30
+ }
31
+ if (opts.input) {
32
+ let raw;
33
+ try {
34
+ raw = stripBom(opts.input === '-' ? await readStdin() : await readFile(String(opts.input), 'utf8'));
35
+ }
36
+ catch {
37
+ throw fnaValidationError('input_unreadable', `无法读取 --input:${String(opts.input)}`);
38
+ }
39
+ input = parseJsonInput(raw, '--input');
40
+ }
41
+ return {
42
+ ...input,
43
+ ...Object.fromEntries(Object.entries(extra).filter(([, value]) => value !== undefined && value !== '')),
44
+ };
45
+ }
46
+ function parseJsonInput(raw, label) {
47
+ try {
48
+ const parsed = JSON.parse(stripBom(raw));
49
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
50
+ throw new Error('input must be an object');
51
+ }
52
+ return parsed;
53
+ }
54
+ catch {
55
+ throw fnaValidationError('input_invalid', `${label} 不是合法 JSON 对象`);
56
+ }
57
+ }
58
+ export function successEnvelope(operation, result) {
59
+ return {
60
+ schemaVersion: 1,
61
+ ok: true,
62
+ operation,
63
+ data: result.data === undefined ? null : result.data,
64
+ ...(result.meta ? { meta: result.meta } : {}),
65
+ warnings: [],
66
+ };
67
+ }
68
+ function failureEnvelope(error) {
69
+ const structured = error;
70
+ return {
71
+ schemaVersion: 1,
72
+ ok: false,
73
+ ...(structured?.partialData === undefined ? {} : { data: structured.partialData }),
74
+ error: toErrorEnvelope(error),
75
+ };
76
+ }
77
+ async function executeAndPrint(ctx, operation, input) {
78
+ try {
79
+ const result = await executeFnaOperation(operation, input, {
80
+ ctx,
81
+ host: createFnaHost(ctx),
82
+ continuation: createFnaContinuationSigner(ctx),
83
+ });
84
+ ctx.output.write(successEnvelope(operation, result), { json: true });
85
+ }
86
+ catch (error) {
87
+ console.error(JSON.stringify(failureEnvelope(error), null, 2));
88
+ process.exitCode = isCliError(error) ? error.exitCode : ExitCode.GeneralError;
89
+ }
90
+ }
91
+ export const fnaShortcut = {
92
+ name: 'fna',
93
+ description: '泛微E10齐业成费控中心(预算/费用中心/借款管理/发票核销)CLI',
94
+ category: 'shortcut',
95
+ register({ program, action }) {
96
+ const fna = program.command('fna').description('泛微E10齐业成费控中心(预算查询/费用中心/借款管理/发票核销)');
97
+ fna.command('schema')
98
+ .description('Print fna operation manifest for agents')
99
+ .action(action((ctx) => {
100
+ ctx.output.write(fnaManifest, { json: true });
101
+ }));
102
+ fna.command('run')
103
+ .description('Run an fna operation with JSON input')
104
+ .argument('<operation>', 'operation name, e.g. fna.expense.reimbursed.sum')
105
+ .option('--input <path>', 'JSON input file, or - for stdin')
106
+ .option('--input-json <json>', 'inline JSON input object')
107
+ .action(action(async (ctx, operation, options) => {
108
+ await executeAndPrint(ctx, String(operation), await inputFrom(options));
109
+ }));
110
+ },
111
+ };