weaver-work-cli 0.1.42 → 0.1.44

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 (318) hide show
  1. package/README.md +17 -0
  2. package/dist/chunks/{archive-J4I6MCKF.js → archive-P6TBQGKL.js} +13 -5
  3. package/dist/chunks/{archive-oa-BRZKKTO4.js → archive-oa-7TQ2NXOH.js} +12 -5
  4. package/dist/chunks/{asset-L7D4FAOZ.js → asset-3ELRG37G.js} +11 -4
  5. package/dist/chunks/{asset-idle-DADLLV75.js → asset-idle-WIGMUFMD.js} +7 -3
  6. package/dist/chunks/{attachment-content-K4C7VLWQ.js → attachment-content-E3276UOV.js} +5 -4
  7. package/dist/chunks/{blog-BVGQ7NZL.js → blog-C5NMZAAC.js} +11 -4
  8. package/dist/chunks/{caizhilian-SAADNFD6.js → caizhilian-5XSM2DFP.js} +13 -6
  9. package/dist/chunks/{calendar-Q7NQY5Z2.js → calendar-FI2WNSBO.js} +12 -5
  10. package/dist/chunks/{chunk-YRSZQUD2.js → chunk-3YBDYOC4.js} +3 -3
  11. package/dist/chunks/{chunk-OOUTBLZ4.js → chunk-56EZERK4.js} +1 -1
  12. package/dist/chunks/chunk-6N4JPNFL.js +76 -0
  13. package/dist/chunks/{chunk-ZUX3P6BQ.js → chunk-727FH2NI.js} +1 -1
  14. package/dist/chunks/chunk-7BDPM5ST.js +11 -0
  15. package/dist/chunks/{chunk-EKWAQSLU.js → chunk-BCVYBYYT.js} +432 -2248
  16. package/dist/chunks/{chunk-W7BEHOSR.js → chunk-CWYGFU5B.js} +2 -2
  17. package/dist/chunks/{chunk-NOODWMCL.js → chunk-D4ADSZ7H.js} +1 -1
  18. package/dist/chunks/{chunk-SA6VBIHY.js → chunk-ETNJSKMM.js} +214 -16
  19. package/dist/chunks/{chunk-BBKDXQEC.js → chunk-F4E4EM35.js} +3 -3
  20. package/dist/chunks/{chunk-IZ7S7QUS.js → chunk-FAZTGX7S.js} +6 -6
  21. package/dist/chunks/{chunk-NKZRQXST.js → chunk-FRZKBMSW.js} +52 -36
  22. package/dist/chunks/{chunk-BYBSCN4X.js → chunk-G7PQWD4L.js} +6 -3
  23. package/dist/chunks/{chunk-GEWYMQME.js → chunk-GAMZLAG2.js} +1 -1
  24. package/dist/chunks/{chunk-R4CHUSKC.js → chunk-GM6J7Q4B.js} +4 -4
  25. package/dist/chunks/{chunk-APVFJUQH.js → chunk-GRDRG6HP.js} +3 -3
  26. package/dist/chunks/{chunk-LDZQPUIA.js → chunk-HIT4Y6OI.js} +1 -1
  27. package/dist/chunks/{chunk-EZALDOQH.js → chunk-HP7JIYMT.js} +5 -2
  28. package/dist/chunks/{chunk-LADPYOWC.js → chunk-IAZ3UPY6.js} +3 -3
  29. package/dist/chunks/{chunk-ZEDWSH32.js → chunk-IC62NFM5.js} +1 -1
  30. package/dist/chunks/{chunk-P26ZWSKU.js → chunk-KIHNAS25.js} +5 -2
  31. package/dist/chunks/{chunk-BIPYLLVS.js → chunk-N4M2DDFE.js} +15 -15
  32. package/dist/chunks/{chunk-QKNKR4RH.js → chunk-OF4S23UB.js} +4 -4
  33. package/dist/chunks/{chunk-JPRO6ER2.js → chunk-PC7VKEB5.js} +57 -60
  34. package/dist/chunks/{chunk-4PD5NWAX.js → chunk-PUQS5MWL.js} +2 -2
  35. package/dist/chunks/{chunk-2LV74IWP.js → chunk-Q4OYAQYH.js} +1 -1
  36. package/dist/chunks/{chunk-72CKAUAG.js → chunk-QVSWRLLU.js} +7 -5
  37. package/dist/chunks/{chunk-4RAE6JXP.js → chunk-TA7FXXJD.js} +6 -3
  38. package/dist/chunks/{chunk-GPMFD4RD.js → chunk-TXUG266F.js} +1 -1
  39. package/dist/chunks/{chunk-FOAA27U5.js → chunk-UFIT2UU3.js} +16 -4
  40. package/dist/chunks/{chunk-LUSPKZKY.js → chunk-UG5G54VL.js} +1 -0
  41. package/dist/chunks/{chunk-NIAJ5ZCG.js → chunk-UL5XUQ25.js} +5 -2
  42. package/dist/chunks/{chunk-FMPJJYYI.js → chunk-WRXSAVKO.js} +1 -1
  43. package/dist/chunks/{chunk-G4UR6NXN.js → chunk-WSF4NNMR.js} +3 -3
  44. package/dist/chunks/chunk-XHK4MDR5.js +2497 -0
  45. package/dist/chunks/{chunk-3KTFS4IA.js → chunk-XNIK66I4.js} +19 -9
  46. package/dist/chunks/{chunk-3SO6QL6U.js → chunk-YWX377BY.js} +5 -2
  47. package/dist/chunks/{chunk-BYATLLEF.js → chunk-Z3GDFVJR.js} +1 -1
  48. package/dist/chunks/{chunk-GHXCDPTM.js → chunk-Z7VYWPZV.js} +1 -1
  49. package/dist/chunks/{conflict-F2OMZRTO.js → conflict-ARLSZJ6V.js} +4 -3
  50. package/dist/chunks/{continuation-2CKSBLA6.js → continuation-3S37AUSH.js} +4 -3
  51. package/dist/chunks/{continuation-RN6PZN2M.js → continuation-3XLYYTKV.js} +4 -3
  52. package/dist/chunks/{continuation-HZIZRZBX.js → continuation-HFW2YT5S.js} +4 -3
  53. package/dist/chunks/{continuation-NLECEJPX.js → continuation-KI7DRRZN.js} +4 -3
  54. package/dist/chunks/{contract-5BETHRSG.js → contract-DNIIW5VJ.js} +13 -5
  55. package/dist/chunks/{cowork-3MN6EQQO.js → cowork-GMLRGVIW.js} +11 -4
  56. package/dist/chunks/{create-flow-5FQNNMVO.js → create-flow-J22BO65E.js} +8 -7
  57. package/dist/chunks/{ebuilder-form-SBHOYBUD.js → ebuilder-form-ANV2FHYV.js} +12 -7
  58. package/dist/chunks/{ehr-KMOJULKG.js → ehr-GSTGAIY3.js} +266 -24
  59. package/dist/chunks/{employee-SAK2QYXX.js → employee-22BGJ3QS.js} +3 -3
  60. package/dist/chunks/{env-LB7NBL2O.js → env-BX3VRFS7.js} +4 -3
  61. package/dist/chunks/{esb-W2PJCFCX.js → esb-ATAIASX2.js} +12 -7
  62. package/dist/chunks/{factory-6ZFQXQ46.js → factory-PETTFME6.js} +3 -2
  63. package/dist/chunks/{fna-ZQPCUV4R.js → fna-YEKBSFSX.js} +14 -8
  64. package/dist/chunks/{group-chat-2HHAJN46.js → group-chat-BFVXAYFX.js} +5 -4
  65. package/dist/chunks/{host-ATKVNZAT.js → host-HRBXEPDQ.js} +5 -5
  66. package/dist/chunks/{host-BQH22NTQ.js → host-LR55CTHP.js} +5 -5
  67. package/dist/chunks/{host-X2CSLFM6.js → host-SUOY6VYQ.js} +5 -5
  68. package/dist/chunks/{host-4CBHGOHT.js → host-SZGV4UNT.js} +5 -5
  69. package/dist/chunks/{host-YTODKMSL.js → host-WIKN2EJ5.js} +5 -5
  70. package/dist/chunks/{hrm-FFM4UJFS.js → hrm-NRDO4W5G.js} +11 -7
  71. package/dist/chunks/{im-VEHKDQPB.js → im-IQ2HN23S.js} +8 -7
  72. package/dist/chunks/{invoice-LVIKSIIF.js → invoice-MNRW76PP.js} +636 -1768
  73. package/dist/chunks/{jiuchuanhui-X6DINO5P.js → jiuchuanhui-DTRBAX4N.js} +14 -6
  74. package/dist/chunks/{lazy-dispatch-KSWTN5L6.js → lazy-dispatch-ZVWAI25B.js} +7 -6
  75. package/dist/chunks/{mail-VDKRGUD3.js → mail-ZVAUXOJA.js} +16 -14
  76. package/dist/chunks/{meeting-CLC6HP3Z.js → meeting-FEVPZ67S.js} +21 -14
  77. package/dist/chunks/{okr-CHG4OO3U.js → okr-SDH3E5RA.js} +12 -5
  78. package/dist/chunks/{operations-5QL3AECO.js → operations-62N6EP3C.js} +4 -3
  79. package/dist/chunks/{plan-XWR75667.js → plan-E35JFDI7.js} +12 -5
  80. package/dist/chunks/{project-5BXOOKMG.js → project-73QXBAB2.js} +11 -4
  81. package/dist/chunks/reception-UWZVACBN.js +1899 -0
  82. package/dist/chunks/{recruit-stage-DGMFNNDE.js → recruit-stage-4MAOCKFY.js} +320 -57
  83. package/dist/chunks/registry-IM5G23LS.js +24 -0
  84. package/dist/chunks/{registry-RHMW6ANW.js → registry-JDUS4E7D.js} +7 -6
  85. package/dist/chunks/{registry-7FFOXIAW.js → registry-KNKSCJNT.js} +7 -6
  86. package/dist/chunks/{registry-Z43434VG.js → registry-PO7SI256.js} +4 -4
  87. package/dist/chunks/{registry-OZSMDVPP.js → registry-PVUZQDDQ.js} +3 -3
  88. package/dist/chunks/{room-recommend-62H7ZQQ6.js → room-recommend-H7KLXA5R.js} +6 -5
  89. package/dist/chunks/{schedule-FNXKH3DQ.js → schedule-ESZIBAUO.js} +6 -5
  90. package/dist/chunks/{workflow-ADHKCAJK.js → workflow-CWJFJLQU.js} +13 -8
  91. package/dist/cmd/action.js +6 -0
  92. package/dist/cmd/identity/index.js +45 -0
  93. package/dist/cmd/index.js +2 -0
  94. package/dist/core/continuation-ttl.js +18 -0
  95. package/dist/core/error-codes.js +85 -0
  96. package/dist/core/logger.js +11 -0
  97. package/dist/index.js +37 -31
  98. package/dist/internal/e10/auth/commands.js +163 -8
  99. package/dist/internal/e10/auth/error-log.js +182 -0
  100. package/dist/internal/e10/auth/session.js +17 -3
  101. package/dist/internal/e10/auth-recovery.js +39 -12
  102. package/dist/internal/e10/context.js +17 -2
  103. package/dist/internal/skills/install.js +9 -1
  104. package/dist/shortcuts/archive/continuation.js +2 -1
  105. package/dist/shortcuts/archive/index.js +3 -0
  106. package/dist/shortcuts/archive/operations/confirm.js +2 -1
  107. package/dist/shortcuts/archive-oa/continuation.js +2 -1
  108. package/dist/shortcuts/archive-oa/index.js +2 -0
  109. package/dist/shortcuts/archive-oa/operations/confirm.js +2 -1
  110. package/dist/shortcuts/asset/continuation.js +2 -1
  111. package/dist/shortcuts/asset/index.js +2 -0
  112. package/dist/shortcuts/asset-idle/index.js +2 -0
  113. package/dist/shortcuts/blog/continuation.js +2 -1
  114. package/dist/shortcuts/blog/index.js +2 -0
  115. package/dist/shortcuts/caizhilian/continuation.js +2 -1
  116. package/dist/shortcuts/caizhilian/index.js +2 -0
  117. package/dist/shortcuts/caizhilian/operations/confirm.js +3 -2
  118. package/dist/shortcuts/calendar/continuation.js +2 -1
  119. package/dist/shortcuts/calendar/index.js +2 -0
  120. package/dist/shortcuts/calendar/operations/write.js +1 -1
  121. package/dist/shortcuts/contract/continuation.js +2 -1
  122. package/dist/shortcuts/contract/index.js +2 -0
  123. package/dist/shortcuts/contract/operations/write.js +2 -1
  124. package/dist/shortcuts/cowork/continuation.js +2 -1
  125. package/dist/shortcuts/cowork/index.js +2 -0
  126. package/dist/shortcuts/ebuilder-form/continuation.js +2 -1
  127. package/dist/shortcuts/ebuilder-form/index.js +2 -0
  128. package/dist/shortcuts/ebuilder-form/operations/write.js +3 -2
  129. package/dist/shortcuts/ehr/continuation.js +2 -1
  130. package/dist/shortcuts/ehr/index.js +2 -0
  131. package/dist/shortcuts/ehr/operations/attend-write.js +1 -1
  132. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +182 -3
  133. package/dist/shortcuts/ehr/operations/recruit-position.js +134 -2
  134. package/dist/shortcuts/ehr/operations/recruit-write.js +1 -1
  135. package/dist/shortcuts/esb/continuation.js +2 -1
  136. package/dist/shortcuts/esb/index.js +2 -0
  137. package/dist/shortcuts/esb/operations/trigger.js +2 -1
  138. package/dist/shortcuts/fna/continuation.js +2 -1
  139. package/dist/shortcuts/fna/index.js +2 -0
  140. package/dist/shortcuts/fna/operations/invoice-writeoff.js +1 -1
  141. package/dist/shortcuts/fna/operations/loan.js +1 -1
  142. package/dist/shortcuts/hrm/index.js +2 -0
  143. package/dist/shortcuts/im/continuation.js +2 -1
  144. package/dist/shortcuts/index.js +5 -0
  145. package/dist/shortcuts/invoice/continuation.js +2 -1
  146. package/dist/shortcuts/invoice/index.js +14 -15
  147. package/dist/shortcuts/invoice/invoice-record.js +93 -0
  148. package/dist/shortcuts/invoice/manifest.js +190 -393
  149. package/dist/shortcuts/invoice/operations/add.js +2 -1
  150. package/dist/shortcuts/invoice/operations/delete.js +2 -1
  151. package/dist/shortcuts/invoice/operations/import.js +2 -1
  152. package/dist/shortcuts/invoice/operations/issuing-contract-detail.js +86 -0
  153. package/dist/shortcuts/invoice/operations/issuing-contracts.js +210 -0
  154. package/dist/shortcuts/invoice/operations/registry.js +17 -17
  155. package/dist/shortcuts/invoice/operations/reim-auto.js +4 -569
  156. package/dist/shortcuts/invoice/operations/reim.js +52 -341
  157. package/dist/shortcuts/invoice/operations/shared.js +21 -4
  158. package/dist/shortcuts/invoice/operations/update.js +2 -1
  159. package/dist/shortcuts/invoice/projection.js +10 -62
  160. package/dist/shortcuts/jiuchuanhui/continuation.js +2 -1
  161. package/dist/shortcuts/jiuchuanhui/index.js +2 -0
  162. package/dist/shortcuts/jiuchuanhui/operations/datajson.js +2 -1
  163. package/dist/shortcuts/jiuchuanhui/operations/esb.js +2 -1
  164. package/dist/shortcuts/mail/continuation.js +2 -1
  165. package/dist/shortcuts/mail/index.js +2 -0
  166. package/dist/shortcuts/mail/operations/mail-blacklist.js +1 -1
  167. package/dist/shortcuts/mail/operations/mail-contacts.js +1 -1
  168. package/dist/shortcuts/mail/operations/mail-send.js +1 -1
  169. package/dist/shortcuts/mail/operations/mail-sign.js +1 -1
  170. package/dist/shortcuts/mail/operations/mail-template.js +1 -1
  171. package/dist/shortcuts/meeting/continuation.js +2 -1
  172. package/dist/shortcuts/meeting/index.js +2 -0
  173. package/dist/shortcuts/meeting/operations/change.js +1 -1
  174. package/dist/shortcuts/meeting/operations/create.js +1 -1
  175. package/dist/shortcuts/meeting/operations/eb/create-flow.js +16 -7
  176. package/dist/shortcuts/meeting/operations/eb/decision.js +1 -1
  177. package/dist/shortcuts/meeting/operations/eb/factory.js +1 -1
  178. package/dist/shortcuts/meeting/operations/lifecycle.js +1 -1
  179. package/dist/shortcuts/meeting/operations/receipts.js +1 -1
  180. package/dist/shortcuts/meeting/operations/signs.js +1 -1
  181. package/dist/shortcuts/okr/continuation.js +2 -1
  182. package/dist/shortcuts/okr/index.js +2 -0
  183. package/dist/shortcuts/okr/operations/write.js +1 -1
  184. package/dist/shortcuts/plan/continuation.js +2 -1
  185. package/dist/shortcuts/plan/index.js +2 -0
  186. package/dist/shortcuts/plan/operations/write.js +1 -1
  187. package/dist/shortcuts/project/continuation.js +2 -1
  188. package/dist/shortcuts/project/index.js +2 -0
  189. package/dist/shortcuts/reception/constants.js +53 -0
  190. package/dist/shortcuts/reception/errors.js +54 -0
  191. package/dist/shortcuts/reception/host.js +125 -0
  192. package/dist/shortcuts/reception/index.js +198 -0
  193. package/dist/shortcuts/reception/manifest.js +177 -0
  194. package/dist/shortcuts/reception/operations/ask.js +71 -0
  195. package/dist/shortcuts/reception/operations/browsertool.js +58 -0
  196. package/dist/shortcuts/reception/operations/compose.js +129 -0
  197. package/dist/shortcuts/reception/operations/customparams.js +74 -0
  198. package/dist/shortcuts/reception/operations/doc.js +238 -0
  199. package/dist/shortcuts/reception/operations/docrender.js +36 -0
  200. package/dist/shortcuts/reception/operations/panels.js +179 -0
  201. package/dist/shortcuts/reception/operations/registry.js +26 -0
  202. package/dist/shortcuts/reception/operations/render-assets.js +184 -0
  203. package/dist/shortcuts/reception/operations/render.js +123 -0
  204. package/dist/shortcuts/reception/operations/runs.js +38 -0
  205. package/dist/shortcuts/reception/operations/schedule.js +127 -0
  206. package/dist/shortcuts/reception/operations/shared.js +196 -0
  207. package/dist/shortcuts/reception/operations/snapshot.js +68 -0
  208. package/dist/shortcuts/reception/operations/types.js +1 -0
  209. package/dist/shortcuts/reception/operations.js +33 -0
  210. package/dist/shortcuts/reception/upload.js +218 -0
  211. package/dist/shortcuts/recruit-stage/context.js +145 -33
  212. package/dist/shortcuts/recruit-stage/continuation.js +2 -1
  213. package/dist/shortcuts/recruit-stage/operations/jd-create.js +106 -17
  214. package/dist/shortcuts/recruit-stage/operations/resume-import.js +166 -10
  215. package/dist/shortcuts/workflow/continuation.js +2 -1
  216. package/dist/shortcuts/workflow/index.js +2 -0
  217. package/dist/shortcuts/workflow/operations/form.js +32 -8
  218. package/dist/shortcuts/workflow/operations/write.js +1 -1
  219. package/docs/_catalog.md +3 -0
  220. package/docs/agent-invoice.md +1 -1
  221. package/docs/archive-oa.md +1 -1
  222. package/docs/caizhilian.md +1 -1
  223. package/docs/calendar.md +1 -1
  224. package/docs/contract.md +1 -1
  225. package/docs/e10-auth.md +16 -0
  226. package/docs/ehr.md +2 -2
  227. package/docs/esb.md +1 -1
  228. package/docs/im.md +1 -1
  229. package/docs/invoice.md +8 -12
  230. package/docs/okr.md +1 -1
  231. package/docs/reception.md +119 -0
  232. package/package.json +1 -1
  233. package/scripts/clean.mjs +43 -2
  234. package/skill-template/business-info.json +18 -2
  235. package/skill-template/domains/caizhilian.md +1 -1
  236. package/skill-template/domains/reception-flow.md +18 -0
  237. package/skill-template/domains/yepiaotong.md +4 -7
  238. package/skills/weaver-e10-archive-oa/references/source-manifest.json +14 -14
  239. package/skills/weaver-e10-blog/references/blog-publish.md +1 -1
  240. package/skills/weaver-e10-blog/references/source-manifest.json +7 -7
  241. package/skills/weaver-e10-caizhilian/references/source-manifest.json +21 -21
  242. package/skills/weaver-e10-caizhilian/references/write-protocol.md +2 -2
  243. package/skills/weaver-e10-calendar/references/calendar-write.md +1 -1
  244. package/skills/weaver-e10-cowork/SKILL.md +1 -1
  245. package/skills/weaver-e10-ebuilder-form/SKILL.md +1 -1
  246. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -1
  247. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -1
  248. package/skills/weaver-e10-esb/SKILL.md +2 -2
  249. package/skills/weaver-e10-esb/references/source-manifest.json +22 -22
  250. package/skills/weaver-e10-esb/references/trigger.md +2 -2
  251. package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +1 -1
  252. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +1 -1
  253. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +1 -1
  254. package/skills/weaver-e10-jinchengda/references/source-manifest.json +29 -29
  255. package/skills/weaver-e10-jucailin/SKILL.md +1 -1
  256. package/skills/weaver-e10-jucailin/references/attend-write.md +2 -2
  257. package/skills/weaver-e10-jucailin/references/recruit-create.md +12 -3
  258. package/skills/weaver-e10-jucailin/references/recruit-write.md +1 -1
  259. package/skills/weaver-e10-meeting/SKILL.md +8 -6
  260. package/skills/weaver-e10-meeting/references/meeting-change.md +1 -1
  261. package/skills/weaver-e10-meeting/references/meeting-create.md +1 -1
  262. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +1 -1
  263. package/skills/weaver-e10-meeting/references/meeting-verification.md +1 -1
  264. package/skills/weaver-e10-okr/references/okr-align.md +1 -1
  265. package/skills/weaver-e10-okr/references/okr-keyresult.md +1 -1
  266. package/skills/weaver-e10-okr/references/okr-write.md +1 -1
  267. package/skills/weaver-e10-okr/references/source-manifest.json +8 -8
  268. package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
  269. package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
  270. package/skills/weaver-e10-qiyecheng/references/loan-management.md +1 -1
  271. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +18 -18
  272. package/skills/weaver-e10-reception-flow/SKILL.md +173 -0
  273. package/skills/weaver-e10-reception-flow/assets//350/241/214/347/250/213/345/215/225/346/250/241/346/235/277-/346/263/233/345/276/256.docx +0 -0
  274. package/skills/weaver-e10-reception-flow/data/fields-snapshot.json +213 -0
  275. package/skills/weaver-e10-reception-flow/references/browsertool.md +68 -0
  276. package/skills/weaver-e10-reception-flow/references/env-pitfalls.md +51 -0
  277. package/skills/weaver-e10-reception-flow/references/fields-snapshot.md +227 -0
  278. package/skills/weaver-e10-reception-flow/references/guide.md +179 -0
  279. package/skills/weaver-e10-reception-flow/scripts/locate.sh +14 -0
  280. package/skills/weaver-e10-reception-flow/scripts/render.py +724 -0
  281. package/skills/weaver-e10-recruit-stage/SKILL.md +9 -5
  282. package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +1 -1
  283. package/skills/weaver-e10-recruit-stage/lib/xiaoe-session.mjs +66 -0
  284. package/skills/weaver-e10-recruit-stage/references/position-templates.md +202 -0
  285. package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +22 -0
  286. package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +14 -1
  287. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +6 -0
  288. package/skills/weaver-e10-shijingran/SKILL.md +5 -5
  289. package/skills/weaver-e10-shijingran/references/source-manifest.json +37 -36
  290. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +2 -0
  291. package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
  292. package/skills/weaver-e10-workflow/references/source-manifest.json +32 -32
  293. package/skills/weaver-e10-yepiaotong/SKILL.md +19 -26
  294. package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +13 -10
  295. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +2 -0
  296. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +194 -155
  297. package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +28 -32
  298. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +5 -1
  299. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +8 -10
  300. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +211 -616
  301. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +149 -117
  302. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +17 -20
  303. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +20 -39
  304. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +55 -22
  305. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -17
  306. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +88 -92
  307. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +144 -354
  308. package/skills/weaver-e10-yimiaoban/SKILL.md +1 -1
  309. package/skills/weaver-e10-yimiaoban/references/msg-write.md +1 -1
  310. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +1 -1
  311. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +7 -7
  312. package/dist/chunks/chunk-TTPJJJC4.js +0 -465
  313. package/dist/chunks/registry-BKBZPBAJ.js +0 -23
  314. package/dist/shortcuts/invoice/markdown.js +0 -172
  315. package/dist/shortcuts/invoice/operations/issuing-qys.js +0 -424
  316. package/skills/weaver-e10-meeting.zip +0 -0
  317. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +0 -131
  318. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +0 -179
