chainlesschain 0.162.11 → 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.
Files changed (166) hide show
  1. package/README.md +30 -25
  2. package/package.json +4 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-ebtJGjAG.js → AIOps-Bq_zxhCr.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-CypkRN-G.js → ActionButton-CaevDm9t.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-B2JMlIng.js → Analytics-B0gOmwPw.js} +1 -1
  7. package/src/assets/web-panel/assets/{AppLayout-B8QQ4pk7.js → AppLayout-DWhZiV0Q.js} +2 -2
  8. package/src/assets/web-panel/assets/{Audit-BoYaAyFa.js → Audit-ZuZJBCxo.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-BfackGZ5.js → Backup-CX7jhH5l.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-C06FUpDz.js → BaseInput-CVLx7HVq.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-BWxMkBYZ.js → Chat-C6yL5tRD.js} +1 -1
  12. package/src/assets/web-panel/assets/{Checkbox-XJMvS3PV.js → Checkbox-BePhbqVq.js} +1 -1
  13. package/src/assets/web-panel/assets/{Codegen-CzR462RK.js → Codegen-B5E4x1Lm.js} +1 -1
  14. package/src/assets/web-panel/assets/{Col-BQHpLNCA.js → Col-CWhNU6A7.js} +1 -1
  15. package/src/assets/web-panel/assets/{Community-BWRRbJYd.js → Community-mSEAuJhp.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compact-BunoKIy9.js → Compact-DSudHzX3.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compliance-CtJfZctm.js → Compliance-CxJLYjyn.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cowork-ER5-_bod.js → Cowork-C-trppQj.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cron-C80jYBw1.js → Cron-_Ij4v5fY.js} +1 -1
  20. package/src/assets/web-panel/assets/{Crosschain-fEMlCNsL.js → Crosschain-eLHXzp5T.js} +1 -1
  21. package/src/assets/web-panel/assets/{DID-BZpctKmU.js → DID-BP04AUUB.js} +1 -1
  22. package/src/assets/web-panel/assets/{Dashboard-RQhZmLi4.js → Dashboard-CzEeQv62.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dropdown-CrpwS84l.js → Dropdown-C_SGOB22.js} +1 -1
  24. package/src/assets/web-panel/assets/{Federation-BEQyZtdR.js → Federation-BgaP4BOv.js} +1 -1
  25. package/src/assets/web-panel/assets/{FormItemContext-DCwvl6Vh.js → FormItemContext-BxGLLt9r.js} +1 -1
  26. package/src/assets/web-panel/assets/{Git-6FihOxMK.js → Git-Bt_uM_Gw.js} +2 -2
  27. package/src/assets/web-panel/assets/{Governance-DlBLHSlJ.js → Governance-N2-0RG_o.js} +1 -1
  28. package/src/assets/web-panel/assets/{Inference-DdSokzV0.js → Inference-eS3g-CzP.js} +1 -1
  29. package/src/assets/web-panel/assets/{KnowledgeGraph-bg8GBHMr.js → KnowledgeGraph-CUuvNVah.js} +1 -1
  30. package/src/assets/web-panel/assets/{Logs-DdFYdLQ-.js → Logs-wPbwEt2r.js} +1 -1
  31. package/src/assets/web-panel/assets/{Marketplace-DjnlAeYF.js → Marketplace-DH91kTwo.js} +1 -1
  32. package/src/assets/web-panel/assets/{McpTools-Czs41YUh.js → McpTools-D-GyyBrI.js} +1 -1
  33. package/src/assets/web-panel/assets/{Memory-CX0b3c8D.js → Memory-BOtUy-tw.js} +1 -1
  34. package/src/assets/web-panel/assets/{MobileBridge-BoFGb9Mm.js → MobileBridge-DIP__XQd.js} +1 -1
  35. package/src/assets/web-panel/assets/{MobileProjects-B8qQ9H-0.js → MobileProjects-1nqr1UsU.js} +1 -1
  36. package/src/assets/web-panel/assets/{Mtc-CRF1NLae.js → Mtc-CCE0x7h2.js} +1 -1
  37. package/src/assets/web-panel/assets/{MtcAudit-CdCm70cJ.js → MtcAudit-BBkz0XUO.js} +1 -1
  38. package/src/assets/web-panel/assets/{Multisig-yoZlpq2Y.js → Multisig-CIKSJvTY.js} +2 -2
  39. package/src/assets/web-panel/assets/{NLProgramming-hFCgqDxJ.js → NLProgramming-BDkgeFcq.js} +1 -1
  40. package/src/assets/web-panel/assets/{Notes-DC8pnxs-.js → Notes-ONiUxfN1.js} +1 -1
  41. package/src/assets/web-panel/assets/{NotificationSettings-DDVg5Nc8.js → NotificationSettings-CGcyKEIe.js} +1 -1
  42. package/src/assets/web-panel/assets/{Organization-0YCtAFMS.js → Organization-BZtMYBJt.js} +4 -4
  43. package/src/assets/web-panel/assets/{Overflow-DhPLoAdz.js → Overflow-C4LfFZAI.js} +1 -1
  44. package/src/assets/web-panel/assets/{OverrideContext-x9ZzjLwk.js → OverrideContext-C_4H9tGA.js} +1 -1
  45. package/src/assets/web-panel/assets/{P2P-BWpuJhkD.js → P2P-D71Cpk-m.js} +1 -1
  46. package/src/assets/web-panel/assets/{Permissions-B4IrizO9.js → Permissions-DRGYF29v.js} +1 -1
  47. package/src/assets/web-panel/assets/PersonalDataHub-CfRYoIua.js +1 -0
  48. package/src/assets/web-panel/assets/PersonalDataHub-Dvaa8niQ.css +1 -0
  49. package/src/assets/web-panel/assets/{Pipeline-M65jR6sq.js → Pipeline-BOyp0_Qo.js} +1 -1
  50. package/src/assets/web-panel/assets/{Privacy-BeO8zLup.js → Privacy-a_AcphvF.js} +1 -1
  51. package/src/assets/web-panel/assets/{ProjectInit-Ck_ZjrVZ.js → ProjectInit-CFu1grYt.js} +1 -1
  52. package/src/assets/web-panel/assets/{ProjectSettings-ijn-97s0.js → ProjectSettings-p54Eivhh.js} +1 -1
  53. package/src/assets/web-panel/assets/{Projects-BsNBemeh.js → Projects-DkB88XAu.js} +1 -1
  54. package/src/assets/web-panel/assets/{Providers-CI7UxKVO.js → Providers-EK7f8DEd.js} +1 -1
  55. package/src/assets/web-panel/assets/{QuickAsk-dE2M1KOB.js → QuickAsk-CpO0w3iP.js} +1 -1
  56. package/src/assets/web-panel/assets/{Recommend-B30EgbKS.js → Recommend-BUJVQdv9.js} +1 -1
  57. package/src/assets/web-panel/assets/{Reputation-CV6n7wMx.js → Reputation-kU2fOuZt.js} +1 -1
  58. package/src/assets/web-panel/assets/{Row-DSaoTjlN.js → Row-oGWRbk6g.js} +1 -1
  59. package/src/assets/web-panel/assets/{RssFeed-_NgBmHaC.js → RssFeed-saC_46Yo.js} +1 -1
  60. package/src/assets/web-panel/assets/{Search-B341ooTV.js → Search-CjtRqFUu.js} +1 -1
  61. package/src/assets/web-panel/assets/{Security-CqCQD8hf.js → Security-BX0NBVfQ.js} +1 -1
  62. package/src/assets/web-panel/assets/{Services-Cju_95rB.js → Services-Bgxsnei_.js} +1 -1
  63. package/src/assets/web-panel/assets/{Skeleton-kh_uW22l.js → Skeleton-CwBb3k2a.js} +1 -1
  64. package/src/assets/web-panel/assets/{Skills-BVRPgciI.js → Skills-CZCMYH6Z.js} +1 -1
  65. package/src/assets/web-panel/assets/{Sla-y-vKFYkI.js → Sla-Djy1uHnZ.js} +1 -1
  66. package/src/assets/web-panel/assets/{SpeechSettings-BXJm9zyo.js → SpeechSettings-CGUI_Uyh.js} +1 -1
  67. package/src/assets/web-panel/assets/{SyncSettings-BmHZR-Kv.js → SyncSettings-DK2CKHRD.js} +1 -1
  68. package/src/assets/web-panel/assets/{Tasks-C7zmYW9f.js → Tasks-BKiOzeIO.js} +1 -1
  69. package/src/assets/web-panel/assets/{Templates-DVEG7FdA.js → Templates-CnQpleXj.js} +1 -1
  70. package/src/assets/web-panel/assets/{Tenant-CpvjzPCo.js → Tenant-DwKz0cjm.js} +1 -1
  71. package/src/assets/web-panel/assets/{Terminal-D_Wpp2iE.js → Terminal-A7t_wsR8.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tokens-QBrjdNqi.js → Tokens-BqYY9l44.js} +1 -1
  73. package/src/assets/web-panel/assets/{Trigger-BhR_VEvQ.js → Trigger-BI4bXFmi.js} +1 -1
  74. package/src/assets/web-panel/assets/{Trust-C0xhM2lC.js → Trust-yMynKTRG.js} +1 -1
  75. package/src/assets/web-panel/assets/{UkeySign-BnyP-W3-.js → UkeySign-Br4IScM6.js} +1 -1
  76. package/src/assets/web-panel/assets/{VideoEditing-C5Y8MyEK.js → VideoEditing-CWcThGsP.js} +1 -1
  77. package/src/assets/web-panel/assets/{Wallet-DzCPCQNF.js → Wallet-CZcAtjxj.js} +1 -1
  78. package/src/assets/web-panel/assets/{WebAuthn-6X5bLtHU.js → WebAuthn-BnTZFMA0.js} +3 -3
  79. package/src/assets/web-panel/assets/{WorkflowEditor-ekS27G9f.js → WorkflowEditor-N7gGz3_n.js} +1 -1
  80. package/src/assets/web-panel/assets/{chat-BikodUwh.js → chat-D175ZIO0.js} +1 -1
  81. package/src/assets/web-panel/assets/{collapseMotion-CjFH_Jop.js → collapseMotion-DfnRZex1.js} +1 -1
  82. package/src/assets/web-panel/assets/{colors-8yIg5K7E.js → colors-LKhZyttv.js} +1 -1
  83. package/src/assets/web-panel/assets/{compact-item-MLWo5-GY.js → compact-item-CsJSebxT.js} +1 -1
  84. package/src/assets/web-panel/assets/{createContext-nir7ccDv.js → createContext-BJ_CPYFC.js} +1 -1
  85. package/src/assets/web-panel/assets/{echarts-Bq-n0MtJ.js → echarts-Dj_pBaVI.js} +1 -1
  86. package/src/assets/web-panel/assets/{hasIn-DxUIHW2P.js → hasIn-CzD3IqH8.js} +1 -1
  87. package/src/assets/web-panel/assets/{icons-CLQTHa5-.js → icons-BOPtEWK4.js} +4 -4
  88. package/src/assets/web-panel/assets/{index-vVrIg9Jk.js → index-6qPbrYF7.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-CCGf6IJj.js → index-B7UYymse.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-DSjWvxVr.js → index-BDSZDDb2.js} +4 -4
  91. package/src/assets/web-panel/assets/{index-BURKtxBq.js → index-BEDFHKO3.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-q3Lr2UzW.js → index-BMvdoiFr.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-BgQtoOHc.js → index-BNVLVzN5.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-Bn5VWKW1.js → index-BSNibAqz.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-4SFekeAy.js → index-BV-__mlC.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-CfeuuE7v.js → index-BXH9ujMW.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-h05fIj9Q.js → index-BZluCuTH.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-9Y0IyfeM.js → index-BhiZDGg7.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BkMtxzcM.js → index-BjOrt4vw.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DOIryna2.js → index-BmJdof_c.js} +2 -2
  101. package/src/assets/web-panel/assets/{index-TB5vrA0Z.js → index-BsirlkJ0.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BgHPrMXP.js → index-BvF2tC6C.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BSIaRmzU.js → index-C2HBKw07.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CkSN2Ki_.js → index-CKjBAdm0.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DLiexKJ2.js → index-CRGNuUIM.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CeX-HLIi.js → index-CTIkCKav.js} +1 -1
  107. package/src/assets/web-panel/assets/index-CY1mQA2I.js +1 -0
  108. package/src/assets/web-panel/assets/{index-78olN7S9.js → index-CyHdYUeZ.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BcyG-9vV.js → index-D401L3yx.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C_W1kVtY.js → index-D5IZCkZG.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Bpa9senE.js → index-D7ZcBI5s.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-dgZZAsxo.js → index-D8kltMTW.js} +1 -1
  113. package/src/assets/web-panel/assets/index-D9nXHfUB.js +1 -0
  114. package/src/assets/web-panel/assets/{index-DkIon-Gv.js → index-DJVkBmSc.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C-UB9bYd.js → index-DM3uBEWD.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-Dx5xZmzt.js → index-DOO73rHE.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DVLJ1iGu.js → index-DXp1jVsK.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-S8mYImvf.js → index-Dd7dICwB.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-SUYLhwZI.js → index-Dm-3kvtD.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-C_Xi08tu.js → index-DnPt5OdD.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-hu-wjfWv.js → index-E7t1hAnk.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Cp-YnzHN.js → index-JTX9A7w0.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-8qrwsaKy.js → index-Kn-Of5ew.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Dl-O2OkQ.js → index-R1cFADfk.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-yfNusVbo.js → index-RIO4JKMP.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DDmc4cig.js → index-uTEVWPYA.js} +1 -1
  127. package/src/assets/web-panel/assets/{initDefaultProps-xUjF_bq0.js → initDefaultProps-CBW0okek.js} +1 -1
  128. package/src/assets/web-panel/assets/{motion-B019-Q6h.js → motion-DGAffQ0Z.js} +1 -1
  129. package/src/assets/web-panel/assets/{move-D2XYj_gA.js → move-DFJ0-5IW.js} +1 -1
  130. package/src/assets/web-panel/assets/{omit-AIzzlguv.js → omit-AvrDghg1.js} +1 -1
  131. package/src/assets/web-panel/assets/{pickAttrs-CRkEQaLs.js → pickAttrs-D7csw9i1.js} +1 -1
  132. package/src/assets/web-panel/assets/{placementArrow-s4kAStH6.js → placementArrow-hZ6Lg6kG.js} +1 -1
  133. package/src/assets/web-panel/assets/{responsiveObserve-BCsWrTkb.js → responsiveObserve-DLLx5VvS.js} +1 -1
  134. package/src/assets/web-panel/assets/{slide-B_Hggtvv.js → slide-BaRIT3ev.js} +1 -1
  135. package/src/assets/web-panel/assets/{statusUtils-DnNf15VW.js → statusUtils-Cdjyuhrz.js} +1 -1
  136. package/src/assets/web-panel/assets/{styleChecker-CSQdy9SQ.js → styleChecker-CbrNybTt.js} +1 -1
  137. package/src/assets/web-panel/assets/useFlexGapSupport-B8gAhiRC.js +1 -0
  138. package/src/assets/web-panel/assets/{useFs-D78PlgeG.js → useFs-BZPy4ICP.js} +1 -1
  139. package/src/assets/web-panel/assets/{useMergedState-O7QXt4P5.js → useMergedState-WwedrFR0.js} +1 -1
  140. package/src/assets/web-panel/assets/{useRefs-0J6m8UWN.js → useRefs-Cdq8EWeF.js} +1 -1
  141. package/src/assets/web-panel/assets/{useState-CSzR8F8O.js → useState-DGS1NOyn.js} +1 -1
  142. package/src/assets/web-panel/assets/{vendor-M5lGV-wr.js → vendor-DhFY8mDK.js} +1 -1
  143. package/src/assets/web-panel/assets/{vnode-BTMmpsWu.js → vnode-6Y0NDMVv.js} +1 -1
  144. package/src/assets/web-panel/assets/{zoom-CwOTbvKc.js → zoom-DTbMGsSH.js} +1 -1
  145. package/src/assets/web-panel/index.html +3 -3
  146. package/src/commands/__tests__/hub-aichat.test.js +277 -0
  147. package/src/commands/__tests__/hub-wechat.test.js +243 -0
  148. package/src/commands/hub.js +881 -0
  149. package/src/commands/sync-providers.js +436 -0
  150. package/src/gateways/ws/personal-data-hub-protocol.js +68 -0
  151. package/src/index.js +6 -0
  152. package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +209 -0
  153. package/src/lib/__tests__/sync-credentials.test.js +265 -0
  154. package/src/lib/__tests__/sync-engine-cli.test.js +293 -0
  155. package/src/lib/personal-data-hub-aichat-wizard.js +242 -0
  156. package/src/lib/personal-data-hub-wiring.js +189 -0
  157. package/src/lib/sync-cli-db.js +194 -0
  158. package/src/lib/sync-credentials.js +225 -0
  159. package/src/lib/sync-engine-cli.js +406 -0
  160. package/src/lib/sync-oss-client.js +273 -0
  161. package/src/lib/sync-webdav-client.js +194 -0
  162. package/src/assets/web-panel/assets/PersonalDataHub-BK7I0Rsb.css +0 -1
  163. package/src/assets/web-panel/assets/PersonalDataHub-ZbziiUr6.js +0 -1
  164. package/src/assets/web-panel/assets/index-BeA3spHc.js +0 -1
  165. package/src/assets/web-panel/assets/index-DoLRjAoc.js +0 -1
  166. package/src/assets/web-panel/assets/useFlexGapSupport-Bt-T27Pf.js +0 -1
@@ -1,4 +1,4 @@
1
- import{K as o}from"./index-DSjWvxVr.js";import{i as f}from"./motion-B019-Q6h.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),{[`
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-DSjWvxVr.js"></script>
12
- <link rel="modulepreload" crossorigin href="./assets/vendor-M5lGV-wr.js">
13
- <link rel="modulepreload" crossorigin href="./assets/icons-CLQTHa5-.js">
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
+ });