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.
- package/README.md +17 -0
- package/dist/chunks/{archive-J4I6MCKF.js → archive-P6TBQGKL.js} +13 -5
- package/dist/chunks/{archive-oa-BRZKKTO4.js → archive-oa-7TQ2NXOH.js} +12 -5
- package/dist/chunks/{asset-L7D4FAOZ.js → asset-3ELRG37G.js} +11 -4
- package/dist/chunks/{asset-idle-DADLLV75.js → asset-idle-WIGMUFMD.js} +7 -3
- package/dist/chunks/{attachment-content-K4C7VLWQ.js → attachment-content-E3276UOV.js} +5 -4
- package/dist/chunks/{blog-BVGQ7NZL.js → blog-C5NMZAAC.js} +11 -4
- package/dist/chunks/{caizhilian-SAADNFD6.js → caizhilian-5XSM2DFP.js} +13 -6
- package/dist/chunks/{calendar-Q7NQY5Z2.js → calendar-FI2WNSBO.js} +12 -5
- package/dist/chunks/{chunk-YRSZQUD2.js → chunk-3YBDYOC4.js} +3 -3
- package/dist/chunks/{chunk-OOUTBLZ4.js → chunk-56EZERK4.js} +1 -1
- package/dist/chunks/chunk-6N4JPNFL.js +76 -0
- package/dist/chunks/{chunk-ZUX3P6BQ.js → chunk-727FH2NI.js} +1 -1
- package/dist/chunks/chunk-7BDPM5ST.js +11 -0
- package/dist/chunks/{chunk-EKWAQSLU.js → chunk-BCVYBYYT.js} +432 -2248
- package/dist/chunks/{chunk-W7BEHOSR.js → chunk-CWYGFU5B.js} +2 -2
- package/dist/chunks/{chunk-NOODWMCL.js → chunk-D4ADSZ7H.js} +1 -1
- package/dist/chunks/{chunk-SA6VBIHY.js → chunk-ETNJSKMM.js} +214 -16
- package/dist/chunks/{chunk-BBKDXQEC.js → chunk-F4E4EM35.js} +3 -3
- package/dist/chunks/{chunk-IZ7S7QUS.js → chunk-FAZTGX7S.js} +6 -6
- package/dist/chunks/{chunk-NKZRQXST.js → chunk-FRZKBMSW.js} +52 -36
- package/dist/chunks/{chunk-BYBSCN4X.js → chunk-G7PQWD4L.js} +6 -3
- package/dist/chunks/{chunk-GEWYMQME.js → chunk-GAMZLAG2.js} +1 -1
- package/dist/chunks/{chunk-R4CHUSKC.js → chunk-GM6J7Q4B.js} +4 -4
- package/dist/chunks/{chunk-APVFJUQH.js → chunk-GRDRG6HP.js} +3 -3
- package/dist/chunks/{chunk-LDZQPUIA.js → chunk-HIT4Y6OI.js} +1 -1
- package/dist/chunks/{chunk-EZALDOQH.js → chunk-HP7JIYMT.js} +5 -2
- package/dist/chunks/{chunk-LADPYOWC.js → chunk-IAZ3UPY6.js} +3 -3
- package/dist/chunks/{chunk-ZEDWSH32.js → chunk-IC62NFM5.js} +1 -1
- package/dist/chunks/{chunk-P26ZWSKU.js → chunk-KIHNAS25.js} +5 -2
- package/dist/chunks/{chunk-BIPYLLVS.js → chunk-N4M2DDFE.js} +15 -15
- package/dist/chunks/{chunk-QKNKR4RH.js → chunk-OF4S23UB.js} +4 -4
- package/dist/chunks/{chunk-JPRO6ER2.js → chunk-PC7VKEB5.js} +57 -60
- package/dist/chunks/{chunk-4PD5NWAX.js → chunk-PUQS5MWL.js} +2 -2
- package/dist/chunks/{chunk-2LV74IWP.js → chunk-Q4OYAQYH.js} +1 -1
- package/dist/chunks/{chunk-72CKAUAG.js → chunk-QVSWRLLU.js} +7 -5
- package/dist/chunks/{chunk-4RAE6JXP.js → chunk-TA7FXXJD.js} +6 -3
- package/dist/chunks/{chunk-GPMFD4RD.js → chunk-TXUG266F.js} +1 -1
- package/dist/chunks/{chunk-FOAA27U5.js → chunk-UFIT2UU3.js} +16 -4
- package/dist/chunks/{chunk-LUSPKZKY.js → chunk-UG5G54VL.js} +1 -0
- package/dist/chunks/{chunk-NIAJ5ZCG.js → chunk-UL5XUQ25.js} +5 -2
- package/dist/chunks/{chunk-FMPJJYYI.js → chunk-WRXSAVKO.js} +1 -1
- package/dist/chunks/{chunk-G4UR6NXN.js → chunk-WSF4NNMR.js} +3 -3
- package/dist/chunks/chunk-XHK4MDR5.js +2497 -0
- package/dist/chunks/{chunk-3KTFS4IA.js → chunk-XNIK66I4.js} +19 -9
- package/dist/chunks/{chunk-3SO6QL6U.js → chunk-YWX377BY.js} +5 -2
- package/dist/chunks/{chunk-BYATLLEF.js → chunk-Z3GDFVJR.js} +1 -1
- package/dist/chunks/{chunk-GHXCDPTM.js → chunk-Z7VYWPZV.js} +1 -1
- package/dist/chunks/{conflict-F2OMZRTO.js → conflict-ARLSZJ6V.js} +4 -3
- package/dist/chunks/{continuation-2CKSBLA6.js → continuation-3S37AUSH.js} +4 -3
- package/dist/chunks/{continuation-RN6PZN2M.js → continuation-3XLYYTKV.js} +4 -3
- package/dist/chunks/{continuation-HZIZRZBX.js → continuation-HFW2YT5S.js} +4 -3
- package/dist/chunks/{continuation-NLECEJPX.js → continuation-KI7DRRZN.js} +4 -3
- package/dist/chunks/{contract-5BETHRSG.js → contract-DNIIW5VJ.js} +13 -5
- package/dist/chunks/{cowork-3MN6EQQO.js → cowork-GMLRGVIW.js} +11 -4
- package/dist/chunks/{create-flow-5FQNNMVO.js → create-flow-J22BO65E.js} +8 -7
- package/dist/chunks/{ebuilder-form-SBHOYBUD.js → ebuilder-form-ANV2FHYV.js} +12 -7
- package/dist/chunks/{ehr-KMOJULKG.js → ehr-GSTGAIY3.js} +266 -24
- package/dist/chunks/{employee-SAK2QYXX.js → employee-22BGJ3QS.js} +3 -3
- package/dist/chunks/{env-LB7NBL2O.js → env-BX3VRFS7.js} +4 -3
- package/dist/chunks/{esb-W2PJCFCX.js → esb-ATAIASX2.js} +12 -7
- package/dist/chunks/{factory-6ZFQXQ46.js → factory-PETTFME6.js} +3 -2
- package/dist/chunks/{fna-ZQPCUV4R.js → fna-YEKBSFSX.js} +14 -8
- package/dist/chunks/{group-chat-2HHAJN46.js → group-chat-BFVXAYFX.js} +5 -4
- package/dist/chunks/{host-ATKVNZAT.js → host-HRBXEPDQ.js} +5 -5
- package/dist/chunks/{host-BQH22NTQ.js → host-LR55CTHP.js} +5 -5
- package/dist/chunks/{host-X2CSLFM6.js → host-SUOY6VYQ.js} +5 -5
- package/dist/chunks/{host-4CBHGOHT.js → host-SZGV4UNT.js} +5 -5
- package/dist/chunks/{host-YTODKMSL.js → host-WIKN2EJ5.js} +5 -5
- package/dist/chunks/{hrm-FFM4UJFS.js → hrm-NRDO4W5G.js} +11 -7
- package/dist/chunks/{im-VEHKDQPB.js → im-IQ2HN23S.js} +8 -7
- package/dist/chunks/{invoice-LVIKSIIF.js → invoice-MNRW76PP.js} +636 -1768
- package/dist/chunks/{jiuchuanhui-X6DINO5P.js → jiuchuanhui-DTRBAX4N.js} +14 -6
- package/dist/chunks/{lazy-dispatch-KSWTN5L6.js → lazy-dispatch-ZVWAI25B.js} +7 -6
- package/dist/chunks/{mail-VDKRGUD3.js → mail-ZVAUXOJA.js} +16 -14
- package/dist/chunks/{meeting-CLC6HP3Z.js → meeting-FEVPZ67S.js} +21 -14
- package/dist/chunks/{okr-CHG4OO3U.js → okr-SDH3E5RA.js} +12 -5
- package/dist/chunks/{operations-5QL3AECO.js → operations-62N6EP3C.js} +4 -3
- package/dist/chunks/{plan-XWR75667.js → plan-E35JFDI7.js} +12 -5
- package/dist/chunks/{project-5BXOOKMG.js → project-73QXBAB2.js} +11 -4
- package/dist/chunks/reception-UWZVACBN.js +1899 -0
- package/dist/chunks/{recruit-stage-DGMFNNDE.js → recruit-stage-4MAOCKFY.js} +320 -57
- package/dist/chunks/registry-IM5G23LS.js +24 -0
- package/dist/chunks/{registry-RHMW6ANW.js → registry-JDUS4E7D.js} +7 -6
- package/dist/chunks/{registry-7FFOXIAW.js → registry-KNKSCJNT.js} +7 -6
- package/dist/chunks/{registry-Z43434VG.js → registry-PO7SI256.js} +4 -4
- package/dist/chunks/{registry-OZSMDVPP.js → registry-PVUZQDDQ.js} +3 -3
- package/dist/chunks/{room-recommend-62H7ZQQ6.js → room-recommend-H7KLXA5R.js} +6 -5
- package/dist/chunks/{schedule-FNXKH3DQ.js → schedule-ESZIBAUO.js} +6 -5
- package/dist/chunks/{workflow-ADHKCAJK.js → workflow-CWJFJLQU.js} +13 -8
- package/dist/cmd/action.js +6 -0
- package/dist/cmd/identity/index.js +45 -0
- package/dist/cmd/index.js +2 -0
- package/dist/core/continuation-ttl.js +18 -0
- package/dist/core/error-codes.js +85 -0
- package/dist/core/logger.js +11 -0
- package/dist/index.js +37 -31
- package/dist/internal/e10/auth/commands.js +163 -8
- package/dist/internal/e10/auth/error-log.js +182 -0
- package/dist/internal/e10/auth/session.js +17 -3
- package/dist/internal/e10/auth-recovery.js +39 -12
- package/dist/internal/e10/context.js +17 -2
- package/dist/internal/skills/install.js +9 -1
- package/dist/shortcuts/archive/continuation.js +2 -1
- package/dist/shortcuts/archive/index.js +3 -0
- package/dist/shortcuts/archive/operations/confirm.js +2 -1
- package/dist/shortcuts/archive-oa/continuation.js +2 -1
- package/dist/shortcuts/archive-oa/index.js +2 -0
- package/dist/shortcuts/archive-oa/operations/confirm.js +2 -1
- package/dist/shortcuts/asset/continuation.js +2 -1
- package/dist/shortcuts/asset/index.js +2 -0
- package/dist/shortcuts/asset-idle/index.js +2 -0
- package/dist/shortcuts/blog/continuation.js +2 -1
- package/dist/shortcuts/blog/index.js +2 -0
- package/dist/shortcuts/caizhilian/continuation.js +2 -1
- package/dist/shortcuts/caizhilian/index.js +2 -0
- package/dist/shortcuts/caizhilian/operations/confirm.js +3 -2
- package/dist/shortcuts/calendar/continuation.js +2 -1
- package/dist/shortcuts/calendar/index.js +2 -0
- package/dist/shortcuts/calendar/operations/write.js +1 -1
- package/dist/shortcuts/contract/continuation.js +2 -1
- package/dist/shortcuts/contract/index.js +2 -0
- package/dist/shortcuts/contract/operations/write.js +2 -1
- package/dist/shortcuts/cowork/continuation.js +2 -1
- package/dist/shortcuts/cowork/index.js +2 -0
- package/dist/shortcuts/ebuilder-form/continuation.js +2 -1
- package/dist/shortcuts/ebuilder-form/index.js +2 -0
- package/dist/shortcuts/ebuilder-form/operations/write.js +3 -2
- package/dist/shortcuts/ehr/continuation.js +2 -1
- package/dist/shortcuts/ehr/index.js +2 -0
- package/dist/shortcuts/ehr/operations/attend-write.js +1 -1
- package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +182 -3
- package/dist/shortcuts/ehr/operations/recruit-position.js +134 -2
- package/dist/shortcuts/ehr/operations/recruit-write.js +1 -1
- package/dist/shortcuts/esb/continuation.js +2 -1
- package/dist/shortcuts/esb/index.js +2 -0
- package/dist/shortcuts/esb/operations/trigger.js +2 -1
- package/dist/shortcuts/fna/continuation.js +2 -1
- package/dist/shortcuts/fna/index.js +2 -0
- package/dist/shortcuts/fna/operations/invoice-writeoff.js +1 -1
- package/dist/shortcuts/fna/operations/loan.js +1 -1
- package/dist/shortcuts/hrm/index.js +2 -0
- package/dist/shortcuts/im/continuation.js +2 -1
- package/dist/shortcuts/index.js +5 -0
- package/dist/shortcuts/invoice/continuation.js +2 -1
- package/dist/shortcuts/invoice/index.js +14 -15
- package/dist/shortcuts/invoice/invoice-record.js +93 -0
- package/dist/shortcuts/invoice/manifest.js +190 -393
- package/dist/shortcuts/invoice/operations/add.js +2 -1
- package/dist/shortcuts/invoice/operations/delete.js +2 -1
- package/dist/shortcuts/invoice/operations/import.js +2 -1
- package/dist/shortcuts/invoice/operations/issuing-contract-detail.js +86 -0
- package/dist/shortcuts/invoice/operations/issuing-contracts.js +210 -0
- package/dist/shortcuts/invoice/operations/registry.js +17 -17
- package/dist/shortcuts/invoice/operations/reim-auto.js +4 -569
- package/dist/shortcuts/invoice/operations/reim.js +52 -341
- package/dist/shortcuts/invoice/operations/shared.js +21 -4
- package/dist/shortcuts/invoice/operations/update.js +2 -1
- package/dist/shortcuts/invoice/projection.js +10 -62
- package/dist/shortcuts/jiuchuanhui/continuation.js +2 -1
- package/dist/shortcuts/jiuchuanhui/index.js +2 -0
- package/dist/shortcuts/jiuchuanhui/operations/datajson.js +2 -1
- package/dist/shortcuts/jiuchuanhui/operations/esb.js +2 -1
- package/dist/shortcuts/mail/continuation.js +2 -1
- package/dist/shortcuts/mail/index.js +2 -0
- package/dist/shortcuts/mail/operations/mail-blacklist.js +1 -1
- package/dist/shortcuts/mail/operations/mail-contacts.js +1 -1
- package/dist/shortcuts/mail/operations/mail-send.js +1 -1
- package/dist/shortcuts/mail/operations/mail-sign.js +1 -1
- package/dist/shortcuts/mail/operations/mail-template.js +1 -1
- package/dist/shortcuts/meeting/continuation.js +2 -1
- package/dist/shortcuts/meeting/index.js +2 -0
- package/dist/shortcuts/meeting/operations/change.js +1 -1
- package/dist/shortcuts/meeting/operations/create.js +1 -1
- package/dist/shortcuts/meeting/operations/eb/create-flow.js +16 -7
- package/dist/shortcuts/meeting/operations/eb/decision.js +1 -1
- package/dist/shortcuts/meeting/operations/eb/factory.js +1 -1
- package/dist/shortcuts/meeting/operations/lifecycle.js +1 -1
- package/dist/shortcuts/meeting/operations/receipts.js +1 -1
- package/dist/shortcuts/meeting/operations/signs.js +1 -1
- package/dist/shortcuts/okr/continuation.js +2 -1
- package/dist/shortcuts/okr/index.js +2 -0
- package/dist/shortcuts/okr/operations/write.js +1 -1
- package/dist/shortcuts/plan/continuation.js +2 -1
- package/dist/shortcuts/plan/index.js +2 -0
- package/dist/shortcuts/plan/operations/write.js +1 -1
- package/dist/shortcuts/project/continuation.js +2 -1
- package/dist/shortcuts/project/index.js +2 -0
- package/dist/shortcuts/reception/constants.js +53 -0
- package/dist/shortcuts/reception/errors.js +54 -0
- package/dist/shortcuts/reception/host.js +125 -0
- package/dist/shortcuts/reception/index.js +198 -0
- package/dist/shortcuts/reception/manifest.js +177 -0
- package/dist/shortcuts/reception/operations/ask.js +71 -0
- package/dist/shortcuts/reception/operations/browsertool.js +58 -0
- package/dist/shortcuts/reception/operations/compose.js +129 -0
- package/dist/shortcuts/reception/operations/customparams.js +74 -0
- package/dist/shortcuts/reception/operations/doc.js +238 -0
- package/dist/shortcuts/reception/operations/docrender.js +36 -0
- package/dist/shortcuts/reception/operations/panels.js +179 -0
- package/dist/shortcuts/reception/operations/registry.js +26 -0
- package/dist/shortcuts/reception/operations/render-assets.js +184 -0
- package/dist/shortcuts/reception/operations/render.js +123 -0
- package/dist/shortcuts/reception/operations/runs.js +38 -0
- package/dist/shortcuts/reception/operations/schedule.js +127 -0
- package/dist/shortcuts/reception/operations/shared.js +196 -0
- package/dist/shortcuts/reception/operations/snapshot.js +68 -0
- package/dist/shortcuts/reception/operations/types.js +1 -0
- package/dist/shortcuts/reception/operations.js +33 -0
- package/dist/shortcuts/reception/upload.js +218 -0
- package/dist/shortcuts/recruit-stage/context.js +145 -33
- package/dist/shortcuts/recruit-stage/continuation.js +2 -1
- package/dist/shortcuts/recruit-stage/operations/jd-create.js +106 -17
- package/dist/shortcuts/recruit-stage/operations/resume-import.js +166 -10
- package/dist/shortcuts/workflow/continuation.js +2 -1
- package/dist/shortcuts/workflow/index.js +2 -0
- package/dist/shortcuts/workflow/operations/form.js +32 -8
- package/dist/shortcuts/workflow/operations/write.js +1 -1
- package/docs/_catalog.md +3 -0
- package/docs/agent-invoice.md +1 -1
- package/docs/archive-oa.md +1 -1
- package/docs/caizhilian.md +1 -1
- package/docs/calendar.md +1 -1
- package/docs/contract.md +1 -1
- package/docs/e10-auth.md +16 -0
- package/docs/ehr.md +2 -2
- package/docs/esb.md +1 -1
- package/docs/im.md +1 -1
- package/docs/invoice.md +8 -12
- package/docs/okr.md +1 -1
- package/docs/reception.md +119 -0
- package/package.json +1 -1
- package/scripts/clean.mjs +43 -2
- package/skill-template/business-info.json +18 -2
- package/skill-template/domains/caizhilian.md +1 -1
- package/skill-template/domains/reception-flow.md +18 -0
- package/skill-template/domains/yepiaotong.md +4 -7
- package/skills/weaver-e10-archive-oa/references/source-manifest.json +14 -14
- package/skills/weaver-e10-blog/references/blog-publish.md +1 -1
- package/skills/weaver-e10-blog/references/source-manifest.json +7 -7
- package/skills/weaver-e10-caizhilian/references/source-manifest.json +21 -21
- package/skills/weaver-e10-caizhilian/references/write-protocol.md +2 -2
- package/skills/weaver-e10-calendar/references/calendar-write.md +1 -1
- package/skills/weaver-e10-cowork/SKILL.md +1 -1
- package/skills/weaver-e10-ebuilder-form/SKILL.md +1 -1
- package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -1
- package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -1
- package/skills/weaver-e10-esb/SKILL.md +2 -2
- package/skills/weaver-e10-esb/references/source-manifest.json +22 -22
- package/skills/weaver-e10-esb/references/trigger.md +2 -2
- package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +1 -1
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +1 -1
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +1 -1
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +29 -29
- package/skills/weaver-e10-jucailin/SKILL.md +1 -1
- package/skills/weaver-e10-jucailin/references/attend-write.md +2 -2
- package/skills/weaver-e10-jucailin/references/recruit-create.md +12 -3
- package/skills/weaver-e10-jucailin/references/recruit-write.md +1 -1
- package/skills/weaver-e10-meeting/SKILL.md +8 -6
- package/skills/weaver-e10-meeting/references/meeting-change.md +1 -1
- package/skills/weaver-e10-meeting/references/meeting-create.md +1 -1
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +1 -1
- package/skills/weaver-e10-meeting/references/meeting-verification.md +1 -1
- package/skills/weaver-e10-okr/references/okr-align.md +1 -1
- package/skills/weaver-e10-okr/references/okr-keyresult.md +1 -1
- package/skills/weaver-e10-okr/references/okr-write.md +1 -1
- package/skills/weaver-e10-okr/references/source-manifest.json +8 -8
- package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
- package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
- package/skills/weaver-e10-qiyecheng/references/loan-management.md +1 -1
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +18 -18
- package/skills/weaver-e10-reception-flow/SKILL.md +173 -0
- 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
- package/skills/weaver-e10-reception-flow/data/fields-snapshot.json +213 -0
- package/skills/weaver-e10-reception-flow/references/browsertool.md +68 -0
- package/skills/weaver-e10-reception-flow/references/env-pitfalls.md +51 -0
- package/skills/weaver-e10-reception-flow/references/fields-snapshot.md +227 -0
- package/skills/weaver-e10-reception-flow/references/guide.md +179 -0
- package/skills/weaver-e10-reception-flow/scripts/locate.sh +14 -0
- package/skills/weaver-e10-reception-flow/scripts/render.py +724 -0
- package/skills/weaver-e10-recruit-stage/SKILL.md +9 -5
- package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +1 -1
- package/skills/weaver-e10-recruit-stage/lib/xiaoe-session.mjs +66 -0
- package/skills/weaver-e10-recruit-stage/references/position-templates.md +202 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +22 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +14 -1
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +6 -0
- package/skills/weaver-e10-shijingran/SKILL.md +5 -5
- package/skills/weaver-e10-shijingran/references/source-manifest.json +37 -36
- package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +2 -0
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
- package/skills/weaver-e10-workflow/references/source-manifest.json +32 -32
- package/skills/weaver-e10-yepiaotong/SKILL.md +19 -26
- package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +13 -10
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +2 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +194 -155
- package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +28 -32
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +5 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +8 -10
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +211 -616
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +149 -117
- package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +17 -20
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +20 -39
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +55 -22
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -17
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +88 -92
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +144 -354
- package/skills/weaver-e10-yimiaoban/SKILL.md +1 -1
- package/skills/weaver-e10-yimiaoban/references/msg-write.md +1 -1
- package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +1 -1
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +7 -7
- package/dist/chunks/chunk-TTPJJJC4.js +0 -465
- package/dist/chunks/registry-BKBZPBAJ.js +0 -23
- package/dist/shortcuts/invoice/markdown.js +0 -172
- package/dist/shortcuts/invoice/operations/issuing-qys.js +0 -424
- package/skills/weaver-e10-meeting.zip +0 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +0 -131
- 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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
19
|
-
|
|
9
|
+
E10_REAUTH_GUIDANCE,
|
|
10
|
+
E10_SESSION_EXPIRED_MESSAGE,
|
|
11
|
+
getActiveProfile
|
|
12
|
+
} from "./chunk-UFIT2UU3.js";
|
|
20
13
|
import {
|
|
21
|
-
|
|
22
|
-
} from "./chunk-
|
|
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
|
|
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 =
|
|
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
|
|
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) =>
|
|
1230
|
-
writeErr: (str) =>
|
|
1188
|
+
writeOut: (str) => process.stdout.write(str),
|
|
1189
|
+
writeErr: (str) => process.stderr.write(str),
|
|
1231
1190
|
outputError: (str, write) => write(str),
|
|
1232
|
-
getOutHelpWidth: () =>
|
|
1233
|
-
getErrHelpWidth: () =>
|
|
1234
|
-
getOutHasColors: () => useColor() ?? (
|
|
1235
|
-
getErrHasColors: () => useColor() ?? (
|
|
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
|
-
|
|
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 (
|
|
1975
|
+
if (process.versions?.electron) {
|
|
2017
1976
|
parseOptions.from = "electron";
|
|
2018
1977
|
}
|
|
2019
|
-
const 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 =
|
|
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 (
|
|
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 (
|
|
2182
|
+
if (process.platform !== "win32") {
|
|
2224
2183
|
if (launchWithNode) {
|
|
2225
2184
|
args.unshift(executableFile);
|
|
2226
|
-
args = incrementNodeInspectorPort(
|
|
2227
|
-
proc = childProcess.spawn(
|
|
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(
|
|
2239
|
-
proc = childProcess.spawn(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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()}`,
|
|
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(
|
|
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 (
|
|
3282
|
+
if (process.env.NO_COLOR || process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false")
|
|
3324
3283
|
return false;
|
|
3325
|
-
if (
|
|
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/
|
|
3357
|
-
var
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
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
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
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
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
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
|
|
3799
|
-
return
|
|
3800
|
-
|
|
3801
|
-
|
|
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
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
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
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
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
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
if (
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3423
|
+
const value = await (await entry()).getPassword();
|
|
3424
|
+
return typeof value === "string" && value.trim() ? value : null;
|
|
4060
3425
|
} catch {
|
|
4061
|
-
|
|
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
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
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
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
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
|
-
|
|
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
|
|
4200
|
-
return
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
function
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
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
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
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
|
|
4341
|
-
if (
|
|
4342
|
-
|
|
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
|
-
|
|
4373
|
-
|
|
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
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
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
|
-
|
|
4718
|
-
|
|
3510
|
+
async function clearCachedInvoiceToken() {
|
|
3511
|
+
invoiceToken = null;
|
|
3512
|
+
await tokenStore?.clear().catch(() => false);
|
|
4719
3513
|
}
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
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
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
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
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
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
|
-
|
|
4750
|
-
}
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
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
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
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
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
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
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
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
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
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
|
-
|
|
4994
|
-
const
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
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
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
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
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
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
|
-
|
|
5038
|
-
|
|
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
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
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
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
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
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
}
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
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
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
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
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
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
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
3773
|
+
InvoiceCliError,
|
|
3774
|
+
invoiceValidationError,
|
|
3775
|
+
invoiceConfirmationError,
|
|
3776
|
+
invoicePartialError,
|
|
3777
|
+
isInvoiceNetworkError,
|
|
3778
|
+
clearInvoiceTokenForSession,
|
|
3779
|
+
createInvoiceHost,
|
|
3780
|
+
Command,
|
|
3781
|
+
Option
|
|
5598
3782
|
};
|