chainlesschain 0.162.20 → 0.162.26

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 (156) hide show
  1. package/package.json +2 -2
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-Buh_mYlF.js → AIOps-DEhhAYYj.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-Dc7c0bZf.js → ActionButton-DEyfUz5F.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-CR9TWfM-.js → Analytics-D1rjS61W.js} +1 -1
  6. package/src/assets/web-panel/assets/{AppLayout-DVfanUep.js → AppLayout-CptFJPy6.js} +2 -2
  7. package/src/assets/web-panel/assets/{Audit-BxojBqRe.js → Audit-BG6KQUHY.js} +1 -1
  8. package/src/assets/web-panel/assets/{Backup-CGkreaK9.js → Backup-D2ikQT54.js} +1 -1
  9. package/src/assets/web-panel/assets/{BaseInput-B-Q2ZGfz.js → BaseInput-BG_d8yMt.js} +1 -1
  10. package/src/assets/web-panel/assets/{Chat-Dd_VC5Av.js → Chat-CcHmGkLY.js} +1 -1
  11. package/src/assets/web-panel/assets/{ChatBubbleRenderer-B64kZfRH.js → ChatBubbleRenderer-DIXrOHbn.js} +1 -1
  12. package/src/assets/web-panel/assets/{Checkbox-NYBD1rCW.js → Checkbox-Bx2h6vT3.js} +1 -1
  13. package/src/assets/web-panel/assets/{Codegen-B3Kqhgv1.js → Codegen-o14zzfuK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Col-2A3Bg2GC.js → Col-HlZjxy7V.js} +1 -1
  15. package/src/assets/web-panel/assets/{Community-C84SkDEJ.js → Community-DXxMflr2.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compact-Crv3pyZJ.js → Compact-DbswbBjd.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compliance-D4qasxoY.js → Compliance-C7Q4Da2p.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cowork-Bfbvysw-.js → Cowork-BLImywOe.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cron-Dkjyiekd.js → Cron-DpXu1G4m.js} +1 -1
  20. package/src/assets/web-panel/assets/{Crosschain-DbJm9Kjd.js → Crosschain-C4qokeJu.js} +1 -1
  21. package/src/assets/web-panel/assets/{DID-C2HI6acG.js → DID-C0BjPiij.js} +1 -1
  22. package/src/assets/web-panel/assets/{Dashboard-BXMY7QVP.js → Dashboard-CsfDXwPl.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dropdown-DcOykpfh.js → Dropdown-CiwMUKrx.js} +1 -1
  24. package/src/assets/web-panel/assets/{EmailListRenderer-Doo52F2M.js → EmailListRenderer-DX7xfm5a.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-cHubZT6U.js → Federation-CA4Ibsg0.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-B5OVlspi.js → FormItemContext-DvM0lU-7.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-OgA46PJq.js → GenericCardRenderer-REjsnTHA.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-_OKH_JOq.js → Git-ZhnSDQGH.js} +1 -1
  29. package/src/assets/web-panel/assets/{Governance-CTByBwSV.js → Governance-BL8iUV_g.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-C0nqgySA.js → Inference-BONrgLk-.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph-CWW4ZIqH.js → KnowledgeGraph-q9SAz7h7.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-DrwqUltr.js → Logs-eHfEFnEZ.js} +1 -1
  33. package/src/assets/web-panel/assets/{Marketplace-LJMRx-dm.js → Marketplace-DzwuVedm.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-F_EjC8j3.js → McpTools-BRoLIeq5.js} +1 -1
  35. package/src/assets/web-panel/assets/{Memory-VonDem9-.js → Memory-DjvAa1Ce.js} +1 -1
  36. package/src/assets/web-panel/assets/{MobileBridge-CUWxIrfb.js → MobileBridge-CGTanjsT.js} +1 -1
  37. package/src/assets/web-panel/assets/{MobileProjects-CGOo70lk.js → MobileProjects-cTccXHwN.js} +1 -1
  38. package/src/assets/web-panel/assets/{Mtc-CqUquFbQ.js → Mtc-CNUe29wS.js} +1 -1
  39. package/src/assets/web-panel/assets/{MtcAudit-CRVusaip.js → MtcAudit-COk24mdH.js} +1 -1
  40. package/src/assets/web-panel/assets/{Multisig-B0o8Mv8T.js → Multisig-CFq2j0BU.js} +1 -1
  41. package/src/assets/web-panel/assets/{NLProgramming-CxQINUhu.js → NLProgramming-dfRr-FGW.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-B6Q_apFW.js → Notes-iM4aoXiw.js} +1 -1
  43. package/src/assets/web-panel/assets/{NotificationSettings-DO-lgp6x.js → NotificationSettings-CeVJ-942.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-DxoBoMtz.js → OrderTableRenderer-zQ5jvUZI.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization-DqJ_KawH.js → Organization-CTSWyMGT.js} +1 -1
  46. package/src/assets/web-panel/assets/{Overflow-Cg4iKODM.js → Overflow---n60sAp.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-n5GPMrwC.js → P2P-BCQurpAB.js} +1 -1
  48. package/src/assets/web-panel/assets/{PdhVaultBrowser-BdZI0EJs.js → PdhVaultBrowser-C5L1qAc0.js} +2 -2
  49. package/src/assets/web-panel/assets/{Permissions-BjtwAIGb.js → Permissions-I8sgLLE5.js} +1 -1
  50. package/src/assets/web-panel/assets/PersonalDataHub-CEUfFRCj.js +2 -0
  51. package/src/assets/web-panel/assets/{PersonalDataHub-D0ncF92t.css → PersonalDataHub-CO9-IYDY.css} +1 -1
  52. package/src/assets/web-panel/assets/{Pipeline-BZe2-Flj.js → Pipeline-BTBjJaRd.js} +1 -1
  53. package/src/assets/web-panel/assets/{Privacy-OJqMon4c.js → Privacy-aCs44rpW.js} +1 -1
  54. package/src/assets/web-panel/assets/{ProjectInit-Dw-5SMG1.js → ProjectInit-DZ2iIlbN.js} +1 -1
  55. package/src/assets/web-panel/assets/{ProjectSettings-DxqW44cV.js → ProjectSettings-oYUtNgHP.js} +1 -1
  56. package/src/assets/web-panel/assets/{Projects-CPOqs2ec.js → Projects-FonFg0ie.js} +1 -1
  57. package/src/assets/web-panel/assets/{Providers-hBfwscEl.js → Providers-CRmOuabY.js} +1 -1
  58. package/src/assets/web-panel/assets/{QuickAsk-DA3WFFAr.js → QuickAsk-BHd6UZ1A.js} +1 -1
  59. package/src/assets/web-panel/assets/{Recommend-DMpz3URg.js → Recommend-BkzGGuq-.js} +1 -1
  60. package/src/assets/web-panel/assets/{Reputation-6-z56FwC.js → Reputation-Do7cPr9u.js} +1 -1
  61. package/src/assets/web-panel/assets/{Row-CL1Y6SfW.js → Row-D_sR3MmD.js} +1 -1
  62. package/src/assets/web-panel/assets/{RssFeed-BIHU2bMf.js → RssFeed-pWSbZ06l.js} +1 -1
  63. package/src/assets/web-panel/assets/{Search-CRAfuEX-.js → Search-BTL71JSs.js} +1 -1
  64. package/src/assets/web-panel/assets/{Security-CVya3gvH.js → Security-8lbNoqY6.js} +1 -1
  65. package/src/assets/web-panel/assets/{Services-Cxv7_umF.js → Services-yr3QVduo.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skeleton-D_GvsCtv.js → Skeleton-DdnY1ZTz.js} +1 -1
  67. package/src/assets/web-panel/assets/{Skills-DyiEpcvf.js → Skills-fk24WY3D.js} +1 -1
  68. package/src/assets/web-panel/assets/{Sla-wiglQzXV.js → Sla-bOXRT7wR.js} +1 -1
  69. package/src/assets/web-panel/assets/{SpeechSettings-CLtovaa5.js → SpeechSettings-DjonFUbP.js} +1 -1
  70. package/src/assets/web-panel/assets/{SyncSettings-BOgVef1O.js → SyncSettings-C-7HTl6d.js} +1 -1
  71. package/src/assets/web-panel/assets/{Tasks-Ik8AX7-J.js → Tasks-DDohfzFT.js} +1 -1
  72. package/src/assets/web-panel/assets/{Templates-CireiINW.js → Templates-C8PI_WTt.js} +1 -1
  73. package/src/assets/web-panel/assets/{Tenant-t7jF9NkQ.js → Tenant-CIvbeRkn.js} +1 -1
  74. package/src/assets/web-panel/assets/{Terminal-Btq_O951.js → Terminal-BuIPGugj.js} +1 -1
  75. package/src/assets/web-panel/assets/{TimelineRenderer-hC_Piiwy.js → TimelineRenderer-BefCbTxN.js} +1 -1
  76. package/src/assets/web-panel/assets/{Tokens-BTIqA2J1.js → Tokens-gGAeez46.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trigger-Dzv2gJpK.js → Trigger-C_86E2v7.js} +1 -1
  78. package/src/assets/web-panel/assets/{Trust-B13QpWOh.js → Trust-Beg23C1W.js} +1 -1
  79. package/src/assets/web-panel/assets/{UkeySign-CFj3UF4G.js → UkeySign--sGSaISg.js} +1 -1
  80. package/src/assets/web-panel/assets/{VideoEditing-CGMOGTQb.js → VideoEditing-DIsnY6D_.js} +1 -1
  81. package/src/assets/web-panel/assets/{Wallet-BkCJ573Y.js → Wallet-a7ECYY0i.js} +1 -1
  82. package/src/assets/web-panel/assets/{WebAuthn-C8dCrmGH.js → WebAuthn-CsVpkUE8.js} +1 -1
  83. package/src/assets/web-panel/assets/{WorkflowEditor-CclfhxwH.js → WorkflowEditor-BOJ4WTgl.js} +1 -1
  84. package/src/assets/web-panel/assets/{chat-CW_X_A9l.js → chat-ezCR5ZZX.js} +1 -1
  85. package/src/assets/web-panel/assets/{colors-6GtheJb2.js → colors-DSUEQ7GR.js} +1 -1
  86. package/src/assets/web-panel/assets/{compact-item-tz7dJapw.js → compact-item-D4w3DGj_.js} +1 -1
  87. package/src/assets/web-panel/assets/{createContext-CbiGcRCw.js → createContext-B_hvu-NR.js} +1 -1
  88. package/src/assets/web-panel/assets/{hasIn-bmNFD3PH.js → hasIn-FY775Vpc.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-DxHmNJ8S.js → index-1ki6aTIz.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-UId2JAY6.js → index-B3lbDu2b.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-BM4slfDH.js → index-B9LXVosT.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-b7sSMzkC.js → index-BGdchdRx.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-KFdfLxVt.js → index-BGrm33US.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-B9sJpsz3.js → index-BHPD-_s2.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-B6GgMo1k.js → index-BMnGj-Ui.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-B2P1c5yD.js → index-BSp1hSN8.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-S9g45I5s.js → index-BaZmrJ6j.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Cb33JbDx.js → index-BnvLdkR8.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CQ7aJ-8s.js → index-BzME19Nh.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DeoJYTHX.js → index-C0wDzrUK.js} +3 -3
  101. package/src/assets/web-panel/assets/{index-CBNnbQxM.js → index-CAa3LSKI.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CLk3xgD2.js → index-CE3vDzJj.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-De0xvTEv.js → index-CLp4V3Tb.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CKP-AZD3.js → index-CNUQnJsg.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CzIQ0u4e.js → index-CSbCIyga.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-UjxsY00y.js → index-CUNYcWEF.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CgLF_zD1.js → index-CV-F9a_X.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C5zlrlPd.js → index-CcvzscCg.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-B3UH6whC.js → index-CdzLJsac.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CU0MeCwH.js → index-Cug_yoee.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DxdLksCx.js → index-CxMArAIk.js} +1 -1
  112. package/src/assets/web-panel/assets/index-CzkEIn_T.js +1 -0
  113. package/src/assets/web-panel/assets/index-D2PcvXPP.js +1 -0
  114. package/src/assets/web-panel/assets/{index-DMGJqZ-o.js → index-D6yJ0RMr.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DaYfMM7r.js → index-DM77-xyl.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CV9aPPYM.js → index-DfU6zsU8.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-l2VM-W36.js → index-DqsQUPY7.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DK7ee5hC.js → index-DqxLCUYa.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DaK59dFw.js → index-DtztktoP.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Cs5KWviO.js → index-Dz8-7APi.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Da2RUdcb.js → index-Enin7rzK.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CYIwY9zQ.js → index-S6A76pR1.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DvWXdCxl.js → index-ZGJo2fz1.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Dj1N1idV.js → index-d0HXotWE.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CTnIkosg.js → index-gAtp_KkQ.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-zP_o4yKV.js → index-mlTTTHla.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BxCPkuTG.js → index-wWVM6ENX.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-BTGwT0NA.js → initDefaultProps-BoLcNBz9.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-BheHkG8e.js → motion-ouRvP3eO.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-BkMMNkAw.js → move-BBITvaOV.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-B9zmSFf6.js → omit-D8Yxdvbb.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-CFNBcA5Z.js → pickAttrs-BIUy7mER.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-B4mvrUYw.js → placementArrow-CrNWpNSF.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-BJqsSjxJ.js → responsiveObserve-aHLPN464.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-Cj78MXSi.js → slide-2qNtePjk.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-Bk6ChXAV.js → statusUtils-FAF3iR3R.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-B_YDSNYf.js → styleChecker-BNFTkrbl.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-q90prOQL.js → useFlexGapSupport-BgdPlW7E.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-BtpFJ9kI.js → useFs-q1QvAh3f.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-C3qhf1sQ.js → usePersonalDataHub-DEZ6cY8C.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-Bz2j0JiG.js → vnode-vp6H-NL_.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-CzaEtel2.js → zoom-UatfJMw4.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/__tests__/hub-bilibili-adb-sync.test.js +350 -0
  145. package/src/commands/__tests__/hub-douyin-adb-sync.test.js +199 -0
  146. package/src/commands/__tests__/hub-kuaishou-adb-sync.test.js +161 -0
  147. package/src/commands/__tests__/hub-toutiao-adb-sync.test.js +158 -0
  148. package/src/commands/__tests__/hub-weibo-adb-sync.test.js +163 -0
  149. package/src/commands/__tests__/hub-xhs-adb-sync.test.js +155 -0
  150. package/src/commands/hub.js +883 -0
  151. package/src/gateways/ws/personal-data-hub-protocol.js +84 -0
  152. package/src/lib/host-adb-bridge.js +77 -1
  153. package/src/lib/personal-data-hub-wiring.js +471 -12
  154. package/src/assets/web-panel/assets/PersonalDataHub-Bsf3Wh6n.js +0 -1
  155. package/src/assets/web-panel/assets/index-BFkZAdio.js +0 -1
  156. package/src/assets/web-panel/assets/index-BhgINPAH.js +0 -1
@@ -64,6 +64,12 @@ const {
64
64
  JdAdapter,
65
65
  MeituanAdapter,
66
66
  PinduoduoAdapter,
67
+ Train12306Adapter,
68
+ TaobaoAdapter,
69
+ CtripAdapter,
70
+ AmapAdapter,
71
+ TelegramAdapter,
72
+ WhatsAppAdapter,
67
73
  EntityResolver,
68
74
  EntityResolverEmbeddingStage,
69
75
  EntityResolverLLMStage,
@@ -147,6 +153,11 @@ export function resolveHubDir() {
147
153
  }
148
154
 
149
155
  async function initHub() {
156
+ // Phase 1c: hoisted so the hub-level `bilibiliAdbSync` method can reuse
157
+ // the same bridge instance the system-data-android adapter wires below.
158
+ // Single bridge per hub keeps `bilibili.cookies` extension state /
159
+ // adb path resolution / device picking consistent across callers.
160
+ let hostAdbBridge = null;
150
161
  const hubDir = resolveHubDir();
151
162
  mkdirSync(hubDir, { recursive: true });
152
163
  mkdirSync(join(hubDir, "keys"), { recursive: true });
@@ -204,9 +215,20 @@ async function initHub() {
204
215
  // and skip embedding+LLM stages entirely. Rule-stage still runs; the
205
216
  // resolve_queue picks up enqueued pairs later if a host with Ollama is
206
217
  // ever attached (e.g. desktop-side replay).
218
+ //
219
+ // 2026-05-25 — broadened the detection. The old startsWith("/data/data/
220
+ // com.chainlesschain.android") missed two cases:
221
+ // 1. /data/user/0/ — on Android 7+ (multi-user), context.filesDir
222
+ // resolves under /data/user/0/<pkg>/ instead of /data/data/<pkg>/,
223
+ // so the legacy startsWith never matched on real device.
224
+ // 2. Variant suffixes — com.chainlesschain.android.debug,
225
+ // .staging, etc. all have a separate package id but should share
226
+ // the in-APK skip behaviour.
227
+ // Match either path prefix + optional variant suffix in one regex; if
228
+ // the env override is set, honour it unconditionally.
207
229
  const isInAppAndroidCc =
208
230
  typeof process.env.PREFIX === "string" &&
209
- process.env.PREFIX.startsWith("/data/data/com.chainlesschain.android");
231
+ /\/com\.chainlesschain\.android(\.[a-z]+)?\//.test(process.env.PREFIX);
210
232
  const skipEmbeddings =
211
233
  isInAppAndroidCc || process.env.CC_HUB_DISABLE_EMBEDDINGS === "1";
212
234
  try {
@@ -290,7 +312,47 @@ async function initHub() {
290
312
  // + caveats (Windows CRLF parse trap, 0/multi device, ENOENT).
291
313
  try {
292
314
  const { createHostAdbBridge } = await import("./host-adb-bridge.js");
293
- const hostAdbBridge = createHostAdbBridge();
315
+ // Phase 1b: register `bilibili.cookies` extension so the Phase 1c
316
+ // collector can pull WebView cookies from the user's Android Bilibili
317
+ // App. The factory is a pure function — no side effects until the
318
+ // handler is invoked, so cost of always-registering is zero.
319
+ const { createBilibiliCookiesExtension } =
320
+ await import("@chainlesschain/personal-data-hub/adapters/social-bilibili-adb");
321
+ // Phase 2a: register `douyin.pull-im-db` extension so the
322
+ // douyinAdbSync hub method can pull <uid>_im.db cohort from the
323
+ // user's Android Douyin App.
324
+ const { createDouyinDbExtension } =
325
+ await import("@chainlesschain/personal-data-hub/adapters/social-douyin-adb");
326
+ // Phase 3a: register `weibo.cookies` extension for the Weibo
327
+ // C-path collector (m.weibo.cn cookies + 4 HTTP endpoints).
328
+ const { createWeiboCookiesExtension } =
329
+ await import("@chainlesschain/personal-data-hub/adapters/social-weibo-adb");
330
+ // Phase 3c: register `xhs.cookies` extension for the Xhs C-path
331
+ // collector (xiaohongshu.com cookies + 4 endpoints with X-S sign).
332
+ const { createXhsCookiesExtension } =
333
+ await import("@chainlesschain/personal-data-hub/adapters/social-xiaohongshu-adb");
334
+ // Phase 6c: register `toutiao.cookies` extension for the Toutiao
335
+ // C-path collector (www.toutiao.com cookies + 4 endpoints, 3 of
336
+ // which need _signature signing — CLI context falls back to -99
337
+ // short-circuit, desktop wiring upgrades via ToutiaoSignBridge).
338
+ const { createToutiaoCookiesExtension } =
339
+ await import("@chainlesschain/personal-data-hub/adapters/social-toutiao-adb");
340
+ // Phase 6d: register `kuaishou.cookies` extension. Profile from
341
+ // cookie's api_ph payload (no HTTP); 3 GraphQL POST endpoints need
342
+ // __NS_sig3 + kpf/kpn — CLI short-circuits, desktop upgrades via
343
+ // KuaishouSignBridge.
344
+ const { createKuaishouCookiesExtension } =
345
+ await import("@chainlesschain/personal-data-hub/adapters/social-kuaishou-adb");
346
+ hostAdbBridge = createHostAdbBridge({
347
+ extensions: {
348
+ "bilibili.cookies": createBilibiliCookiesExtension(),
349
+ "douyin.pull-im-db": createDouyinDbExtension(),
350
+ "weibo.cookies": createWeiboCookiesExtension(),
351
+ "xhs.cookies": createXhsCookiesExtension(),
352
+ "toutiao.cookies": createToutiaoCookiesExtension(),
353
+ "kuaishou.cookies": createKuaishouCookiesExtension(),
354
+ },
355
+ });
294
356
  sda._deps.bridgeProvider = () => hostAdbBridge;
295
357
  } catch (_e) {
296
358
  // Bridge module missing or failed to load — leave snapshot-only.
@@ -387,14 +449,21 @@ async function initHub() {
387
449
  // reads it; no per-account credential needed at boot. Each wrapped in
388
450
  // its own try so one broken ctor doesn't cascade.
389
451
  //
390
- // **Deferred** (need per-account credential `<vendor>-accounts.json`
391
- // loader infra similar to email/alipay/wechat, not yet built):
392
- // Train12306Adapter (opts.account.username)
393
- // CtripAdapter (opts.account.email)
394
- // AmapAdapter (opts.account.deviceId)
395
- // TaobaoAdapter (opts.account.userId)
396
- // TelegramAdapter (opts.account.userId)
397
- // WhatsAppAdapter (opts.account.phone)
452
+ // **No more deferred adapters at boot** 2026-05-25 final pass made all
453
+ // sqlite/device-pull adapters (Amap/Telegram/WhatsApp) ctor-optional:
454
+ // account.<x> dropped from required, inputPath alias added. The sqlite
455
+ // sync still requires the user to pre-extract the SQLite db (Telegram
456
+ // cache4.db unencrypted; WhatsApp msgstore.db needs WhatsApp Crypt key;
457
+ // Amap amap.db needs root ADB pull) — but the registry slot is now
458
+ // claimed so syncAdapter("<name>", path) routes correctly instead of
459
+ // "no adapter X" silent swallow. v0.2 followup: Android in-APK extractor
460
+ // for these 3 sqlite adapters (depends on root ADB / device-specific
461
+ // Crypt key recovery; previously blocked the whole code path before).
462
+ // Train12306Adapter moved out of deferred (v0.2 added snapshot mode —
463
+ // account.username OPTIONAL, see adapters/travel-12306/index.js:53-56);
464
+ // Android Kyfw12306LocalCollector ships snapshot JSON via
465
+ // ccRunner.syncAdapter("travel-12306", path) — must be registered here
466
+ // or cc returns "unknown adapter" + UI shows misleading "v0.2 补齐" hint.
398
467
  // Earlier oversight: v5.0.3.84 wired Telegram + WhatsApp here, but their
399
468
  // ctors throw without account args, so they were silently swallowed by
400
469
  // try/catch and never actually registered. Removed to make the list
@@ -411,6 +480,12 @@ async function initHub() {
411
480
  JdAdapter,
412
481
  MeituanAdapter,
413
482
  PinduoduoAdapter,
483
+ Train12306Adapter,
484
+ TaobaoAdapter,
485
+ CtripAdapter,
486
+ AmapAdapter,
487
+ TelegramAdapter,
488
+ WhatsAppAdapter,
414
489
  ]) {
415
490
  try {
416
491
  const adapter = new Cls();
@@ -420,6 +495,21 @@ async function initHub() {
420
495
  }
421
496
  }
422
497
 
498
+ // Phase 5.8 — email-imap snapshot mode (2026-05-25): Android
499
+ // EmailLocalCollector does Jakarta Mail IMAP fetch on-device + writes
500
+ // staging JSON; desktop EmailAdapter consumes it via snapshot path
501
+ // (no IMAP-account credential needed at boot). The user-driven
502
+ // `registerEmailAdapter` per-account flow still wires explicit IMAP
503
+ // sessions for desktop-direct IMAP fetch (different code path, both
504
+ // resolve `name === "email-imap"` — registry de-dups by name; the
505
+ // per-account flow wins when the user has registered an account).
506
+ try {
507
+ const emailSnapshot = new EmailAdapter({ snapshotMode: true });
508
+ if (!registry.has(emailSnapshot.name)) registry.register(emailSnapshot);
509
+ } catch (_err) {
510
+ // Continue boot even if snapshot ctor throws (shouldn't happen — no required opts)
511
+ }
512
+
423
513
  // Phase 6: auto-register persisted Alipay accounts.
424
514
  const alipayAccountsPath = join(hubDir, "alipay-accounts.json");
425
515
  const alipayAccounts = loadAlipayAccounts(alipayAccountsPath);
@@ -529,8 +619,12 @@ async function initHub() {
529
619
  if (!account || typeof account !== "object")
530
620
  throw new Error("account required");
531
621
  const adapter = new EmailAdapter({ account, ...opts });
622
+ // Phase 5.8 — if the boot-time snapshot stub claimed the "email-imap"
623
+ // slot, swap it out for this per-account IMAP adapter (user's explicit
624
+ // IMAP credentials should take priority over the Android-snapshot
625
+ // fallback). Both share `name === "email-imap"`.
532
626
  if (registry.has(adapter.name)) {
533
- throw new Error(`adapter name "${adapter.name}" already registered`);
627
+ registry.unregister(adapter.name);
534
628
  }
535
629
  registry.register(adapter);
536
630
  const accounts = loadEmailAccounts(emailAccountsPath);
@@ -550,7 +644,16 @@ async function initHub() {
550
644
  const target = accounts.find((c) => c.account.email === emailAddress);
551
645
  const next = accounts.filter((c) => c.account.email !== emailAddress);
552
646
  saveEmailAccounts(emailAccountsPath, next);
553
- if (target) registry.unregister("email-imap");
647
+ if (target) {
648
+ registry.unregister("email-imap");
649
+ // Phase 5.8 — restore the snapshot stub so Android sync paths still
650
+ // work after the user unregisters their explicit IMAP account.
651
+ try {
652
+ registry.register(new EmailAdapter({ snapshotMode: true }));
653
+ } catch (_err) {
654
+ // Defensive — snapshot ctor has no required opts so this shouldn't fail
655
+ }
656
+ }
554
657
  return { ok: true, removed: !!target };
555
658
  },
556
659
 
@@ -735,6 +838,362 @@ async function initHub() {
735
838
  lastSyncAt: row.lastSyncAt || null,
736
839
  }));
737
840
  },
841
+
842
+ // ─── Phase 1e — Bilibili C 路径 dry-run env probe ────────────────────
843
+ //
844
+ // "Doctor" mode mirrors `cc hub wechat doctor`: runs only the cookies-
845
+ // extraction half of the sync pipeline (no API calls, no vault writes)
846
+ // so the user can confirm root / Bilibili-installed / cookie-complete
847
+ // status before triggering a real sync. Same 9 typed reasons as
848
+ // bilibiliAdbSync — UI maps reasons to the same banners — but with
849
+ // an extra `cookieDiagnostic` payload on success so the doctor can
850
+ // print "found 5 of 5 cookies, no encrypted_value rows skipped, uid=N".
851
+ //
852
+ // Returns one of:
853
+ // {ok: true, uid, extractedAt, cookieDiagnostic: {cookieCount, hadEncrypted}}
854
+ // {ok: false, reason, message} — same reason taxonomy as
855
+ // bilibiliAdbSync; UI re-uses bilibiliReasonMessage()
856
+ async bilibiliAdbDoctor() {
857
+ if (!hostAdbBridge) {
858
+ return {
859
+ ok: false,
860
+ reason: "BRIDGE_UNAVAILABLE",
861
+ message:
862
+ "host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
863
+ };
864
+ }
865
+ try {
866
+ const result = await hostAdbBridge.invoke("bilibili.cookies");
867
+ return {
868
+ ok: true,
869
+ uid: result.uid,
870
+ extractedAt: result.extractedAt,
871
+ cookieDiagnostic: result.diagnostic || null,
872
+ };
873
+ } catch (err) {
874
+ const msg = err && err.message ? err.message : String(err);
875
+ const m = msg.match(/^(BILIBILI_[A-Z_]+)/);
876
+ return {
877
+ ok: false,
878
+ reason: m ? m[1] : "PROBE_FAILED",
879
+ message: msg,
880
+ };
881
+ }
882
+ },
883
+
884
+ // ─── Phase 1c — Bilibili C 路径 one-shot sync ────────────────────────
885
+ //
886
+ // Pulls cookies via the bilibili.cookies extension (P1a) → fetches
887
+ // history/favourite/dynamic/follow via BilibiliApiClient (P1b) → writes
888
+ // a snapshot JSON → calls registry.syncAdapter("social-bilibili") to
889
+ // ingest into the vault. Always cleans up the staging file even on
890
+ // error. Returns `{ok: true, report}` on success or
891
+ // `{ok: false, reason, message}` on failure with a stable typed reason
892
+ // string the UI can pattern-match (BILIBILI_NO_ROOT /
893
+ // BILIBILI_NOT_INSTALLED_OR_NEVER_LOGGED_IN / BILIBILI_COOKIES_INCOMPLETE
894
+ // / SYNC_FAILED / BRIDGE_UNAVAILABLE).
895
+ async bilibiliAdbSync(opts = {}) {
896
+ if (!hostAdbBridge) {
897
+ return {
898
+ ok: false,
899
+ reason: "BRIDGE_UNAVAILABLE",
900
+ message:
901
+ "host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
902
+ };
903
+ }
904
+ let collector;
905
+ try {
906
+ const mod =
907
+ await import("@chainlesschain/personal-data-hub/adapters/social-bilibili-adb");
908
+ collector = mod.default ? mod.default : mod;
909
+ } catch (err) {
910
+ return {
911
+ ok: false,
912
+ reason: "MODULE_LOAD_FAILED",
913
+ message: err && err.message ? err.message : String(err),
914
+ };
915
+ }
916
+ try {
917
+ const report = await collector.collectAndSync(
918
+ hostAdbBridge,
919
+ registry,
920
+ opts,
921
+ );
922
+ return { ok: true, report };
923
+ } catch (err) {
924
+ const msg = err && err.message ? err.message : String(err);
925
+ // Extract a typed reason prefix from the BILIBILI_* error codes
926
+ // the cookies-extension throws, falling back to SYNC_FAILED for
927
+ // anything from the API client / registry path.
928
+ const m = msg.match(/^(BILIBILI_[A-Z_]+)/);
929
+ return {
930
+ ok: false,
931
+ reason: m ? m[1] : "SYNC_FAILED",
932
+ message: msg,
933
+ };
934
+ }
935
+ },
936
+
937
+ // ─── Phase 2a — Douyin C 路径 one-shot sync ─────────────────────────
938
+ //
939
+ // Pulls <uid>_im.db cohort via the douyin.pull-im-db extension (P2a) →
940
+ // parses msg + SIMPLE_USER (abrignoni DFIR) → writes snapshot →
941
+ // syncAdapter("social-douyin") snapshot mode.
942
+ //
943
+ // 9 typed reason codes: BRIDGE_UNAVAILABLE / MODULE_LOAD_FAILED /
944
+ // DOUYIN_NO_ROOT / DOUYIN_NOT_INSTALLED / DOUYIN_NO_IM_DB /
945
+ // DOUYIN_MULTIPLE_USERS / DOUYIN_PULL_FAILED / DOUYIN_NOT_SQLITE /
946
+ // SYNC_FAILED.
947
+ async douyinAdbSync(opts = {}) {
948
+ if (!hostAdbBridge) {
949
+ return {
950
+ ok: false,
951
+ reason: "BRIDGE_UNAVAILABLE",
952
+ message:
953
+ "host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
954
+ };
955
+ }
956
+ let collector;
957
+ try {
958
+ const mod =
959
+ await import("@chainlesschain/personal-data-hub/adapters/social-douyin-adb");
960
+ collector = mod.default ? mod.default : mod;
961
+ } catch (err) {
962
+ return {
963
+ ok: false,
964
+ reason: "MODULE_LOAD_FAILED",
965
+ message: err && err.message ? err.message : String(err),
966
+ };
967
+ }
968
+ try {
969
+ const report = await collector.collectAndSync(
970
+ hostAdbBridge,
971
+ registry,
972
+ opts,
973
+ );
974
+ return { ok: true, report };
975
+ } catch (err) {
976
+ const msg = err && err.message ? err.message : String(err);
977
+ const m = msg.match(/^(DOUYIN_[A-Z_]+)/);
978
+ return {
979
+ ok: false,
980
+ reason: m ? m[1] : "SYNC_FAILED",
981
+ message: msg,
982
+ };
983
+ }
984
+ },
985
+
986
+ // ─── Phase 3a — Weibo C 路径 one-shot sync ──────────────────────────
987
+ //
988
+ // Pulls m.weibo.cn cookies via the weibo.cookies extension → fetchUid
989
+ // (/api/config — cookie has no inline UID) → 3 endpoints (posts /
990
+ // favourites / follows) → snapshot → syncAdapter("social-weibo")
991
+ // snapshot mode. **No WBI signing** (m.weibo.cn mobile API is
992
+ // sign-less).
993
+ //
994
+ // Typed reason codes: BRIDGE_UNAVAILABLE / MODULE_LOAD_FAILED /
995
+ // WEIBO_NO_ROOT / WEIBO_NOT_INSTALLED / WEIBO_COOKIES_EMPTY /
996
+ // WEIBO_COOKIES_TRUNCATED / WEIBO_NOT_SQLITE / WEIBO_COOKIES_INCOMPLETE /
997
+ // WEIBO_BASE64_PARSE / SYNC_FAILED.
998
+ async weiboAdbSync(opts = {}) {
999
+ if (!hostAdbBridge) {
1000
+ return {
1001
+ ok: false,
1002
+ reason: "BRIDGE_UNAVAILABLE",
1003
+ message:
1004
+ "host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
1005
+ };
1006
+ }
1007
+ let collector;
1008
+ try {
1009
+ const mod =
1010
+ await import("@chainlesschain/personal-data-hub/adapters/social-weibo-adb");
1011
+ collector = mod.default ? mod.default : mod;
1012
+ } catch (err) {
1013
+ return {
1014
+ ok: false,
1015
+ reason: "MODULE_LOAD_FAILED",
1016
+ message: err && err.message ? err.message : String(err),
1017
+ };
1018
+ }
1019
+ try {
1020
+ const report = await collector.collectAndSync(
1021
+ hostAdbBridge,
1022
+ registry,
1023
+ opts,
1024
+ );
1025
+ return { ok: true, report };
1026
+ } catch (err) {
1027
+ const msg = err && err.message ? err.message : String(err);
1028
+ const m = msg.match(/^(WEIBO_[A-Z_]+)/);
1029
+ return {
1030
+ ok: false,
1031
+ reason: m ? m[1] : "SYNC_FAILED",
1032
+ message: msg,
1033
+ };
1034
+ }
1035
+ },
1036
+
1037
+ // ─── Phase 3c — Xhs C 路径 one-shot sync ────────────────────────────
1038
+ //
1039
+ // Pulls xiaohongshu.com cookies via xhs.cookies extension → fetchMe
1040
+ // (/user/me — no X-S) → 3 endpoints (notes/liked/follows, X-S signed)
1041
+ // → snapshot → syncAdapter("social-xiaohongshu") snapshot mode.
1042
+ //
1043
+ // **X-S signing is best-effort** (~60% GET hit, <30% POST). Endpoint
1044
+ // failures tolerated as partial results — lastErrorCode surfaces the
1045
+ // 461 X-S rejection so UI can recommend "稍后重试".
1046
+ //
1047
+ // Typed reason codes: BRIDGE_UNAVAILABLE / MODULE_LOAD_FAILED /
1048
+ // XHS_NO_ROOT / XHS_NOT_INSTALLED / XHS_COOKIES_EMPTY /
1049
+ // XHS_COOKIES_TRUNCATED / XHS_NOT_SQLITE / XHS_COOKIES_INCOMPLETE /
1050
+ // XHS_BASE64_PARSE / SYNC_FAILED.
1051
+ async xhsAdbSync(opts = {}) {
1052
+ if (!hostAdbBridge) {
1053
+ return {
1054
+ ok: false,
1055
+ reason: "BRIDGE_UNAVAILABLE",
1056
+ message:
1057
+ "host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
1058
+ };
1059
+ }
1060
+ let collector;
1061
+ try {
1062
+ const mod =
1063
+ await import("@chainlesschain/personal-data-hub/adapters/social-xiaohongshu-adb");
1064
+ collector = mod.default ? mod.default : mod;
1065
+ } catch (err) {
1066
+ return {
1067
+ ok: false,
1068
+ reason: "MODULE_LOAD_FAILED",
1069
+ message: err && err.message ? err.message : String(err),
1070
+ };
1071
+ }
1072
+ try {
1073
+ const report = await collector.collectAndSync(
1074
+ hostAdbBridge,
1075
+ registry,
1076
+ opts,
1077
+ );
1078
+ return { ok: true, report };
1079
+ } catch (err) {
1080
+ const msg = err && err.message ? err.message : String(err);
1081
+ const m = msg.match(/^(XHS_[A-Z_]+)/);
1082
+ return {
1083
+ ok: false,
1084
+ reason: m ? m[1] : "SYNC_FAILED",
1085
+ message: msg,
1086
+ };
1087
+ }
1088
+ },
1089
+
1090
+ // ─── Phase 6c — Toutiao C 路径 one-shot sync ────────────────────────
1091
+ //
1092
+ // Pulls www.toutiao.com cookies via toutiao.cookies extension →
1093
+ // fetchProfile (/passport/account/info/v2 — no _sig) → 3 endpoints
1094
+ // (feed/collection/search, _signature required).
1095
+ //
1096
+ // **CLI context has NO sign bridge** — the 3 _signature endpoints
1097
+ // short-circuit with lastErrorCode=-99 (no HTTP traffic). Profile is
1098
+ // still fetched. Desktop wiring upgrades via ToutiaoSignBridge.
1099
+ //
1100
+ // Typed reason codes: BRIDGE_UNAVAILABLE / MODULE_LOAD_FAILED /
1101
+ // TOUTIAO_NO_ROOT / TOUTIAO_NOT_INSTALLED / TOUTIAO_COOKIES_EMPTY /
1102
+ // TOUTIAO_COOKIES_TRUNCATED / TOUTIAO_NOT_SQLITE /
1103
+ // TOUTIAO_COOKIES_INCOMPLETE / TOUTIAO_BASE64_PARSE / SYNC_FAILED.
1104
+ async toutiaoAdbSync(opts = {}) {
1105
+ if (!hostAdbBridge) {
1106
+ return {
1107
+ ok: false,
1108
+ reason: "BRIDGE_UNAVAILABLE",
1109
+ message:
1110
+ "host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
1111
+ };
1112
+ }
1113
+ let collector;
1114
+ try {
1115
+ const mod =
1116
+ await import("@chainlesschain/personal-data-hub/adapters/social-toutiao-adb");
1117
+ collector = mod.default ? mod.default : mod;
1118
+ } catch (err) {
1119
+ return {
1120
+ ok: false,
1121
+ reason: "MODULE_LOAD_FAILED",
1122
+ message: err && err.message ? err.message : String(err),
1123
+ };
1124
+ }
1125
+ try {
1126
+ const report = await collector.collectAndSync(
1127
+ hostAdbBridge,
1128
+ registry,
1129
+ opts,
1130
+ );
1131
+ return { ok: true, report };
1132
+ } catch (err) {
1133
+ const msg = err && err.message ? err.message : String(err);
1134
+ const m = msg.match(/^(TOUTIAO_[A-Z_]+)/);
1135
+ return {
1136
+ ok: false,
1137
+ reason: m ? m[1] : "SYNC_FAILED",
1138
+ message: msg,
1139
+ };
1140
+ }
1141
+ },
1142
+
1143
+ // ─── Phase 6d — Kuaishou C 路径 one-shot sync ───────────────────────
1144
+ //
1145
+ // Pulls www.kuaishou.com cookies via kuaishou.cookies extension →
1146
+ // fetchProfile (PURE COOKIE PARSE — reads api_ph payload, no HTTP)
1147
+ // → 3 signed GraphQL POST endpoints (visionFeedRecommend /
1148
+ // visionProfilePhotoList / visionSearchPhoto, __NS_sig3 + kpf/kpn).
1149
+ //
1150
+ // **CLI context has NO sign bridge** — 3 signed endpoints short-
1151
+ // circuit with lastErrorCode=-99 (no HTTP traffic). Profile + uid
1152
+ // still emit from cookie payload. Desktop wiring upgrades via
1153
+ // KuaishouSignBridge.
1154
+ //
1155
+ // Typed reason codes: BRIDGE_UNAVAILABLE / MODULE_LOAD_FAILED /
1156
+ // KUAISHOU_NO_ROOT / KUAISHOU_NOT_INSTALLED / KUAISHOU_COOKIES_EMPTY /
1157
+ // KUAISHOU_COOKIES_TRUNCATED / KUAISHOU_NOT_SQLITE /
1158
+ // KUAISHOU_COOKIES_INCOMPLETE / KUAISHOU_BASE64_PARSE / SYNC_FAILED.
1159
+ async kuaishouAdbSync(opts = {}) {
1160
+ if (!hostAdbBridge) {
1161
+ return {
1162
+ ok: false,
1163
+ reason: "BRIDGE_UNAVAILABLE",
1164
+ message:
1165
+ "host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
1166
+ };
1167
+ }
1168
+ let collector;
1169
+ try {
1170
+ const mod =
1171
+ await import("@chainlesschain/personal-data-hub/adapters/social-kuaishou-adb");
1172
+ collector = mod.default ? mod.default : mod;
1173
+ } catch (err) {
1174
+ return {
1175
+ ok: false,
1176
+ reason: "MODULE_LOAD_FAILED",
1177
+ message: err && err.message ? err.message : String(err),
1178
+ };
1179
+ }
1180
+ try {
1181
+ const report = await collector.collectAndSync(
1182
+ hostAdbBridge,
1183
+ registry,
1184
+ opts,
1185
+ );
1186
+ return { ok: true, report };
1187
+ } catch (err) {
1188
+ const msg = err && err.message ? err.message : String(err);
1189
+ const m = msg.match(/^(KUAISHOU_[A-Z_]+)/);
1190
+ return {
1191
+ ok: false,
1192
+ reason: m ? m[1] : "SYNC_FAILED",
1193
+ message: msg,
1194
+ };
1195
+ }
1196
+ },
738
1197
  };
739
1198
  }
740
1199