chainlesschain 0.162.12 → 0.162.13
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 +30 -25
- package/package.json +4 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-C3TDNq29.js → AIOps-Bq_zxhCr.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C9fE18pE.js → ActionButton-CaevDm9t.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-wnZF602C.js → Analytics-B0gOmwPw.js} +1 -1
- package/src/assets/web-panel/assets/{AppLayout-BjgTMK7O.js → AppLayout-DWhZiV0Q.js} +2 -2
- package/src/assets/web-panel/assets/{Audit-BBL0BW5_.js → Audit-ZuZJBCxo.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BKLqYCWU.js → Backup-CX7jhH5l.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BGSzMCZs.js → BaseInput-CVLx7HVq.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CQWzZWEY.js → Chat-C6yL5tRD.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-BkTri12Q.js → Checkbox-BePhbqVq.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BH1m09EO.js → Codegen-B5E4x1Lm.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BXnBuqIa.js → Col-CWhNU6A7.js} +1 -1
- package/src/assets/web-panel/assets/{Community-C_Nr4XCx.js → Community-mSEAuJhp.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Du6GwLrj.js → Compact-DSudHzX3.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-66M0oi1Q.js → Compliance-CxJLYjyn.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DQrkZRNd.js → Cowork-C-trppQj.js} +1 -1
- package/src/assets/web-panel/assets/{Cron-CwdIFH_v.js → Cron-_Ij4v5fY.js} +1 -1
- package/src/assets/web-panel/assets/{Crosschain-DqlcrQ9L.js → Crosschain-eLHXzp5T.js} +1 -1
- package/src/assets/web-panel/assets/{DID-OmPLKf7L.js → DID-BP04AUUB.js} +1 -1
- package/src/assets/web-panel/assets/{Dashboard-D_dampTL.js → Dashboard-CzEeQv62.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CA1W7jAn.js → Dropdown-C_SGOB22.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Chlk9a7s.js → Federation-BgaP4BOv.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-t0UqYFLq.js → FormItemContext-BxGLLt9r.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CEq0raYm.js → Git-Bt_uM_Gw.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-C06CX7Ge.js → Governance-N2-0RG_o.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-6VIFHxIP.js → Inference-eS3g-CzP.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BCJPjMBQ.js → KnowledgeGraph-CUuvNVah.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BBpOYFct.js → Logs-wPbwEt2r.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BFH6jMWt.js → Marketplace-DH91kTwo.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-uCFvRqGs.js → McpTools-D-GyyBrI.js} +1 -1
- package/src/assets/web-panel/assets/{Memory-B0Kux_KT.js → Memory-BOtUy-tw.js} +1 -1
- package/src/assets/web-panel/assets/{MobileBridge-DHow2jiK.js → MobileBridge-DIP__XQd.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BFo9YQZp.js → MobileProjects-1nqr1UsU.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-riOh1G_F.js → Mtc-CCE0x7h2.js} +1 -1
- package/src/assets/web-panel/assets/{MtcAudit-Bm-hE2SP.js → MtcAudit-BBkz0XUO.js} +1 -1
- package/src/assets/web-panel/assets/{Multisig-DfUQxh5a.js → Multisig-CIKSJvTY.js} +2 -2
- package/src/assets/web-panel/assets/{NLProgramming-DuNvLBEq.js → NLProgramming-BDkgeFcq.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DB20wd3c.js → Notes-ONiUxfN1.js} +1 -1
- package/src/assets/web-panel/assets/{NotificationSettings-CB-GkOWR.js → NotificationSettings-CGcyKEIe.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-3bU7PZuG.js → Organization-BZtMYBJt.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BGCPP_0Y.js → Overflow-C4LfFZAI.js} +1 -1
- package/src/assets/web-panel/assets/{OverrideContext-x9ZzjLwk.js → OverrideContext-C_4H9tGA.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BHgAe1oC.js → P2P-D71Cpk-m.js} +1 -1
- package/src/assets/web-panel/assets/{Permissions-BuOD4xwc.js → Permissions-DRGYF29v.js} +1 -1
- package/src/assets/web-panel/assets/PersonalDataHub-CfRYoIua.js +1 -0
- package/src/assets/web-panel/assets/PersonalDataHub-Dvaa8niQ.css +1 -0
- package/src/assets/web-panel/assets/{Pipeline-DBS5U4LB.js → Pipeline-BOyp0_Qo.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-UNjIc5El.js → Privacy-a_AcphvF.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CicqCJGy.js → ProjectInit-CFu1grYt.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectSettings-CIxAbt4Y.js → ProjectSettings-p54Eivhh.js} +1 -1
- package/src/assets/web-panel/assets/{Projects-BJycZScO.js → Projects-DkB88XAu.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DxXvprme.js → Providers-EK7f8DEd.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-rrqjU8_Y.js → QuickAsk-CpO0w3iP.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BEwHMhI7.js → Recommend-BUJVQdv9.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-DoVKCCMn.js → Reputation-kU2fOuZt.js} +1 -1
- package/src/assets/web-panel/assets/{Row-F5XcDhHr.js → Row-oGWRbk6g.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-cZrRG7k8.js → RssFeed-saC_46Yo.js} +1 -1
- package/src/assets/web-panel/assets/{Search-B9ctZjqx.js → Search-CjtRqFUu.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Z62hl1mc.js → Security-BX0NBVfQ.js} +1 -1
- package/src/assets/web-panel/assets/{Services-CQf5XqgZ.js → Services-Bgxsnei_.js} +1 -1
- package/src/assets/web-panel/assets/{Skeleton-DuCKw2Eh.js → Skeleton-CwBb3k2a.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-qVkhva0s.js → Skills-CZCMYH6Z.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BQbatr7s.js → Sla-Djy1uHnZ.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DLFBzAgD.js → SpeechSettings-CGUI_Uyh.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CrzETZMW.js → SyncSettings-DK2CKHRD.js} +1 -1
- package/src/assets/web-panel/assets/{Tasks-D_EQ1nJ7.js → Tasks-BKiOzeIO.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D4y-dGRc.js → Templates-CnQpleXj.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-2XI0jkPn.js → Tenant-DwKz0cjm.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-fUi5V2Z9.js → Terminal-A7t_wsR8.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BuUNB2mg.js → Tokens-BqYY9l44.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-7DqLLuej.js → Trigger-BI4bXFmi.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CeACvTYx.js → Trust-yMynKTRG.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-mDP9EXHq.js → UkeySign-Br4IScM6.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-veWlKclv.js → VideoEditing-CWcThGsP.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Cd2Hheb8.js → Wallet-CZcAtjxj.js} +1 -1
- package/src/assets/web-panel/assets/{WebAuthn-DyL7ZiHX.js → WebAuthn-BnTZFMA0.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-C7-7LJH9.js → WorkflowEditor-N7gGz3_n.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DXomZMuo.js → chat-D175ZIO0.js} +1 -1
- package/src/assets/web-panel/assets/{collapseMotion-CjFH_Jop.js → collapseMotion-DfnRZex1.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DlU92QNs.js → colors-LKhZyttv.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-sBiTL8mX.js → compact-item-CsJSebxT.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DZXEnzum.js → createContext-BJ_CPYFC.js} +1 -1
- package/src/assets/web-panel/assets/{echarts-Bq-n0MtJ.js → echarts-Dj_pBaVI.js} +1 -1
- package/src/assets/web-panel/assets/{hasIn-CpCHBZ2M.js → hasIn-CzD3IqH8.js} +1 -1
- package/src/assets/web-panel/assets/{icons-CLQTHa5-.js → icons-BOPtEWK4.js} +4 -4
- package/src/assets/web-panel/assets/{index-ClN_JuFa.js → index-6qPbrYF7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDyzZ8_O.js → index-B7UYymse.js} +1 -1
- package/src/assets/web-panel/assets/{index-C52udT0_.js → index-BDSZDDb2.js} +4 -4
- package/src/assets/web-panel/assets/{index-s8tvk-fF.js → index-BEDFHKO3.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_IgY63-.js → index-BMvdoiFr.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dyg6ikIL.js → index-BNVLVzN5.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0Qbxr57.js → index-BSNibAqz.js} +1 -1
- package/src/assets/web-panel/assets/{index-DeGnHcp5.js → index-BV-__mlC.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_-RETt0.js → index-BXH9ujMW.js} +1 -1
- package/src/assets/web-panel/assets/{index-XI6772AD.js → index-BZluCuTH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqnhEJls.js → index-BhiZDGg7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BK2AFy44.js → index-BjOrt4vw.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dn8m1d1f.js → index-BmJdof_c.js} +2 -2
- package/src/assets/web-panel/assets/{index-C6SDf50u.js → index-BsirlkJ0.js} +1 -1
- package/src/assets/web-panel/assets/{index-CD3iljXs.js → index-BvF2tC6C.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJ7XYa5K.js → index-C2HBKw07.js} +1 -1
- package/src/assets/web-panel/assets/{index-_zyXBoS7.js → index-CKjBAdm0.js} +1 -1
- package/src/assets/web-panel/assets/{index-X48zYgZ6.js → index-CRGNuUIM.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dj9Nvz6S.js → index-CTIkCKav.js} +1 -1
- package/src/assets/web-panel/assets/index-CY1mQA2I.js +1 -0
- package/src/assets/web-panel/assets/{index-C59FgSkU.js → index-CyHdYUeZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B23tuoo9.js → index-D401L3yx.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKe9jmKG.js → index-D5IZCkZG.js} +1 -1
- package/src/assets/web-panel/assets/{index-F9cBucYf.js → index-D7ZcBI5s.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjXSvceY.js → index-D8kltMTW.js} +1 -1
- package/src/assets/web-panel/assets/index-D9nXHfUB.js +1 -0
- package/src/assets/web-panel/assets/{index-Dq5Rn5VS.js → index-DJVkBmSc.js} +1 -1
- package/src/assets/web-panel/assets/{index-ibFHnqHz.js → index-DM3uBEWD.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChahjdYE.js → index-DOO73rHE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CivbS-57.js → index-DXp1jVsK.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3k9UPHc.js → index-Dd7dICwB.js} +1 -1
- package/src/assets/web-panel/assets/{index-Di1_EQ-X.js → index-Dm-3kvtD.js} +1 -1
- package/src/assets/web-panel/assets/{index-DygNvCeR.js → index-DnPt5OdD.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_MzScPM.js → index-E7t1hAnk.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUe5t5Aa.js → index-JTX9A7w0.js} +1 -1
- package/src/assets/web-panel/assets/{index-CwbWZubA.js → index-Kn-Of5ew.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUlPMzoM.js → index-R1cFADfk.js} +1 -1
- package/src/assets/web-panel/assets/{index-TwQZkVGh.js → index-RIO4JKMP.js} +1 -1
- package/src/assets/web-panel/assets/{index-ThrAiEF9.js → index-uTEVWPYA.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DEi92ZnZ.js → initDefaultProps-CBW0okek.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BtYKzpOc.js → motion-DGAffQ0Z.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cb3A1-v-.js → move-DFJ0-5IW.js} +1 -1
- package/src/assets/web-panel/assets/{omit-B6qPDdOf.js → omit-AvrDghg1.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DDyeQMUc.js → pickAttrs-D7csw9i1.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BPV6VO47.js → placementArrow-hZ6Lg6kG.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DJ1ra4dT.js → responsiveObserve-DLLx5VvS.js} +1 -1
- package/src/assets/web-panel/assets/{slide-D6v8tHvB.js → slide-BaRIT3ev.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DulKcQLZ.js → statusUtils-Cdjyuhrz.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Bne7zwMt.js → styleChecker-CbrNybTt.js} +1 -1
- package/src/assets/web-panel/assets/useFlexGapSupport-B8gAhiRC.js +1 -0
- package/src/assets/web-panel/assets/{useFs-CR-iLa4Z.js → useFs-BZPy4ICP.js} +1 -1
- package/src/assets/web-panel/assets/{useMergedState-O7QXt4P5.js → useMergedState-WwedrFR0.js} +1 -1
- package/src/assets/web-panel/assets/{useRefs-0J6m8UWN.js → useRefs-Cdq8EWeF.js} +1 -1
- package/src/assets/web-panel/assets/{useState-CSzR8F8O.js → useState-DGS1NOyn.js} +1 -1
- package/src/assets/web-panel/assets/{vendor-M5lGV-wr.js → vendor-DhFY8mDK.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-yL9axxBy.js → vnode-6Y0NDMVv.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-B-VCMXSD.js → zoom-DTbMGsSH.js} +1 -1
- package/src/assets/web-panel/index.html +3 -3
- package/src/commands/__tests__/hub-aichat.test.js +277 -0
- package/src/commands/__tests__/hub-wechat.test.js +243 -0
- package/src/commands/hub.js +417 -0
- package/src/commands/sync-providers.js +436 -0
- package/src/gateways/ws/personal-data-hub-protocol.js +68 -0
- package/src/index.js +4 -0
- package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +209 -0
- package/src/lib/__tests__/sync-credentials.test.js +265 -0
- package/src/lib/__tests__/sync-engine-cli.test.js +293 -0
- package/src/lib/personal-data-hub-aichat-wizard.js +242 -0
- package/src/lib/personal-data-hub-wiring.js +189 -0
- package/src/lib/sync-cli-db.js +194 -0
- package/src/lib/sync-credentials.js +225 -0
- package/src/lib/sync-engine-cli.js +406 -0
- package/src/lib/sync-oss-client.js +273 -0
- package/src/lib/sync-webdav-client.js +194 -0
- package/src/assets/web-panel/assets/PersonalDataHub--WA-aZAJ.js +0 -1
- package/src/assets/web-panel/assets/PersonalDataHub-BK7I0Rsb.css +0 -1
- package/src/assets/web-panel/assets/index-CcRX6BlT.js +0 -1
- package/src/assets/web-panel/assets/index-z6h6tqP3.js +0 -1
- package/src/assets/web-panel/assets/useFlexGapSupport-C1miTomM.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{K as o}from"./index-
|
|
1
|
+
import{K as o}from"./index-BDSZDDb2.js";import{i as f}from"./motion-DGAffQ0Z.js";const c=new o("antZoomIn",{"0%":{transform:"scale(0.2)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),y=new o("antZoomOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.2)",opacity:0}}),a=new o("antZoomBigIn",{"0%":{transform:"scale(0.8)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),s=new o("antZoomBigOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.8)",opacity:0}}),g=new o("antZoomUpIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 0%"}}),O=new o("antZoomUpOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 0%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0}}),l=new o("antZoomLeftIn",{"0%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"0% 50%"}}),u=new o("antZoomLeftOut",{"0%":{transform:"scale(1)",transformOrigin:"0% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0}}),p=new o("antZoomRightIn",{"0%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"100% 50%"}}),z=new o("antZoomRightOut",{"0%":{transform:"scale(1)",transformOrigin:"100% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0}}),K=new o("antZoomDownIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 100%"}}),w=new o("antZoomDownOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 100%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0}}),I={zoom:{inKeyframes:c,outKeyframes:y},"zoom-big":{inKeyframes:a,outKeyframes:s},"zoom-big-fast":{inKeyframes:a,outKeyframes:s},"zoom-left":{inKeyframes:l,outKeyframes:u},"zoom-right":{inKeyframes:p,outKeyframes:z},"zoom-up":{inKeyframes:g,outKeyframes:O},"zoom-down":{inKeyframes:K,outKeyframes:w}},h=(n,r)=>{const{antCls:m}=n,t=`${m}-${r}`,{inKeyframes:i,outKeyframes:e}=I[r];return[f(t,i,e,r==="zoom-big-fast"?n.motionDurationFast:n.motionDurationMid),{[`
|
|
2
2
|
${t}-enter,
|
|
3
3
|
${t}-appear
|
|
4
4
|
`]:{transform:"scale(0)",opacity:0,animationTimingFunction:n.motionEaseOutCirc,"&-prepare":{transform:"none"}},[`${t}-leave`]:{animationTimingFunction:n.motionEaseInOutCirc}}]};export{h as i,c as z};
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
// Injected by web-ui-server.js at serve time
|
|
9
9
|
window.__CC_CONFIG__ = __CC_CONFIG_PLACEHOLDER__;
|
|
10
10
|
</script>
|
|
11
|
-
<script type="module" crossorigin src="./assets/index-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="./assets/vendor-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="./assets/icons-
|
|
11
|
+
<script type="module" crossorigin src="./assets/index-BDSZDDb2.js"></script>
|
|
12
|
+
<link rel="modulepreload" crossorigin href="./assets/vendor-DhFY8mDK.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="./assets/icons-BOPtEWK4.js">
|
|
14
14
|
<link rel="stylesheet" crossorigin href="./assets/index-CfX1DEtk.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cc hub aichat <verb> CLI command unit tests (Phase 10.3.6 CLI surface).
|
|
3
|
+
*
|
|
4
|
+
* The command handlers accept `_wizard` / `_getHub` / `_factoryDeps` test
|
|
5
|
+
* seams so this suite never starts a real hub or fs. We invoke the handler
|
|
6
|
+
* functions directly via the `_internal` export.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
|
|
10
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
|
|
14
|
+
import { _internal } from "../hub.js";
|
|
15
|
+
|
|
16
|
+
let logSpy, errSpy, exitSpy;
|
|
17
|
+
|
|
18
|
+
function fakeWizard(overrides = {}) {
|
|
19
|
+
return {
|
|
20
|
+
openVendorLogin: vi.fn(async ({ vendor }) => ({
|
|
21
|
+
ok: true,
|
|
22
|
+
vendor,
|
|
23
|
+
fallbackMode: "paste",
|
|
24
|
+
loginUrl: "https://" + vendor + ".example/",
|
|
25
|
+
requiredCookies: ["theToken"],
|
|
26
|
+
helpText: "登录 " + vendor,
|
|
27
|
+
...overrides.openVendorLogin,
|
|
28
|
+
})),
|
|
29
|
+
probeCookies: vi.fn(async ({ vendor, cookieHeader }) => ({
|
|
30
|
+
ok: cookieHeader && cookieHeader.includes("theToken="),
|
|
31
|
+
source: "paste",
|
|
32
|
+
vendor,
|
|
33
|
+
cookies: { theToken: "v" },
|
|
34
|
+
foundRequired:
|
|
35
|
+
cookieHeader && cookieHeader.includes("theToken=") ? ["theToken"] : [],
|
|
36
|
+
missingRequired:
|
|
37
|
+
cookieHeader && cookieHeader.includes("theToken=") ? [] : ["theToken"],
|
|
38
|
+
foundOptional: [],
|
|
39
|
+
...overrides.probeCookies,
|
|
40
|
+
})),
|
|
41
|
+
registerVendor: vi.fn(async ({ vendor, cookies }) => {
|
|
42
|
+
if (!cookies || !cookies.includes("theToken=")) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
reason: "REQUIRED_COOKIES_MISSING",
|
|
46
|
+
missingRequired: ["theToken"],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return { ok: true, vendor, accountId: `${vendor}:u1` };
|
|
50
|
+
}),
|
|
51
|
+
rotateLoginPartition: vi.fn(async () => ({ ok: true })),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
57
|
+
errSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
58
|
+
exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => {
|
|
59
|
+
throw new Error("process.exit called");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
afterEach(() => {
|
|
64
|
+
logSpy.mockRestore();
|
|
65
|
+
errSpy.mockRestore();
|
|
66
|
+
exitSpy.mockRestore();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ─── cmdAIChatList ────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
describe("cc hub aichat list", () => {
|
|
72
|
+
it("prints all 9 default vendors with login URLs (text mode)", async () => {
|
|
73
|
+
const wiz = fakeWizard();
|
|
74
|
+
await _internal.cmdAIChatList({ _wizard: wiz });
|
|
75
|
+
expect(wiz.openVendorLogin).toHaveBeenCalledTimes(9);
|
|
76
|
+
const calledVendors = wiz.openVendorLogin.mock.calls.map(
|
|
77
|
+
(c) => c[0].vendor,
|
|
78
|
+
);
|
|
79
|
+
expect(calledVendors).toEqual(_internal._defaultKnownVendors());
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("emits JSON with --json including the vendor array", async () => {
|
|
83
|
+
const wiz = fakeWizard();
|
|
84
|
+
await _internal.cmdAIChatList({ _wizard: wiz, json: true });
|
|
85
|
+
const printed = logSpy.mock.calls.map((c) => c[0]).join("\n");
|
|
86
|
+
const parsed = JSON.parse(printed);
|
|
87
|
+
expect(parsed.vendors.length).toBe(9);
|
|
88
|
+
expect(parsed.vendors[0]).toHaveProperty("vendor");
|
|
89
|
+
expect(parsed.vendors[0]).toHaveProperty("loginUrl");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("restricts to a custom vendor list via _knownVendors", async () => {
|
|
93
|
+
const wiz = fakeWizard();
|
|
94
|
+
await _internal.cmdAIChatList({
|
|
95
|
+
_wizard: wiz,
|
|
96
|
+
_knownVendors: ["kimi", "doubao"],
|
|
97
|
+
});
|
|
98
|
+
expect(wiz.openVendorLogin).toHaveBeenCalledTimes(2);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// ─── cmdAIChatLogin ───────────────────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
describe("cc hub aichat login <vendor>", () => {
|
|
105
|
+
it("prints loginUrl + helpText for the given vendor", async () => {
|
|
106
|
+
const wiz = fakeWizard();
|
|
107
|
+
await _internal.cmdAIChatLogin("deepseek", { _wizard: wiz });
|
|
108
|
+
expect(wiz.openVendorLogin).toHaveBeenCalledWith({ vendor: "deepseek" });
|
|
109
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
110
|
+
expect(out).toMatch(/deepseek\.example/);
|
|
111
|
+
expect(out).toMatch(/登录 deepseek/);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("--json passes the wizard return shape verbatim", async () => {
|
|
115
|
+
const wiz = fakeWizard();
|
|
116
|
+
await _internal.cmdAIChatLogin("kimi", { _wizard: wiz, json: true });
|
|
117
|
+
const printed = logSpy.mock.calls.map((c) => c[0]).join("\n");
|
|
118
|
+
const parsed = JSON.parse(printed);
|
|
119
|
+
expect(parsed.ok).toBe(true);
|
|
120
|
+
expect(parsed.fallbackMode).toBe("paste");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("exits with code 1 when wizard returns ok=false", async () => {
|
|
124
|
+
const wiz = fakeWizard({
|
|
125
|
+
openVendorLogin: { ok: false, reason: "UNKNOWN_VENDOR" },
|
|
126
|
+
});
|
|
127
|
+
await expect(
|
|
128
|
+
_internal.cmdAIChatLogin("ghost", { _wizard: wiz }),
|
|
129
|
+
).rejects.toThrow(/process.exit/);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// ─── cmdAIChatProbe ───────────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
describe("cc hub aichat probe <vendor> --cookies", () => {
|
|
136
|
+
it("ok when --cookies contains required token", async () => {
|
|
137
|
+
const wiz = fakeWizard();
|
|
138
|
+
await _internal.cmdAIChatProbe("deepseek", {
|
|
139
|
+
_wizard: wiz,
|
|
140
|
+
cookies: "theToken=abc; other=1",
|
|
141
|
+
});
|
|
142
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
143
|
+
expect(out).toMatch(/cookies look valid/);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("exits 1 with reason when required missing", async () => {
|
|
147
|
+
const wiz = fakeWizard();
|
|
148
|
+
await expect(
|
|
149
|
+
_internal.cmdAIChatProbe("deepseek", { _wizard: wiz, cookies: "junk=x" }),
|
|
150
|
+
).rejects.toThrow(/process.exit/);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("throws when --cookies omitted", async () => {
|
|
154
|
+
const wiz = fakeWizard();
|
|
155
|
+
await expect(
|
|
156
|
+
_internal.cmdAIChatProbe("deepseek", { _wizard: wiz }),
|
|
157
|
+
).rejects.toThrow(/process.exit/);
|
|
158
|
+
expect(errSpy).toHaveBeenCalled();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// ─── cmdAIChatRegister ────────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
describe("cc hub aichat register <vendor> --cookies", () => {
|
|
165
|
+
it("happy path: prints confirmation with accountId", async () => {
|
|
166
|
+
const wiz = fakeWizard();
|
|
167
|
+
await _internal.cmdAIChatRegister("doubao", {
|
|
168
|
+
_wizard: wiz,
|
|
169
|
+
cookies: "theToken=abc",
|
|
170
|
+
});
|
|
171
|
+
expect(wiz.registerVendor).toHaveBeenCalledWith({
|
|
172
|
+
vendor: "doubao",
|
|
173
|
+
cookies: "theToken=abc",
|
|
174
|
+
});
|
|
175
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
176
|
+
expect(out).toMatch(/registered doubao/);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("exits 1 when required cookies missing", async () => {
|
|
180
|
+
const wiz = fakeWizard();
|
|
181
|
+
await expect(
|
|
182
|
+
_internal.cmdAIChatRegister("doubao", {
|
|
183
|
+
_wizard: wiz,
|
|
184
|
+
cookies: "junk=1",
|
|
185
|
+
}),
|
|
186
|
+
).rejects.toThrow(/process.exit/);
|
|
187
|
+
const errs = errSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
188
|
+
expect(errs).toMatch(/REQUIRED_COOKIES_MISSING/);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// ─── cmdAIChatHealth ──────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
describe("cc hub aichat health", () => {
|
|
195
|
+
let hubDir;
|
|
196
|
+
beforeEach(() => {
|
|
197
|
+
hubDir = mkdtempSync(join(tmpdir(), "aichat-cli-health-"));
|
|
198
|
+
});
|
|
199
|
+
afterEach(() => rmSync(hubDir, { recursive: true, force: true }));
|
|
200
|
+
|
|
201
|
+
it("returns zero counts on an empty accounts store", async () => {
|
|
202
|
+
const accountsStore = {
|
|
203
|
+
list: async () => [],
|
|
204
|
+
put: async () => {},
|
|
205
|
+
get: async () => null,
|
|
206
|
+
delete: async () => {},
|
|
207
|
+
};
|
|
208
|
+
const vendorAdapter = { registerVendor: async () => ({ ok: true }) };
|
|
209
|
+
await _internal.cmdAIChatHealth({
|
|
210
|
+
json: true,
|
|
211
|
+
_factoryDeps: { hubDir, accountsStore, vendorAdapter },
|
|
212
|
+
});
|
|
213
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
214
|
+
const parsed = JSON.parse(out);
|
|
215
|
+
expect(parsed).toMatchObject({ checked: 0, ok: 0, failed: 0, mismatch: 0 });
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("text output summarises checked / ok / failed / mismatch", async () => {
|
|
219
|
+
const accountsStore = {
|
|
220
|
+
list: async () => [
|
|
221
|
+
{ vendor: "deepseek", cookies: { x: "y" }, cookieSpecVersion: 1 },
|
|
222
|
+
],
|
|
223
|
+
put: async () => {},
|
|
224
|
+
get: async () => null,
|
|
225
|
+
delete: async () => {},
|
|
226
|
+
};
|
|
227
|
+
const vendorAdapter = { registerVendor: async () => ({ ok: true }) };
|
|
228
|
+
await _internal.cmdAIChatHealth({
|
|
229
|
+
_factoryDeps: { hubDir, accountsStore, vendorAdapter },
|
|
230
|
+
});
|
|
231
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
232
|
+
expect(out).toMatch(/checked=1/);
|
|
233
|
+
expect(out).toMatch(/ok=1/);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// ─── cmdAIChatUnregister ──────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
describe("cc hub aichat unregister <vendor>", () => {
|
|
240
|
+
let hubDir;
|
|
241
|
+
beforeEach(() => {
|
|
242
|
+
hubDir = mkdtempSync(join(tmpdir(), "aichat-cli-unreg-"));
|
|
243
|
+
});
|
|
244
|
+
afterEach(() => rmSync(hubDir, { recursive: true, force: true }));
|
|
245
|
+
|
|
246
|
+
it("removes a registered vendor", async () => {
|
|
247
|
+
const store = new Map([["deepseek", { vendor: "deepseek" }]]);
|
|
248
|
+
const accountsStore = {
|
|
249
|
+
list: async () => Array.from(store.values()),
|
|
250
|
+
get: async (v) => store.get(v) || null,
|
|
251
|
+
put: async (v, e) => store.set(v, e),
|
|
252
|
+
delete: async (v) => store.delete(v),
|
|
253
|
+
};
|
|
254
|
+
await _internal.cmdAIChatUnregister("deepseek", {
|
|
255
|
+
_factoryDeps: { hubDir, accountsStore },
|
|
256
|
+
});
|
|
257
|
+
expect(store.has("deepseek")).toBe(false);
|
|
258
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
259
|
+
expect(out).toMatch(/removed deepseek/);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("exits 1 when the vendor is not registered", async () => {
|
|
263
|
+
const accountsStore = {
|
|
264
|
+
list: async () => [],
|
|
265
|
+
get: async () => null,
|
|
266
|
+
put: async () => {},
|
|
267
|
+
delete: async () => {},
|
|
268
|
+
};
|
|
269
|
+
await expect(
|
|
270
|
+
_internal.cmdAIChatUnregister("kimi", {
|
|
271
|
+
_factoryDeps: { hubDir, accountsStore },
|
|
272
|
+
}),
|
|
273
|
+
).rejects.toThrow(/process.exit/);
|
|
274
|
+
const errs = errSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
275
|
+
expect(errs).toMatch(/not registered/);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cc hub wechat <verb> CLI command unit tests (Phase 12.6.9 CLI surface).
|
|
3
|
+
*
|
|
4
|
+
* The command handlers accept `_getHub` test seam so this suite never
|
|
5
|
+
* starts a real hub. We synthesize a tiny fake hub whose methods return
|
|
6
|
+
* canned responses matching the real ones (Phase 12.6.8 wiring methods).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
|
|
10
|
+
|
|
11
|
+
import { _internal } from "../hub.js";
|
|
12
|
+
|
|
13
|
+
let logSpy, errSpy, exitSpy;
|
|
14
|
+
|
|
15
|
+
function fakeHub(overrides = {}) {
|
|
16
|
+
return {
|
|
17
|
+
probeWechatEnv: vi.fn(async () => ({
|
|
18
|
+
ok: true,
|
|
19
|
+
suggestedKeyProvider: "md5",
|
|
20
|
+
reasons: ["WeChat 7.0.22 — md5 path"],
|
|
21
|
+
device: { reachable: true, serial: "DEVICE_A", abi: "arm64-v8a" },
|
|
22
|
+
root: { detected: false, magiskInstalled: false },
|
|
23
|
+
frida: { serverRunning: false, port: null },
|
|
24
|
+
wechat: { installed: true, versionName: "7.0.22", majorVersion: 7 },
|
|
25
|
+
warnings: [],
|
|
26
|
+
...overrides.probe,
|
|
27
|
+
})),
|
|
28
|
+
registerWechatAdapter: vi.fn(async (opts) => {
|
|
29
|
+
if (!opts.account || !opts.account.uin) {
|
|
30
|
+
return { ok: false, reason: "UIN_REQUIRED" };
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
ok: true,
|
|
34
|
+
name: "wechat",
|
|
35
|
+
version: "0.5.0",
|
|
36
|
+
capabilities: ["sync:sqlite"],
|
|
37
|
+
sensitivity: "high",
|
|
38
|
+
chosenKeyProvider: opts.keyProviderOverride || "md5",
|
|
39
|
+
probe: { suggestedKeyProvider: "md5", reasons: [] },
|
|
40
|
+
registeredAt: 1716280000000,
|
|
41
|
+
...overrides.register,
|
|
42
|
+
};
|
|
43
|
+
}),
|
|
44
|
+
listWechatAccounts: vi.fn(() => overrides.list || [
|
|
45
|
+
{
|
|
46
|
+
uin: "1234567890",
|
|
47
|
+
dbPath: "/tmp/EnMicroMsg.db",
|
|
48
|
+
hasWechatDataPath: true,
|
|
49
|
+
chosenKeyProvider: "md5",
|
|
50
|
+
registeredAt: 1716280000000,
|
|
51
|
+
lastSyncAt: null,
|
|
52
|
+
},
|
|
53
|
+
]),
|
|
54
|
+
unregisterWechatAdapter: vi.fn(async (uin) => {
|
|
55
|
+
if (!uin) return { ok: false, reason: "UIN_REQUIRED" };
|
|
56
|
+
return { ok: true, removed: uin === "1234567890", uin, ...overrides.unregister };
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
beforeEach(() => {
|
|
62
|
+
logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
63
|
+
errSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
64
|
+
exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => {
|
|
65
|
+
throw new Error("process.exit called");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
afterEach(() => {
|
|
70
|
+
logSpy.mockRestore();
|
|
71
|
+
errSpy.mockRestore();
|
|
72
|
+
exitSpy.mockRestore();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe("cc hub wechat env-probe", () => {
|
|
76
|
+
it("prints human-readable summary by default", async () => {
|
|
77
|
+
const hub = fakeHub();
|
|
78
|
+
await _internal.cmdWechatEnvProbe({ _getHub: async () => hub });
|
|
79
|
+
expect(hub.probeWechatEnv).toHaveBeenCalledOnce();
|
|
80
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
81
|
+
expect(out).toMatch(/suggested.*md5/);
|
|
82
|
+
expect(out).toMatch(/device.*reachable.*DEVICE_A/);
|
|
83
|
+
expect(out).toMatch(/wechat.*7\.0\.22/);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("--json prints raw probe shape", async () => {
|
|
87
|
+
const hub = fakeHub();
|
|
88
|
+
await _internal.cmdWechatEnvProbe({ _getHub: async () => hub, json: true });
|
|
89
|
+
const out = logSpy.mock.calls.map((c) => c[0]).join("\n");
|
|
90
|
+
expect(JSON.parse(out)).toEqual(
|
|
91
|
+
expect.objectContaining({
|
|
92
|
+
suggestedKeyProvider: "md5",
|
|
93
|
+
device: expect.objectContaining({ reachable: true }),
|
|
94
|
+
}),
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe("cc hub wechat register", () => {
|
|
100
|
+
it("requires --uin (exits 1 via fail())", async () => {
|
|
101
|
+
const hub = fakeHub();
|
|
102
|
+
// With --json, fail() writes { error: "..." } to console.log; without
|
|
103
|
+
// --json, it writes a red ✗ to logger.error. We test both paths and
|
|
104
|
+
// assert at least one captured the missing-uin reason.
|
|
105
|
+
await expect(
|
|
106
|
+
_internal.cmdWechatRegister({ _getHub: async () => hub, json: true }),
|
|
107
|
+
).rejects.toThrow(/process\.exit/);
|
|
108
|
+
const allOut =
|
|
109
|
+
logSpy.mock.calls.map((c) => c.map((p) => (typeof p === "string" ? p : JSON.stringify(p))).join(" ")).join("\n") +
|
|
110
|
+
"\n" +
|
|
111
|
+
errSpy.mock.calls.map((c) => c.map((p) => (typeof p === "string" ? p : JSON.stringify(p))).join(" ")).join("\n");
|
|
112
|
+
expect(allOut).toMatch(/--uin|uin/i);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("forwards --uin / --db / --wechat-data-path / --force-provider to hub", async () => {
|
|
116
|
+
const hub = fakeHub();
|
|
117
|
+
await _internal.cmdWechatRegister({
|
|
118
|
+
_getHub: async () => hub,
|
|
119
|
+
uin: "1234567890",
|
|
120
|
+
db: "/tmp/EnMicroMsg.db",
|
|
121
|
+
wechatDataPath: "/tmp/com.tencent.mm",
|
|
122
|
+
forceProvider: "md5",
|
|
123
|
+
});
|
|
124
|
+
const callArg = hub.registerWechatAdapter.mock.calls[0][0];
|
|
125
|
+
expect(callArg.account.uin).toBe("1234567890");
|
|
126
|
+
expect(callArg.dbPath).toBe("/tmp/EnMicroMsg.db");
|
|
127
|
+
expect(callArg.wechatDataPath).toBe("/tmp/com.tencent.mm");
|
|
128
|
+
expect(callArg.keyProviderOverride).toBe("md5");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("forwards --frida-device-id into fridaOpts", async () => {
|
|
132
|
+
const hub = fakeHub();
|
|
133
|
+
await _internal.cmdWechatRegister({
|
|
134
|
+
_getHub: async () => hub,
|
|
135
|
+
uin: "wxid_abc",
|
|
136
|
+
forceProvider: "frida",
|
|
137
|
+
fridaDeviceId: "EMU_X",
|
|
138
|
+
});
|
|
139
|
+
const callArg = hub.registerWechatAdapter.mock.calls[0][0];
|
|
140
|
+
expect(callArg.fridaOpts).toEqual({ deviceId: "EMU_X" });
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("prints provider + sensitivity on success", async () => {
|
|
144
|
+
const hub = fakeHub();
|
|
145
|
+
await _internal.cmdWechatRegister({
|
|
146
|
+
_getHub: async () => hub,
|
|
147
|
+
uin: "1234567890",
|
|
148
|
+
});
|
|
149
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
150
|
+
expect(out).toMatch(/wechat registered.*1234567890/);
|
|
151
|
+
expect(out).toMatch(/provider.*md5/);
|
|
152
|
+
expect(out).toMatch(/sensitivity.*high/);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("exits 1 and surfaces reason + probe.reasons on ENV_UNSUPPORTED", async () => {
|
|
156
|
+
const hub = fakeHub({
|
|
157
|
+
register: {
|
|
158
|
+
ok: false,
|
|
159
|
+
reason: "ENV_UNSUPPORTED",
|
|
160
|
+
message: "No root",
|
|
161
|
+
probe: { reasons: ["WeChat 8.0.50 needs root", "frida not running"] },
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
await expect(
|
|
165
|
+
_internal.cmdWechatRegister({
|
|
166
|
+
_getHub: async () => hub,
|
|
167
|
+
uin: "wxid_abc",
|
|
168
|
+
}),
|
|
169
|
+
).rejects.toThrow(/process\.exit/);
|
|
170
|
+
const errOut = errSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
171
|
+
expect(errOut).toMatch(/ENV_UNSUPPORTED/);
|
|
172
|
+
expect(errOut).toMatch(/needs root/);
|
|
173
|
+
expect(errOut).toMatch(/frida not running/);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("--json prints raw register response without ANSI noise", async () => {
|
|
177
|
+
const hub = fakeHub();
|
|
178
|
+
await _internal.cmdWechatRegister({
|
|
179
|
+
_getHub: async () => hub,
|
|
180
|
+
uin: "1234567890",
|
|
181
|
+
json: true,
|
|
182
|
+
});
|
|
183
|
+
const out = logSpy.mock.calls.map((c) => c[0]).join("\n");
|
|
184
|
+
const parsed = JSON.parse(out);
|
|
185
|
+
expect(parsed.ok).toBe(true);
|
|
186
|
+
expect(parsed.chosenKeyProvider).toBe("md5");
|
|
187
|
+
expect(parsed.sensitivity).toBe("high");
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe("cc hub wechat list", () => {
|
|
192
|
+
it("prints account rows", async () => {
|
|
193
|
+
const hub = fakeHub();
|
|
194
|
+
await _internal.cmdWechatList({ _getHub: async () => hub });
|
|
195
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
196
|
+
expect(out).toMatch(/uin=1234567890/);
|
|
197
|
+
expect(out).toMatch(/provider=md5/);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("prints '(no registered)' when empty", async () => {
|
|
201
|
+
const hub = fakeHub({ list: [] });
|
|
202
|
+
await _internal.cmdWechatList({ _getHub: async () => hub });
|
|
203
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
204
|
+
expect(out).toMatch(/no registered/);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("--json prints accounts array", async () => {
|
|
208
|
+
const hub = fakeHub();
|
|
209
|
+
await _internal.cmdWechatList({ _getHub: async () => hub, json: true });
|
|
210
|
+
const out = logSpy.mock.calls.map((c) => c[0]).join("\n");
|
|
211
|
+
const parsed = JSON.parse(out);
|
|
212
|
+
expect(Array.isArray(parsed.accounts)).toBe(true);
|
|
213
|
+
expect(parsed.accounts[0].uin).toBe("1234567890");
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe("cc hub wechat unregister", () => {
|
|
218
|
+
it("calls hub with uin + reports removed", async () => {
|
|
219
|
+
const hub = fakeHub();
|
|
220
|
+
await _internal.cmdWechatUnregister("1234567890", { _getHub: async () => hub });
|
|
221
|
+
expect(hub.unregisterWechatAdapter).toHaveBeenCalledWith("1234567890");
|
|
222
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
223
|
+
expect(out).toMatch(/removed wechat account.*1234567890/);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("reports nothing-removed for missing uin (still ok:true)", async () => {
|
|
227
|
+
const hub = fakeHub({ unregister: { removed: false } });
|
|
228
|
+
await _internal.cmdWechatUnregister("ghost", { _getHub: async () => hub });
|
|
229
|
+
const out = logSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
230
|
+
expect(out).toMatch(/was not registered/);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("--json prints raw response", async () => {
|
|
234
|
+
const hub = fakeHub();
|
|
235
|
+
await _internal.cmdWechatUnregister("1234567890", {
|
|
236
|
+
_getHub: async () => hub,
|
|
237
|
+
json: true,
|
|
238
|
+
});
|
|
239
|
+
const out = logSpy.mock.calls.map((c) => c[0]).join("\n");
|
|
240
|
+
const parsed = JSON.parse(out);
|
|
241
|
+
expect(parsed).toEqual(expect.objectContaining({ ok: true, removed: true, uin: "1234567890" }));
|
|
242
|
+
});
|
|
243
|
+
});
|