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
|
@@ -5,6 +5,7 @@ import { CliError, ExitCode } from '../../../core/errors.js';
|
|
|
5
5
|
import { clearInvoiceTokenForSession } from '../../../shortcuts/invoice/host.js';
|
|
6
6
|
import { buildE10CookieHeader, E10AuthSession, clearProfileAuthFile, extractRawSetCookie, extractSessionTicket, findAuthFile, getActiveProfile, getProfileAuthPath, getProfileDir, listProfiles, profileNameFromUrl, readProfileConfig, readTeamsCheckUserInfo, saveAuthFile, saveProfileConfig, setActiveProfile, switchActiveProfile, } from './session.js';
|
|
7
7
|
import { getE10AuthRoot } from './paths.js';
|
|
8
|
+
import { appendXiaoEAuthErrorLog, clearXiaoEAuthErrorLog, getXiaoEAuthErrorLogPath, normalizeXiaoEAuthErrorLogLimit, readXiaoEAuthErrorLog, xiaoEAuthLogSecrets, } from './error-log.js';
|
|
8
9
|
import { XIAOE_AGENT_TYPE, createXiaoEUnifiedLoginUnavailableError, hasXiaoEEnv, inspectXiaoEUnifiedLoginSources, resolveXiaoEPreferredBaseUrl, tryXiaoEUnifiedLogin as tryXiaoEUnifiedSessionLogin, } from './xiaoe.js';
|
|
9
10
|
export { DEFAULT_E10_BASE_URL, XIAOE_AGENT_TYPE, hasXiaoEEnv, hasXiaoETokenScript, hasXiaoEUnifiedLoginSource, inspectXiaoEUnifiedLoginSources, resolveXiaoEDefaultBaseUrl, resolveXiaoEPreferredBaseUrl, resolveXiaoEUnifiedLoginCredential, } from './xiaoe.js';
|
|
10
11
|
const DEFAULT_AGENT_TYPE = 'weaver-work-cli';
|
|
@@ -385,7 +386,7 @@ async function saveEteamsIdLogin(input) {
|
|
|
385
386
|
version: input.version || '',
|
|
386
387
|
};
|
|
387
388
|
}
|
|
388
|
-
async function tryXiaoEUnifiedLogin(ctx, baseUrl, tenantKeyFallback, profileHint, allowTokenScript = false) {
|
|
389
|
+
async function tryXiaoEUnifiedLogin(ctx, baseUrl, tenantKeyFallback, profileHint, allowTokenScript = false, diagnostics) {
|
|
389
390
|
const login = await tryXiaoEUnifiedSessionLogin({
|
|
390
391
|
env: ctx.env,
|
|
391
392
|
baseUrl,
|
|
@@ -394,6 +395,7 @@ async function tryXiaoEUnifiedLogin(ctx, baseUrl, tenantKeyFallback, profileHint
|
|
|
394
395
|
profileHint,
|
|
395
396
|
allowTokenScript,
|
|
396
397
|
logger: ctx.logger,
|
|
398
|
+
diagnostics,
|
|
397
399
|
});
|
|
398
400
|
return login?.result || null;
|
|
399
401
|
}
|
|
@@ -529,6 +531,15 @@ async function runXiaoELogin(ctx, options) {
|
|
|
529
531
|
const useXiaoELogin = xiaoESources.any;
|
|
530
532
|
const baseUrl = preferredXiaoEBaseUrl;
|
|
531
533
|
const tenantKey = optionString(commandOpts, 'tenantKey');
|
|
534
|
+
const diagnostics = {
|
|
535
|
+
attemptedSteps: [],
|
|
536
|
+
baseUrl,
|
|
537
|
+
clientType: xiaoESources.clientType,
|
|
538
|
+
platformCredentialDetected: xiaoESources.platformCredential,
|
|
539
|
+
};
|
|
540
|
+
if (!useXiaoELogin) {
|
|
541
|
+
diagnostics.attemptedSteps.push('platform_token:missing', 'bundled_env_script:missing', xiaoESources.clientType === 'cloud' ? 'token_script:disabled' : 'token_script:missing', xiaoESources.clientType === 'cloud' ? 'client_session:disabled' : 'client_session:missing', 'environment_map:empty');
|
|
542
|
+
}
|
|
532
543
|
ctx.logger.info([
|
|
533
544
|
'XiaoE unified login preflight:',
|
|
534
545
|
'authMode=xiaoe',
|
|
@@ -542,12 +553,34 @@ async function runXiaoELogin(ctx, options) {
|
|
|
542
553
|
`baseUrl=${baseUrl || '(unresolved)'}`,
|
|
543
554
|
].join(' '));
|
|
544
555
|
if (useXiaoELogin) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
556
|
+
try {
|
|
557
|
+
const xiaoEResult = await tryXiaoEUnifiedLogin(ctx, baseUrl, tenantKey, profileFromGlobal, true, diagnostics);
|
|
558
|
+
if (xiaoEResult)
|
|
559
|
+
return xiaoEResult;
|
|
560
|
+
}
|
|
561
|
+
catch (error) {
|
|
562
|
+
await appendXiaoEAuthErrorLog({
|
|
563
|
+
source: 'login',
|
|
564
|
+
profile: profileFromGlobal || getActiveProfile(),
|
|
565
|
+
baseUrl,
|
|
566
|
+
diagnostics,
|
|
567
|
+
error,
|
|
568
|
+
secrets: xiaoEAuthLogSecrets(ctx.env),
|
|
569
|
+
}).catch((logError) => ctx.logger.debug(`Could not persist XiaoE auth error log: ${logError instanceof Error ? logError.message : String(logError)}`));
|
|
570
|
+
throw error;
|
|
571
|
+
}
|
|
548
572
|
}
|
|
549
573
|
ctx.logger.warn(xiaoEUnifiedLoginUnavailableMessage(baseUrl, useXiaoELogin));
|
|
550
|
-
|
|
574
|
+
const error = createXiaoEUnifiedLoginUnavailableError(baseUrl);
|
|
575
|
+
await appendXiaoEAuthErrorLog({
|
|
576
|
+
source: 'login',
|
|
577
|
+
profile: profileFromGlobal || getActiveProfile(),
|
|
578
|
+
baseUrl,
|
|
579
|
+
diagnostics,
|
|
580
|
+
error,
|
|
581
|
+
secrets: xiaoEAuthLogSecrets(ctx.env),
|
|
582
|
+
}).catch((logError) => ctx.logger.debug(`Could not persist XiaoE auth error log: ${logError instanceof Error ? logError.message : String(logError)}`));
|
|
583
|
+
throw error;
|
|
551
584
|
}
|
|
552
585
|
async function runBrowserLogin(ctx, options) {
|
|
553
586
|
const commandOpts = asOptions(options);
|
|
@@ -768,7 +801,78 @@ function formatWhoami(title, data) {
|
|
|
768
801
|
'User-Agent: ' + (data.userAgent || ''),
|
|
769
802
|
].join('\n');
|
|
770
803
|
}
|
|
771
|
-
function
|
|
804
|
+
function formatXiaoEAuthErrorLogEntry(entry) {
|
|
805
|
+
const lines = [
|
|
806
|
+
`[${entry.timestamp}] ${entry.source} id=${entry.id}`,
|
|
807
|
+
...(entry.profile ? [`profile: ${entry.profile}`] : []),
|
|
808
|
+
...(entry.baseUrl ? [`baseUrl: ${entry.baseUrl}`] : []),
|
|
809
|
+
...(entry.clientType ? [`clientType: ${entry.clientType}`] : []),
|
|
810
|
+
...(entry.attemptedSteps.length ? [`attemptedSteps: ${entry.attemptedSteps.join(', ')}`] : []),
|
|
811
|
+
...(entry.lastError ? [`lastError: ${entry.lastError}`] : []),
|
|
812
|
+
...(entry.resultSessionExpired ? ['resultSessionExpired: true'] : []),
|
|
813
|
+
...(entry.error ? [`error: ${entry.error.type}/${entry.error.subtype}: ${entry.error.message}`] : []),
|
|
814
|
+
];
|
|
815
|
+
for (const failure of entry.failures || []) {
|
|
816
|
+
lines.push([
|
|
817
|
+
`failure: ${failure.stage}/${failure.kind}`,
|
|
818
|
+
failure.causeCode ? `causeCode=${failure.causeCode}` : '',
|
|
819
|
+
failure.httpStatus === undefined ? '' : `httpStatus=${failure.httpStatus}`,
|
|
820
|
+
failure.message,
|
|
821
|
+
].filter(Boolean).join(' '));
|
|
822
|
+
}
|
|
823
|
+
return lines.join('\n');
|
|
824
|
+
}
|
|
825
|
+
async function showXiaoEAuthErrorLogs(ctx, options) {
|
|
826
|
+
const commandOpts = asOptions(options);
|
|
827
|
+
let limit;
|
|
828
|
+
try {
|
|
829
|
+
limit = normalizeXiaoEAuthErrorLogLimit(commandOpts.limit);
|
|
830
|
+
}
|
|
831
|
+
catch (error) {
|
|
832
|
+
throw new CliError(error instanceof Error ? error.message : String(error), ExitCode.UsageError);
|
|
833
|
+
}
|
|
834
|
+
const result = await readXiaoEAuthErrorLog(limit);
|
|
835
|
+
const text = result.entries.length
|
|
836
|
+
? [
|
|
837
|
+
`XiaoE auth error logs (${result.returned}/${result.total}, newest first)`,
|
|
838
|
+
`logFile: ${result.path}`,
|
|
839
|
+
...(result.invalidLines ? [`invalidLines: ${result.invalidLines}`] : []),
|
|
840
|
+
'',
|
|
841
|
+
result.entries.map(formatXiaoEAuthErrorLogEntry).join('\n\n'),
|
|
842
|
+
].join('\n')
|
|
843
|
+
: [
|
|
844
|
+
'No XiaoE auth error logs.',
|
|
845
|
+
`logFile: ${result.path}`,
|
|
846
|
+
...(result.invalidLines ? [`invalidLines: ${result.invalidLines}`] : []),
|
|
847
|
+
].join('\n');
|
|
848
|
+
ctx.output.write(result, { text });
|
|
849
|
+
}
|
|
850
|
+
function registerXiaoEAuthLogCommands(auth, action) {
|
|
851
|
+
const logs = auth.command('logs')
|
|
852
|
+
.description('View or clear persisted XiaoE authentication error logs')
|
|
853
|
+
.option('--limit <n>', 'number of recent entries to show (1-500)', '50')
|
|
854
|
+
.action(action(showXiaoEAuthErrorLogs));
|
|
855
|
+
logs.command('show')
|
|
856
|
+
.description('Show persisted XiaoE authentication error logs')
|
|
857
|
+
.option('--limit <n>', 'number of recent entries to show (1-500)', '50')
|
|
858
|
+
.action(action(showXiaoEAuthErrorLogs));
|
|
859
|
+
logs.command('path')
|
|
860
|
+
.description('Print the XiaoE authentication error log path')
|
|
861
|
+
.action(action((ctx) => {
|
|
862
|
+
const path = getXiaoEAuthErrorLogPath();
|
|
863
|
+
ctx.output.write({ path }, { text: path });
|
|
864
|
+
}));
|
|
865
|
+
logs.command('clear')
|
|
866
|
+
.description('Clear persisted XiaoE authentication error logs')
|
|
867
|
+
.action(action(async (ctx) => {
|
|
868
|
+
const result = await clearXiaoEAuthErrorLog();
|
|
869
|
+
const text = result.cleared
|
|
870
|
+
? `Cleared XiaoE auth error logs.\nlogFile: ${result.path}`
|
|
871
|
+
: `No XiaoE auth error logs to clear.\nlogFile: ${result.path}`;
|
|
872
|
+
ctx.output.write(result, { text });
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
function registerBrowserLoginCommand(auth, action, name, description, machine = false) {
|
|
772
876
|
const command = auth.command(name)
|
|
773
877
|
.description(description)
|
|
774
878
|
.option('--base-url <url>', 'E10 base URL')
|
|
@@ -778,8 +882,28 @@ function registerBrowserLoginCommand(auth, action, name, description) {
|
|
|
778
882
|
.option('--agent-type <value>', 'Alias of --agent_type')
|
|
779
883
|
.option('--agent-return-url <url>', 'Desktop application URL linked by the login success page');
|
|
780
884
|
command.action(action(async (ctx, options) => {
|
|
781
|
-
|
|
782
|
-
|
|
885
|
+
if (!machine) {
|
|
886
|
+
const result = await runBrowserLogin(ctx, options);
|
|
887
|
+
ctx.output.write(result, { text: formatLoginResult(result) });
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
// 平台型连接器契约:stdout 只出严格 JSON,进度与授权链接走 stderr。
|
|
891
|
+
ctx.logger.machineMode = true;
|
|
892
|
+
try {
|
|
893
|
+
const result = await runBrowserLogin(ctx, options);
|
|
894
|
+
ctx.output.raw(JSON.stringify({
|
|
895
|
+
status: 'authorized',
|
|
896
|
+
employeeId: result.userId || '',
|
|
897
|
+
tenantKey: result.tenantKey || '',
|
|
898
|
+
}));
|
|
899
|
+
}
|
|
900
|
+
catch (error) {
|
|
901
|
+
ctx.output.raw(JSON.stringify({ status: 'unauthorized' }));
|
|
902
|
+
throw error;
|
|
903
|
+
}
|
|
904
|
+
finally {
|
|
905
|
+
ctx.logger.machineMode = false;
|
|
906
|
+
}
|
|
783
907
|
}));
|
|
784
908
|
}
|
|
785
909
|
function registerXiaoELoginCommand(auth, action) {
|
|
@@ -847,6 +971,35 @@ export function registerE10AuthCommands(parent, action) {
|
|
|
847
971
|
};
|
|
848
972
|
ctx.output.write(status, { text: formatAuthStatus(status) });
|
|
849
973
|
}));
|
|
974
|
+
auth.command('show')
|
|
975
|
+
.description('Platform contract: print login status as {"status":"authorized"|"unauthorized"}')
|
|
976
|
+
.option('--status', 'print only the strict JSON status object')
|
|
977
|
+
.option('--no-check', 'skip remote session validity check')
|
|
978
|
+
.action(action(async (ctx, options) => {
|
|
979
|
+
const opts = ctx.getGlobalOptions();
|
|
980
|
+
const commandOpts = asOptions(options);
|
|
981
|
+
const authFile = findAuthFile(ctx.cwd, opts);
|
|
982
|
+
const session = authFile ? E10AuthSession.fromFile(authFile, opts.baseUrl, opts.passportUrl) : null;
|
|
983
|
+
const profile = opts.profile || getActiveProfile();
|
|
984
|
+
const expired = session ? session.isExpired() : false;
|
|
985
|
+
// 三态探活:只有明确失效(401/403)才算未授权,网络异常保持乐观,避免逼用户重复登录。
|
|
986
|
+
const probe = session && !expired && commandOpts.check !== false
|
|
987
|
+
? await session.probeValid()
|
|
988
|
+
: undefined;
|
|
989
|
+
const authorized = Boolean(session) && !expired && probe !== false;
|
|
990
|
+
if (commandOpts.status === true) {
|
|
991
|
+
ctx.output.raw(JSON.stringify({ status: authorized ? 'authorized' : 'unauthorized' }));
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
ctx.output.write({
|
|
995
|
+
status: authorized ? 'authorized' : 'unauthorized',
|
|
996
|
+
loggedIn: Boolean(session),
|
|
997
|
+
expired,
|
|
998
|
+
reachable: probe,
|
|
999
|
+
profile,
|
|
1000
|
+
baseUrl: session ? session.getBaseUrl() : '',
|
|
1001
|
+
}, { json: true });
|
|
1002
|
+
}));
|
|
850
1003
|
auth.command('set')
|
|
851
1004
|
.description('Save E10 auth from an ETEAMSID cookie')
|
|
852
1005
|
.requiredOption('--eteamsid <id>', 'ETEAMSID cookie value')
|
|
@@ -882,7 +1035,9 @@ export function registerE10AuthCommands(parent, action) {
|
|
|
882
1035
|
}));
|
|
883
1036
|
registerBrowserLoginCommand(auth, action, 'login', 'Open browser OAuth2.0 login and save E10 auth');
|
|
884
1037
|
registerBrowserLoginCommand(auth, action, 'oidc', 'Alias of auth login for OAuth2.0 browser login');
|
|
1038
|
+
registerBrowserLoginCommand(auth, action, 'init', 'Platform contract alias of auth login: stdout is strict JSON {"status":"authorized"}', true);
|
|
885
1039
|
registerXiaoELoginCommand(auth, action);
|
|
1040
|
+
registerXiaoEAuthLogCommands(auth, action);
|
|
886
1041
|
auth.command('logout')
|
|
887
1042
|
.alias('clear')
|
|
888
1043
|
.description('Clear saved E10 auth for the current or selected profile')
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { appendFile, chmod, mkdir, readFile, unlink } from 'node:fs/promises';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { toErrorEnvelope } from '../../../core/errors.js';
|
|
5
|
+
import { getE10AuthRoot } from './paths.js';
|
|
6
|
+
const XIAOE_AUTH_ERROR_LOG_NAME = 'xiaoe-auth-errors.ndjson';
|
|
7
|
+
const DEFAULT_LOG_LIMIT = 50;
|
|
8
|
+
export const MAX_XIAOE_AUTH_ERROR_LOG_LIMIT = 500;
|
|
9
|
+
/**
|
|
10
|
+
* The log lives beside the CLI-owned E10 profiles, never beside a caller-owned
|
|
11
|
+
* `--auth` file. Keeping the target fixed also makes the clear command safe.
|
|
12
|
+
*/
|
|
13
|
+
export function getXiaoEAuthErrorLogPath() {
|
|
14
|
+
return resolve(getE10AuthRoot(), 'logs', XIAOE_AUTH_ERROR_LOG_NAME);
|
|
15
|
+
}
|
|
16
|
+
export function xiaoEAuthLogSecrets(env) {
|
|
17
|
+
return Object.entries(env)
|
|
18
|
+
.filter(([key, value]) => Boolean(value
|
|
19
|
+
&& (key.startsWith('XIAOE_') || key.startsWith('WEAVER_XIAOE_'))
|
|
20
|
+
&& /(?:TOKEN|AUTH|ETEAMSID|COOKIE|SESSION|SECRET|PASSWORD)/iu.test(key)))
|
|
21
|
+
.map(([, value]) => value);
|
|
22
|
+
}
|
|
23
|
+
function redactSensitiveText(value, secrets = []) {
|
|
24
|
+
let text = value;
|
|
25
|
+
for (const secret of secrets) {
|
|
26
|
+
if (secret && secret.length >= 6)
|
|
27
|
+
text = text.split(secret).join('<redacted>');
|
|
28
|
+
}
|
|
29
|
+
return text
|
|
30
|
+
// Query strings regularly carry temporary tickets. The path is enough for diagnostics.
|
|
31
|
+
.replace(/(https?:\/\/[^\s?#]+)\?[^\s#]*/giu, '$1?<redacted>')
|
|
32
|
+
.replace(/\b(Bearer\s+)[A-Za-z0-9._~+/=-]+/giu, '$1<redacted>')
|
|
33
|
+
.replace(/((?:eteamsid|access[_-]?token|refresh[_-]?token|auth(?:orization)?|cookie|session[_-]?id|secret|password)\s*[:=]\s*)(["']?)[^\s,;}"']+/giu, '$1$2<redacted>')
|
|
34
|
+
.replace(/(["'](?:eteamsid|access[_-]?token|refresh[_-]?token|authorization|cookie|session[_-]?id|secret|password)["']\s*:\s*["'])[^"']*(["'])/giu, '$1<redacted>$2')
|
|
35
|
+
// Opaque credentials that were not labelled by the producer.
|
|
36
|
+
.replace(/\b[A-Za-z0-9_-]{48,}\b/gu, '<redacted>');
|
|
37
|
+
}
|
|
38
|
+
function sanitizeBaseUrl(value, secrets) {
|
|
39
|
+
if (!value)
|
|
40
|
+
return undefined;
|
|
41
|
+
try {
|
|
42
|
+
const url = new URL(value);
|
|
43
|
+
url.username = '';
|
|
44
|
+
url.password = '';
|
|
45
|
+
url.search = '';
|
|
46
|
+
url.hash = '';
|
|
47
|
+
return redactSensitiveText(url.toString().replace(/\/$/u, ''), secrets);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return redactSensitiveText(value, secrets);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function sanitizeFailure(failure, secrets) {
|
|
54
|
+
return {
|
|
55
|
+
stage: failure.stage,
|
|
56
|
+
kind: failure.kind,
|
|
57
|
+
message: redactSensitiveText(failure.message, secrets),
|
|
58
|
+
...(failure.causeCode ? { causeCode: redactSensitiveText(failure.causeCode, secrets) } : {}),
|
|
59
|
+
...(failure.httpStatus === undefined ? {} : { httpStatus: failure.httpStatus }),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function sanitizeError(error, secrets) {
|
|
63
|
+
if (error === undefined)
|
|
64
|
+
return undefined;
|
|
65
|
+
const envelope = toErrorEnvelope(error);
|
|
66
|
+
return {
|
|
67
|
+
...envelope,
|
|
68
|
+
message: redactSensitiveText(envelope.message, secrets),
|
|
69
|
+
// Error details can contain arbitrary server payloads. The normalized
|
|
70
|
+
// diagnostics fields above are the only details persisted to disk.
|
|
71
|
+
...(envelope.details === undefined ? {} : { details: '<omitted from persistent auth log>' }),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function createEntry(input) {
|
|
75
|
+
const secrets = input.secrets || [];
|
|
76
|
+
const diagnostics = input.diagnostics;
|
|
77
|
+
const baseUrl = sanitizeBaseUrl(input.baseUrl || diagnostics?.baseUrl, secrets);
|
|
78
|
+
const lastError = diagnostics?.lastError
|
|
79
|
+
? redactSensitiveText(diagnostics.lastError, secrets)
|
|
80
|
+
: undefined;
|
|
81
|
+
const failures = diagnostics?.failures?.map((failure) => sanitizeFailure(failure, secrets));
|
|
82
|
+
const error = sanitizeError(input.error, secrets);
|
|
83
|
+
return {
|
|
84
|
+
schemaVersion: 1,
|
|
85
|
+
id: randomUUID(),
|
|
86
|
+
timestamp: new Date().toISOString(),
|
|
87
|
+
source: input.source,
|
|
88
|
+
...(input.profile ? { profile: redactSensitiveText(input.profile, secrets) } : {}),
|
|
89
|
+
...(baseUrl ? { baseUrl } : {}),
|
|
90
|
+
...(diagnostics?.clientType ? { clientType: diagnostics.clientType } : {}),
|
|
91
|
+
...(diagnostics?.platformCredentialDetected === undefined
|
|
92
|
+
? {}
|
|
93
|
+
: { platformCredentialDetected: diagnostics.platformCredentialDetected }),
|
|
94
|
+
attemptedSteps: (diagnostics?.attemptedSteps || []).map((step) => redactSensitiveText(step, secrets)),
|
|
95
|
+
...(lastError ? { lastError } : {}),
|
|
96
|
+
...(failures?.length ? { failures } : {}),
|
|
97
|
+
...(input.resultSessionExpired ? { resultSessionExpired: true } : {}),
|
|
98
|
+
...(error ? { error } : {}),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Append-only persistence keeps concurrent CLI processes from overwriting one
|
|
103
|
+
* another. A logging failure is returned to the caller and must never replace
|
|
104
|
+
* the original authentication error.
|
|
105
|
+
*/
|
|
106
|
+
export async function appendXiaoEAuthErrorLog(input) {
|
|
107
|
+
const path = getXiaoEAuthErrorLogPath();
|
|
108
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
109
|
+
await chmod(dirname(path), 0o700).catch(() => undefined);
|
|
110
|
+
const entry = createEntry(input);
|
|
111
|
+
await appendFile(path, `${JSON.stringify(entry)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
112
|
+
// Existing files may have been created under a permissive umask.
|
|
113
|
+
await chmod(path, 0o600).catch(() => undefined);
|
|
114
|
+
return entry;
|
|
115
|
+
}
|
|
116
|
+
function isLogEntry(value) {
|
|
117
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
118
|
+
return false;
|
|
119
|
+
const candidate = value;
|
|
120
|
+
return candidate.schemaVersion === 1
|
|
121
|
+
&& typeof candidate.id === 'string'
|
|
122
|
+
&& typeof candidate.timestamp === 'string'
|
|
123
|
+
&& (candidate.source === 'login' || candidate.source === 'recovery')
|
|
124
|
+
&& Array.isArray(candidate.attemptedSteps);
|
|
125
|
+
}
|
|
126
|
+
export function normalizeXiaoEAuthErrorLogLimit(value) {
|
|
127
|
+
if (value === undefined || value === null || value === '')
|
|
128
|
+
return DEFAULT_LOG_LIMIT;
|
|
129
|
+
const limit = Number(value);
|
|
130
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > MAX_XIAOE_AUTH_ERROR_LOG_LIMIT) {
|
|
131
|
+
throw new RangeError(`limit must be an integer between 1 and ${MAX_XIAOE_AUTH_ERROR_LOG_LIMIT}`);
|
|
132
|
+
}
|
|
133
|
+
return limit;
|
|
134
|
+
}
|
|
135
|
+
export async function readXiaoEAuthErrorLog(limit = DEFAULT_LOG_LIMIT) {
|
|
136
|
+
const normalizedLimit = normalizeXiaoEAuthErrorLogLimit(limit);
|
|
137
|
+
const path = getXiaoEAuthErrorLogPath();
|
|
138
|
+
let content = '';
|
|
139
|
+
try {
|
|
140
|
+
content = await readFile(path, 'utf8');
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (error?.code !== 'ENOENT')
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
let invalidLines = 0;
|
|
147
|
+
const entries = [];
|
|
148
|
+
for (const line of content.split(/\r?\n/u)) {
|
|
149
|
+
if (!line.trim())
|
|
150
|
+
continue;
|
|
151
|
+
try {
|
|
152
|
+
const value = JSON.parse(line);
|
|
153
|
+
if (isLogEntry(value))
|
|
154
|
+
entries.push(value);
|
|
155
|
+
else
|
|
156
|
+
invalidLines += 1;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
invalidLines += 1;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const recent = entries.slice(-normalizedLimit).reverse();
|
|
163
|
+
return {
|
|
164
|
+
path,
|
|
165
|
+
total: entries.length,
|
|
166
|
+
returned: recent.length,
|
|
167
|
+
invalidLines,
|
|
168
|
+
entries: recent,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export async function clearXiaoEAuthErrorLog() {
|
|
172
|
+
const path = getXiaoEAuthErrorLogPath();
|
|
173
|
+
try {
|
|
174
|
+
await unlink(path);
|
|
175
|
+
return { path, cleared: true };
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (error?.code === 'ENOENT')
|
|
179
|
+
return { path, cleared: false };
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -478,7 +478,14 @@ export class E10AuthSession {
|
|
|
478
478
|
clear();
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
|
-
|
|
481
|
+
/**
|
|
482
|
+
* 三态探活:`true` 明确有效、`false` 明确失效(401/403)、`undefined` 无法判定(网络/5xx)。
|
|
483
|
+
*
|
|
484
|
+
* 为什么要和 `checkValid()` 分开:平台连接器判断"是否已登录"时,
|
|
485
|
+
* 把网络抖动当成"未登录"会逼用户重复登录;而把 401 当成"已登录"会让后续业务全失败。
|
|
486
|
+
* 未认定失效时保持乐观,明确失效才降级。
|
|
487
|
+
*/
|
|
488
|
+
async probeValid() {
|
|
482
489
|
const { signal, clear } = createTimeoutSignal(E10_TEAMS_CHECK_TIMEOUT_MS);
|
|
483
490
|
try {
|
|
484
491
|
const resp = await fetch(`${this.getBaseUrl()}/api/ecode/tree/list?parentId=0`, {
|
|
@@ -491,15 +498,22 @@ export class E10AuthSession {
|
|
|
491
498
|
redirect: 'manual',
|
|
492
499
|
signal,
|
|
493
500
|
});
|
|
494
|
-
|
|
501
|
+
if (resp.status === 200)
|
|
502
|
+
return true;
|
|
503
|
+
if (resp.status === 401 || resp.status === 403)
|
|
504
|
+
return false;
|
|
505
|
+
return undefined;
|
|
495
506
|
}
|
|
496
507
|
catch {
|
|
497
|
-
return
|
|
508
|
+
return undefined;
|
|
498
509
|
}
|
|
499
510
|
finally {
|
|
500
511
|
clear();
|
|
501
512
|
}
|
|
502
513
|
}
|
|
514
|
+
async checkValid() {
|
|
515
|
+
return (await this.probeValid()) === true;
|
|
516
|
+
}
|
|
503
517
|
async ensureValid() {
|
|
504
518
|
if (await this.checkValid())
|
|
505
519
|
return true;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isXiaoERuntimeAgent } from '../../core/runtime-agent.js';
|
|
2
2
|
import { getActiveProfile, readProfileConfig } from './auth/session.js';
|
|
3
|
+
import { appendXiaoEAuthErrorLog, xiaoEAuthLogSecrets } from './auth/error-log.js';
|
|
3
4
|
import { hasXiaoEEnv, resolveXiaoEPreferredBaseUrl, tryXiaoEUnifiedLogin, } from './auth/xiaoe.js';
|
|
4
5
|
const AUTH_REQUIRED_CODES = new Set(['-2', '401']);
|
|
5
6
|
const AUTH_REQUIRED_MARKERS = [
|
|
@@ -242,6 +243,10 @@ function recoveryLogger(ctx) {
|
|
|
242
243
|
warn: (message) => adapter.debug(message),
|
|
243
244
|
};
|
|
244
245
|
}
|
|
246
|
+
function reportAuthLogWriteFailure(ctx, error) {
|
|
247
|
+
const logger = ctx.logger;
|
|
248
|
+
logger?.debug?.(`Could not persist XiaoE auth error log: ${error instanceof Error ? error.message : String(error)}`);
|
|
249
|
+
}
|
|
245
250
|
/**
|
|
246
251
|
* Silently recover a stale or missing XiaoE session. Without a local session,
|
|
247
252
|
* current runtime evidence is required before obtaining credentials.
|
|
@@ -278,18 +283,40 @@ export async function recoverXiaoEAuthSessionWithDiagnostics(ctx, currentSession
|
|
|
278
283
|
return existing;
|
|
279
284
|
const diagnostics = { attemptedSteps: [] };
|
|
280
285
|
const recovery = (async () => {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
286
|
+
try {
|
|
287
|
+
const login = await tryXiaoEUnifiedLogin({
|
|
288
|
+
env: ctx.env,
|
|
289
|
+
baseUrl,
|
|
290
|
+
profileBaseUrl: baseUrl,
|
|
291
|
+
allowBundledEnvScript: true,
|
|
292
|
+
allowTokenScript: true,
|
|
293
|
+
tenantKeyFallback: currentSession?.tenantKey || config.tenantKey,
|
|
294
|
+
profileHint: profile,
|
|
295
|
+
diagnostics,
|
|
296
|
+
logger: recoveryLogger(ctx),
|
|
297
|
+
});
|
|
298
|
+
if (!login) {
|
|
299
|
+
await appendXiaoEAuthErrorLog({
|
|
300
|
+
source: 'recovery',
|
|
301
|
+
profile,
|
|
302
|
+
baseUrl,
|
|
303
|
+
diagnostics,
|
|
304
|
+
secrets: xiaoEAuthLogSecrets(ctx.env),
|
|
305
|
+
}).catch((error) => reportAuthLogWriteFailure(ctx, error));
|
|
306
|
+
}
|
|
307
|
+
return { session: login?.session || null, diagnostics };
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
await appendXiaoEAuthErrorLog({
|
|
311
|
+
source: 'recovery',
|
|
312
|
+
profile,
|
|
313
|
+
baseUrl,
|
|
314
|
+
diagnostics,
|
|
315
|
+
error,
|
|
316
|
+
secrets: xiaoEAuthLogSecrets(ctx.env),
|
|
317
|
+
}).catch((logError) => reportAuthLogWriteFailure(ctx, logError));
|
|
318
|
+
throw error;
|
|
319
|
+
}
|
|
293
320
|
})();
|
|
294
321
|
recoveryInFlight.set(key, recovery);
|
|
295
322
|
try {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CliError, ExitCode } from '../../core/errors.js';
|
|
2
2
|
import { E10_AUTH_REQUIRED_MESSAGE, E10_XIAOE_HOST_CREDENTIAL_MISSING_MESSAGE, E10_XIAOE_NETWORK_UNAVAILABLE_MESSAGE, E10_XIAOE_RECOVERY_FAILED_MESSAGE, } from './auth/messages.js';
|
|
3
3
|
import { lastXiaoEFailure, summarizeXiaoEFailureKind, } from './auth/xiaoe.js';
|
|
4
|
-
import {
|
|
4
|
+
import { appendXiaoEAuthErrorLog, xiaoEAuthLogSecrets } from './auth/error-log.js';
|
|
5
|
+
import { E10AuthSession, getActiveProfile } from './auth/session.js';
|
|
5
6
|
import { E10ApiClient } from './client.js';
|
|
6
7
|
import { canAutomaticallyRecoverXiaoE, recoverXiaoEAuthSession, recoverXiaoEAuthSessionWithDiagnostics, } from './auth-recovery.js';
|
|
7
8
|
/**
|
|
@@ -57,12 +58,26 @@ export async function getE10Session(ctx, load = {}) {
|
|
|
57
58
|
return E10AuthSession.fromOptions(options, ctx.cwd, load);
|
|
58
59
|
}
|
|
59
60
|
export async function requireE10Session(ctx, load = {}) {
|
|
61
|
+
const options = ctx.getGlobalOptions();
|
|
60
62
|
let session = await getE10Session(ctx, load);
|
|
61
63
|
if (session?.isExpired() && canAutomaticallyRecoverXiaoE(ctx, session)) {
|
|
62
64
|
const outcome = await recoverXiaoEAuthSessionWithDiagnostics(ctx, session).catch(() => null);
|
|
63
65
|
session = outcome?.session || null;
|
|
64
66
|
if (!session || session.isExpired()) {
|
|
65
|
-
|
|
67
|
+
const resultSessionExpired = session?.isExpired() === true;
|
|
68
|
+
const error = xiaoERecoveryFailedError(outcome?.diagnostics, resultSessionExpired);
|
|
69
|
+
if (resultSessionExpired) {
|
|
70
|
+
await appendXiaoEAuthErrorLog({
|
|
71
|
+
source: 'recovery',
|
|
72
|
+
profile: options.profile || getActiveProfile(),
|
|
73
|
+
baseUrl: session?.getBaseUrl(),
|
|
74
|
+
diagnostics: outcome?.diagnostics,
|
|
75
|
+
resultSessionExpired: true,
|
|
76
|
+
error,
|
|
77
|
+
secrets: xiaoEAuthLogSecrets(ctx.env),
|
|
78
|
+
}).catch(() => undefined);
|
|
79
|
+
}
|
|
80
|
+
throw error;
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
83
|
if (!session && canAutomaticallyRecoverXiaoE(ctx)) {
|
|
@@ -272,6 +272,14 @@ function writeProductMetadata(target, productContent) {
|
|
|
272
272
|
return;
|
|
273
273
|
writeFileSync(resolve(target, 'product.json'), productContent, 'utf8');
|
|
274
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* 拷贝白名单:整目录复制,只剔除本地依赖与系统垃圾。
|
|
277
|
+
*
|
|
278
|
+
* 历史实现把 `scripts/` 与 `assets/` 一并排除,导致带资产的技能装出来是残缺的——
|
|
279
|
+
* reception 缺 `scripts/render.py` 与 `assets/行程单模板-泛微.docx` 会直接跑不出 docx,
|
|
280
|
+
* builder 缺 `assets/dom-structure/` 也少一半能力。
|
|
281
|
+
* 技能包是受控的内部产物,资产就应当随包分发,因此只保留 node_modules 这一条硬排除。
|
|
282
|
+
*/
|
|
275
283
|
function shouldCopy(entry, sourceRoot, skipSkillProduct) {
|
|
276
284
|
const relativePath = relative(sourceRoot, entry);
|
|
277
285
|
const name = basename(entry);
|
|
@@ -282,7 +290,7 @@ function shouldCopy(entry, sourceRoot, skipSkillProduct) {
|
|
|
282
290
|
if (name === '.DS_Store' || name.startsWith('.'))
|
|
283
291
|
return false;
|
|
284
292
|
const parts = relativePath.split(sep);
|
|
285
|
-
return !parts.includes('node_modules')
|
|
293
|
+
return !parts.includes('node_modules');
|
|
286
294
|
}
|
|
287
295
|
function countFiles(root) {
|
|
288
296
|
let count = 0;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CONTINUATION_TTL_MS } from '../../core/continuation-ttl.js';
|
|
1
2
|
import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
3
|
import { existsSync } from 'node:fs';
|
|
3
4
|
import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
@@ -35,7 +36,7 @@ function signature(payload, key) {
|
|
|
35
36
|
}
|
|
36
37
|
export function createArchiveContinuationSigner(ctx) {
|
|
37
38
|
return {
|
|
38
|
-
async issue(payload, ttlMs =
|
|
39
|
+
async issue(payload, ttlMs = CONTINUATION_TTL_MS) {
|
|
39
40
|
const issuedAt = Date.now();
|
|
40
41
|
const body = encode({ ...payload, issuedAt, expiresAt: issuedAt + ttlMs });
|
|
41
42
|
const sig = signature(body, await loadKey(ctx));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { ExitCode, isCliError, toErrorEnvelope } from '../../core/errors.js';
|
|
4
|
+
import { reportPlatformError } from '../../core/error-codes.js';
|
|
4
5
|
import { formatSearchCard, formatSearchHtml, formatSearchText } from './render/search-format.js';
|
|
5
6
|
import { createArchiveContinuationSigner } from './continuation.js';
|
|
6
7
|
import { createArchiveHost } from './host.js';
|
|
@@ -99,6 +100,7 @@ async function executeAndPrint(ctx, operation, input) {
|
|
|
99
100
|
ctx.output.write(successEnvelope(result), { json: true });
|
|
100
101
|
}
|
|
101
102
|
catch (error) {
|
|
103
|
+
reportPlatformError(error);
|
|
102
104
|
console.error(JSON.stringify(failureEnvelope(error), null, 2));
|
|
103
105
|
process.exitCode = isCliError(error) ? error.exitCode : ExitCode.GeneralError;
|
|
104
106
|
}
|
|
@@ -140,6 +142,7 @@ async function executeSearchPrint(ctx, input, format, outputPath) {
|
|
|
140
142
|
ctx.output.raw(formatSearchText(rows, meta));
|
|
141
143
|
}
|
|
142
144
|
catch (error) {
|
|
145
|
+
reportPlatformError(error);
|
|
143
146
|
console.error(JSON.stringify(failureEnvelope(error), null, 2));
|
|
144
147
|
process.exitCode = isCliError(error) ? error.exitCode : ExitCode.GeneralError;
|
|
145
148
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CONTINUATION_TTL_MS } from '../../../core/continuation-ttl.js';
|
|
1
2
|
import { archiveConfirmationError, archiveValidationError } from '../errors.js';
|
|
2
3
|
/** apply 类写操作必须显式确认。 */
|
|
3
4
|
export function requireConfirm(args, action) {
|
|
@@ -11,7 +12,7 @@ export function requireConfirm(args, action) {
|
|
|
11
12
|
* prepare 阶段签发 continuation。
|
|
12
13
|
* 环境指纹(baseUrl + 登录账号)写进票据,apply 时校验,避免跨环境/跨账号复用。
|
|
13
14
|
*/
|
|
14
|
-
export async function issueLease(env, action, payload, ttlMs =
|
|
15
|
+
export async function issueLease(env, action, payload, ttlMs = CONTINUATION_TTL_MS) {
|
|
15
16
|
const session = await env.host.getSession();
|
|
16
17
|
const continuation = await env.continuation.issue({
|
|
17
18
|
operation: action,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CONTINUATION_TTL_MS } from '../../core/continuation-ttl.js';
|
|
1
2
|
import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
3
|
import { existsSync } from 'node:fs';
|
|
3
4
|
import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
@@ -35,7 +36,7 @@ function signature(payload, key) {
|
|
|
35
36
|
}
|
|
36
37
|
export function createArchiveOaContinuationSigner(ctx) {
|
|
37
38
|
return {
|
|
38
|
-
async issue(payload, ttlMs =
|
|
39
|
+
async issue(payload, ttlMs = CONTINUATION_TTL_MS) {
|
|
39
40
|
const issuedAt = Date.now();
|
|
40
41
|
const body = encode({ ...payload, issuedAt, expiresAt: issuedAt + ttlMs });
|
|
41
42
|
const sig = signature(body, await loadKey(ctx));
|