@@ -1,59 +1,18 @@
1
1
  import { createRequire as __esbuildCreateRequire } from 'node:module';
2
2
  const require = __esbuildCreateRequire(import.meta.url);
3
3
  import {
4
- DEFAULT_RESULT_THRESHOLD_BYTES,
5
- Output,
6
- RefError,
7
- bytesOf,
8
- listRefs,
9
- pickValue,
10
- pruneRefs,
11
- readRef,
12
- refMaxBytes,
13
- refMaxCount,
14
- resolveRefInput,
15
- resultThresholdBytes
16
- } from "./chunk-ZUX3P6BQ.js";
4
+ createE10RequestRuntime,
5
+ isE10SessionExpiredResponse,
6
+ requireE10Session
7
+ } from "./chunk-ETNJSKMM.js";
17
8
  import {
18
- refsDir
19
- } from "./chunk-AJ62BGAW.js";
9
+ E10_REAUTH_GUIDANCE,
10
+ E10_SESSION_EXPIRED_MESSAGE,
11
+ getActiveProfile
12
+ } from "./chunk-UFIT2UU3.js";
20
13
  import {
21
- clearInvoiceTokenForSession
22
- } from "./chunk-TTPJJJC4.js";
23
- import {
24
- E10AuthSession,
25
- XIAOE_AGENT_TYPE,
26
- buildE10CookieHeader,
27
- clearProfileAuthFile,
28
- createXiaoEUnifiedLoginUnavailableError,
29
- extractRawSetCookie,
30
- extractSessionTicket,
31
- findAuthFile,
32
- getActiveProfile,
33
- getE10AuthRoot,
34
- getProfileAuthPath,
35
- getProfileDir,
36
- hasXiaoEEnv,
37
- inspectXiaoEUnifiedLoginSources,
38
- listProfiles,
39
- normalizeGlobalOptions,
40
- packageFileUrl,
41
- packagePath,
42
- profileNameFromUrl,
43
- readProfileConfig,
44
- readTeamsCheckUserInfo,
45
- resolveXiaoEPreferredBaseUrl,
46
- saveAuthFile,
47
- saveProfileConfig,
48
- setActiveProfile,
49
- switchActiveProfile,
50
- tryXiaoEUnifiedLogin
51
- } from "./chunk-FOAA27U5.js";
52
- import {
53
- CliError,
54
- isCliError,
55
- toErrorEnvelope
56
- } from "./chunk-LUSPKZKY.js";
14
+ CliError
15
+ } from "./chunk-UG5G54VL.js";
57
16
  import {
58
17
  __commonJS,
59
18
  __require,
@@ -1096,7 +1055,7 @@ var require_option = __commonJS({
1096
1055
  var require_suggestSimilar = __commonJS({
1097
1056
  "node_modules/commander/lib/suggestSimilar.js"(exports) {
1098
1057
  var maxDistance = 3;
1099
- function editDistance2(a, b) {
1058
+ function editDistance(a, b) {
1100
1059
  if (Math.abs(a.length - b.length) > maxDistance)
1101
1060
  return Math.max(a.length, b.length);
1102
1061
  const d = [];
@@ -1142,7 +1101,7 @@ var require_suggestSimilar = __commonJS({
1142
1101
  const minSimilarity = 0.4;
1143
1102
  candidates.forEach((candidate) => {
1144
1103
  if (candidate.length <= 1) return;
1145
- const distance = editDistance2(word, candidate);
1104
+ const distance = editDistance(word, candidate);
1146
1105
  const length = Math.max(word.length, candidate.length);
1147
1106
  const similarity = (length - distance) / length;
1148
1107
  if (similarity > minSimilarity) {
@@ -1179,7 +1138,7 @@ var require_command = __commonJS({
1179
1138
  var childProcess = __require("node:child_process");
1180
1139
  var path = __require("node:path");
1181
1140
  var fs = __require("node:fs");
1182
- var process2 = __require("node:process");
1141
+ var process = __require("node:process");
1183
1142
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1184
1143
  var { CommanderError: CommanderError2 } = require_error();
1185
1144
  var { Help: Help2, stripColor } = require_help();
@@ -1226,13 +1185,13 @@ var require_command = __commonJS({
1226
1185
  this._showSuggestionAfterError = true;
1227
1186
  this._savedState = null;
1228
1187
  this._outputConfiguration = {
1229
- writeOut: (str) => process2.stdout.write(str),
1230
- writeErr: (str) => process2.stderr.write(str),
1188
+ writeOut: (str) => process.stdout.write(str),
1189
+ writeErr: (str) => process.stderr.write(str),
1231
1190
  outputError: (str, write) => write(str),
1232
- getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : void 0,
1233
- getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : void 0,
1234
- getOutHasColors: () => useColor() ?? (process2.stdout.isTTY && process2.stdout.hasColors?.()),
1235
- getErrHasColors: () => useColor() ?? (process2.stderr.isTTY && process2.stderr.hasColors?.()),
1191
+ getOutHelpWidth: () => process.stdout.isTTY ? process.stdout.columns : void 0,
1192
+ getErrHelpWidth: () => process.stderr.isTTY ? process.stderr.columns : void 0,
1193
+ getOutHasColors: () => useColor() ?? (process.stdout.isTTY && process.stdout.hasColors?.()),
1194
+ getErrHasColors: () => useColor() ?? (process.stderr.isTTY && process.stderr.hasColors?.()),
1236
1195
  stripColor: (str) => stripColor(str)
1237
1196
  };
1238
1197
  this._hidden = false;
@@ -1615,7 +1574,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1615
1574
  if (this._exitCallback) {
1616
1575
  this._exitCallback(new CommanderError2(exitCode, code, message));
1617
1576
  }
1618
- process2.exit(exitCode);
1577
+ process.exit(exitCode);
1619
1578
  }
1620
1579
  /**
1621
1580
  * Register callback `fn` for the command.
@@ -2013,16 +1972,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
2013
1972
  }
2014
1973
  parseOptions = parseOptions || {};
2015
1974
  if (argv === void 0 && parseOptions.from === void 0) {
2016
- if (process2.versions?.electron) {
1975
+ if (process.versions?.electron) {
2017
1976
  parseOptions.from = "electron";
2018
1977
  }
2019
- const execArgv = process2.execArgv ?? [];
1978
+ const execArgv = process.execArgv ?? [];
2020
1979
  if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
2021
1980
  parseOptions.from = "eval";
2022
1981
  }
2023
1982
  }
2024
1983
  if (argv === void 0) {
2025
- argv = process2.argv;
1984
+ argv = process.argv;
2026
1985
  }
2027
1986
  this.rawArgs = argv.slice();
2028
1987
  let userArgs;
@@ -2033,7 +1992,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2033
1992
  userArgs = argv.slice(2);
2034
1993
  break;
2035
1994
  case "electron":
2036
- if (process2.defaultApp) {
1995
+ if (process.defaultApp) {
2037
1996
  this._scriptPath = argv[1];
2038
1997
  userArgs = argv.slice(2);
2039
1998
  } else {
@@ -2220,11 +2179,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2220
2179
  }
2221
2180
  launchWithNode = sourceExt.includes(path.extname(executableFile));
2222
2181
  let proc;
2223
- if (process2.platform !== "win32") {
2182
+ if (process.platform !== "win32") {
2224
2183
  if (launchWithNode) {
2225
2184
  args.unshift(executableFile);
2226
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
2227
- proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
2185
+ args = incrementNodeInspectorPort(process.execArgv).concat(args);
2186
+ proc = childProcess.spawn(process.argv[0], args, { stdio: "inherit" });
2228
2187
  } else {
2229
2188
  proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
2230
2189
  }
@@ -2235,13 +2194,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2235
2194
  subcommand._name
2236
2195
  );
2237
2196
  args.unshift(executableFile);
2238
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
2239
- proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
2197
+ args = incrementNodeInspectorPort(process.execArgv).concat(args);
2198
+ proc = childProcess.spawn(process.execPath, args, { stdio: "inherit" });
2240
2199
  }
2241
2200
  if (!proc.killed) {
2242
2201
  const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
2243
2202
  signals.forEach((signal) => {
2244
- process2.on(signal, () => {
2203
+ process.on(signal, () => {
2245
2204
  if (proc.killed === false && proc.exitCode === null) {
2246
2205
  proc.kill(signal);
2247
2206
  }
@@ -2252,7 +2211,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2252
2211
  proc.on("close", (code) => {
2253
2212
  code = code ?? 1;
2254
2213
  if (!exitCallback) {
2255
- process2.exit(code);
2214
+ process.exit(code);
2256
2215
  } else {
2257
2216
  exitCallback(
2258
2217
  new CommanderError2(
@@ -2274,7 +2233,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2274
2233
  throw new Error(`'${executableFile}' not executable`);
2275
2234
  }
2276
2235
  if (!exitCallback) {
2277
- process2.exit(1);
2236
+ process.exit(1);
2278
2237
  } else {
2279
2238
  const wrappedError = new CommanderError2(
2280
2239
  1,
@@ -2769,13 +2728,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2769
2728
  */
2770
2729
  _parseOptionsEnv() {
2771
2730
  this.options.forEach((option) => {
2772
- if (option.envVar && option.envVar in process2.env) {
2731
+ if (option.envVar && option.envVar in process.env) {
2773
2732
  const optionKey = option.attributeName();
2774
2733
  if (this.getOptionValue(optionKey) === void 0 || ["default", "config", "env"].includes(
2775
2734
  this.getOptionValueSource(optionKey)
2776
2735
  )) {
2777
2736
  if (option.required || option.optional) {
2778
- this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
2737
+ this.emit(`optionEnv:${option.name()}`, process.env[option.envVar]);
2779
2738
  } else {
2780
2739
  this.emit(`optionEnv:${option.name()}`);
2781
2740
  }
@@ -3230,7 +3189,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3230
3189
  */
3231
3190
  help(contextOptions) {
3232
3191
  this.outputHelp(contextOptions);
3233
- let exitCode = Number(process2.exitCode ?? 0);
3192
+ let exitCode = Number(process.exitCode ?? 0);
3234
3193
  if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
3235
3194
  exitCode = 1;
3236
3195
  }
@@ -3320,9 +3279,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3320
3279
  });
3321
3280
  }
3322
3281
  function useColor() {
3323
- if (process2.env.NO_COLOR || process2.env.FORCE_COLOR === "0" || process2.env.FORCE_COLOR === "false")
3282
+ if (process.env.NO_COLOR || process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false")
3324
3283
  return false;
3325
- if (process2.env.FORCE_COLOR || process2.env.CLICOLOR_FORCE !== void 0)
3284
+ if (process.env.FORCE_COLOR || process.env.CLICOLOR_FORCE !== void 0)
3326
3285
  return true;
3327
3286
  return void 0;
3328
3287
  }
@@ -3353,2048 +3312,446 @@ var require_commander = __commonJS({
3353
3312
  }
3354
3313
  });
3355
3314
 
3356
- // src/cmd/argv.ts
3357
- var VALUE_TAKING_GLOBAL_OPTIONS = /* @__PURE__ */ new Set([
3358
- "--config",
3359
- "--auth",
3360
- "--profile",
3361
- "--runtime-agent",
3362
- "--base-url",
3363
- "--passport-url"
3364
- ]);
3365
- function firstPositionalToken(argv) {
3366
- for (let index = 0; index < argv.length; index += 1) {
3367
- const token = argv[index];
3368
- if (token === void 0) return void 0;
3369
- if (token === "--") return argv[index + 1];
3370
- if (token.startsWith("-")) {
3371
- if (VALUE_TAKING_GLOBAL_OPTIONS.has(token)) index += 1;
3372
- continue;
3373
- }
3374
- return token;
3375
- }
3376
- return void 0;
3377
- }
3378
- function toCommandMetadata(commands) {
3379
- return commands.map((command) => ({
3380
- name: command.name,
3381
- description: command.description,
3382
- category: command.category
3383
- }));
3384
- }
3385
-
3386
- // src/cmd/commands/index.ts
3387
- var commandsCommand = {
3388
- name: "commands",
3389
- description: "Registered command discovery",
3390
- category: "system",
3391
- register({ program: program2, action }) {
3392
- const commands = program2.command("commands").alias("module").description("Inspect registered commands");
3393
- commands.command("list").description("List registered commands").action(action((ctx) => {
3394
- ctx.output.write({ commands: ctx.commands, modules: ctx.modules });
3395
- }));
3396
- }
3397
- };
3398
-
3399
- // src/cmd/config/index.ts
3400
- function parseValue(value) {
3401
- if (value === "true") return true;
3402
- if (value === "false") return false;
3403
- if (value === "null") return null;
3404
- if (/^-?\d+(\.\d+)?$/.test(value)) return Number(value);
3405
- try {
3406
- return JSON.parse(value);
3407
- } catch {
3408
- return value;
3409
- }
3410
- }
3411
- var configCommand = {
3412
- name: "config",
3413
- description: "Generic local configuration commands",
3414
- category: "system",
3415
- register({ program: program2, action }) {
3416
- const config = program2.command("config").description("Manage weaver-work-cli config");
3417
- config.command("path").description("Print the active config file path").action(action((ctx) => {
3418
- ctx.output.write({ path: ctx.config.path() }, { text: ctx.config.path() });
3419
- }));
3420
- config.command("list").description("Print all config values").action(action((ctx) => {
3421
- ctx.output.write(ctx.config.all());
3422
- }));
3423
- config.command("get").description("Print one config value").argument("<key>", "config key").action(action((ctx, key) => {
3424
- if (typeof key !== "string") throw new CliError("key must be a string", 2 /* UsageError */);
3425
- ctx.output.write({ key, value: ctx.config.get(key) });
3426
- }));
3427
- config.command("set").description("Set one config value").argument("<key>", "config key").argument("<value>", "config value").action(action((ctx, key, value) => {
3428
- if (typeof key !== "string" || typeof value !== "string") {
3429
- throw new CliError("key and value must be strings", 2 /* UsageError */);
3430
- }
3431
- const parsed = parseValue(value);
3432
- ctx.config.set(key, parsed);
3433
- ctx.output.write({ key, value: parsed, path: ctx.config.path() }, { text: "Saved " + key });
3434
- }));
3435
- config.command("delete").description("Delete one config value").argument("<key>", "config key").action(action((ctx, key) => {
3436
- if (typeof key !== "string") throw new CliError("key must be a string", 2 /* UsageError */);
3437
- const deleted = ctx.config.delete(key);
3438
- ctx.output.write({ key, deleted, path: ctx.config.path() }, { text: deleted ? "Deleted " + key : "No value for " + key });
3439
- }));
3440
- }
3441
- };
3442
-
3443
- // src/cmd/docs/index.ts
3444
- import { cpSync, existsSync, readdirSync, readFileSync } from "node:fs";
3445
- import { resolve } from "node:path";
3446
- var DOCS_DIR = packagePath("docs");
3447
- var PKG_JSON_URL = packageFileUrl("package.json");
3448
- function packageVersion() {
3449
- try {
3450
- return JSON.parse(readFileSync(PKG_JSON_URL, "utf-8")).version;
3451
- } catch {
3452
- return "unknown";
3453
- }
3454
- }
3455
- function countFiles(dir) {
3456
- let count = 0;
3457
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
3458
- const entryPath = resolve(dir, entry.name);
3459
- count += entry.isDirectory() ? countFiles(entryPath) : 1;
3460
- }
3461
- return count;
3462
- }
3463
- function ensureDocs() {
3464
- if (!existsSync(DOCS_DIR)) {
3465
- throw new CliError("docs directory does not exist: " + DOCS_DIR);
3466
- }
3467
- }
3468
- var docsCommand = {
3469
- name: "docs",
3470
- description: "Packaged docs and template copy commands",
3471
- category: "system",
3472
- register({ program: program2, action }) {
3473
- const docs = program2.command("docs").description("Read or copy packaged docs");
3474
- docs.command("root").description("Print packaged docs root path").action(action((ctx) => {
3475
- ensureDocs();
3476
- const root = DOCS_DIR.replace(/[\\/]+$/, "");
3477
- ctx.output.write({ root, version: packageVersion() }, { text: root + "\nversion: " + packageVersion() });
3478
- }));
3479
- docs.command("copy").description("Copy packaged docs to <target>/weaver-work-cli-docs").argument("[target]", "target directory", process.cwd()).action(action((ctx, target) => {
3480
- ensureDocs();
3481
- const dest = resolve(String(target || process.cwd()), "weaver-work-cli-docs");
3482
- const sourceRoot = DOCS_DIR.replace(/[\\/]+$/, "");
3483
- if (dest === sourceRoot || dest.startsWith(sourceRoot + "/") || dest.startsWith(sourceRoot + "\\")) {
3484
- throw new CliError("target directory is inside docs source: " + dest);
3485
- }
3486
- cpSync(DOCS_DIR, dest, { recursive: true });
3487
- const files = countFiles(dest);
3488
- ctx.output.write({ files, dest, version: packageVersion() }, { text: "Copied " + files + " files to " + dest });
3489
- }));
3315
+ // src/shortcuts/invoice/errors.ts
3316
+ var InvoiceCliError = class extends CliError {
3317
+ type;
3318
+ subtype;
3319
+ code;
3320
+ retryable;
3321
+ stage;
3322
+ details;
3323
+ partialData;
3324
+ constructor(type, subtype, message, options = {}) {
3325
+ super(message, options.exitCode ?? 5 /* InternalError */);
3326
+ this.name = "InvoiceCliError";
3327
+ this.type = type;
3328
+ this.subtype = subtype;
3329
+ this.code = options.code;
3330
+ this.retryable = options.retryable ?? false;
3331
+ this.stage = options.stage;
3332
+ this.details = options.details;
3333
+ this.partialData = options.partialData;
3490
3334
  }
3491
3335
  };
3492
-
3493
- // src/cmd/doctor/index.ts
3494
- import { existsSync as existsSync2 } from "node:fs";
3495
- function versionMajor(version) {
3496
- return Number(version.replace(/^v/, "").split(".")[0] || 0);
3497
- }
3498
- var doctorCommand = {
3499
- name: "doctor",
3500
- description: "Environment diagnostics",
3501
- category: "system",
3502
- register({ program: program2, action }) {
3503
- program2.command("doctor").description("Check local CLI environment").option("--e10", "also check E10 auth file discovery").action(action((ctx, options) => {
3504
- const opts = options && typeof options === "object" ? options : {};
3505
- const checks = [
3506
- {
3507
- name: "node",
3508
- ok: versionMajor(process.version) >= 18,
3509
- detail: process.version
3510
- },
3511
- {
3512
- name: "package",
3513
- ok: Boolean(ctx.packageInfo.version),
3514
- detail: ctx.packageInfo.name + "@" + ctx.packageInfo.version
3515
- },
3516
- {
3517
- name: "configPath",
3518
- ok: true,
3519
- detail: ctx.config.path()
3520
- }
3521
- ];
3522
- if (opts.e10) {
3523
- const authFile = findAuthFile(ctx.cwd);
3524
- checks.push({
3525
- name: "e10AuthFile",
3526
- ok: Boolean(authFile && existsSync2(authFile)),
3527
- detail: authFile || "not found"
3528
- });
3529
- }
3530
- const ok = checks.every((check) => check.ok);
3531
- ctx.output.write({ ok, checks });
3532
- }));
3533
- }
3534
- };
3535
-
3536
- // src/internal/e10/auth/commands.ts
3537
- import { execFile } from "node:child_process";
3538
- import { randomBytes } from "node:crypto";
3539
- import { createServer } from "node:http";
3540
- var DEFAULT_AGENT_TYPE = "weaver-work-cli";
3541
- var EXPLICIT_AGENT_TYPE_ENV_KEYS = [
3542
- "WORKBUDDY_AGENT_TYPE",
3543
- "CODEX_AGENT_TYPE",
3544
- "WEAVER_AGENT_TYPE"
3545
- ];
3546
- var AGENT_RETURN_URL_ENV_KEY = "WEAVER_AGENT_RETURN_URL";
3547
- var AGENT_RETURN_PATH = "/agent-return";
3548
- var AGENT_RETURN_TOKEN_HEADER = "x-weaver-agent-return-token";
3549
- var AGENT_RETURN_TIMEOUT_MS = 9e5;
3550
- var OAUTH_CALLBACK_PROTOCOL_MISMATCH_GRACE_MS = 3e4;
3551
- var UNSAFE_AGENT_RETURN_PROTOCOLS = /* @__PURE__ */ new Set([
3552
- "about:",
3553
- "blob:",
3554
- "data:",
3555
- "file:",
3556
- "ftp:",
3557
- "http:",
3558
- "https:",
3559
- "javascript:",
3560
- "mailto:",
3561
- "sms:",
3562
- "tel:",
3563
- "vbscript:",
3564
- "ws:",
3565
- "wss:"
3566
- ]);
3567
- var BUILT_IN_AGENT_RETURN_TARGETS = [
3568
- {
3569
- aliases: ["workbuddy"],
3570
- label: "WorkBuddy",
3571
- url: "workbuddy://"
3572
- },
3573
- {
3574
- aliases: ["xiaoe", "xiaoeclient", "\u5C0Fe", "\u667A\u80FD\u5C0Fe"],
3575
- label: "\u667A\u80FD\u5C0F E",
3576
- url: "xiaoe-client://"
3577
- },
3578
- {
3579
- aliases: ["codex", "openaicodex"],
3580
- label: "Codex",
3581
- url: "codex://"
3582
- }
3583
- ];
3584
- function asOptions(value) {
3585
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3586
- }
3587
- function optionString(options, ...keys) {
3588
- for (const key of keys) {
3589
- const value = options[key];
3590
- if (typeof value === "string" && value.trim()) return value.trim();
3591
- }
3592
- return "";
3593
- }
3594
- function envString(env, ...keys) {
3595
- for (const key of keys) {
3596
- const value = env[key];
3597
- if (typeof value === "string" && value.trim()) return value.trim();
3598
- }
3599
- return "";
3600
- }
3601
- function hasEnvPrefix(env, prefix) {
3602
- return Object.keys(env).some((key) => key === prefix || key.startsWith(`${prefix}_`));
3603
- }
3604
- function inferAgentTypeFromEnv(env) {
3605
- if (hasXiaoEEnv(env)) return XIAOE_AGENT_TYPE;
3606
- if (hasEnvPrefix(env, "WORKBUDDY")) return "workbuddy";
3607
- if (hasEnvPrefix(env, "CODEX")) return "codex";
3608
- return "";
3609
- }
3610
- function resolveAgentType(options = {}, env = process.env) {
3611
- return optionString(options, "agentType", "agent_type") || envString(env, ...EXPLICIT_AGENT_TYPE_ENV_KEYS) || inferAgentTypeFromEnv(env) || DEFAULT_AGENT_TYPE;
3612
- }
3613
- function normalizeAgentKey(value) {
3614
- return value.toLowerCase().replace(/[^a-z0-9]+/gu, "");
3615
- }
3616
- function normalizeAgentAlias(value) {
3617
- return value.trim().toLowerCase().replace(/[^\p{Letter}\p{Number}]+/gu, "");
3618
- }
3619
- function builtInAgentReturnTarget(agentType) {
3620
- const alias = normalizeAgentAlias(agentType);
3621
- const target = BUILT_IN_AGENT_RETURN_TARGETS.find((candidate) => candidate.aliases.includes(alias));
3622
- return target ? { label: target.label, url: target.url } : null;
3623
- }
3624
- function conventionalAgentReturnUrl(agentType) {
3625
- const scheme = agentType.trim().toLowerCase();
3626
- if (normalizeAgentAlias(agentType) === normalizeAgentAlias(DEFAULT_AGENT_TYPE) || scheme.length > 64 || !/^[a-z][a-z0-9+.-]*$/u.test(scheme) || UNSAFE_AGENT_RETURN_PROTOCOLS.has(`${scheme}:`)) {
3627
- return "";
3628
- }
3629
- return `${scheme}://`;
3630
- }
3631
- function validateAgentReturnUrl(value) {
3632
- if (value.length > 2048 || /[\u0000-\u001f\u007f\s]/u.test(value) || !/^[a-z][a-z0-9+.-]*:\/\//iu.test(value)) {
3633
- throw new CliError("Invalid --agent-return-url value", 2 /* UsageError */);
3634
- }
3635
- let url;
3636
- try {
3637
- url = new URL(value);
3638
- } catch {
3639
- throw new CliError("Invalid --agent-return-url value", 2 /* UsageError */);
3640
- }
3641
- if (UNSAFE_AGENT_RETURN_PROTOCOLS.has(url.protocol)) {
3642
- throw new CliError("--agent-return-url must use a registered desktop application URL scheme.", 2 /* UsageError */);
3643
- }
3644
- return value;
3645
- }
3646
- function resolveAgentReturnTarget(options = {}, env = process.env, agentType = resolveAgentType(options, env)) {
3647
- const builtInTarget = builtInAgentReturnTarget(agentType);
3648
- const explicitUrl = optionString(options, "agentReturnUrl") || envString(env, AGENT_RETURN_URL_ENV_KEY);
3649
- if (explicitUrl) {
3650
- return {
3651
- label: builtInTarget?.label || agentType,
3652
- url: validateAgentReturnUrl(explicitUrl)
3653
- };
3654
- }
3655
- if (builtInTarget) return builtInTarget;
3656
- const conventionalUrl = conventionalAgentReturnUrl(agentType);
3657
- return conventionalUrl ? { label: agentType, url: conventionalUrl } : null;
3658
- }
3659
- function normalizeUrl(value) {
3660
- return value.replace(/\/+$/, "");
3661
- }
3662
- function readString(data, ...keys) {
3663
- for (const key of keys) {
3664
- const value = data[key];
3665
- if (typeof value === "string" && value) return value;
3666
- if (typeof value === "number") return String(value);
3667
- }
3668
- return "";
3669
- }
3670
- function cookieString(value) {
3671
- if (!value) return "";
3672
- if (typeof value === "string") return value;
3673
- if (typeof value === "object" && !Array.isArray(value)) {
3674
- return Object.entries(value).filter(([, cookieValue2]) => cookieValue2 !== void 0 && cookieValue2 !== null && cookieValue2 !== "").map(([name, cookieValue2]) => `${name}=${String(cookieValue2)}`).join("; ");
3675
- }
3676
- return "";
3677
- }
3678
- function cookieValue(rawCookie, name) {
3679
- const match = rawCookie.match(new RegExp(`${name}=([^;]+)`));
3680
- return match?.[1] || "";
3681
- }
3682
- function formatAuthStatus(status) {
3683
- if (!status.loggedIn) {
3684
- return "Not logged in. Select the appropriate authentication method for the current runtime before retrying.";
3685
- }
3686
- const lines = [
3687
- "Logged in.",
3688
- "userId: " + status.userId,
3689
- "tenantKey: " + (status.tenantKey || ""),
3690
- "tenantName: " + (status.tenantName || ""),
3691
- "department: " + (status.department || ""),
3692
- "subcompany: " + (status.subcompany || ""),
3693
- "position: " + (status.position || ""),
3694
- "version: " + (status.version || ""),
3695
- "agentType: " + (status.agentType || ""),
3696
- "baseUrl: " + status.baseUrl,
3697
- "profile: " + status.profile,
3698
- "authFile: " + status.authFile,
3699
- ..."loginSource" in status && status.loginSource ? ["loginSource: " + status.loginSource] : [],
3700
- ..."credentialSourceStep" in status && status.credentialSourceStep ? ["credentialSourceStep: " + status.credentialSourceStep] : [],
3701
- ..."credentialSourceType" in status && status.credentialSourceType ? ["credentialSourceType: " + status.credentialSourceType] : [],
3702
- ..."credentialSourceLabel" in status && status.credentialSourceLabel ? ["credentialSourceLabel: " + status.credentialSourceLabel] : [],
3703
- ..."expiryTimes" in status && status.expiryTimes ? ["expiryTimes: " + status.expiryTimes] : []
3704
- ];
3705
- if ("valid" in status) {
3706
- lines.push("valid: " + String(status.valid));
3707
- }
3708
- return lines.join("\n");
3709
- }
3710
- function formatLoginResult(result) {
3711
- return [
3712
- "Saved E10 auth.",
3713
- "userId: " + result.userId,
3714
- "tenantKey: " + result.tenantKey,
3715
- "tenantName: " + result.tenantName,
3716
- "baseUrl: " + result.baseUrl,
3717
- "profile: " + result.profile,
3718
- "authFile: " + result.authFile,
3719
- ...result.loginSource ? ["loginSource: " + result.loginSource] : [],
3720
- ...result.credentialSourceStep ? ["credentialSourceStep: " + result.credentialSourceStep] : [],
3721
- ...result.credentialSourceType ? ["credentialSourceType: " + result.credentialSourceType] : [],
3722
- ...result.credentialSourceLabel ? ["credentialSourceLabel: " + result.credentialSourceLabel] : [],
3723
- ...result.expiryTimes ? ["expiryTimes: " + result.expiryTimes] : []
3724
- ].join("\n");
3725
- }
3726
- async function clearInvoiceTokenCache(profile, authData) {
3727
- if (!authData.baseUrl || !authData.userId) return;
3728
- await clearInvoiceTokenForSession({
3729
- baseUrl: normalizeUrl(authData.baseUrl),
3730
- profile,
3731
- userId: authData.userId
3732
- }).catch(() => false);
3733
- }
3734
- function posixShellQuote(value) {
3735
- return `'${value.replace(/'/g, "'\\''")}'`;
3736
- }
3737
- function powershellQuote(value) {
3738
- return `'${value.replace(/'/g, "''")}'`;
3739
- }
3740
- function resolveWeaverEnvShell(shell, platform = process.platform) {
3741
- if (shell === "auto") return platform === "win32" ? "powershell" : "posix";
3742
- if (shell === "posix" || shell === "powershell") return shell;
3743
- throw new CliError("Invalid --shell value. Use auto, posix, or powershell.", 2 /* UsageError */);
3744
- }
3745
- function formatWeaverEnvExports(value, shell = "auto", platform = process.platform) {
3746
- const resolved = resolveWeaverEnvShell(shell, platform);
3747
- return Object.entries(value).map(([name, envValue2]) => resolved === "powershell" ? `$env:${name} = ${powershellQuote(envValue2)}` : `export ${name}=${posixShellQuote(envValue2)}`).join("\n");
3748
- }
3749
- function esc(value) {
3750
- return String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3751
- }
3752
- function renderE10LoginSuccessPage(userId, returnTarget = null, launchToken = "") {
3753
- const safeReturnTarget = returnTarget ? { ...returnTarget, url: validateAgentReturnUrl(returnTarget.url) } : null;
3754
- const agentKey = safeReturnTarget ? normalizeAgentKey(safeReturnTarget.label) || "agent" : "";
3755
- const returnAction = safeReturnTarget && launchToken ? `<div class="overlay" data-agent-return data-token="${esc(launchToken)}" data-agent-key="${esc(agentKey)}" data-agent-label="${esc(safeReturnTarget.label)}" data-fallback-url="${esc(safeReturnTarget.url)}"><section class="prompt" role="dialog" aria-modal="true" aria-labelledby="agent-return-title"><div class="app-icon" aria-hidden="true"><svg viewBox="0 0 64 64"><defs><linearGradient id="app-gradient" x1="8" y1="4" x2="56" y2="60" gradientUnits="userSpaceOnUse"><stop stop-color="#24d3b5"/><stop offset="1" stop-color="#08aa82"/></linearGradient></defs><rect width="64" height="64" rx="16" fill="url(#app-gradient)"/><path d="M18 21.5 32 13l14 8.5v17L32 47 18 38.5v-17Z" fill="#fff" fill-opacity=".96"/><rect x="23" y="25" width="18" height="15" rx="6" fill="#12b991"/><circle cx="28.5" cy="32.5" r="1.8" fill="#fff"/><circle cx="35.5" cy="32.5" r="1.8" fill="#fff"/></svg></div><h1 id="agent-return-title">\u662F\u5426\u6253\u5F00\u201C${esc(safeReturnTarget.label)}\u201D\uFF1F</h1><p>\u767B\u5F55\u6388\u6743\u5DF2\u5B8C\u6210\uFF0C\u8FD4\u56DE ${esc(safeReturnTarget.label)} \u7EE7\u7EED\u4F7F\u7528\u3002</p><button class="primary" type="button" data-action="open">\u6253\u5F00\u201C${esc(safeReturnTarget.label)}\u201D</button><button class="secondary" type="button" data-action="always">\u59CB\u7EC8\u6253\u5F00\u201C${esc(safeReturnTarget.label)}\u201D</button><button class="secondary" type="button" data-action="cancel">\u53D6\u6D88</button><div class="status" role="status" aria-live="polite"></div></section></div>` : "";
3756
- const returnScript = safeReturnTarget && launchToken ? `<script nonce="${esc(launchToken)}">(()=>{const root=document.querySelector('[data-agent-return]');if(!root)return;const status=root.querySelector('.status');const buttons=[...root.querySelectorAll('button')];const agentLabel=root.dataset.agentLabel||'\u5E94\u7528';const fallbackUrl=root.dataset.fallbackUrl||'';const storageKey='weaver-work-cli.agent-return.'+root.dataset.agentKey;let busy=false;const setBusy=value=>{busy=value;buttons.forEach(button=>{button.disabled=value;});};const closePrompt=()=>{root.hidden=true;};const savePreference=()=>{try{localStorage.setItem(storageKey,'1');}catch{}};const clearPreference=()=>{try{localStorage.removeItem(storageKey);}catch{}};const hasPreference=()=>{try{return localStorage.getItem(storageKey)==='1';}catch{return false;}};const post=async action=>{let response;try{response=await fetch('${AGENT_RETURN_PATH}?action='+encodeURIComponent(action),{method:'POST',headers:{'${AGENT_RETURN_TOKEN_HEADER}':root.dataset.token}});}catch{return false;}if(!response.ok)throw new Error(await response.text()||'\u8BF7\u6C42\u5931\u8D25');return true;};const openAgent=async persist=>{if(busy)return;setBusy(true);status.textContent='\u6B63\u5728\u6253\u5F00 '+agentLabel+'\u2026';try{const openedLocally=await post('open');if(persist)savePreference();if(!openedLocally){closePrompt();window.location.href=fallbackUrl;return;}closePrompt();}catch(error){if(persist)clearPreference();status.textContent=error instanceof Error?error.message:'\u65E0\u6CD5\u6253\u5F00\u5E94\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002';setBusy(false);}};root.querySelector('[data-action="open"]').addEventListener('click',()=>openAgent(false));root.querySelector('[data-action="always"]').addEventListener('click',()=>openAgent(true));root.querySelector('[data-action="cancel"]').addEventListener('click',()=>{if(busy)return;clearPreference();closePrompt();post('cancel').catch(()=>{});});if(hasPreference())openAgent(false);})();</script>` : "";
3757
- return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>weaver-work-cli \u767B\u5F55\u6210\u529F</title><style>:root{color-scheme:light}*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Arial,sans-serif;background:radial-gradient(circle at 50% 18%,#eefbf8 0,#f6f7f9 42%,#eef1f5 100%);color:#20242a;display:grid;place-items:center;min-height:100vh;margin:0}.card{background:rgba(255,255,255,.88);border:1px solid #e6e8ec;border-radius:18px;padding:34px 38px;box-shadow:0 18px 55px rgba(18,24,40,.09);width:min(560px,calc(100vw - 40px));text-align:center}.title{font-size:24px;font-weight:700;margin-bottom:10px}.desc{color:#667085;font-size:15px;line-height:24px}.user{color:#98a2b3;font-size:12px;margin-top:18px}.overlay{position:fixed;inset:0;z-index:10;display:grid;place-items:center;padding:20px;background:rgba(28,34,41,.36);backdrop-filter:blur(5px)}.overlay[hidden]{display:none}.prompt{width:min(410px,calc(100vw - 32px));padding:32px 28px 26px;border:1px solid rgba(255,255,255,.75);border-radius:24px;background:rgba(250,250,251,.97);box-shadow:0 24px 70px rgba(15,23,42,.28);text-align:center}.app-icon{width:74px;height:74px;margin:0 auto 24px;filter:drop-shadow(0 8px 14px rgba(8,170,130,.22))}.app-icon svg{display:block;width:100%;height:100%}.prompt h1{margin:0;font-size:20px;line-height:30px;font-weight:700;letter-spacing:-.2px}.prompt p{margin:10px 0 24px;color:#667085;font-size:14px;line-height:22px}.prompt button{display:block;width:100%;min-height:40px;border:0;border-radius:12px;font:600 16px/22px inherit;cursor:pointer;transition:transform .12s ease,filter .12s ease}.prompt button+button{margin-top:10px}.prompt button:hover{filter:brightness(.98)}.prompt button:active{transform:scale(.99)}.prompt button:disabled{cursor:wait;opacity:.62}.primary{background:linear-gradient(180deg,#2f91ff,#0b74e5);color:#fff;box-shadow:0 8px 18px rgba(11,116,229,.2)}.secondary{background:#e9eaec;color:#22252a}.status{min-height:18px;margin-top:14px;color:#667085;font-size:12px;line-height:18px}</style></head><body><main class="card"><div class="title">\u767B\u5F55\u6388\u6743\u6210\u529F</div><div class="desc">\u4F60\u53EF\u4EE5\u5173\u95ED\u6B64\u9875\u9762\uFF0C\u8FD4\u56DE\u667A\u80FD\u4F53\u6216\u7EC8\u7AEF\u7EE7\u7EED\u4F7F\u7528\u3002</div><div class="user">${esc(userId)}</div></main>${returnAction}${returnScript}</body></html>`;
3758
- }
3759
- function resolveBrowserOpenCommand(url, platform = process.platform) {
3760
- if (platform === "win32") {
3761
- return { file: "rundll32.exe", args: ["url.dll,FileProtocolHandler", url] };
3762
- }
3763
- if (platform === "darwin") return { file: "open", args: [url] };
3764
- return { file: "xdg-open", args: [url] };
3765
- }
3766
- function openUrlInBrowser(url, ctx) {
3767
- const command = resolveBrowserOpenCommand(url);
3768
- execFile(command.file, command.args, (error) => {
3769
- if (error) {
3770
- ctx.logger.warn("Could not open browser automatically. Copy the login URL manually.");
3771
- }
3336
+ function invoiceValidationError(subtype, message, details) {
3337
+ return new InvoiceCliError("validation", subtype, message, {
3338
+ details,
3339
+ exitCode: 2 /* UsageError */
3772
3340
  });
3773
3341
  }
3774
- function openUrlWithSystemHandler(url) {
3775
- const command = resolveBrowserOpenCommand(url);
3776
- return new Promise((resolve8, reject) => {
3777
- execFile(command.file, command.args, (error) => {
3778
- if (error) reject(error);
3779
- else resolve8();
3780
- });
3342
+ function invoiceAuthError(subtype, message, details) {
3343
+ return new InvoiceCliError("authentication", subtype, message, {
3344
+ details,
3345
+ exitCode: 3 /* AuthError */
3781
3346
  });
3782
3347
  }
3783
- function buildE10AuthorizeUrl(baseUrl, redirectUri, agentType) {
3784
- const authorizeParams = new URLSearchParams({
3785
- redirect_uri: redirectUri,
3786
- response_type: "code",
3787
- access_type: "agent",
3788
- agent_type: agentType,
3789
- from: agentType
3348
+ function invoiceNetworkError(subtype, message, options = {}) {
3349
+ return new InvoiceCliError("network", subtype, message, {
3350
+ ...options,
3351
+ retryable: options.retryable ?? true,
3352
+ exitCode: 4 /* NetworkError */
3790
3353
  });
3791
- return `${baseUrl}/papi/sso/oauth2.0/authorize?${authorizeParams.toString()}`;
3792
- }
3793
- function isTlsClientHello(error) {
3794
- if (!error || typeof error !== "object") return false;
3795
- const rawPacket = error.rawPacket;
3796
- return Buffer.isBuffer(rawPacket) && rawPacket.length >= 3 && rawPacket[0] === 22 && rawPacket[1] === 3;
3797
3354
  }
3798
- function createOAuthCallbackProtocolMismatchError(port) {
3799
- return Object.assign(new CliError(
3800
- `OAuth callback protocol mismatch: the browser connected to https://127.0.0.1:${port}, but the CLI callback listener uses HTTP. Retry the login and, on the callback error page, change only the URL scheme to http:// before reloading; keep the path and query unchanged. The E10 authorization service should preserve HTTP loopback redirect URIs.`,
3801
- 3 /* AuthError */
3802
- ), {
3803
- type: "authentication",
3804
- subtype: "oauth_callback_protocol_mismatch",
3805
- retryable: false,
3806
- stage: "oauth_callback"
3355
+ function invoiceConfirmationError(action, details) {
3356
+ return new InvoiceCliError("confirmation", "required", "\u8BE5\u64CD\u4F5C\u9700\u8981\u660E\u786E\u786E\u8BA4", {
3357
+ details: { action, ...details },
3358
+ exitCode: 10 /* ConfirmationRequired */
3807
3359
  });
3808
3360
  }
3809
- async function readJsonObject(resp) {
3810
- const data = await resp.json().catch(() => ({}));
3811
- return data && typeof data === "object" && !Array.isArray(data) ? data : {};
3812
- }
3813
- async function resolveUserInfo(baseUrl, eteamsId, rawCookie = "", agentType = "") {
3814
- const resp = await fetch(`${baseUrl}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(baseUrl)}`, {
3815
- method: "POST",
3816
- headers: {
3817
- accept: "application/json",
3818
- "content-type": "application/json",
3819
- eteamsid: eteamsId,
3820
- cookie: buildE10CookieHeader(rawCookie, eteamsId, agentType),
3821
- "user-agent": agentType ? `AgentType=${agentType},IsAgent=true` : DEFAULT_AGENT_TYPE,
3822
- origin: baseUrl
3823
- },
3824
- redirect: "manual"
3361
+ function invoicePartialError(message, partialData, details) {
3362
+ return new InvoiceCliError("partial", "write_uncertain", message, {
3363
+ details,
3364
+ partialData,
3365
+ exitCode: 11 /* Partial */
3825
3366
  });
3826
- const data = await resp.json().catch(() => ({}));
3827
- return { userInfo: readTeamsCheckUserInfo(resp, data), setCookie: extractRawSetCookie(resp) };
3828
- }
3829
- async function saveEteamsIdLogin(input) {
3830
- const baseUrl = normalizeUrl(input.baseUrl);
3831
- const passportUrl = normalizeUrl(input.passportUrl || baseUrl);
3832
- const { userInfo, setCookie } = await resolveUserInfo(baseUrl, input.eteamsId, input.rawCookie || "", input.agentType);
3833
- if (!userInfo.userId) {
3834
- throw new CliError("Could not resolve userId. Check whether ETEAMSID is valid for this E10 domain.", 3 /* AuthError */);
3835
- }
3836
- const tenantKey = userInfo.tenantKey || input.tenantKeyFallback;
3837
- const profile = input.profileHint || profileNameFromUrl(baseUrl);
3838
- setActiveProfile(profile);
3839
- const cookies = { ETEAMSID: input.eteamsId };
3840
- if (input.rawCookie) cookies.raw = input.rawCookie;
3841
- const ztSession = extractSessionTicket(setCookie, input.rawCookie || "");
3842
- const authData = {
3843
- cookies,
3844
- userId: userInfo.userId,
3845
- tenantKey,
3846
- tenantName: userInfo.tenantName,
3847
- department: userInfo.department,
3848
- subcompany: userInfo.subcompany,
3849
- position: userInfo.position,
3850
- agentType: input.agentType,
3851
- version: input.version || "",
3852
- baseUrl,
3853
- passportUrl,
3854
- cookieSavedAt: Date.now(),
3855
- ...ztSession ? { ztSession } : {}
3856
- };
3857
- await clearInvoiceTokenCache(profile, authData);
3858
- const authFile = saveAuthFile(authData, profile);
3859
- saveProfileConfig(baseUrl, passportUrl, profile, tenantKey);
3860
- return {
3861
- ...userInfo,
3862
- tenantKey,
3863
- eteamsId: input.eteamsId,
3864
- baseUrl,
3865
- passportUrl,
3866
- profile,
3867
- authFile,
3868
- agentType: input.agentType,
3869
- version: input.version || ""
3870
- };
3871
3367
  }
3872
- async function tryXiaoEUnifiedLogin2(ctx, baseUrl, tenantKeyFallback, profileHint, allowTokenScript = false) {
3873
- const login = await tryXiaoEUnifiedLogin({
3874
- env: ctx.env,
3875
- baseUrl,
3876
- allowBundledEnvScript: true,
3877
- tenantKeyFallback,
3878
- profileHint,
3879
- allowTokenScript,
3880
- logger: ctx.logger
3881
- });
3882
- return login?.result || null;
3368
+ function isInvoiceNetworkError(error) {
3369
+ return Boolean(
3370
+ error && typeof error === "object" && "type" in error && error.type === "network"
3371
+ );
3883
3372
  }
3884
- async function oidcExchange(code, redirectUri, baseUrl, tenantKeyFallback, agentTypeFallback, profileHint) {
3885
- const base = normalizeUrl(baseUrl);
3886
- const tokenParams = new URLSearchParams({
3887
- grant_type: "authorization_code",
3888
- code,
3889
- redirect_uri: redirectUri
3890
- });
3891
- const tokenResp = await fetch(`${base}/papi/sso/oauth2.0/accessToken`, {
3892
- method: "POST",
3893
- headers: { "content-type": "application/x-www-form-urlencoded" },
3894
- body: tokenParams.toString(),
3895
- redirect: "manual"
3896
- });
3897
- const tokenData = await readJsonObject(tokenResp);
3898
- if (tokenResp.status >= 400) {
3899
- const message = readString(tokenData, "message", "msg", "error_description", "error") || `OAuth token exchange failed: ${tokenResp.status}`;
3900
- throw new CliError(message, 3 /* AuthError */);
3901
- }
3902
- let eteamsId = readString(tokenData, "eteamsId", "eteamsid");
3903
- let userId = readString(tokenData, "id", "userId", "employeeId");
3904
- let rawCookies = cookieString(tokenData.cookies || tokenData.cookie) || extractRawSetCookie(tokenResp);
3905
- let agentType = agentTypeFallback || readString(tokenData, "agentType", "agent_type");
3906
- let version = readString(tokenData, "version", "baselineVersion");
3907
- const accessToken = readString(tokenData, "access_token", "accessToken");
3908
- if (!eteamsId) eteamsId = cookieValue(rawCookies, "ETEAMSID");
3909
- if (accessToken && (!eteamsId || !userId || !rawCookies || !version || !agentType)) {
3910
- const profileResp = await fetch(`${base}/papi/sso/oauth2.0/profile?access_token=${encodeURIComponent(accessToken)}`, {
3911
- method: "POST",
3912
- headers: { accept: "application/json" },
3913
- redirect: "manual"
3914
- });
3915
- const profileData = await readJsonObject(profileResp);
3916
- const profileRawCookies = cookieString(profileData.cookies || profileData.cookie) || extractRawSetCookie(profileResp);
3917
- if (!eteamsId) eteamsId = readString(profileData, "eteamsId", "eteamsid") || cookieValue(profileRawCookies, "ETEAMSID");
3918
- if (!userId) userId = readString(profileData, "id", "userId", "employeeId");
3919
- if (!rawCookies) rawCookies = profileRawCookies;
3920
- if (!agentType) agentType = readString(profileData, "agentType", "agent_type");
3921
- if (!version) version = readString(profileData, "version", "baselineVersion");
3922
- }
3923
- if (!eteamsId) {
3924
- throw new CliError("Could not resolve ETEAMSID from OAuth response.", 3 /* AuthError */);
3373
+
3374
+ // src/shortcuts/invoice/host.ts
3375
+ import { createHash } from "node:crypto";
3376
+ import { readFile } from "node:fs/promises";
3377
+ var MAX_DOWNLOAD_BYTES = 50 * 1024 * 1024;
3378
+ var TOKEN_SERVICE = "cn.weaver.weaver-work-cli.invoice-token";
3379
+ var INVOICE_SESSION_EXPIRED_CODE = "-2";
3380
+ function assertPath(requestPath) {
3381
+ if (typeof requestPath !== "string" || !requestPath.startsWith("/") || requestPath.startsWith("//")) {
3382
+ throw invoiceValidationError("path_invalid", "\u8BF7\u6C42\u8DEF\u5F84\u5FC5\u987B\u662F\u76F8\u5BF9\u7EDD\u5BF9\u8DEF\u5F84");
3383
+ }
3384
+ if (/^https?:/i.test(requestPath) || /[\r\n]/.test(requestPath) || requestPath.includes("/../")) {
3385
+ throw invoiceValidationError("path_invalid", "\u8BF7\u6C42\u8DEF\u5F84\u4E0D\u5141\u8BB8\u8DE8\u57DF\u6216\u8DEF\u5F84\u9003\u9038");
3386
+ }
3387
+ if (!requestPath.startsWith("/api/")) {
3388
+ throw invoiceValidationError("path_not_allowed", "\u4E1A\u7968\u901A\u53EA\u80FD\u8C03\u7528 /api/ \u8DEF\u5F84");
3389
+ }
3390
+ }
3391
+ function responseRoot(value) {
3392
+ return value?.res_base || value?.data?.res_base || value;
3393
+ }
3394
+ function responseMessage(value) {
3395
+ const root = responseRoot(value);
3396
+ return typeof root?.message === "string" ? root.message : typeof root?.msg === "string" ? root.msg : "\u6CDB\u5FAE\u63A5\u53E3\u8FD4\u56DE\u4E1A\u52A1\u5931\u8D25";
3397
+ }
3398
+ function responseCode(value) {
3399
+ const root = responseRoot(value);
3400
+ return root?.ret ?? root?.code;
3401
+ }
3402
+ function isInvoiceSessionExpired(value) {
3403
+ const code = responseCode(value);
3404
+ return code !== void 0 && String(code) === INVOICE_SESSION_EXPIRED_CODE;
3405
+ }
3406
+ function tokenAccount(session) {
3407
+ return createHash("sha256").update(`${session.profile}
3408
+ ${session.baseUrl}
3409
+ ${session.userId}`).digest("hex");
3410
+ }
3411
+ function createInvoiceTokenStore(session) {
3412
+ const account = tokenAccount(session);
3413
+ let entryPromise = null;
3414
+ async function entry() {
3415
+ if (!entryPromise) {
3416
+ entryPromise = import("@napi-rs/keyring").then(({ Entry }) => new Entry(TOKEN_SERVICE, account));
3417
+ }
3418
+ return entryPromise;
3925
3419
  }
3926
- const { userInfo, setCookie } = await resolveUserInfo(base, eteamsId, rawCookies, agentType).catch(() => ({
3927
- userInfo: {
3928
- userId: "",
3929
- tenantKey: "",
3930
- tenantName: "",
3931
- department: "",
3932
- subcompany: "",
3933
- position: ""
3934
- },
3935
- setCookie: ""
3936
- }));
3937
- const tenantKey = readString(tokenData, "tenant_key", "tenantKey") || userInfo.tenantKey || tenantKeyFallback;
3938
- const ztSession = extractSessionTicket(setCookie, rawCookies);
3939
- const authData = {
3940
- cookies: { ETEAMSID: eteamsId, raw: rawCookies },
3941
- userId: userInfo.userId || userId || "unknown",
3942
- tenantKey,
3943
- tenantName: userInfo.tenantName,
3944
- department: userInfo.department,
3945
- subcompany: userInfo.subcompany,
3946
- position: userInfo.position,
3947
- agentType,
3948
- version,
3949
- baseUrl: base,
3950
- passportUrl: base,
3951
- cookieSavedAt: Date.now(),
3952
- ...ztSession ? { ztSession } : {}
3953
- };
3954
- const profile = profileHint || profileNameFromUrl(base);
3955
- setActiveProfile(profile);
3956
- await clearInvoiceTokenCache(profile, authData);
3957
- const authFile = saveAuthFile(authData, profile);
3958
- saveProfileConfig(base, base, profile, tenantKey);
3959
3420
  return {
3960
- userId: authData.userId,
3961
- tenantKey,
3962
- tenantName: authData.tenantName || "",
3963
- department: authData.department || "",
3964
- subcompany: authData.subcompany || "",
3965
- position: authData.position || "",
3966
- eteamsId,
3967
- baseUrl: base,
3968
- passportUrl: base,
3969
- profile,
3970
- authFile,
3971
- agentType,
3972
- version
3973
- };
3974
- }
3975
- function xiaoEUnifiedLoginUnavailableMessage(baseUrl, attempted) {
3976
- return [
3977
- attempted ? "XiaoE \u7EDF\u4E00\u767B\u5F55\u5DF2\u5C1D\u8BD5\uFF0C\u4F46\u672A\u83B7\u53D6\u5230\u53EF\u7528\u4F1A\u8BDD\u3002" : "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 XiaoE \u7EDF\u4E00\u767B\u5F55\u51ED\u636E\u6E90\uFF0C\u672C\u6B21\u672A\u5C1D\u8BD5\u7EDF\u4E00\u767B\u5F55\u3002",
3978
- "`auth xiaoe` \u4E0D\u4F1A\u964D\u7EA7\u5230\u6D4F\u89C8\u5668 OAuth\u3002",
3979
- baseUrl ? `\u5F53\u524D E10 baseUrl: ${baseUrl}\u3002` : "\u672A\u4ECE XiaoE \u51ED\u8BC1\u4E2D\u89E3\u6790\u5230 E10 baseUrl\u3002",
3980
- attempted ? "CLI \u5DF2\u4F9D\u6B21\u5C1D\u8BD5\u5E73\u53F0\u6CE8\u5165\u51ED\u8BC1\u7684 Node \u6362\u7968\u3001CLI \u5185\u7F6E xiaoe_env.py \u517C\u5BB9\u6362\u7968\u3001\u5BBF\u4E3B xiaoeUserData/tokens.py\u3001\u684C\u9762 XiaoE \u5BA2\u6237\u7AEF\u51ED\u8BC1\uFF08XiaoE/Robots/*/user_settings.json\uFF09\u548C WEAVER_XIAOE_* \u73AF\u5883\u6620\u5C04\u3002" : "CLI \u5DF2\u68C0\u67E5\u5E73\u53F0\u6CE8\u5165\u51ED\u8BC1\u3001\u5BBF\u4E3B xiaoeUserData/tokens.py\u3001\u684C\u9762 XiaoE \u5BA2\u6237\u7AEF\u51ED\u8BC1\uFF08XiaoE/Robots/*/user_settings.json\uFF09\u548C WEAVER_XIAOE_* \u73AF\u5883\u6620\u5C04\u3002",
3981
- "CLI \u4F1A\u4F18\u5148\u4F7F\u7528 XiaoE \u5BA2\u6237\u7AEF\u5185\u7F6E Python \u6267\u884C tokens.py\uFF1B\u81EA\u52A8\u53D1\u73B0\u4E0D\u53EF\u7528\u65F6\uFF0C\u53EF\u7528 WEAVER_XIAOE_TOKEN_SCRIPT_PYTHON \u6307\u5B9A\u517C\u5BB9\u89E3\u91CA\u5668\u3002"
3982
- ].join(" ");
3983
- }
3984
- async function runXiaoELogin(ctx, options) {
3985
- const commandOpts = asOptions(options);
3986
- const globalOptions = ctx.getGlobalOptions();
3987
- const profileFromGlobal = globalOptions.profile;
3988
- const cfg = readProfileConfig(profileFromGlobal || getActiveProfile());
3989
- const explicitBaseUrl = optionString(commandOpts, "baseUrl") || globalOptions.baseUrl || "";
3990
- const preferredXiaoEBaseUrl = resolveXiaoEPreferredBaseUrl({
3991
- explicitBaseUrl,
3992
- profileBaseUrl: cfg.baseUrl,
3993
- env: ctx.env
3994
- });
3995
- const xiaoESources = inspectXiaoEUnifiedLoginSources({
3996
- env: ctx.env,
3997
- baseUrl: preferredXiaoEBaseUrl,
3998
- profileBaseUrl: cfg.baseUrl,
3999
- allowTokenScript: true
4000
- });
4001
- const useXiaoELogin = xiaoESources.any;
4002
- const baseUrl = preferredXiaoEBaseUrl;
4003
- const tenantKey = optionString(commandOpts, "tenantKey");
4004
- ctx.logger.info([
4005
- "XiaoE unified login preflight:",
4006
- "authMode=xiaoe",
4007
- `credentialSourceDetected=${String(xiaoESources.any)}`,
4008
- `attempted=${String(useXiaoELogin)}`,
4009
- `platformCredentialDetected=${String(xiaoESources.platformCredential)}`,
4010
- `tokenScriptDetected=${String(xiaoESources.tokenScript)}`,
4011
- `clientSettingsDetected=${String(xiaoESources.clientCredential)}`,
4012
- `environmentCredentialDetected=${String(xiaoESources.environmentCredential)}`,
4013
- `clientType=${xiaoESources.clientType || "(unset)"}`,
4014
- `baseUrl=${baseUrl || "(unresolved)"}`
4015
- ].join(" "));
4016
- if (useXiaoELogin) {
4017
- const xiaoEResult = await tryXiaoEUnifiedLogin2(ctx, baseUrl, tenantKey, profileFromGlobal, true);
4018
- if (xiaoEResult) return xiaoEResult;
4019
- }
4020
- ctx.logger.warn(xiaoEUnifiedLoginUnavailableMessage(baseUrl, useXiaoELogin));
4021
- throw createXiaoEUnifiedLoginUnavailableError(baseUrl);
4022
- }
4023
- async function runBrowserLogin(ctx, options) {
4024
- const commandOpts = asOptions(options);
4025
- const globalOptions = ctx.getGlobalOptions();
4026
- const profileFromGlobal = globalOptions.profile;
4027
- const cfg = readProfileConfig(profileFromGlobal || getActiveProfile());
4028
- const explicitBaseUrl = optionString(commandOpts, "baseUrl") || globalOptions.baseUrl || "";
4029
- const baseUrl = normalizeUrl(explicitBaseUrl || cfg.baseUrl || "");
4030
- const tenantKey = optionString(commandOpts, "tenantKey");
4031
- const portText = optionString(commandOpts, "port") || "19800";
4032
- const port = Number.parseInt(portText, 10);
4033
- const explicitAgentType = optionString(commandOpts, "agentType", "agent_type");
4034
- const agentType = resolveAgentType(commandOpts, ctx.env);
4035
- if (!Number.isInteger(port) || port <= 0 || port > 65535) {
4036
- throw new CliError("Invalid --port value", 2 /* UsageError */);
4037
- }
4038
- if (!baseUrl) throw new CliError("Missing --base-url", 2 /* UsageError */);
4039
- const agentReturnTarget = resolveAgentReturnTarget(commandOpts, ctx.env, agentType);
4040
- const agentReturnToken = agentReturnTarget ? randomBytes(24).toString("base64url") : "";
4041
- const redirectUri = `http://127.0.0.1:${port}/callback`;
4042
- const loginUrl = buildE10AuthorizeUrl(baseUrl, redirectUri, agentType);
4043
- ctx.logger.info("Open browser login: " + loginUrl);
4044
- ctx.logger.info("Waiting for E10 authorization callback...");
4045
- return await new Promise((resolve8, reject) => {
4046
- let settled = false;
4047
- let timer = null;
4048
- let pendingLoginResult = null;
4049
- let tlsCallbackDetected = false;
4050
- const finish = (error, result) => {
4051
- if (settled) return;
4052
- settled = true;
4053
- if (timer) clearTimeout(timer);
4054
- const complete = () => {
4055
- if (error) reject(error);
4056
- else resolve8(result);
4057
- };
3421
+ async load() {
4058
3422
  try {
4059
- server.close(complete);
3423
+ const value = await (await entry()).getPassword();
3424
+ return typeof value === "string" && value.trim() ? value : null;
4060
3425
  } catch {
4061
- complete();
4062
- }
4063
- };
4064
- const server = createServer(async (req, res) => {
4065
- const callbackUrl = new URL(req.url || "/", `http://127.0.0.1:${port}`);
4066
- if (callbackUrl.pathname === AGENT_RETURN_PATH) {
4067
- const requestToken = req.headers[AGENT_RETURN_TOKEN_HEADER];
4068
- if (req.method !== "POST" || !agentReturnTarget || !pendingLoginResult || requestToken !== agentReturnToken) {
4069
- res.writeHead(403, { "cache-control": "no-store", "content-type": "text/plain; charset=utf-8" });
4070
- res.end("Forbidden");
4071
- return;
4072
- }
4073
- const action = callbackUrl.searchParams.get("action");
4074
- if (action === "cancel") {
4075
- const result = pendingLoginResult;
4076
- res.writeHead(204, { "cache-control": "no-store" });
4077
- res.end();
4078
- finish(null, result);
4079
- return;
4080
- }
4081
- if (action !== "open") {
4082
- res.writeHead(400, { "cache-control": "no-store", "content-type": "text/plain; charset=utf-8" });
4083
- res.end("Invalid action");
4084
- return;
4085
- }
4086
- try {
4087
- await openUrlWithSystemHandler(agentReturnTarget.url);
4088
- const result = pendingLoginResult;
4089
- res.writeHead(200, { "cache-control": "no-store", "content-type": "application/json; charset=utf-8" });
4090
- res.end('{"ok":true}');
4091
- finish(null, result);
4092
- } catch {
4093
- ctx.logger.warn(`Could not open ${agentReturnTarget.label} automatically.`);
4094
- res.writeHead(500, { "cache-control": "no-store", "content-type": "text/plain; charset=utf-8" });
4095
- res.end(`\u65E0\u6CD5\u6253\u5F00 ${agentReturnTarget.label}\uFF0C\u8BF7\u786E\u8BA4\u5E94\u7528\u5DF2\u5B89\u88C5\u3002`);
4096
- }
4097
- return;
4098
- }
4099
- if (callbackUrl.pathname !== "/callback") {
4100
- res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
4101
- res.end("Not found");
4102
- return;
4103
- }
4104
- const error = callbackUrl.searchParams.get("error");
4105
- const code = callbackUrl.searchParams.get("code");
4106
- const redirectAgentType = explicitAgentType || callbackUrl.searchParams.get("agent_type") || callbackUrl.searchParams.get("agentType") || callbackUrl.searchParams.get("from") || agentType;
4107
- if (error) {
4108
- const message = callbackUrl.searchParams.get("error_description") || error;
4109
- res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
4110
- res.end(`<h1>Authorization failed</h1><p>${esc(message)}</p>`);
4111
- finish(new CliError("OAuth authorization failed: " + message, 3 /* AuthError */));
4112
- return;
4113
- }
4114
- if (!code) {
4115
- res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
4116
- res.end("<h1>Login failed</h1><p>Missing authorization code.</p>");
4117
- finish(new CliError("No authorization code received.", 3 /* AuthError */));
4118
- return;
4119
- }
4120
- if (tlsCallbackDetected && timer) {
4121
- clearTimeout(timer);
4122
- timer = null;
3426
+ return null;
4123
3427
  }
3428
+ },
3429
+ async save(token) {
3430
+ if (!token.trim()) return false;
4124
3431
  try {
4125
- const result = await oidcExchange(code, redirectUri, baseUrl, tenantKey, redirectAgentType, profileFromGlobal);
4126
- const responseHeaders = {
4127
- "cache-control": "no-store",
4128
- "content-security-policy": agentReturnTarget ? `default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-${agentReturnToken}'; connect-src 'self'` : `default-src 'none'; style-src 'unsafe-inline'`,
4129
- "content-type": "text/html; charset=utf-8",
4130
- "referrer-policy": "no-referrer",
4131
- "x-content-type-options": "nosniff",
4132
- "x-frame-options": "DENY"
4133
- };
4134
- res.writeHead(200, responseHeaders);
4135
- res.end(renderE10LoginSuccessPage(result.userId, agentReturnTarget, agentReturnToken));
4136
- if (!agentReturnTarget) {
4137
- finish(null, result);
4138
- return;
4139
- }
4140
- pendingLoginResult = result;
4141
- if (timer) clearTimeout(timer);
4142
- timer = setTimeout(() => finish(null, result), AGENT_RETURN_TIMEOUT_MS);
4143
- } catch (exchangeError) {
4144
- const message = exchangeError instanceof Error ? exchangeError.message : String(exchangeError);
4145
- res.writeHead(500, { "content-type": "text/html; charset=utf-8" });
4146
- res.end(`<h1>Login failed</h1><p>${esc(message)}</p>`);
4147
- finish(exchangeError);
3432
+ await (await entry()).setPassword(token);
3433
+ return true;
3434
+ } catch {
3435
+ return false;
4148
3436
  }
4149
- });
4150
- server.on("error", (error) => {
4151
- const message = error.code === "EADDRINUSE" ? `Port ${port} is already in use. Retry with --port ${port + 1}.` : error.code === "EACCES" ? `Port ${port} is not accessible. Retry with another --port.` : error.message;
4152
- finish(new CliError(message, 2 /* UsageError */));
4153
- });
4154
- server.on("clientError", (error, socket) => {
4155
- if (isTlsClientHello(error)) {
4156
- if (!tlsCallbackDetected) {
4157
- tlsCallbackDetected = true;
4158
- ctx.logger.warn([
4159
- `OAuth callback protocol mismatch: the browser used HTTPS for 127.0.0.1:${port}, while the CLI listener is HTTP.`,
4160
- "\u5728 30 \u79D2\u5185\u628A\u6D4F\u89C8\u5668\u5F53\u524D\u5730\u5740\u5F00\u5934\u660E\u786E\u6539\u4E3A http://\uFF0C\u4FDD\u7559\u540E\u9762\u7684\u5B8C\u6574\u8DEF\u5F84\u548C\u53C2\u6570\uFF0C\u7136\u540E\u56DE\u8F66\u91CD\u8BD5\u3002",
4161
- "\u4E0D\u8981\u628A\u5730\u5740\u4E2D\u7684\u6388\u6743\u7801\u590D\u5236\u5230\u804A\u5929\u6216\u65E5\u5FD7\u3002"
4162
- ].join(" "));
4163
- if (timer) clearTimeout(timer);
4164
- timer = setTimeout(() => {
4165
- finish(createOAuthCallbackProtocolMismatchError(port));
4166
- }, OAUTH_CALLBACK_PROTOCOL_MISMATCH_GRACE_MS);
4167
- }
4168
- socket.destroy();
4169
- return;
3437
+ },
3438
+ async clear() {
3439
+ try {
3440
+ await (await entry()).deletePassword();
3441
+ return true;
3442
+ } catch {
3443
+ return false;
4170
3444
  }
4171
- socket.destroy();
4172
- });
4173
- server.listen(port, "127.0.0.1", () => {
4174
- ctx.logger.info("Local callback server: " + redirectUri);
4175
- openUrlInBrowser(loginUrl, ctx);
4176
- });
4177
- timer = setTimeout(() => {
4178
- finish(new CliError("Login timed out after 5 minutes.", 3 /* AuthError */));
4179
- }, 3e5);
4180
- });
4181
- }
4182
- function sessionToCachedUser(session, profile) {
4183
- return {
4184
- employeeId: session.userId,
4185
- tenantKey: session.tenantKey,
4186
- tenantName: session.tenantName,
4187
- department: session.department,
4188
- subcompany: session.subcompany,
4189
- position: session.position,
4190
- version: session.version,
4191
- baseUrl: session.getBaseUrl(),
4192
- profile,
4193
- eteamsId: session.eteamsId,
4194
- agentType: session.agentType,
4195
- cookie: session.cookieHeader(),
4196
- userAgent: session.uaHeader()
3445
+ }
4197
3446
  };
4198
3447
  }
4199
- function formatWhoami(title, data) {
4200
- return [
4201
- title,
4202
- "employeeId: " + (data.employeeId || ""),
4203
- "tenantKey: " + (data.tenantKey || ""),
4204
- "tenantName: " + (data.tenantName || ""),
4205
- "department: " + (data.department || ""),
4206
- "subcompany: " + (data.subcompany || ""),
4207
- "position: " + (data.position || ""),
4208
- "version: " + (data.version || ""),
4209
- "baseUrl: " + (data.baseUrl || ""),
4210
- "profile: " + (data.profile || ""),
4211
- "ETEAMSID: " + (data.eteamsId || ""),
4212
- "cookie: " + (data.cookie || ""),
4213
- "User-Agent: " + (data.userAgent || "")
4214
- ].join("\n");
4215
- }
4216
- function registerBrowserLoginCommand(auth, action, name, description) {
4217
- const command = auth.command(name).description(description).option("--base-url <url>", "E10 base URL").option("--tenant-key <key>", "Tenant key fallback after login").option("--port <n>", "Local OAuth callback port", "19800").option("--agent_type <value>", "Agent type sent to E10 authorize endpoint").option("--agent-type <value>", "Alias of --agent_type").option("--agent-return-url <url>", "Desktop application URL linked by the login success page");
4218
- command.action(action(async (ctx, options) => {
4219
- const result = await runBrowserLogin(ctx, options);
4220
- ctx.output.write(result, { text: formatLoginResult(result) });
4221
- }));
4222
- }
4223
- function registerXiaoELoginCommand(auth, action) {
4224
- auth.command("xiaoe").description("Use XiaoE unified login without browser OAuth fallback").option("--base-url <url>", "E10 base URL").option("--tenant-key <key>", "Tenant key fallback after login").option("--port <n>", "Deprecated compatibility option; ignored by XiaoE unified login", "19800").option("--agent_type <value>", "Deprecated compatibility option; ignored by XiaoE unified login").option("--agent-type <value>", "Alias of --agent_type").option("--agent-return-url <url>", "Deprecated compatibility option; ignored by XiaoE unified login").action(action(async (ctx, options) => {
4225
- const result = await runXiaoELogin(ctx, options);
4226
- ctx.output.write(result, { text: formatLoginResult(result) });
4227
- }));
4228
- }
4229
- function registerE10AuthCommands(parent, action) {
4230
- const auth = parent.command("auth").description("E10 auth and profile management");
4231
- auth.command("root").description("Print the E10 auth root directory").action(action((ctx) => {
4232
- const root = getE10AuthRoot();
4233
- ctx.output.write({ root }, { text: root });
4234
- }));
4235
- auth.command("status").description("Show E10 login status").option("--no-check", "skip remote session validity check").action(action(async (ctx, options) => {
4236
- const opts = ctx.getGlobalOptions();
4237
- const commandOpts = asOptions(options);
4238
- const authFile = findAuthFile(ctx.cwd, opts);
4239
- const session = authFile ? E10AuthSession.fromFile(authFile, opts.baseUrl, opts.passportUrl) : null;
4240
- const valid = session && commandOpts.check !== false ? session.isExpired() ? false : await session.checkValid() : void 0;
4241
- const status = session ? {
4242
- loggedIn: true,
4243
- userId: session.userId,
4244
- tenantKey: session.tenantKey,
4245
- tenantName: session.tenantName,
4246
- department: session.department,
4247
- subcompany: session.subcompany,
4248
- position: session.position,
4249
- version: session.version,
4250
- agentType: session.agentType,
4251
- baseUrl: session.getBaseUrl(),
4252
- passportUrl: session.getPassportUrl(),
4253
- profile: opts.profile || getActiveProfile(),
4254
- authFile,
4255
- hasEteamsId: Boolean(session.eteamsId),
4256
- ...session.loginSource ? { loginSource: session.loginSource } : {},
4257
- ...session.credentialSourceStep ? { credentialSourceStep: session.credentialSourceStep } : {},
4258
- ...session.credentialSourceType ? { credentialSourceType: session.credentialSourceType } : {},
4259
- ...session.credentialSourceLabel ? { credentialSourceLabel: session.credentialSourceLabel } : {},
4260
- ...session.expiryTimes ? { expiryTimes: session.expiryTimes } : {},
4261
- valid
4262
- } : {
4263
- loggedIn: false,
4264
- profile: opts.profile || getActiveProfile(),
4265
- authFile
4266
- };
4267
- ctx.output.write(status, { text: formatAuthStatus(status) });
4268
- }));
4269
- auth.command("set").description("Save E10 auth from an ETEAMSID cookie").requiredOption("--eteamsid <id>", "ETEAMSID cookie value").option("--base-url <url>", "E10 base URL").option("--passport-url <url>", "E10 passport URL; defaults to base URL").option("--tenant-key <key>", "Tenant key fallback").option("--agent_type <value>", "Agent type used in cookie and User-Agent").option("--agent-type <value>", "Alias of --agent_type").action(action(async (ctx, options) => {
4270
- const globalOptions = ctx.getGlobalOptions();
4271
- const commandOpts = asOptions(options);
4272
- const profileFromGlobal = globalOptions.profile;
4273
- const cfg = readProfileConfig(profileFromGlobal || getActiveProfile());
4274
- const baseUrl = normalizeUrl(optionString(commandOpts, "baseUrl") || globalOptions.baseUrl || cfg.baseUrl || "");
4275
- const passportUrl = normalizeUrl(optionString(commandOpts, "passportUrl") || globalOptions.passportUrl || cfg.passportUrl || baseUrl);
4276
- const tenantKeyFallback = optionString(commandOpts, "tenantKey");
4277
- const agentType = resolveAgentType(commandOpts, ctx.env);
4278
- const eteamsId = optionString(commandOpts, "eteamsid");
4279
- if (!baseUrl) throw new CliError("Missing --base-url", 2 /* UsageError */);
4280
- if (!eteamsId) throw new CliError("Missing --eteamsid", 2 /* UsageError */);
4281
- ctx.logger.info("Resolving E10 user information...");
4282
- const result = await saveEteamsIdLogin({
4283
- baseUrl,
4284
- passportUrl,
4285
- eteamsId,
4286
- tenantKeyFallback,
4287
- agentType,
4288
- profileHint: profileFromGlobal
4289
- });
4290
- ctx.output.write(result, { text: formatLoginResult(result) });
4291
- }));
4292
- registerBrowserLoginCommand(auth, action, "login", "Open browser OAuth2.0 login and save E10 auth");
4293
- registerBrowserLoginCommand(auth, action, "oidc", "Alias of auth login for OAuth2.0 browser login");
4294
- registerXiaoELoginCommand(auth, action);
4295
- auth.command("logout").alias("clear").description("Clear saved E10 auth for the current or selected profile").action(action(async (ctx) => {
4296
- const opts = ctx.getGlobalOptions();
4297
- const profile2 = opts.profile || getActiveProfile();
4298
- const authFile = getProfileAuthPath(profile2);
4299
- const session = E10AuthSession.fromFile(authFile, opts.baseUrl, opts.passportUrl);
4300
- if (session) {
4301
- await clearInvoiceTokenCache(profile2, {
4302
- baseUrl: session.getBaseUrl(),
4303
- userId: session.userId
4304
- });
4305
- }
4306
- const result = clearProfileAuthFile(profile2);
4307
- const text = result.cleared ? "Cleared E10 auth.\nprofile: " + result.profile + "\nauthFile: " + result.authFile : "No E10 auth to clear.\nprofile: " + result.profile + "\nauthFile: " + result.authFile;
4308
- ctx.output.write(result, { text });
4309
- }));
4310
- auth.command("whoami").description("Show cached or live E10 user information").option("--json", "print output as JSON").option("--live", "call teamsCheck for live user information").action(action(async (ctx, options) => {
4311
- const opts = ctx.getGlobalOptions();
4312
- const commandOpts = asOptions(options);
4313
- const json = commandOpts.json === true;
4314
- const live = commandOpts.live === true;
4315
- const authFile = findAuthFile(ctx.cwd, opts);
4316
- const session = authFile ? E10AuthSession.fromFile(authFile, opts.baseUrl, opts.passportUrl) : null;
4317
- if (!session || !session.eteamsId) throw new CliError("E10 auth not found.", 3 /* AuthError */);
4318
- const profile2 = opts.profile || getActiveProfile();
4319
- const cached = sessionToCachedUser(session, profile2);
4320
- if (!live) {
4321
- ctx.output.write(cached, {
4322
- json,
4323
- text: formatWhoami("Current E10 user (cached)", cached)
4324
- });
4325
- return;
3448
+ async function clearInvoiceTokenForSession(session) {
3449
+ return createInvoiceTokenStore(session).clear();
3450
+ }
3451
+ function inferProfile(ctx) {
3452
+ const options = ctx.getGlobalOptions();
3453
+ return options.profile || getActiveProfile();
3454
+ }
3455
+ function trustedInvoiceHeaders(invoiceToken) {
3456
+ return invoiceToken ? { token: invoiceToken } : {};
3457
+ }
3458
+ function createInvoiceHost(ctx, dependencies = {}) {
3459
+ let e10Session = null;
3460
+ let sessionContext = null;
3461
+ let invoiceToken = null;
3462
+ let tokenStore = null;
3463
+ const requireSession = dependencies.requireSession || requireE10Session;
3464
+ const tokenStoreFactory = dependencies.tokenStoreFactory || createInvoiceTokenStore;
3465
+ async function ensureSession() {
3466
+ if (!e10Session) {
3467
+ e10Session = await requireSession(ctx);
3468
+ sessionContext = {
3469
+ baseUrl: e10Session.getBaseUrl(),
3470
+ profile: inferProfile(ctx),
3471
+ userId: e10Session.userId
3472
+ };
4326
3473
  }
4327
- const base = session.getBaseUrl();
4328
- const resp = await fetch(`${base}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(base)}`, {
4329
- method: "POST",
4330
- headers: {
4331
- accept: "application/json",
4332
- "content-type": "application/json",
4333
- eteamsid: session.eteamsId,
4334
- cookie: session.cookieHeader(),
4335
- "user-agent": session.uaHeader(),
4336
- origin: base
4337
- },
4338
- redirect: "manual"
3474
+ return e10Session;
3475
+ }
3476
+ async function getSession() {
3477
+ await ensureSession();
3478
+ return sessionContext;
3479
+ }
3480
+ async function ensureInvoiceToken(timeoutMs = 3e4) {
3481
+ await ensureSession();
3482
+ const context = await getSession();
3483
+ tokenStore ||= tokenStoreFactory(context);
3484
+ if (invoiceToken) return invoiceToken;
3485
+ invoiceToken = await tokenStore.load();
3486
+ if (invoiceToken) return invoiceToken;
3487
+ const tokenResponse = await invoiceRequest({
3488
+ method: "GET",
3489
+ path: "/api/inc/proxy/getToken",
3490
+ query: { appType: 1 },
3491
+ needsInvoiceToken: false,
3492
+ timeoutMs
4339
3493
  });
4340
- const raw = await resp.json().catch(() => ({}));
4341
- if (json || ctx.getGlobalOptions().json) {
4342
- ctx.output.write(raw, { json: true });
4343
- return;
4344
- }
4345
- const userInfo = readTeamsCheckUserInfo(resp, raw);
4346
- const liveData = {
4347
- ...cached,
4348
- employeeId: userInfo.userId || cached.employeeId,
4349
- tenantKey: userInfo.tenantKey || cached.tenantKey,
4350
- tenantName: userInfo.tenantName || cached.tenantName,
4351
- department: userInfo.department || cached.department,
4352
- subcompany: userInfo.subcompany || cached.subcompany,
4353
- position: userInfo.position || cached.position
4354
- };
4355
- ctx.output.write(liveData, { text: formatWhoami("Current E10 user (live)", liveData) });
4356
- }));
4357
- auth.command("export-weaver-env").description("Print WEAVER_* shell exports for the active E10 auth").option("--shell <shell>", "Shell syntax: auto, posix, or powershell", "auto").action(action(async (ctx, options) => {
4358
- const commandOpts = asOptions(options);
4359
- const session = await E10AuthSession.fromOptions(ctx.getGlobalOptions(), ctx.cwd);
4360
- if (!session) throw new CliError("E10 auth not found.", 3 /* AuthError */);
4361
- const value = {
4362
- WEAVER_BASE_URL: session.getBaseUrl(),
4363
- WEAVER_ETEAMSID: session.eteamsId,
4364
- WEAVER_COOKIE: session.cookieHeader(),
4365
- WEAVER_USER_AGENT: session.uaHeader(),
4366
- WEAVER_AGENT_TYPE: session.agentType
4367
- };
4368
- if (ctx.getGlobalOptions().json) {
4369
- ctx.output.write(value);
4370
- return;
3494
+ const token = tokenResponse?.data?.token;
3495
+ if (typeof token !== "string" || !token.trim()) {
3496
+ throw invoiceAuthError("invoice_token_missing", "\u672A\u53D6\u5F97\u4E1A\u7968\u901A\u4E1A\u52A1 Token");
4371
3497
  }
4372
- const shell = optionString(commandOpts, "shell") || "auto";
4373
- ctx.output.raw(formatWeaverEnvExports(value, shell));
4374
- }));
4375
- const profile = auth.command("profile").description("Manage E10 profiles");
4376
- profile.command("list").description("List E10 profiles").action(action((ctx) => {
4377
- const active = getActiveProfile();
4378
- const profiles = listProfiles().map((name) => ({
4379
- name,
4380
- active: name === active,
4381
- dir: getProfileDir(name)
4382
- }));
4383
- ctx.output.write({ active, profiles });
4384
- }));
4385
- profile.command("use").description("Switch active E10 profile; creates it if missing").argument("<name>", "profile name").action(action((ctx, name) => {
4386
- if (typeof name !== "string") throw new CliError("profile name must be a string", 2 /* UsageError */);
4387
- switchActiveProfile(name);
4388
- const result = {
4389
- active: name,
4390
- dir: getProfileDir(name),
4391
- authFile: getProfileAuthPath(name)
4392
- };
4393
- ctx.output.write(result, { text: "Active E10 profile: " + name + "\ndir: " + result.dir });
4394
- }));
4395
- profile.command("current").description("Print active E10 profile").action(action((ctx) => {
4396
- const active = getActiveProfile();
4397
- ctx.output.write({ active, dir: getProfileDir(active) }, { text: active });
4398
- }));
4399
- return auth;
4400
- }
4401
-
4402
- // src/cmd/e10/index.ts
4403
- var e10Command = {
4404
- name: "e10",
4405
- description: "E10 platform adapter: auth, profiles, and shared API client",
4406
- category: "platform",
4407
- register({ program: program2, ctx, action }) {
4408
- registerE10AuthCommands(program2, action);
4409
- const e10 = program2.command("e10").description("E10 platform commands");
4410
- registerE10AuthCommands(e10, action);
4411
- ctx.hooks.register({
4412
- beforeRun(runCtx) {
4413
- const authFile = findAuthFile(runCtx.cwd);
4414
- const session = authFile ? E10AuthSession.fromFile(authFile) : null;
4415
- if (!session) return;
4416
- runCtx.env.WEAVER_BASE_URL ||= session.getBaseUrl();
4417
- runCtx.env.WEAVER_ETEAMSID ||= session.eteamsId;
4418
- runCtx.env.WEAVER_COOKIE ||= session.cookieHeader();
4419
- runCtx.env.WEAVER_USER_AGENT ||= session.uaHeader();
4420
- runCtx.env.WEAVER_AGENT_TYPE ||= session.agentType;
4421
- }
4422
- });
4423
- }
4424
- };
4425
-
4426
- // src/cmd/refs/index.ts
4427
- function parseDuration(value) {
4428
- const raw = value.trim().toLowerCase();
4429
- const matched = /^(\d+)\s*([dhms])?$/.exec(raw);
4430
- if (!matched) {
4431
- throw new CliError(`\u65E0\u6CD5\u89E3\u6790\u65F6\u957F\uFF1A${value}\uFF08\u793A\u4F8B\uFF1A7d\u300124h\u300130m\uFF09`, 2 /* UsageError */);
4432
- }
4433
- const amount = Number(matched[1]);
4434
- const unit = matched[2] ?? "ms";
4435
- const factor = unit === "d" ? 864e5 : unit === "h" ? 36e5 : unit === "m" ? 6e4 : 1;
4436
- return amount * factor;
4437
- }
4438
- function asOptions2(value) {
4439
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
4440
- }
4441
- var refsCommand = {
4442
- name: "refs",
4443
- description: "Inspect and prune persisted large results",
4444
- category: "system",
4445
- register({ program: program2, action }) {
4446
- const refs = program2.command("refs").description("Manage persisted large results");
4447
- refs.command("path").description("Print the directory holding persisted results").action(action((ctx) => {
4448
- const path = refsDir(ctx);
4449
- ctx.output.write({ path }, { text: path });
4450
- }));
4451
- refs.command("list").description("List persisted results, newest first").action(action((ctx) => {
4452
- const now = Date.now();
4453
- const items = listRefs(ctx).filter((row) => Date.parse(row.expiresAt) > now).map((row) => ({
4454
- refId: row.refId,
4455
- operation: row.operation ?? null,
4456
- bytes: row.bytes,
4457
- createdAt: row.createdAt,
4458
- expiresAt: row.expiresAt
4459
- }));
4460
- ctx.output.write({ count: items.length, items });
4461
- }));
4462
- refs.command("show").description("Print one persisted result in full").argument("<refId>", "reference id").action(action((ctx, refId) => {
4463
- const id = String(refId ?? "").trim();
4464
- if (!id) throw new CliError("refId \u4E0D\u80FD\u4E3A\u7A7A", 2 /* UsageError */);
4465
- const record = readRef(ctx, id);
4466
- const configuredLimit = resultThresholdBytes(ctx);
4467
- const displayLimit = configuredLimit > 0 ? configuredLimit : DEFAULT_RESULT_THRESHOLD_BYTES;
4468
- if (bytesOf(record.envelope) > displayLimit) {
4469
- throw new CliError(
4470
- `\u7ED3\u679C\u592A\u5927\uFF0C\u4E0D\u80FD\u5B89\u5168\u5730\u4E00\u6B21\u663E\u793A\u3002\u8BF7\u7528 refs get ${id} <json-path> \u8BFB\u53D6\u9700\u8981\u7684\u5B57\u6BB5\u3002`,
4471
- 2 /* UsageError */
4472
- );
4473
- }
4474
- ctx.output.write(record.envelope, { json: true, persist: false });
4475
- }));
4476
- refs.command("get").description("Print one value from a persisted result by JSON path").argument("<refId>", "reference id").argument("<path>", "JSON path, e.g. data.items[0].fid").action(action((ctx, refId, path) => {
4477
- const id = String(refId ?? "").trim();
4478
- const jsonPath = String(path ?? "").trim();
4479
- if (!id || !jsonPath) throw new CliError("refId \u548C JSON \u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A", 2 /* UsageError */);
4480
- const record = readRef(ctx, id);
4481
- ctx.output.write(pickValue(record.envelope, jsonPath));
4482
- }));
4483
- refs.command("prune").description("Prune persisted results").option("--older-than <duration>", "remove results created before this age, e.g. 7d").option("--all", "remove every persisted result").action(action((ctx, options) => {
4484
- const opts = asOptions2(options);
4485
- if (opts.all === true) {
4486
- const result2 = pruneRefs(ctx, { maxCount: 0, maxBytes: 0 });
4487
- ctx.output.write({
4488
- removed: result2.removed,
4489
- kept: result2.kept,
4490
- bytes: result2.bytes,
4491
- cleanupIncomplete: result2.cleanupIncomplete
4492
- });
4493
- return;
4494
- }
4495
- const olderThanMs = opts.olderThan ? parseDuration(String(opts.olderThan)) : void 0;
4496
- const result = pruneRefs(ctx, {
4497
- maxCount: refMaxCount(ctx),
4498
- maxBytes: refMaxBytes(ctx),
4499
- ...olderThanMs === void 0 ? {} : { olderThanMs }
4500
- });
4501
- ctx.output.write({
4502
- removed: result.removed,
4503
- kept: result.kept,
4504
- bytes: result.bytes,
4505
- cleanupIncomplete: result.cleanupIncomplete
4506
- });
4507
- }));
4508
- }
4509
- };
4510
-
4511
- // src/cmd/run/index.ts
4512
- import { resolve as resolve2 } from "node:path";
4513
-
4514
- // src/services/command-runner.ts
4515
- import { spawn } from "node:child_process";
4516
- var CommandRunner = class {
4517
- constructor(ctx) {
4518
- this.ctx = ctx;
4519
- }
4520
- ctx;
4521
- async run(command, args = [], options = {}) {
4522
- const runContext = {
4523
- cwd: options.cwd || this.ctx.cwd,
4524
- command,
4525
- args,
4526
- env: options.env || this.ctx.env,
4527
- shell: options.shell
4528
- };
4529
- await this.ctx.hooks.beforeRun(runContext);
4530
- const result = await new Promise((resolve8) => {
4531
- const child = spawn(command, args, {
4532
- cwd: runContext.cwd,
4533
- env: runContext.env,
4534
- shell: runContext.shell,
4535
- stdio: options.stdio === "inherit" ? "inherit" : "pipe"
4536
- });
4537
- const stdout = [];
4538
- const stderr = [];
4539
- if (child.stdout) child.stdout.on("data", (chunk) => stdout.push(chunk));
4540
- if (child.stderr) child.stderr.on("data", (chunk) => stderr.push(chunk));
4541
- child.on("close", (code, signal) => {
4542
- resolve8({
4543
- command,
4544
- args,
4545
- cwd: runContext.cwd,
4546
- code,
4547
- signal,
4548
- stdout: Buffer.concat(stdout).toString("utf-8"),
4549
- stderr: Buffer.concat(stderr).toString("utf-8")
4550
- });
4551
- });
4552
- });
4553
- await this.ctx.hooks.afterRun(runContext, result);
4554
- return result;
4555
- }
4556
- };
4557
-
4558
- // src/cmd/run/index.ts
4559
- var runCommand = {
4560
- name: "run",
4561
- description: "Generic external command runner with hooks",
4562
- category: "system",
4563
- register({ program: program2, action }) {
4564
- program2.command("run").description("Run an external command through the shared command runner").argument("<command>", "command to run").argument("[args...]", "command arguments").option("--cwd <dir>", "working directory").option("--shell", "run through the platform shell").option("--inherit", "inherit stdio instead of capturing output").allowUnknownOption(true).action(action(async (ctx, command, args, options) => {
4565
- if (typeof command !== "string") {
4566
- throw new CliError("command must be a string", 2 /* UsageError */);
4567
- }
4568
- const opts = options && typeof options === "object" ? options : {};
4569
- const result = await new CommandRunner(ctx).run(command, Array.isArray(args) ? args.map(String) : [], {
4570
- cwd: opts.cwd ? resolve2(opts.cwd) : void 0,
4571
- shell: opts.shell,
4572
- stdio: opts.inherit ? "inherit" : "pipe"
4573
- });
4574
- if (!opts.inherit && result.stdout) process.stdout.write(result.stdout);
4575
- if (!opts.inherit && result.stderr) process.stderr.write(result.stderr);
4576
- if (result.code && result.code !== 0) {
4577
- throw new CliError("command exited with code " + result.code, result.code);
4578
- }
4579
- }));
4580
- }
4581
- };
4582
-
4583
- // src/cmd/setup/index.ts
4584
- import { existsSync as existsSync4 } from "node:fs";
4585
-
4586
- // src/internal/skills/install.ts
4587
- import { cpSync as cpSync2, existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync, writeFileSync } from "node:fs";
4588
- import { homedir } from "node:os";
4589
- import { basename, posix, relative, resolve as resolve3, sep, win32 } from "node:path";
4590
- var SKILL_PREFIX = "weaver-e10-";
4591
- var LEGACY_SKILL_PREFIX = "weaver-work-cli-";
4592
- var SHARED_SKILL_NAME = "weaver-e10-shared";
4593
- function envValue(env, name) {
4594
- const direct = env[name];
4595
- if (typeof direct === "string" && direct.trim()) return direct.trim();
4596
- const expected = name.toUpperCase();
4597
- for (const [key, value] of Object.entries(env)) {
4598
- if (key.toUpperCase() === expected && typeof value === "string" && value.trim()) return value.trim();
4599
- }
4600
- return "";
4601
- }
4602
- function hasEnvFamily(env, prefix, ignoredNames = []) {
4603
- const expected = `${prefix.toUpperCase()}_`;
4604
- const ignored = new Set(ignoredNames.map((name) => name.toUpperCase()));
4605
- return Object.entries(env).some(([key, value]) => key.toUpperCase().startsWith(expected) && !ignored.has(key.toUpperCase()) && typeof value === "string" && Boolean(value.trim()));
4606
- }
4607
- function normalizedAgentType(value) {
4608
- const normalized = value.trim().toLowerCase();
4609
- if (normalized === "codex-cli") return "codex";
4610
- if (normalized === "work-buddy") return "workbuddy";
4611
- return normalized || "unknown";
4612
- }
4613
- function isKnownSkillsHost(host) {
4614
- return host === "codex" || host === "workbuddy";
4615
- }
4616
- function resolveSkillsTargetPath(value, options = {}) {
4617
- const trimmed = value.trim();
4618
- if (!trimmed) throw new Error("skills target path must not be empty");
4619
- const platform = options.platform ?? process.platform;
4620
- const pathApi = platform === "win32" ? win32 : posix;
4621
- const userHome = options.homeDir ?? homedir();
4622
- if (trimmed === "~") return pathApi.resolve(userHome);
4623
- if (/^~[\\/]/u.test(trimmed)) {
4624
- const segments = trimmed.slice(2).split(/[\\/]+/u).filter(Boolean);
4625
- return pathApi.resolve(userHome, ...segments);
4626
- }
4627
- return pathApi.resolve(trimmed);
4628
- }
4629
- function hostSkillsRoot(host, env, options) {
4630
- const platform = options.platform ?? process.platform;
4631
- const pathApi = platform === "win32" ? win32 : posix;
4632
- const userHome = options.homeDir ?? homedir();
4633
- const envName = host === "codex" ? "CODEX_HOME" : "WORKBUDDY_HOME";
4634
- const configuredHome = envValue(env, envName);
4635
- const hostHome = configuredHome ? resolveSkillsTargetPath(configuredHome, options) : pathApi.resolve(userHome, host === "codex" ? ".codex" : ".workbuddy");
4636
- return pathApi.resolve(hostHome, "skills");
4637
- }
4638
- function detectSkillsHost(env = process.env) {
4639
- const explicitAgent = envValue(env, "WEAVER_AGENT_TYPE");
4640
- if (explicitAgent) return normalizedAgentType(explicitAgent);
4641
- const hasCodexRuntime = hasEnvFamily(env, "CODEX", ["CODEX_HOME"]);
4642
- const hasWorkBuddyRuntime = hasEnvFamily(env, "WORKBUDDY", ["WORKBUDDY_HOME"]);
4643
- if (hasCodexRuntime !== hasWorkBuddyRuntime) return hasCodexRuntime ? "codex" : "workbuddy";
4644
- const hasCodexHome = Boolean(envValue(env, "CODEX_HOME"));
4645
- const hasWorkBuddyHome = Boolean(envValue(env, "WORKBUDDY_HOME"));
4646
- if (hasCodexHome !== hasWorkBuddyHome) return hasCodexHome ? "codex" : "workbuddy";
4647
- return "unknown";
4648
- }
4649
- function resolveSkillsRoot(env = process.env, options = {}) {
4650
- const configuredRoot = envValue(env, "WEAVER_SKILLS_ROOT");
4651
- if (configuredRoot) {
4652
- const explicitAgent = envValue(env, "WEAVER_AGENT_TYPE");
4653
- const detectedHost = explicitAgent ? normalizedAgentType(explicitAgent) : detectSkillsHost(env);
4654
- return {
4655
- root: resolveSkillsTargetPath(configuredRoot, options),
4656
- host: detectedHost === "unknown" ? "explicit" : detectedHost,
4657
- source: "explicit-env",
4658
- environmentVariable: "WEAVER_SKILLS_ROOT"
4659
- };
4660
- }
4661
- const host = detectSkillsHost(env);
4662
- if (isKnownSkillsHost(host)) {
4663
- const environmentVariable = envValue(env, host === "codex" ? "CODEX_HOME" : "WORKBUDDY_HOME") ? host === "codex" ? "CODEX_HOME" : "WORKBUDDY_HOME" : void 0;
4664
- return {
4665
- root: hostSkillsRoot(host, env, options),
4666
- host,
4667
- source: environmentVariable ? "explicit-env" : "host-detected",
4668
- ...environmentVariable ? { environmentVariable } : {}
4669
- };
3498
+ await tokenStore.save(token);
3499
+ invoiceToken = token;
3500
+ return token;
4670
3501
  }
4671
- const codexRoot = hostSkillsRoot("codex", env, options);
4672
- const workBuddyRoot = hostSkillsRoot("workbuddy", env, options);
4673
- const pathExists = options.pathExists ?? existsSync3;
4674
- if (host === "unknown") {
4675
- const existing = [
4676
- { root: codexRoot, host: "codex" },
4677
- { root: workBuddyRoot, host: "workbuddy" }
4678
- ].filter((candidate) => pathExists(candidate.root));
4679
- if (existing.length === 1) {
4680
- return { ...existing[0], source: "filesystem-detected" };
3502
+ async function ensureContext(needsInvoiceToken, timeoutMs, path) {
3503
+ await ensureSession();
3504
+ const tokenEndpoint = path === "/api/inc/proxy/getToken" || path === "/api/app/inc/proxy/getToken";
3505
+ if (tokenEndpoint) return void 0;
3506
+ if (!needsInvoiceToken) {
4681
3507
  }
4682
- return {
4683
- root: codexRoot,
4684
- host,
4685
- source: "fallback",
4686
- requiresExplicitTarget: true,
4687
- reason: existing.length > 1 ? "ambiguous-host" : "unknown-host",
4688
- candidates: [codexRoot, workBuddyRoot]
4689
- };
4690
- }
4691
- return {
4692
- root: codexRoot,
4693
- host,
4694
- source: "fallback",
4695
- requiresExplicitTarget: true,
4696
- reason: "unsupported-host",
4697
- candidates: [codexRoot, workBuddyRoot]
4698
- };
4699
- }
4700
- function unresolvedSkillsRootMessage(resolution, targetOption = "--target-dir") {
4701
- const reason = resolution.reason === "ambiguous-host" ? "\u68C0\u6D4B\u5230\u591A\u4E2A\u53EF\u80FD\u7684\u5BBF\u4E3B\u76EE\u5F55" : resolution.reason === "unsupported-host" ? `\u68C0\u6D4B\u5230\u5F53\u524D\u667A\u80FD\u4F53 ${resolution.host}\uFF0C\u4F46\u4E0D\u77E5\u9053\u5B83\u7684 skills \u76EE\u5F55` : "\u672A\u68C0\u6D4B\u5230\u5F53\u524D\u667A\u80FD\u4F53\u53CA\u5176 skills \u76EE\u5F55";
4702
- return [
4703
- `${reason}\uFF0C\u4E3A\u907F\u514D\u88C5\u9519\u4F4D\u7F6E\uFF0C\u672C\u6B21\u672A\u6267\u884C\u5B89\u88C5\u3002`,
4704
- `\u8BF7\u4F7F\u7528 ${targetOption} <\u5F53\u524D\u667A\u80FD\u4F53\u7684 skills \u6839\u76EE\u5F55>\uFF0C\u6216\u8BBE\u7F6E WEAVER_SKILLS_ROOT \u540E\u91CD\u8BD5\u3002`,
4705
- ...resolution.candidates?.length ? [`\u5DF2\u77E5\u5019\u9009\u76EE\u5F55\uFF1A${resolution.candidates.join("\uFF0C")}`] : []
4706
- ].join("\n");
4707
- }
4708
- function normalizePackagedSkillName(value) {
4709
- const trimmed = value.trim();
4710
- if (!trimmed || trimmed === "all") return trimmed;
4711
- if (trimmed.includes("/") || trimmed.includes("\\") || trimmed === "." || trimmed === "..") {
4712
- throw new Error(`invalid skill name: ${value}`);
4713
- }
4714
- if (!/^[A-Za-z0-9._-]+$/u.test(trimmed)) {
4715
- throw new Error(`invalid skill name: ${value}`);
3508
+ return ensureInvoiceToken(timeoutMs);
4716
3509
  }
4717
- if (trimmed.startsWith(LEGACY_SKILL_PREFIX)) {
4718
- return `${SKILL_PREFIX}${trimmed.slice(LEGACY_SKILL_PREFIX.length)}`;
3510
+ async function clearCachedInvoiceToken() {
3511
+ invoiceToken = null;
3512
+ await tokenStore?.clear().catch(() => false);
4719
3513
  }
4720
- return trimmed.startsWith(SKILL_PREFIX) ? trimmed : `${SKILL_PREFIX}${trimmed}`;
4721
- }
4722
- function resolvePackagedSkillNames(sourceRoot, requested = "all") {
4723
- const available = readdirSync2(sourceRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && existsSync3(resolve3(sourceRoot, entry.name, "SKILL.md"))).map((entry) => entry.name).sort();
4724
- const normalized = normalizePackagedSkillName(requested);
4725
- if (!normalized || normalized === "all") return available;
4726
- if (!available.includes(normalized)) {
4727
- const shortName = normalized.slice(SKILL_PREFIX.length);
4728
- const suggestions = available.filter((name) => editDistance(shortName, name.replace(/^weaver-e10-/u, "")) <= 2);
4729
- throw new Error([
4730
- `unknown packaged skill: ${requested}`,
4731
- ...suggestions.length ? [`Did you mean: ${suggestions.join(", ")}?`] : [],
4732
- 'Run "weaver-work-cli skills list" to see available skills.'
4733
- ].join("\n"));
3514
+ async function runtime() {
3515
+ return createE10RequestRuntime(ctx, await ensureSession(), {
3516
+ interceptors: dependencies.interceptors,
3517
+ fetch: dependencies.fetch
3518
+ });
4734
3519
  }
4735
- const names = [];
4736
- if (normalized !== SHARED_SKILL_NAME && available.includes(SHARED_SKILL_NAME)) {
4737
- names.push(SHARED_SKILL_NAME);
3520
+ function businessError(value) {
3521
+ const code = responseCode(value);
3522
+ return new InvoiceCliError("api", "business_error", responseMessage(value), {
3523
+ code: String(code),
3524
+ details: { ret: code },
3525
+ exitCode: 1
3526
+ });
4738
3527
  }
4739
- names.push(normalized);
4740
- return names;
4741
- }
4742
- function editDistance(left, right) {
4743
- let row = Array.from({ length: right.length + 1 }, (_, index) => index);
4744
- for (let i = 0; i < left.length; i += 1) {
4745
- const next = [i + 1];
4746
- for (let j = 0; j < right.length; j += 1) {
4747
- next.push(Math.min(next[j] + 1, row[j + 1] + 1, row[j] + (left[i] === right[j] ? 0 : 1)));
3528
+ async function handleBusinessResponse(value, retry, canRetry) {
3529
+ const code = responseCode(value);
3530
+ if (code === void 0 || code === 0 || code === 200) return value;
3531
+ if (isInvoiceSessionExpired(value)) {
3532
+ await clearCachedInvoiceToken();
3533
+ if (canRetry) return retry();
3534
+ throw invoiceAuthError(
3535
+ "invoice_session_expired",
3536
+ `\u53D1\u7968\u4E1A\u52A1\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u5DF2\u6E05\u7406\u672C\u5730\u53D1\u7968 Token\u3002${E10_REAUTH_GUIDANCE}`,
3537
+ { ret: code }
3538
+ );
4748
3539
  }
4749
- row = next;
4750
- }
4751
- return row[right.length];
4752
- }
4753
- function installPackagedSkills(sourceRoot, targetRoot, requested = "all") {
4754
- const resolvedSourceRoot = resolve3(sourceRoot);
4755
- const resolvedTargetRoot = resolve3(targetRoot);
4756
- const skillNames = resolvePackagedSkillNames(resolvedSourceRoot, requested);
4757
- const productContent = productMetadataContent(resolvedSourceRoot);
4758
- mkdirSync(resolvedTargetRoot, { recursive: true, mode: 448 });
4759
- const installed = skillNames.map((name) => {
4760
- const source = resolveInside(resolvedSourceRoot, name);
4761
- const target = resolve3(resolvedTargetRoot, basename(name));
4762
- statSync(resolve3(source, "SKILL.md"));
4763
- cpSync2(source, target, {
4764
- recursive: true,
4765
- force: true,
4766
- filter: (entry) => shouldCopy(entry, source, Boolean(productContent))
3540
+ throw businessError(value);
3541
+ }
3542
+ async function invoiceRequest(request, canRetryExpiredToken = true) {
3543
+ const {
3544
+ method = "POST",
3545
+ path,
3546
+ query,
3547
+ headers,
3548
+ body,
3549
+ operation,
3550
+ needsInvoiceToken = true,
3551
+ timeoutMs = 3e4
3552
+ } = request;
3553
+ assertPath(path);
3554
+ const token = await ensureContext(needsInvoiceToken, timeoutMs, path);
3555
+ const response = await (await runtime()).requestJson({
3556
+ module: "invoice",
3557
+ operation,
3558
+ method,
3559
+ path,
3560
+ query,
3561
+ headers,
3562
+ body,
3563
+ timeoutMs,
3564
+ trustedHeaders: trustedInvoiceHeaders(token)
4767
3565
  });
4768
- writeProductMetadata(target, productContent);
4769
- const current = {
4770
- name,
4771
- source,
4772
- target,
4773
- files: countFiles2(target)
4774
- };
4775
- return current;
4776
- });
4777
- return {
4778
- sourceRoot: resolvedSourceRoot,
4779
- targetRoot: resolvedTargetRoot,
4780
- skillNames,
4781
- installed
4782
- };
4783
- }
4784
- function productMetadataContent(sourceRoot) {
4785
- const productPath = productMetadataPath(sourceRoot);
4786
- if (!existsSync3(productPath)) return null;
4787
- const product = JSON.parse(readFileSync2(productPath, "utf8"));
4788
- const packageInfo = readPackageInfo(resolve3(sourceRoot, "..", "package.json"));
4789
- const metadata = {
4790
- schemaVersion: typeof product.schemaVersion === "number" ? product.schemaVersion : 1,
4791
- product: stringOrEmpty(product.product),
4792
- productVersion: stringOrEmpty(packageInfo?.version) || stringOrEmpty(product.productVersion),
4793
- packageName: stringOrEmpty(packageInfo?.name) || stringOrEmpty(product.packageName),
4794
- command: stringOrEmpty(product.command),
4795
- nodeEngine: stringOrEmpty(packageInfo?.engines?.node) || stringOrEmpty(product.nodeEngine)
4796
- };
4797
- if (metadata.product !== "weaver-work-cli" || metadata.packageName !== "weaver-work-cli" || metadata.command !== "weaver-work-cli" || !metadata.productVersion || !metadata.nodeEngine) {
4798
- throw new Error("skill-template/product.json or package.json is invalid for weaver-work-cli skills");
4799
- }
4800
- return `${JSON.stringify(metadata, null, 2)}
4801
- `;
4802
- }
4803
- function productMetadataPath(sourceRoot) {
4804
- const templatePath = resolve3(sourceRoot, "..", "skill-template", "product.json");
4805
- if (existsSync3(templatePath)) return templatePath;
4806
- return resolve3(sourceRoot, "product.json");
4807
- }
4808
- function readPackageInfo(packagePath2) {
4809
- if (!existsSync3(packagePath2)) return null;
4810
- return JSON.parse(readFileSync2(packagePath2, "utf8"));
4811
- }
4812
- function stringOrEmpty(value) {
4813
- return typeof value === "string" ? value : "";
4814
- }
4815
- function writeProductMetadata(target, productContent) {
4816
- if (!productContent) return;
4817
- writeFileSync(resolve3(target, "product.json"), productContent, "utf8");
4818
- }
4819
- function shouldCopy(entry, sourceRoot, skipSkillProduct) {
4820
- const relativePath = relative(sourceRoot, entry);
4821
- const name = basename(entry);
4822
- if (!relativePath) return true;
4823
- if (skipSkillProduct && relativePath === "product.json") return false;
4824
- if (name === ".DS_Store" || name.startsWith(".")) return false;
4825
- const parts = relativePath.split(sep);
4826
- return !parts.includes("node_modules") && !parts.includes("scripts") && !parts.includes("assets");
4827
- }
4828
- function countFiles2(root) {
4829
- let count = 0;
4830
- for (const entry of readdirSync2(root, { withFileTypes: true })) {
4831
- const child = resolve3(root, entry.name);
4832
- if (entry.isDirectory()) count += countFiles2(child);
4833
- if (entry.isFile()) count += 1;
4834
- }
4835
- return count;
4836
- }
4837
- function resolveInside(base, subpath = "") {
4838
- if (subpath.startsWith("/") || subpath.split(/[\\/]/u).includes("..")) {
4839
- throw new Error(`invalid skill path: ${subpath}`);
4840
- }
4841
- const target = resolve3(base, subpath || ".");
4842
- const rel = relative(base, target);
4843
- if (rel === ".." || rel.startsWith(`..${sep}`)) {
4844
- throw new Error(`invalid skill path: ${subpath}`);
4845
- }
4846
- return target;
4847
- }
4848
-
4849
- // src/cmd/setup/index.ts
4850
- var SKILLS_DIR = packagePath("skills");
4851
- function versionMajor2(version) {
4852
- return Number(version.replace(/^v/, "").split(".")[0] || 0);
4853
- }
4854
- var setupCommand = {
4855
- name: "setup",
4856
- description: "One-step setup checks for business shortcuts",
4857
- category: "system",
4858
- register({ program: program2, action }) {
4859
- const setup = program2.command("setup").description("One-step setup checks for business shortcuts");
4860
- setup.command("invoice").description("Check invoice CLI readiness and optionally install Agent skills").option("--install-skill", "install packaged invoice skill into the current Agent skills directory").option("--skill-target-dir <path>", "override target Agent skills directory").action(action((ctx, options) => {
4861
- const opts = options && typeof options === "object" ? options : {};
4862
- const authFile = findAuthFile(ctx.cwd, ctx.getGlobalOptions());
4863
- const packagedSkills = resolvePackagedSkillNames(SKILLS_DIR, "yepiaotong");
4864
- const checks = [
4865
- {
4866
- name: "node",
4867
- ok: versionMajor2(process.version) >= 18,
4868
- detail: process.version
4869
- },
4870
- {
4871
- name: "package",
4872
- ok: true,
4873
- detail: ctx.packageInfo.name + "@" + ctx.packageInfo.version
4874
- },
4875
- {
4876
- name: "invoiceSkillPackaged",
4877
- ok: packagedSkills.includes("weaver-e10-yepiaotong"),
4878
- detail: packagedSkills.join(", ")
4879
- },
4880
- {
4881
- name: "e10Auth",
4882
- ok: Boolean(authFile && existsSync4(authFile)),
4883
- detail: authFile || "not found"
4884
- }
4885
- ];
4886
- const specifiedSkillRoot = typeof opts.skillTargetDir === "string" && opts.skillTargetDir.trim() ? resolveSkillsTargetPath(opts.skillTargetDir) : "";
4887
- const skillResolution = opts.installSkill ? specifiedSkillRoot ? { root: specifiedSkillRoot, host: "explicit", source: "target-dir" } : resolveSkillsRoot(ctx.env) : null;
4888
- if (skillResolution?.requiresExplicitTarget) {
4889
- throw new CliError(
4890
- unresolvedSkillsRootMessage(skillResolution, "--skill-target-dir"),
4891
- 2 /* UsageError */
4892
- );
3566
+ if (isE10SessionExpiredResponse(response)) {
3567
+ throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
3568
+ }
3569
+ if (response.parseError) {
3570
+ if (response.status < 200 || response.status >= 300) {
3571
+ throw new InvoiceCliError("api", "http_error", `\u6CDB\u5FAE\u63A5\u53E3 HTTP ${response.status}`, {
3572
+ code: response.status,
3573
+ details: { status: response.status },
3574
+ exitCode: 1
3575
+ });
4893
3576
  }
4894
- const skillInstall = skillResolution ? {
4895
- ...installPackagedSkills(SKILLS_DIR, skillResolution.root, "yepiaotong"),
4896
- skillsHost: skillResolution.host,
4897
- skillsRootSource: skillResolution.source,
4898
- warnings: skillResolution.source === "filesystem-detected" ? ["\u76EE\u6807\u76EE\u5F55\u4EC5\u6839\u636E\u672C\u673A\u5DF2\u6709\u76EE\u5F55\u63A8\u65AD\uFF1B\u5982\u4E0E\u5F53\u524D\u667A\u80FD\u4F53\u4E0D\u7B26\uFF0C\u8BF7\u663E\u5F0F\u6307\u5B9A\u3002"] : []
4899
- } : null;
4900
- const nextActions = [];
4901
- if (!checks.find((check) => check.name === "e10Auth")?.ok) {
4902
- nextActions.push("Authenticate using the method required by the current runtime, then rerun setup.");
4903
- }
4904
- if (!skillInstall) {
4905
- nextActions.push("Optional Agent setup: weaver-work-cli skills install yepiaotong");
4906
- }
4907
- nextActions.push("Verify invoice operations: weaver-work-cli invoice schema");
4908
- const ok = checks.every((check) => check.ok);
4909
- ctx.output.write({
4910
- ok,
4911
- module: "invoice",
4912
- checks,
4913
- skillInstall,
4914
- nextActions
4915
- }, {
4916
- text: [
4917
- ok ? "Invoice setup checks passed." : "Invoice setup needs attention.",
4918
- ...checks.map((check) => `- ${check.name}: ${check.ok ? "ok" : "missing"} (${check.detail})`),
4919
- ...skillInstall ? skillInstall.installed.map((entry) => `- installed skill: ${entry.name} -> ${entry.target}`) : [],
4920
- ...skillInstall ? skillInstall.warnings.map((warning) => `- warning: ${warning}`) : [],
4921
- "Next:",
4922
- ...nextActions.map((actionText) => `- ${actionText}`)
4923
- ].join("\n")
3577
+ throw invoiceNetworkError("protocol", `\u63A5\u53E3\u8FD4\u56DE\u4E0D\u662F\u5408\u6CD5 JSON\uFF08HTTP ${response.status}\uFF09`, { retryable: false });
3578
+ }
3579
+ if (response.status < 200 || response.status >= 300) {
3580
+ throw new InvoiceCliError("api", "http_error", `\u6CDB\u5FAE\u63A5\u53E3 HTTP ${response.status}`, {
3581
+ code: response.status,
3582
+ details: { status: response.status, message: responseMessage(response.value) },
3583
+ exitCode: 1
4924
3584
  });
4925
- }));
4926
- }
4927
- };
4928
-
4929
- // src/cmd/skills/index.ts
4930
- import { existsSync as existsSync6 } from "node:fs";
4931
- import { spawnSync } from "node:child_process";
4932
-
4933
- // src/internal/skills/detector.ts
4934
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
4935
- import { join, resolve as resolve4 } from "node:path";
4936
- var PACKAGED_DETECTOR_VERSION = "1.0.13";
4937
- var PACKAGED_DETECTOR_NAME = `weaver-skill-detector-${PACKAGED_DETECTOR_VERSION}`;
4938
- function packagedDetectorDir() {
4939
- return packagePath("tools", PACKAGED_DETECTOR_NAME);
4940
- }
4941
- function detectorScriptPath(detectorDir) {
4942
- return join(detectorDir, "scripts", "validate_skill.py");
4943
- }
4944
- function legacySiblingDetectorDir() {
4945
- return resolve4(packagedDetectorDir(), "..", "..", "..", PACKAGED_DETECTOR_NAME);
4946
- }
4947
- function detectorVersion(detectorDir) {
4948
- let version = PACKAGED_DETECTOR_VERSION;
4949
- const metaPath = join(detectorDir, "_meta.json");
4950
- if (existsSync5(metaPath)) {
4951
- try {
4952
- const meta = JSON.parse(readFileSync3(metaPath, "utf8"));
4953
- if (typeof meta.version === "string" && meta.version) version = meta.version;
4954
- } catch {
4955
- version = PACKAGED_DETECTOR_VERSION;
4956
3585
  }
4957
- }
4958
- return version;
4959
- }
4960
- function resolveDetectorInfo(detectorDir) {
4961
- const candidates = detectorDir ? [resolve4(detectorDir)] : [packagedDetectorDir(), legacySiblingDetectorDir()].map((candidate) => resolve4(candidate));
4962
- for (const candidate of candidates) {
4963
- const scriptPath = detectorScriptPath(candidate);
4964
- if (existsSync5(scriptPath)) {
4965
- return { detectorDir: candidate, scriptPath, version: detectorVersion(candidate) };
3586
+ let value = response.value;
3587
+ if (request.rewriteJsonText && response.text) {
3588
+ try {
3589
+ value = JSON.parse(request.rewriteJsonText(response.text));
3590
+ } catch {
3591
+ value = response.value;
3592
+ }
4966
3593
  }
4967
- }
4968
- throw new CliError(`weaver skill detector is not available; checked: ${candidates.map(detectorScriptPath).join(", ")}`, 2 /* UsageError */);
4969
- }
4970
-
4971
- // src/internal/skills/reader.ts
4972
- import { readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
4973
- import { relative as relative2, resolve as resolve5, sep as sep2 } from "node:path";
4974
- var SKILL_PREFIX2 = "weaver-e10-";
4975
- var LEGACY_SKILL_PREFIX2 = "weaver-work-cli-";
4976
- var SkillReader = class {
4977
- constructor(root) {
4978
- this.root = root;
4979
- }
4980
- root;
4981
- list() {
4982
- return readdirSync3(this.root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => this.skillInfo(entry.name)).filter((entry) => Boolean(entry)).sort((a, b) => a.name.localeCompare(b.name));
4983
- }
4984
- listPath(target) {
4985
- const { name, subpath } = splitTarget(target);
4986
- const skill = this.resolveSkill(name);
4987
- const skillRoot = skill.root;
4988
- const dir = this.resolveInside(skillRoot, subpath);
4989
- const info = statSync2(dir);
4990
- if (!info.isDirectory()) {
4991
- throw new Error(`path is a file, not a directory: ${target}`);
3594
+ return handleBusinessResponse(value, () => invoiceRequest(request, false), canRetryExpiredToken && Boolean(token));
3595
+ }
3596
+ async function invoiceMultipartRequest(request, canRetryExpiredToken = true) {
3597
+ const {
3598
+ method = "POST",
3599
+ path,
3600
+ query,
3601
+ fields = {},
3602
+ file,
3603
+ headers,
3604
+ operation,
3605
+ needsInvoiceToken = true,
3606
+ timeoutMs = 3e4
3607
+ } = request;
3608
+ if (!file && !Object.values(fields).some((value) => value !== void 0 && value !== null && value !== "")) {
3609
+ throw invoiceValidationError("input_invalid", "multipart \u8BF7\u6C42\u9700\u8981\u6587\u4EF6\u3001URL \u6216\u8868\u5355\u5B57\u6BB5");
4992
3610
  }
4993
- const listed = cleanOutputPath(skill.name, subpath);
4994
- const entries = readdirSync3(dir, { withFileTypes: true }).map((entry) => ({
4995
- path: cleanOutputPath(listed, entry.name),
4996
- isDir: entry.isDirectory()
4997
- })).sort((a, b) => a.path.localeCompare(b.path));
4998
- return { path: listed, entries };
4999
- }
5000
- read(target, pathArg = "") {
5001
- const split = splitTarget(target);
5002
- const skill = this.resolveSkill(split.name);
5003
- const subpath = pathArg || split.subpath || "SKILL.md";
5004
- const file = this.resolveInside(skill.root, subpath);
5005
- const info = statSync2(file);
5006
- if (info.isDirectory()) {
5007
- throw new Error(`path is a directory, not a file: ${cleanOutputPath(skill.name, subpath)}`);
3611
+ assertPath(path);
3612
+ const token = await ensureContext(needsInvoiceToken, timeoutMs, path);
3613
+ const form = new FormData();
3614
+ for (const [key, value] of Object.entries(fields)) {
3615
+ if (value === void 0 || value === null) continue;
3616
+ form.append(key, typeof value === "string" ? value : JSON.stringify(value));
5008
3617
  }
5009
- return {
5010
- skill: skill.name,
5011
- path: cleanOutputPath(subpath),
5012
- content: readFileSync4(file, "utf-8")
5013
- };
5014
- }
5015
- skillInfo(name) {
5016
- try {
5017
- const skillRoot = this.ensureSkill(name);
5018
- const content = readFileSync4(resolve5(skillRoot, "SKILL.md"), "utf-8");
5019
- const frontmatter = parseFrontmatter(content);
5020
- return {
5021
- name,
5022
- title: frontmatter.name,
5023
- description: frontmatter.description,
5024
- version: frontmatter.version
5025
- };
5026
- } catch {
5027
- return null;
3618
+ if (file) {
3619
+ const content = await readFile(file.path);
3620
+ form.append("file", new Blob([content], { type: file.mimeType || "application/octet-stream" }), file.name);
5028
3621
  }
5029
- }
5030
- ensureSkill(name) {
5031
- return this.resolveSkill(name).root;
5032
- }
5033
- resolveSkill(name) {
5034
- if (!name || name.includes("/") || name.includes("\\") || name === "." || name === "..") {
5035
- throw new Error(`unknown skill: ${name}`);
3622
+ const response = await (await runtime()).requestJson({
3623
+ module: "invoice",
3624
+ operation,
3625
+ method,
3626
+ path,
3627
+ query,
3628
+ headers,
3629
+ formData: form,
3630
+ timeoutMs,
3631
+ trustedHeaders: trustedInvoiceHeaders(token)
3632
+ });
3633
+ if (isE10SessionExpiredResponse(response)) {
3634
+ throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
5036
3635
  }
5037
- const skillRoot = this.resolveInside(this.root, name);
5038
- if (!existsDirectoryWithSkill(skillRoot)) {
5039
- const normalized = normalizeLegacySkillName(name);
5040
- if (normalized !== name) {
5041
- const normalizedRoot = this.resolveInside(this.root, normalized);
5042
- if (existsDirectoryWithSkill(normalizedRoot)) return { name: normalized, root: normalizedRoot };
5043
- }
3636
+ if (response.parseError) {
3637
+ throw invoiceNetworkError("protocol", `\u63A5\u53E3\u8FD4\u56DE\u4E0D\u662F\u5408\u6CD5 JSON\uFF08HTTP ${response.status}\uFF09`, { retryable: false });
5044
3638
  }
5045
- const info = statSync2(skillRoot);
5046
- if (!info.isDirectory()) throw new Error(`unknown skill: ${name}`);
5047
- statSync2(resolve5(skillRoot, "SKILL.md"));
5048
- return { name, root: skillRoot };
5049
- }
5050
- resolveInside(base, subpath = "") {
5051
- const cleaned = subpath.replace(/\\/g, "/");
5052
- if (cleaned.startsWith("/") || cleaned.split("/").includes("..")) {
5053
- throw new Error(`invalid skill path: ${subpath}`);
3639
+ if (response.status < 200 || response.status >= 300) {
3640
+ throw new InvoiceCliError("api", "http_error", `\u6CDB\u5FAE\u63A5\u53E3 HTTP ${response.status}`, {
3641
+ code: response.status,
3642
+ details: { status: response.status, message: responseMessage(response.value) },
3643
+ exitCode: 1
3644
+ });
5054
3645
  }
5055
- const target = resolve5(base, cleaned || ".");
5056
- const rel = relative2(base, target);
5057
- if (rel === ".." || rel.startsWith(`..${sep2}`) || resolve5(base) === target && cleaned === "..") {
5058
- throw new Error(`invalid skill path: ${subpath}`);
3646
+ return handleBusinessResponse(response.value, () => invoiceMultipartRequest(request, false), canRetryExpiredToken && Boolean(token));
3647
+ }
3648
+ async function invoiceFormRequest(request, canRetryExpiredToken = true) {
3649
+ const {
3650
+ method = "POST",
3651
+ path,
3652
+ query,
3653
+ fields = {},
3654
+ operation,
3655
+ needsInvoiceToken = true,
3656
+ timeoutMs = 3e4
3657
+ } = request;
3658
+ assertPath(path);
3659
+ const token = await ensureContext(needsInvoiceToken, timeoutMs, path);
3660
+ const form = new URLSearchParams();
3661
+ for (const [key, value] of Object.entries(fields)) {
3662
+ if (value === void 0 || value === null) continue;
3663
+ form.set(key, typeof value === "string" ? value : JSON.stringify(value));
5059
3664
  }
5060
- return target;
5061
- }
5062
- };
5063
- function normalizeLegacySkillName(name) {
5064
- return name.startsWith(LEGACY_SKILL_PREFIX2) ? `${SKILL_PREFIX2}${name.slice(LEGACY_SKILL_PREFIX2.length)}` : name;
5065
- }
5066
- function existsDirectoryWithSkill(skillRoot) {
5067
- try {
5068
- const info = statSync2(skillRoot);
5069
- if (!info.isDirectory()) return false;
5070
- statSync2(resolve5(skillRoot, "SKILL.md"));
5071
- return true;
5072
- } catch {
5073
- return false;
5074
- }
5075
- }
5076
- function splitTarget(target) {
5077
- const index = target.indexOf("/");
5078
- if (index === -1) return { name: target, subpath: "" };
5079
- return {
5080
- name: target.slice(0, index),
5081
- subpath: target.slice(index + 1)
5082
- };
5083
- }
5084
- function cleanOutputPath(...parts) {
5085
- return parts.filter(Boolean).join("/").replace(/\/+/g, "/").replace(/^\.\//, "");
5086
- }
5087
- function parseFrontmatter(content) {
5088
- const lines = content.split(/\r?\n/u);
5089
- if (lines[0] !== "---") return {};
5090
- const result = {};
5091
- for (let index = 1; index < lines.length; index += 1) {
5092
- const line = lines[index];
5093
- if (line === "---") return result;
5094
- const match = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\s*(.*)$/u);
5095
- if (!match) continue;
5096
- result[match[1]] = match[2].replace(/^['"]|['"]$/g, "");
5097
- }
5098
- return {};
5099
- }
5100
-
5101
- // src/cmd/skills/index.ts
5102
- var SKILLS_DIR2 = packagePath("skills");
5103
- function reader() {
5104
- if (!existsSync6(SKILLS_DIR2)) {
5105
- throw new CliError("skills directory does not exist: " + SKILLS_DIR2);
5106
- }
5107
- return new SkillReader(SKILLS_DIR2);
5108
- }
5109
- function commandOptions(value) {
5110
- if (!value || typeof value !== "object" || !("opts" in value)) return {};
5111
- const opts = value.opts();
5112
- return opts && typeof opts === "object" ? opts : {};
5113
- }
5114
- function describeRoot(resolution) {
5115
- if (resolution.source === "target-dir") return "\u7531 --target-dir \u6307\u5B9A";
5116
- if (resolution.source === "explicit-env") {
5117
- return `\u7531 ${resolution.environmentVariable || "\u5BBF\u4E3B\u73AF\u5883\u53D8\u91CF"} \u6307\u5B9A\uFF08${resolution.host}\uFF09`;
5118
- }
5119
- if (resolution.source === "host-detected") return `\u81EA\u52A8\u63A2\u6D4B\u5BBF\u4E3B ${resolution.host}`;
5120
- if (resolution.source === "filesystem-detected") return `\u7531\u672C\u673A\u552F\u4E00\u5DF2\u5B58\u5728\u7684\u5BBF\u4E3B\u76EE\u5F55\u63A8\u65AD\uFF08${resolution.host}\uFF09`;
5121
- return "\u65E0\u6CD5\u53EF\u9760\u5224\u65AD\u5BBF\u4E3B";
5122
- }
5123
- function pythonInvocation(opts) {
5124
- if (opts.python) return { command: opts.python, args: [] };
5125
- if (process.platform === "win32") return { command: "py", args: ["-3"] };
5126
- return { command: "python3", args: [] };
5127
- }
5128
- function detectorArgs(target, opts, globalJson) {
5129
- const args = [target];
5130
- if (opts.json || globalJson) args.push("--json");
5131
- if (opts.noHtml || opts.html === false) args.push("--no-html");
5132
- if (opts.out) args.push("--out", opts.out);
5133
- if (typeof opts.html === "string") args.push("--html", opts.html);
5134
- if (opts.platform) args.push("--platform", opts.platform);
5135
- if (opts.marketCatalog) args.push("--market-catalog", opts.marketCatalog);
5136
- if (opts.marketLive) args.push("--market-live");
5137
- return args;
5138
- }
5139
- var skillsCommand = {
5140
- name: "skills",
5141
- description: "Read packaged agent skill content",
5142
- category: "skills",
5143
- register({ program: program2, action }) {
5144
- const skills = program2.command("skills").description("Read packaged agent skill content");
5145
- skills.command("list").description("List skills, or list one layer under a skill path").argument("[target]", "skill name or name/path").option("--json", "accepted for symmetry; output is always JSON").action(action((ctx, target) => {
5146
- const skillReader = reader();
5147
- if (typeof target !== "string" || !target) {
5148
- const listed2 = skillReader.list();
5149
- ctx.output.write({ ok: true, skills: listed2, count: listed2.length }, { json: true });
5150
- return;
5151
- }
5152
- const listed = skillReader.listPath(target);
5153
- ctx.output.write({ ok: true, ...listed, count: listed.entries.length }, { json: true });
5154
- }));
5155
- skills.command("read").description("Print a skill SKILL.md or a file under the skill").argument("<target>", "skill name or name/path").argument("[path]", "path under the skill").option("--json", "output as a JSON envelope instead of raw markdown").action(action((ctx, target, pathArg, command) => {
5156
- if (typeof target !== "string") throw new CliError("target must be a string");
5157
- const opts = commandOptions(command || pathArg);
5158
- const result = reader().read(target, typeof pathArg === "string" ? pathArg : "");
5159
- if (opts.json || ctx.getGlobalOptions().json) {
5160
- ctx.output.write(result, { json: true });
5161
- return;
5162
- }
5163
- ctx.output.raw(result.content);
5164
- }));
5165
- skills.command("install").description("Install packaged skills into the current Agent skills directory").argument("[target]", "skill name (weaver-e10-* or legacy weaver-work-cli-*), short name such as skill-maker, or all", "all").option("--target-dir <path>", "override target skills directory").action(action((ctx, target, options) => {
5166
- const opts = options && typeof options === "object" ? options : {};
5167
- const specified = typeof opts.targetDir === "string" && opts.targetDir.trim() ? resolveSkillsTargetPath(opts.targetDir) : "";
5168
- const resolution = specified ? { root: specified, host: "explicit", source: "target-dir" } : resolveSkillsRoot(ctx.env);
5169
- if (resolution.requiresExplicitTarget) {
5170
- throw new CliError(unresolvedSkillsRootMessage(resolution), 2 /* UsageError */);
5171
- }
5172
- const targetRoot = resolution.root;
5173
- const result = installPackagedSkills(SKILLS_DIR2, targetRoot, typeof target === "string" ? target : "all");
5174
- const warnings = resolution.source === "filesystem-detected" ? ["\u63D0\u793A\uFF1A\u8BE5\u76EE\u5F55\u4EC5\u6839\u636E\u672C\u673A\u5DF2\u6709\u76EE\u5F55\u63A8\u65AD\uFF1B\u5982\u4E0E\u5F53\u524D\u667A\u80FD\u4F53\u4E0D\u7B26\uFF0C\u8BF7\u7528 --target-dir \u6216 WEAVER_SKILLS_ROOT \u6307\u5B9A\u3002"] : [];
5175
- ctx.output.write({
5176
- ...result,
5177
- targetRoot,
5178
- skillsHost: resolution.host,
5179
- skillsRootSource: resolution.source,
5180
- warnings
5181
- }, {
5182
- text: [
5183
- `Skills root: ${targetRoot}\uFF08${describeRoot(resolution)}\uFF09`,
5184
- "Installed packaged skills:",
5185
- ...result.installed.map((entry) => `- ${entry.name} -> ${entry.target}`),
5186
- ...warnings
5187
- ].join("\n")
3665
+ const response = await (await runtime()).requestJson({
3666
+ module: "invoice",
3667
+ operation,
3668
+ method,
3669
+ path,
3670
+ query,
3671
+ form,
3672
+ timeoutMs,
3673
+ trustedHeaders: trustedInvoiceHeaders(token)
3674
+ });
3675
+ if (isE10SessionExpiredResponse(response)) {
3676
+ throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
3677
+ }
3678
+ if (response.parseError) {
3679
+ throw invoiceNetworkError("protocol", `\u63A5\u53E3\u8FD4\u56DE\u4E0D\u662F\u5408\u6CD5 JSON\uFF08HTTP ${response.status}\uFF09`, { retryable: false });
3680
+ }
3681
+ if (response.status < 200 || response.status >= 300) {
3682
+ throw new InvoiceCliError("api", "http_error", `\u6CDB\u5FAE\u63A5\u53E3 HTTP ${response.status}`, {
3683
+ code: response.status,
3684
+ details: { status: response.status, message: responseMessage(response.value) },
3685
+ exitCode: 1
5188
3686
  });
5189
- }));
5190
- skills.command("validate").description("Validate a generated skill using the packaged Weaver skill detector").argument("<target>", "skill directory, SKILL.md, or skill zip").option("--detector-dir <path>", "override detector directory; defaults to the packaged detector").option("--python <path>", "Python executable; defaults to python3, or py -3 on Windows").option("--json", "ask the detector to print JSON").option("--no-html", "disable detector HTML report output").option("--out <path>", "write detector markdown report").option("--html <path>", "write detector HTML report").option("--platform <platform>", "detector platform: weaver or qwenwork").option("--market-catalog <path>", "detector market catalog JSON").option("--market-live", "enable detector live market checks").action(action((ctx, target, options) => {
5191
- if (typeof target !== "string") throw new CliError("target must be a string");
5192
- const opts = options && typeof options === "object" ? options : {};
5193
- const detector = resolveDetectorInfo(opts.detectorDir);
5194
- const python = pythonInvocation(opts);
5195
- const child = spawnSync(python.command, [
5196
- ...python.args,
5197
- detector.scriptPath,
5198
- ...detectorArgs(target, opts, Boolean(ctx.getGlobalOptions().json))
5199
- ], { stdio: "inherit" });
5200
- if (child.error) throw new CliError(`failed to run Python detector: ${child.error.message}`);
5201
- if (typeof child.status === "number") {
5202
- process.exitCode = child.status;
5203
- return;
5204
- }
5205
- if (child.signal) throw new CliError(`detector terminated by signal: ${child.signal}`);
5206
- throw new CliError("detector exited without a status code");
5207
- }));
5208
- }
5209
- };
5210
-
5211
- // src/cmd/index.ts
5212
- var builtinCommands = [
5213
- configCommand,
5214
- docsCommand,
5215
- doctorCommand,
5216
- commandsCommand,
5217
- runCommand,
5218
- refsCommand,
5219
- e10Command,
5220
- setupCommand,
5221
- skillsCommand
5222
- ];
5223
-
5224
- // src/core/input.ts
5225
- var FileInputPolicyError = class extends CliError {
5226
- type = "policy";
5227
- subtype = "file_input_denied";
5228
- retryable = false;
5229
- constructor() {
5230
- super(
5231
- "\u4E0D\u5141\u8BB8\u901A\u8FC7 --input <path> \u8BFB\u53D6 JSON \u6587\u4EF6\u3002\u8BF7\u6539\u7528 --input-json\u3001--input -\uFF0C\u6216\u7528 --input-ref \u4F20\u9012\u4E0A\u4E00\u6B65\u7684\u7ED3\u679C\u3002",
5232
- 6 /* PolicyError */
5233
- );
5234
- this.name = "FileInputPolicyError";
5235
- }
5236
- };
5237
- function configuredPolicy(ctx) {
5238
- const io = ctx.config.get("io");
5239
- if (io && typeof io === "object" && !Array.isArray(io) && "fileInput" in io) {
5240
- return io.fileInput;
5241
- }
5242
- return ctx.config.get("io.fileInput");
5243
- }
5244
- function resolveFileInputPolicy(ctx, options) {
5245
- const allow = options.allowFileInput === true;
5246
- const deny = options.fileInput === false;
5247
- if (allow && deny) {
5248
- throw new CliError("\u4E0D\u80FD\u540C\u65F6\u4F20 --allow-file-input \u548C --no-file-input", 2 /* UsageError */);
5249
- }
5250
- if (allow) return "allow";
5251
- if (deny) return "deny";
5252
- const fromEnv = (ctx.env.WEAVER_WORK_CLI_FILE_INPUT ?? "").trim().toLowerCase();
5253
- if (fromEnv === "allow" || fromEnv === "warn" || fromEnv === "deny") return fromEnv;
5254
- const fromConfig = configuredPolicy(ctx);
5255
- if (fromConfig === "allow" || fromConfig === "warn" || fromConfig === "deny") return fromConfig;
5256
- return "warn";
5257
- }
5258
- function guardFileInput(ctx, options) {
5259
- const input = options.input;
5260
- if (input === void 0 || input === null || String(input).trim() === "" || input === "-") return;
5261
- const policy = resolveFileInputPolicy(ctx, options);
5262
- if (policy === "allow") return;
5263
- if (policy === "deny") throw new FileInputPolicyError();
5264
- process.stderr.write(
5265
- "[weaver-work-cli] \u4F7F\u7528 --input <path> \u8BFB\u53D6 JSON \u6587\u4EF6\uFF1B\u591A\u6B65\u4F20\u9012\u8BF7\u4F18\u5148\u7528 --input-ref\uFF0C\u7B80\u5355\u6570\u636E\u8BF7\u7528 --input-json\u3002\n"
5266
- );
5267
- }
5268
-
5269
- // src/cmd/action.ts
5270
- function commandFromArgs(args) {
5271
- const last = args[args.length - 1];
5272
- return last && typeof last === "object" && "name" in last && "opts" in last ? last : void 0;
5273
- }
5274
- function optionsHolderFrom(args) {
5275
- return args.find((arg) => Boolean(
5276
- arg && typeof arg === "object" && !Array.isArray(arg) && !("opts" in arg) && ("inputRef" in arg || "pick" in arg || "pickAs" in arg || "allowFileInput" in arg || "fileInput" in arg)
5277
- ));
5278
- }
5279
- function applyRefInput(ctx, args) {
5280
- const holder = optionsHolderFrom(args);
5281
- if (!holder) return;
5282
- const refId = String(holder.inputRef ?? "").trim();
5283
- if (!refId) {
5284
- if (holder.pick || holder.pickAs) {
5285
- throw new RefError("input_ref_required", "--pick \u548C --pick-as \u5FC5\u987B\u4E0E --input-ref \u4E00\u8D77\u4F7F\u7528");
5286
3687
  }
5287
- return;
5288
- }
5289
- if (holder.inputJson !== void 0 || holder.input !== void 0) {
5290
- throw new RefError("input_conflict", "\u4E0D\u80FD\u540C\u65F6\u4F20 --input-ref \u4E0E --input/--input-json");
5291
- }
5292
- const pick = holder.pick === void 0 || holder.pick === null || holder.pick === "" ? void 0 : String(holder.pick);
5293
- const pickAs = holder.pickAs === void 0 || holder.pickAs === null || holder.pickAs === "" ? void 0 : String(holder.pickAs);
5294
- holder.inputJson = JSON.stringify(resolveRefInput(ctx, {
5295
- refId,
5296
- ...pick ? { pick } : {},
5297
- ...pickAs ? { pickAs } : {}
5298
- }));
5299
- delete holder.inputRef;
5300
- delete holder.pick;
5301
- delete holder.pickAs;
5302
- }
5303
- function cleanupRefs(ctx) {
5304
- try {
5305
- pruneRefs(ctx, { maxCount: refMaxCount(ctx), maxBytes: refMaxBytes(ctx) });
5306
- } catch {
5307
- process.stderr.write("[weaver-work-cli] \u6682\u5B58\u7ED3\u679C\u6E05\u7406\u5931\u8D25\uFF1B\u672C\u6B21\u547D\u4EE4\u7EE7\u7EED\u6267\u884C\u3002\n");
5308
- }
5309
- }
5310
- function isRefsShow(command) {
5311
- const names = [];
5312
- let current = command;
5313
- while (current) {
5314
- const name = current.name();
5315
- if (name) names.unshift(name);
5316
- current = current.parent;
5317
- }
5318
- return names.slice(-2).join(" ") === "refs show";
5319
- }
5320
- function createAction(ctx) {
5321
- return (handler) => async (...args) => {
5322
- const commandCtx = ctx.forCommand(commandFromArgs(args));
5323
- try {
5324
- await commandCtx.hooks.beforeCommand(commandCtx);
5325
- applyRefInput(commandCtx, args);
5326
- const options = commandCtx.activeCommand?.opts();
5327
- if (options) guardFileInput(commandCtx, options);
5328
- if (!isRefsShow(commandCtx.activeCommand)) cleanupRefs(commandCtx);
5329
- const result = await handler(commandCtx, ...args);
5330
- await commandCtx.hooks.afterCommand(commandCtx, result);
5331
- } catch (error) {
5332
- await commandCtx.hooks.onError(commandCtx, error);
5333
- if (commandCtx.getGlobalOptions().json) {
5334
- console.error(JSON.stringify({
5335
- schemaVersion: 1,
5336
- ok: false,
5337
- error: toErrorEnvelope(error)
5338
- }, null, 2));
5339
- process.exitCode = isCliError(error) ? error.exitCode : 1 /* GeneralError */;
5340
- return;
5341
- }
5342
- if (isCliError(error)) {
5343
- commandCtx.logger.error(error.message);
5344
- process.exitCode = error.exitCode;
5345
- return;
5346
- }
5347
- const message = error instanceof Error ? error.message : String(error);
5348
- commandCtx.logger.error(message);
5349
- process.exitCode = 1 /* GeneralError */;
3688
+ return handleBusinessResponse(response.value, () => invoiceFormRequest(request, false), canRetryExpiredToken && Boolean(token));
3689
+ }
3690
+ async function invoiceDownload({ id, fid, needLog = false, operation, timeoutMs = 3e4 }, canRetryExpiredToken = true) {
3691
+ const token = await ensureContext(true, timeoutMs, "/api/inc/file/download");
3692
+ const response = await (await runtime()).requestBinary({
3693
+ module: "invoice",
3694
+ operation,
3695
+ method: "GET",
3696
+ path: "/api/inc/file/download",
3697
+ query: { id, fid, needLog },
3698
+ headers: { Accept: "application/octet-stream, application/pdf, */*" },
3699
+ timeoutMs,
3700
+ trustedHeaders: trustedInvoiceHeaders(token)
3701
+ });
3702
+ if (isE10SessionExpiredResponse(response)) {
3703
+ throw invoiceAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
5350
3704
  }
5351
- };
5352
- }
5353
-
5354
- // src/cmd/register.ts
5355
- var IO_CHANNEL_OPTIONS = [
5356
- { flags: "--input-ref <ref>", description: "consume a persisted large result reference" },
5357
- { flags: "--pick <path>", description: "pick a sub path from --input-ref, e.g. items[0].fid" },
5358
- { flags: "--pick-as <field>", description: "map a scalar picked value to this input field, e.g. fid" },
5359
- { flags: "--allow-file-input", description: "allow reading JSON input from --input <path>" },
5360
- { flags: "--no-file-input", description: "reject JSON input from --input <path>" }
5361
- ];
5362
- function ensureRefInputOptions(command) {
5363
- if (command.commands.length === 0) {
5364
- for (const option of IO_CHANNEL_OPTIONS) {
5365
- const long = option.flags.split(" ")[0];
5366
- if (!command.options.some((existing) => existing.long === long)) {
5367
- command.option(option.flags, option.description);
3705
+ const contentType = response.contentType;
3706
+ const declaredLength = Number(response.headers.get("content-length"));
3707
+ if (Number.isFinite(declaredLength) && declaredLength > MAX_DOWNLOAD_BYTES) {
3708
+ throw invoiceNetworkError("response_too_large", `\u4E0B\u8F7D\u6587\u4EF6\u8D85\u8FC7 ${MAX_DOWNLOAD_BYTES} \u5B57\u8282\u9650\u5236`, { retryable: false });
3709
+ }
3710
+ const content = response.content;
3711
+ const looksLikeJson = /^[\s\r\n]*[\[{]/u.test(content.subarray(0, 64).toString("utf8"));
3712
+ if (response.status < 200 || response.status >= 300 || contentType.includes("json") || looksLikeJson) {
3713
+ let value = {};
3714
+ try {
3715
+ value = JSON.parse(content.toString("utf8"));
3716
+ } catch {
3717
+ value = {};
3718
+ }
3719
+ if (isInvoiceSessionExpired(value)) {
3720
+ await clearCachedInvoiceToken();
3721
+ if (canRetryExpiredToken && token) return invoiceDownload({ id, fid, needLog, operation, timeoutMs }, false);
3722
+ throw invoiceAuthError(
3723
+ "invoice_session_expired",
3724
+ `\u53D1\u7968\u4E1A\u52A1\u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u5DF2\u6E05\u7406\u672C\u5730\u53D1\u7968 Token\u3002${E10_REAUTH_GUIDANCE}`,
3725
+ { ret: responseCode(value), status: response.status }
3726
+ );
5368
3727
  }
3728
+ throw new InvoiceCliError("api", "download_failed", responseMessage(value) || `\u4E0B\u8F7D\u5931\u8D25\uFF08HTTP ${response.status}\uFF09`, {
3729
+ code: response.status,
3730
+ details: { status: response.status, ret: responseCode(value) },
3731
+ exitCode: 1
3732
+ });
5369
3733
  }
5370
- return;
5371
- }
5372
- for (const child of command.commands) {
5373
- ensureRefInputOptions(child);
5374
- }
5375
- }
5376
- async function registerCommands(program2, ctx, commands) {
5377
- ctx.commands = commands.map((command) => ({
5378
- name: command.name,
5379
- description: command.description,
5380
- category: command.category
5381
- }));
5382
- ctx.modules = ctx.commands;
5383
- for (const command of commands) {
5384
- if (command.hooks) {
5385
- ctx.hooks.register(command.hooks);
3734
+ if (!content.length) {
3735
+ throw invoiceNetworkError("protocol", "\u4E0B\u8F7D\u63A5\u53E3\u8FD4\u56DE\u7A7A\u6587\u4EF6", { retryable: false });
5386
3736
  }
3737
+ if (content.length > MAX_DOWNLOAD_BYTES) {
3738
+ throw invoiceNetworkError("response_too_large", `\u4E0B\u8F7D\u6587\u4EF6\u8D85\u8FC7 ${MAX_DOWNLOAD_BYTES} \u5B57\u8282\u9650\u5236`, { retryable: false });
3739
+ }
3740
+ return { content, contentType };
5387
3741
  }
5388
- const action = createAction(ctx);
5389
- for (const command of commands) {
5390
- await command.register({ program: program2, ctx, action });
5391
- }
5392
- ensureRefInputOptions(program2);
3742
+ return {
3743
+ invoiceRequest,
3744
+ invoiceMultipartRequest,
3745
+ invoiceFormRequest,
3746
+ invoiceDownload,
3747
+ getSession,
3748
+ invalidateToken() {
3749
+ invoiceToken = null;
3750
+ void clearCachedInvoiceToken();
3751
+ }
3752
+ };
5393
3753
  }
5394
3754
 
5395
- // src/cmd/root.ts
5396
- import { readFileSync as readFileSync6 } from "node:fs";
5397
-
5398
3755
  // node_modules/commander/esm.mjs
5399
3756
  var import_index = __toESM(require_commander(), 1);
5400
3757
  var {
@@ -5412,187 +3769,14 @@ var {
5412
3769
  Help
5413
3770
  } = import_index.default;
5414
3771
 
5415
- // src/core/context.ts
5416
- import { homedir as homedir2 } from "node:os";
5417
- import { resolve as resolve7 } from "node:path";
5418
-
5419
- // src/core/config-store.ts
5420
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "node:fs";
5421
- import { dirname } from "node:path";
5422
- var ConfigStore = class {
5423
- constructor(getPath) {
5424
- this.getPath = getPath;
5425
- }
5426
- getPath;
5427
- path() {
5428
- return this.getPath();
5429
- }
5430
- all() {
5431
- const filePath = this.path();
5432
- if (!existsSync7(filePath)) return {};
5433
- try {
5434
- const value = JSON.parse(readFileSync5(filePath, "utf-8"));
5435
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
5436
- } catch {
5437
- return {};
5438
- }
5439
- }
5440
- get(key) {
5441
- return this.all()[key];
5442
- }
5443
- set(key, value) {
5444
- const data = this.all();
5445
- data[key] = value;
5446
- this.save(data);
5447
- }
5448
- delete(key) {
5449
- const data = this.all();
5450
- const existed = Object.prototype.hasOwnProperty.call(data, key);
5451
- delete data[key];
5452
- this.save(data);
5453
- return existed;
5454
- }
5455
- save(data) {
5456
- const filePath = this.path();
5457
- mkdirSync2(dirname(filePath), { recursive: true });
5458
- writeFileSync2(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
5459
- }
5460
- };
5461
-
5462
- // src/core/logger.ts
5463
- var Logger = class {
5464
- constructor(getOptions) {
5465
- this.getOptions = getOptions;
5466
- }
5467
- getOptions;
5468
- info(message) {
5469
- const opts = this.getOptions();
5470
- if (!opts.quiet && !opts.json) {
5471
- console.log(message);
5472
- }
5473
- }
5474
- warn(message) {
5475
- const opts = this.getOptions();
5476
- if (!opts.quiet && !opts.json) {
5477
- console.warn(message);
5478
- }
5479
- }
5480
- error(message) {
5481
- console.error(message);
5482
- }
5483
- debug(message) {
5484
- const opts = this.getOptions();
5485
- if (opts.verbose && !opts.json) {
5486
- console.error("[debug] " + message);
5487
- }
5488
- }
5489
- };
5490
-
5491
- // src/core/context.ts
5492
- function createCliContext(program2, hooks, packageInfo) {
5493
- const getGlobalOptions = () => normalizeGlobalOptions(program2.opts());
5494
- const configStore = new ConfigStore(() => {
5495
- const opts = getGlobalOptions();
5496
- const home = process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve7(homedir2(), ".weaver-work-cli");
5497
- return opts.config ? resolve7(opts.config) : resolve7(home, "config.json");
5498
- });
5499
- const partialCtx = {
5500
- cwd: process.cwd(),
5501
- env: process.env,
5502
- program: program2,
5503
- hooks,
5504
- packageInfo,
5505
- commands: [],
5506
- modules: [],
5507
- getGlobalOptions,
5508
- forCommand(command) {
5509
- return { ...ctx, activeCommand: command };
5510
- }
5511
- };
5512
- const ctx = partialCtx;
5513
- ctx.logger = new Logger(getGlobalOptions);
5514
- ctx.output = new Output(ctx);
5515
- ctx.config = configStore;
5516
- return ctx;
5517
- }
5518
-
5519
- // src/core/hooks.ts
5520
- var HookManager = class {
5521
- hooks = {
5522
- beforeCommand: [],
5523
- afterCommand: [],
5524
- onError: [],
5525
- beforeRun: [],
5526
- afterRun: []
5527
- };
5528
- e10RequestInterceptors = [];
5529
- register(hooks) {
5530
- for (const [name, handler] of Object.entries(hooks)) {
5531
- if (handler) {
5532
- this.hooks[name].push(handler);
5533
- }
5534
- }
5535
- }
5536
- async beforeCommand(ctx) {
5537
- for (const hook of this.hooks.beforeCommand) {
5538
- await hook(ctx);
5539
- }
5540
- }
5541
- async afterCommand(ctx, result) {
5542
- for (const hook of this.hooks.afterCommand) {
5543
- await hook(ctx, result);
5544
- }
5545
- }
5546
- async onError(ctx, error) {
5547
- for (const hook of this.hooks.onError) {
5548
- await hook(ctx, error);
5549
- }
5550
- }
5551
- async beforeRun(ctx) {
5552
- for (const hook of this.hooks.beforeRun) {
5553
- await hook(ctx);
5554
- }
5555
- }
5556
- async afterRun(ctx, result) {
5557
- for (const hook of this.hooks.afterRun) {
5558
- await hook(ctx, result);
5559
- }
5560
- }
5561
- registerE10RequestInterceptor(interceptor) {
5562
- this.e10RequestInterceptors.push(interceptor);
5563
- }
5564
- getE10RequestInterceptors() {
5565
- return this.e10RequestInterceptors;
5566
- }
5567
- };
5568
-
5569
- // src/cmd/root.ts
5570
- var CLI_COMMAND_NAME = "weaver-work-cli";
5571
- function readPackageInfo2() {
5572
- const pkg = JSON.parse(readFileSync6(packagePath("package.json"), "utf-8"));
5573
- return {
5574
- name: pkg.name || CLI_COMMAND_NAME,
5575
- version: pkg.version || "0.0.0",
5576
- description: pkg.description
5577
- };
5578
- }
5579
- function createProgram() {
5580
- const packageInfo = readPackageInfo2();
5581
- const program2 = new Command();
5582
- const hooks = new HookManager();
5583
- const ctx = createCliContext(program2, hooks, packageInfo);
5584
- program2.name(CLI_COMMAND_NAME).description(packageInfo.description || "Extensible TypeScript CLI").version(packageInfo.version).option("--json", "print command output as JSON").option("--quiet", "suppress non-error logs").option("--verbose", "print debug logs").option("--config <path>", "use a custom weaver-work-cli config file").option("--auth <path>", "use a specific E10 auth file").option("--profile <name>", "use a specific E10 profile").option("--runtime-agent <name>", "identify the current agent runtime (for example: xiaoe)").option(
5585
- "--is-connector [value]",
5586
- "run as the WorkBuddy connector: use the fixed E10 profile managed by the connector"
5587
- ).option("--base-url <url>", "override E10 base URL").option("--passport-url <url>", "override E10 passport URL");
5588
- program2.showHelpAfterError();
5589
- return { program: program2, ctx };
5590
- }
5591
-
5592
3772
  export {
5593
- firstPositionalToken,
5594
- toCommandMetadata,
5595
- builtinCommands,
5596
- registerCommands,
5597
- createProgram
3773
+ InvoiceCliError,
3774
+ invoiceValidationError,
3775
+ invoiceConfirmationError,
3776
+ invoicePartialError,
3777
+ isInvoiceNetworkError,
3778
+ clearInvoiceTokenForSession,
3779
+ createInvoiceHost,
3780
+ Command,
3781
+ Option
5598
3782
  };