chainlesschain 0.162.12 → 0.162.14

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 (170) hide show
  1. package/README.md +29 -24
  2. package/package.json +5 -2
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-C3TDNq29.js → AIOps-D34d_Nh1.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-C9fE18pE.js → ActionButton-Br7HxCnl.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-wnZF602C.js → Analytics-bVKq79Xd.js} +1 -1
  7. package/src/assets/web-panel/assets/{AppLayout-BjgTMK7O.js → AppLayout-CWSLIbAz.js} +2 -2
  8. package/src/assets/web-panel/assets/{Audit-BBL0BW5_.js → Audit-Cmnu1qqa.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-BKLqYCWU.js → Backup-Rok20-TL.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-BGSzMCZs.js → BaseInput-BJzs_ZtT.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-CQWzZWEY.js → Chat-CSYapbcq.js} +1 -1
  12. package/src/assets/web-panel/assets/{Checkbox-BkTri12Q.js → Checkbox-BEa7Sr7e.js} +1 -1
  13. package/src/assets/web-panel/assets/{Codegen-BH1m09EO.js → Codegen-C9M4e7ne.js} +1 -1
  14. package/src/assets/web-panel/assets/{Col-BXnBuqIa.js → Col-DU9NoUIi.js} +1 -1
  15. package/src/assets/web-panel/assets/{Community-C_Nr4XCx.js → Community-DA9uz_jP.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compact-Du6GwLrj.js → Compact-3_bEraVw.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compliance-66M0oi1Q.js → Compliance-BtF8jWUQ.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cowork-DQrkZRNd.js → Cowork-BqvA7oaM.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cron-CwdIFH_v.js → Cron-CxZy7Mzg.js} +1 -1
  20. package/src/assets/web-panel/assets/{Crosschain-DqlcrQ9L.js → Crosschain-1DB-XRGu.js} +1 -1
  21. package/src/assets/web-panel/assets/{DID-OmPLKf7L.js → DID-B6Ezp1pt.js} +1 -1
  22. package/src/assets/web-panel/assets/{Dashboard-D_dampTL.js → Dashboard-QDJ6VVsn.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dropdown-CA1W7jAn.js → Dropdown-CovsWjxG.js} +1 -1
  24. package/src/assets/web-panel/assets/{Federation-Chlk9a7s.js → Federation-DbRxS4Y4.js} +1 -1
  25. package/src/assets/web-panel/assets/{FormItemContext-t0UqYFLq.js → FormItemContext-9E9dNGtx.js} +1 -1
  26. package/src/assets/web-panel/assets/{Git-CEq0raYm.js → Git-CqEpyxRZ.js} +2 -2
  27. package/src/assets/web-panel/assets/{Governance-C06CX7Ge.js → Governance-On47KtGq.js} +1 -1
  28. package/src/assets/web-panel/assets/{Inference-6VIFHxIP.js → Inference-RZcjcyaq.js} +1 -1
  29. package/src/assets/web-panel/assets/{KnowledgeGraph-BCJPjMBQ.js → KnowledgeGraph-C-1rRAM9.js} +1 -1
  30. package/src/assets/web-panel/assets/{Logs-BBpOYFct.js → Logs-BuunmG_r.js} +1 -1
  31. package/src/assets/web-panel/assets/{Marketplace-BFH6jMWt.js → Marketplace-CromymyA.js} +1 -1
  32. package/src/assets/web-panel/assets/{McpTools-uCFvRqGs.js → McpTools-5XlFExh7.js} +1 -1
  33. package/src/assets/web-panel/assets/{Memory-B0Kux_KT.js → Memory-DjnUT7YM.js} +1 -1
  34. package/src/assets/web-panel/assets/{MobileBridge-DHow2jiK.js → MobileBridge-BrYIgLg6.js} +1 -1
  35. package/src/assets/web-panel/assets/{MobileProjects-BFo9YQZp.js → MobileProjects-CL5V3fTm.js} +1 -1
  36. package/src/assets/web-panel/assets/{Mtc-riOh1G_F.js → Mtc-CHYJq6zK.js} +1 -1
  37. package/src/assets/web-panel/assets/{MtcAudit-Bm-hE2SP.js → MtcAudit-BZxUO0qt.js} +1 -1
  38. package/src/assets/web-panel/assets/{Multisig-DfUQxh5a.js → Multisig-FZTmJgW1.js} +2 -2
  39. package/src/assets/web-panel/assets/{NLProgramming-DuNvLBEq.js → NLProgramming-C9Mhefph.js} +1 -1
  40. package/src/assets/web-panel/assets/{Notes-DB20wd3c.js → Notes-W7usj-Ar.js} +1 -1
  41. package/src/assets/web-panel/assets/{NotificationSettings-CB-GkOWR.js → NotificationSettings-PBuYv_Bh.js} +1 -1
  42. package/src/assets/web-panel/assets/{Organization-3bU7PZuG.js → Organization-CuYCE-rF.js} +4 -4
  43. package/src/assets/web-panel/assets/{Overflow-BGCPP_0Y.js → Overflow-Dojx-kzE.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-BHgAe1oC.js → P2P-BgIaSrLX.js} +1 -1
  46. package/src/assets/web-panel/assets/{Permissions-BuOD4xwc.js → Permissions-Byj2dkF_.js} +1 -1
  47. package/src/assets/web-panel/assets/PersonalDataHub-CMOOI13-.js +1 -0
  48. package/src/assets/web-panel/assets/PersonalDataHub-Dvaa8niQ.css +1 -0
  49. package/src/assets/web-panel/assets/{Pipeline-DBS5U4LB.js → Pipeline-CWwEOF09.js} +1 -1
  50. package/src/assets/web-panel/assets/{Privacy-UNjIc5El.js → Privacy-VT7gldcN.js} +1 -1
  51. package/src/assets/web-panel/assets/{ProjectInit-CicqCJGy.js → ProjectInit-7UH3c3p7.js} +1 -1
  52. package/src/assets/web-panel/assets/{ProjectSettings-CIxAbt4Y.js → ProjectSettings-DqLp-72a.js} +1 -1
  53. package/src/assets/web-panel/assets/{Projects-BJycZScO.js → Projects-B_54eDhH.js} +1 -1
  54. package/src/assets/web-panel/assets/{Providers-DxXvprme.js → Providers-BIrNfNpc.js} +1 -1
  55. package/src/assets/web-panel/assets/{QuickAsk-rrqjU8_Y.js → QuickAsk-BbYPwCso.js} +1 -1
  56. package/src/assets/web-panel/assets/{Recommend-BEwHMhI7.js → Recommend-BF4qBssF.js} +1 -1
  57. package/src/assets/web-panel/assets/{Reputation-DoVKCCMn.js → Reputation-DPEzlC2V.js} +1 -1
  58. package/src/assets/web-panel/assets/{Row-F5XcDhHr.js → Row-DjHxhH1L.js} +1 -1
  59. package/src/assets/web-panel/assets/{RssFeed-cZrRG7k8.js → RssFeed-D0_j678P.js} +1 -1
  60. package/src/assets/web-panel/assets/{Search-B9ctZjqx.js → Search-DctfGehu.js} +1 -1
  61. package/src/assets/web-panel/assets/{Security-Z62hl1mc.js → Security-BFHggeYM.js} +1 -1
  62. package/src/assets/web-panel/assets/{Services-CQf5XqgZ.js → Services-CmrFMukV.js} +1 -1
  63. package/src/assets/web-panel/assets/{Skeleton-DuCKw2Eh.js → Skeleton-DR4vn_nS.js} +1 -1
  64. package/src/assets/web-panel/assets/{Skills-qVkhva0s.js → Skills-DlXG2yyV.js} +1 -1
  65. package/src/assets/web-panel/assets/{Sla-BQbatr7s.js → Sla-4PPGL3SE.js} +1 -1
  66. package/src/assets/web-panel/assets/{SpeechSettings-DLFBzAgD.js → SpeechSettings-D9EhJOqm.js} +1 -1
  67. package/src/assets/web-panel/assets/{SyncSettings-CrzETZMW.js → SyncSettings-Dasmbi0p.js} +1 -1
  68. package/src/assets/web-panel/assets/{Tasks-D_EQ1nJ7.js → Tasks-vilEiuPA.js} +1 -1
  69. package/src/assets/web-panel/assets/{Templates-D4y-dGRc.js → Templates-Ca9Rvktn.js} +1 -1
  70. package/src/assets/web-panel/assets/{Tenant-2XI0jkPn.js → Tenant-CEZb9gfK.js} +1 -1
  71. package/src/assets/web-panel/assets/{Terminal-fUi5V2Z9.js → Terminal-DanCBdbD.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tokens-BuUNB2mg.js → Tokens-SPkClW2d.js} +1 -1
  73. package/src/assets/web-panel/assets/{Trigger-7DqLLuej.js → Trigger-B645yL7g.js} +1 -1
  74. package/src/assets/web-panel/assets/{Trust-CeACvTYx.js → Trust-D9sM_Ig0.js} +1 -1
  75. package/src/assets/web-panel/assets/{UkeySign-mDP9EXHq.js → UkeySign-B_Nr2K-u.js} +1 -1
  76. package/src/assets/web-panel/assets/{VideoEditing-veWlKclv.js → VideoEditing-U01Lea8j.js} +1 -1
  77. package/src/assets/web-panel/assets/{Wallet-Cd2Hheb8.js → Wallet-6xBySVV8.js} +1 -1
  78. package/src/assets/web-panel/assets/{WebAuthn-DyL7ZiHX.js → WebAuthn-DbgMoBu6.js} +3 -3
  79. package/src/assets/web-panel/assets/{WorkflowEditor-C7-7LJH9.js → WorkflowEditor-Bz-Y6IR2.js} +1 -1
  80. package/src/assets/web-panel/assets/{chat-DXomZMuo.js → chat-BC_O9hag.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-DlU92QNs.js → colors-ChlOGOvr.js} +1 -1
  83. package/src/assets/web-panel/assets/{compact-item-sBiTL8mX.js → compact-item-BSbAYGGF.js} +1 -1
  84. package/src/assets/web-panel/assets/{createContext-DZXEnzum.js → createContext-CFcZly5M.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-CpCHBZ2M.js → hasIn-BomYwwYE.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-B0Qbxr57.js → index-5Ewm6KZA.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-CjXSvceY.js → index-B6LJHQoE.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-CD3iljXs.js → index-BEJ6YiLI.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-BK2AFy44.js → index-BGUbtM3R.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-Di1_EQ-X.js → index-BHGsFwYW.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-B23tuoo9.js → index-BHi69MHF.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DUlPMzoM.js → index-BI1jAWcc.js} +1 -1
  95. package/src/assets/web-panel/assets/index-BIRYt1of.js +1 -0
  96. package/src/assets/web-panel/assets/{index-B3k9UPHc.js → index-BYDvb1pi.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CwbWZubA.js → index-BZGdjNLA.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-ThrAiEF9.js → index-BwFykZ5U.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CUe5t5Aa.js → index-ByZQNO0A.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-Dn8m1d1f.js → index-C0rr1X9W.js} +2 -2
  101. package/src/assets/web-panel/assets/{index-C6SDf50u.js → index-CBhoZhCO.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-ClN_JuFa.js → index-CCRSz2cR.js} +1 -1
  103. package/src/assets/web-panel/assets/index-CZfySmWX.js +1 -0
  104. package/src/assets/web-panel/assets/{index-Dq5Rn5VS.js → index-Cj47XwJQ.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-ChahjdYE.js → index-Cmzh8gKL.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Dyg6ikIL.js → index-CnxlKTDK.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Dj9Nvz6S.js → index-CoF95pYK.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-TwQZkVGh.js → index-Ctx97mH-.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-s8tvk-fF.js → index-D0vX9jQA.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-X48zYgZ6.js → index-DNkth8dM.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DygNvCeR.js → index-DRp5_Xns.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D_MzScPM.js → index-DW-Ji07y.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BqnhEJls.js → index-DXgE2VW6.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CDyzZ8_O.js → index-D_0B3CiU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C59FgSkU.js → index-Dbf5YmDX.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-_zyXBoS7.js → index-DsNQ2hqI.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CJ7XYa5K.js → index-EY733h9z.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-ibFHnqHz.js → index-QD_n54XT.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CivbS-57.js → index-T5Y_9IPv.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-C52udT0_.js → index-b8GbH2Yi.js} +4 -4
  121. package/src/assets/web-panel/assets/{index-XI6772AD.js → index-gUACAWbM.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-F9cBucYf.js → index-onW325hZ.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DKe9jmKG.js → index-ozVPr1gj.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-D_IgY63-.js → index-slYX2rCE.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B_-RETt0.js → index-t9u2bHpH.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DeGnHcp5.js → index-za1GUJBG.js} +1 -1
  127. package/src/assets/web-panel/assets/{initDefaultProps-DEi92ZnZ.js → initDefaultProps-DnadEaxu.js} +1 -1
  128. package/src/assets/web-panel/assets/{motion-BtYKzpOc.js → motion-CC_Na0Tl.js} +1 -1
  129. package/src/assets/web-panel/assets/{move-Cb3A1-v-.js → move-C2d9Mkk9.js} +1 -1
  130. package/src/assets/web-panel/assets/{omit-B6qPDdOf.js → omit-QvpKbF8p.js} +1 -1
  131. package/src/assets/web-panel/assets/{pickAttrs-DDyeQMUc.js → pickAttrs-Dm8r3X1_.js} +1 -1
  132. package/src/assets/web-panel/assets/{placementArrow-BPV6VO47.js → placementArrow-DaqaVfoX.js} +1 -1
  133. package/src/assets/web-panel/assets/{responsiveObserve-DJ1ra4dT.js → responsiveObserve-Iida9fIn.js} +1 -1
  134. package/src/assets/web-panel/assets/{slide-D6v8tHvB.js → slide-YqHexXQD.js} +1 -1
  135. package/src/assets/web-panel/assets/{statusUtils-DulKcQLZ.js → statusUtils-BGKLoeEt.js} +1 -1
  136. package/src/assets/web-panel/assets/{styleChecker-Bne7zwMt.js → styleChecker-aI-gsQO8.js} +1 -1
  137. package/src/assets/web-panel/assets/useFlexGapSupport-BiOsz4rc.js +1 -0
  138. package/src/assets/web-panel/assets/{useFs-CR-iLa4Z.js → useFs-CZy7Zo2X.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-yL9axxBy.js → vnode-B6WqjmE4.js} +1 -1
  144. package/src/assets/web-panel/assets/{zoom-B-VCMXSD.js → zoom-DTeTrJ2z.js} +1 -1
  145. package/src/assets/web-panel/index.html +3 -3
  146. package/src/commands/__tests__/android.test.js +260 -0
  147. package/src/commands/__tests__/hub-aichat.test.js +277 -0
  148. package/src/commands/__tests__/hub-wechat.test.js +243 -0
  149. package/src/commands/android.js +284 -0
  150. package/src/commands/hub.js +457 -0
  151. package/src/commands/sync-providers.js +436 -0
  152. package/src/gateways/ws/personal-data-hub-protocol.js +88 -0
  153. package/src/index.js +6 -0
  154. package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +209 -0
  155. package/src/lib/__tests__/sync-credentials.test.js +265 -0
  156. package/src/lib/__tests__/sync-engine-cli.test.js +293 -0
  157. package/src/lib/cc-android-bridge.js +162 -0
  158. package/src/lib/personal-data-hub-aichat-wizard.js +242 -0
  159. package/src/lib/personal-data-hub-wiring.js +258 -13
  160. package/src/lib/sync-cli-db.js +194 -0
  161. package/src/lib/sync-credentials.js +225 -0
  162. package/src/lib/sync-engine-cli.js +406 -0
  163. package/src/lib/sync-oss-client.js +273 -0
  164. package/src/lib/sync-webdav-client.js +194 -0
  165. package/src/lib/web-ui-server.js +2 -1
  166. package/src/assets/web-panel/assets/PersonalDataHub--WA-aZAJ.js +0 -1
  167. package/src/assets/web-panel/assets/PersonalDataHub-BK7I0Rsb.css +0 -1
  168. package/src/assets/web-panel/assets/index-CcRX6BlT.js +0 -1
  169. package/src/assets/web-panel/assets/index-z6h6tqP3.js +0 -1
  170. package/src/assets/web-panel/assets/useFlexGapSupport-C1miTomM.js +0 -1
@@ -0,0 +1,436 @@
1
+ /**
2
+ * cc sync webdav / cc sync oss subcommand groups — Phase 3c follow-up.
3
+ *
4
+ * v0.1 (Phase 1):configure / status / clear — 凭据落 ~/.chainlesschain/
5
+ * sync-credentials.enc (AES-256-GCM),与 desktop secure-config 同 shape。
6
+ *
7
+ * v0.2 (Phase 2):test (real connectivity probe) + run (本机 vault 同步)
8
+ * — 需 @aws-sdk/client-s3 + webdav npm dep + better-sqlite3 vault wiring,
9
+ * 工程更大;本 commit 不含。
10
+ *
11
+ * 命令树:
12
+ * cc sync webdav configure --url ... --username ... --password ... [--remote-path]
13
+ * cc sync webdav status 显示 mask 后凭据 + configured 标记
14
+ * cc sync webdav clear 擦除凭据 + 在 vault 内移除该 provider
15
+ * cc sync oss configure --endpoint --region --bucket --access-key-id
16
+ * --secret-access-key [--remote-path] [--force-path-style]
17
+ * cc sync oss status
18
+ * cc sync oss clear
19
+ *
20
+ * password / secretAccessKey 走 stdin 提示也支持(避免 shell history 留痕)—
21
+ * 留 v0.2 加 prompts;v0.1 仅 flag。
22
+ */
23
+
24
+ "use strict";
25
+
26
+ import chalk from "chalk";
27
+ import {
28
+ ALLOWED_PROVIDER_IDS,
29
+ getCredentials,
30
+ getCredentialsSanitized,
31
+ hasCredentials,
32
+ setCredentials,
33
+ clearCredentials,
34
+ } from "../lib/sync-credentials.js";
35
+ import { WebDAVClient } from "../lib/sync-webdav-client.js";
36
+ import { OSSClient } from "../lib/sync-oss-client.js";
37
+ import { runSync } from "../lib/sync-engine-cli.js";
38
+ import { openCliVault } from "../lib/sync-cli-db.js";
39
+
40
+ function _ensureValidProvider(name) {
41
+ if (!ALLOWED_PROVIDER_IDS.includes(name)) {
42
+ throw new Error(
43
+ `Unknown sync provider '${name}' (allowed: ${ALLOWED_PROVIDER_IDS.join(", ")})`,
44
+ );
45
+ }
46
+ }
47
+
48
+ function _printStatus(providerId) {
49
+ _ensureValidProvider(providerId);
50
+ const masked = getCredentialsSanitized(providerId);
51
+ const configured = hasCredentials(providerId);
52
+ console.log(
53
+ JSON.stringify(
54
+ {
55
+ provider: providerId,
56
+ configured,
57
+ credentials: masked,
58
+ notes: configured
59
+ ? [
60
+ "secrets are masked; raw values stored encrypted at ~/.chainlesschain/sync-credentials.enc",
61
+ ]
62
+ : ["not configured; run `cc sync <provider> configure --<flags>`"],
63
+ },
64
+ null,
65
+ 2,
66
+ ),
67
+ );
68
+ }
69
+
70
+ function _configureWebDAV(opts) {
71
+ const url = (opts.url || "").trim();
72
+ if (!url) throw new Error("--url required");
73
+ const username = (opts.username || "").trim();
74
+ const password = opts.password;
75
+ if (!password)
76
+ throw new Error("--password required (use stdin or env in v0.2)");
77
+ const remotePath = (opts.remotePath || "/").trim();
78
+ setCredentials("webdav", { url, username, password, remotePath });
79
+ console.log(chalk.green("✓ WebDAV credentials saved"));
80
+ console.log(chalk.dim(` url: ${url}`));
81
+ console.log(chalk.dim(` username: ${username}`));
82
+ console.log(chalk.dim(` password: ********`));
83
+ console.log(chalk.dim(` remotePath: ${remotePath}`));
84
+ }
85
+
86
+ function _configureOSS(opts) {
87
+ const endpoint = (opts.endpoint || "").trim();
88
+ if (!endpoint) throw new Error("--endpoint required");
89
+ const bucket = (opts.bucket || "").trim();
90
+ if (!bucket) throw new Error("--bucket required");
91
+ const accessKeyId = (opts.accessKeyId || "").trim();
92
+ if (!accessKeyId) throw new Error("--access-key-id required");
93
+ const secretAccessKey = opts.secretAccessKey;
94
+ if (!secretAccessKey) {
95
+ throw new Error("--secret-access-key required (use stdin or env in v0.2)");
96
+ }
97
+ const region = (opts.region || "auto").trim();
98
+ const remotePath = (opts.remotePath || "").trim();
99
+ const forcePathStyle = opts.forcePathStyle === true;
100
+ setCredentials("oss", {
101
+ endpoint,
102
+ region,
103
+ bucket,
104
+ accessKeyId,
105
+ secretAccessKey,
106
+ remotePath,
107
+ forcePathStyle,
108
+ });
109
+ console.log(chalk.green("✓ OSS / S3 credentials saved"));
110
+ console.log(chalk.dim(` endpoint: ${endpoint}`));
111
+ console.log(chalk.dim(` region: ${region}`));
112
+ console.log(chalk.dim(` bucket: ${bucket}`));
113
+ console.log(chalk.dim(` accessKeyId: ${accessKeyId}`));
114
+ console.log(chalk.dim(` secretAccessKey: ********`));
115
+ console.log(chalk.dim(` remotePath: ${remotePath}`));
116
+ console.log(chalk.dim(` forcePathStyle: ${forcePathStyle}`));
117
+ }
118
+
119
+ function _clearProvider(providerId) {
120
+ _ensureValidProvider(providerId);
121
+ if (!hasCredentials(providerId)) {
122
+ console.log(chalk.dim(`(${providerId} was already empty)`));
123
+ return;
124
+ }
125
+ clearCredentials(providerId);
126
+ console.log(chalk.green(`✓ ${providerId} credentials cleared`));
127
+ }
128
+
129
+ function _loadWebDAVCreds() {
130
+ const c = getCredentials("webdav");
131
+ if (!c.url || !c.password) return null;
132
+ return {
133
+ url: c.url,
134
+ username: c.username || "",
135
+ password: c.password,
136
+ remotePath: c.remotePath || "/",
137
+ };
138
+ }
139
+
140
+ function _loadOSSCreds() {
141
+ const c = getCredentials("oss");
142
+ if (!c.endpoint || !c.bucket || !c.accessKeyId || !c.secretAccessKey)
143
+ return null;
144
+ return {
145
+ endpoint: c.endpoint,
146
+ region: c.region || "auto",
147
+ bucket: c.bucket,
148
+ accessKeyId: c.accessKeyId,
149
+ secretAccessKey: c.secretAccessKey,
150
+ remotePath: c.remotePath || "",
151
+ forcePathStyle: c.forcePathStyle === true,
152
+ };
153
+ }
154
+
155
+ async function _testProvider(providerId) {
156
+ _ensureValidProvider(providerId);
157
+ const creds = providerId === "webdav" ? _loadWebDAVCreds() : _loadOSSCreds();
158
+ if (!creds) {
159
+ throw new Error(
160
+ `${providerId} 凭据未配置,先跑 \`cc sync ${providerId} configure --...\``,
161
+ );
162
+ }
163
+ const client =
164
+ providerId === "webdav" ? new WebDAVClient(creds) : new OSSClient(creds);
165
+ const res = await client.testConnection();
166
+ if (res.ok) {
167
+ console.log(chalk.green(`✓ ${providerId} 连接 OK`));
168
+ return;
169
+ }
170
+ console.error(
171
+ chalk.red(
172
+ `✗ ${providerId} 连接失败 (${res.status || "n/a"}): ${res.error}`,
173
+ ),
174
+ );
175
+ process.exitCode = 2;
176
+ }
177
+
178
+ async function _runProvider(providerId, opts = {}) {
179
+ _ensureValidProvider(providerId);
180
+ const creds = providerId === "webdav" ? _loadWebDAVCreds() : _loadOSSCreds();
181
+ if (!creds) {
182
+ throw new Error(
183
+ `${providerId} 凭据未配置,先跑 \`cc sync ${providerId} configure --...\``,
184
+ );
185
+ }
186
+
187
+ let vault;
188
+ try {
189
+ vault = await openCliVault();
190
+ } catch (err) {
191
+ if (err.code === "BETTER_SQLITE3_MISSING") {
192
+ console.error(chalk.red(`✗ ${err.message}`));
193
+ process.exitCode = 2;
194
+ return;
195
+ }
196
+ throw err;
197
+ }
198
+ const { dbManager, vaultPath } = vault;
199
+ if (opts.verbose) console.log(chalk.dim(`vault: ${vaultPath}`));
200
+
201
+ const client =
202
+ providerId === "webdav" ? new WebDAVClient(creds) : new OSSClient(creds);
203
+ let lastPrint = 0;
204
+ const onProgress = (e) => {
205
+ // Throttle stdout to avoid TTY thrash (engine already 5/500ms)
206
+ const now = Date.now();
207
+ if (
208
+ e.phase === "start" ||
209
+ ["success", "conflict", "failed"].includes(e.phase) ||
210
+ now - lastPrint >= 1000
211
+ ) {
212
+ lastPrint = now;
213
+ const parts = [`[${e.phase}]`];
214
+ if (e.totalPending != null) parts.push(`total=${e.totalPending}`);
215
+ parts.push(
216
+ `pushed=${e.pushed}`,
217
+ `skipped=${e.skipped}`,
218
+ `deleted=${e.deleted}`,
219
+ );
220
+ console.log(chalk.dim(parts.join(" ")));
221
+ }
222
+ };
223
+
224
+ try {
225
+ const result = await runSync({
226
+ dbManager,
227
+ client,
228
+ providerId,
229
+ accountKey: "",
230
+ onProgress,
231
+ });
232
+ if (result.success) {
233
+ console.log(
234
+ chalk.green(`✓ ${providerId} sync done (${result.status})`) +
235
+ ` — pushed=${result.pushed} skipped=${result.skipped} deleted=${result.deleted} duration=${result.durationMs}ms`,
236
+ );
237
+ } else {
238
+ console.error(
239
+ chalk.red(`✗ ${providerId} sync failed`) +
240
+ ` — pushed=${result.pushed} skipped=${result.skipped} deleted=${result.deleted}`,
241
+ );
242
+ if (result.error) console.error(chalk.red(` error: ${result.error}`));
243
+ process.exitCode = 2;
244
+ }
245
+ } finally {
246
+ try {
247
+ dbManager.close();
248
+ } catch (_e) {
249
+ /* cleanup */
250
+ }
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Attach `cc sync webdav *` and `cc sync oss *` subcommands to the existing
256
+ * `cc sync` parent command. Caller passes the program; we find the sync
257
+ * parent and add children.
258
+ */
259
+ export function registerSyncProviderCommands(program) {
260
+ const parent = program.commands.find((c) => c.name() === "sync");
261
+ if (!parent) {
262
+ throw new Error(
263
+ "registerSyncProviderCommands: parent `sync` command not registered yet — call after registerSyncCommand",
264
+ );
265
+ }
266
+
267
+ // ── webdav subgroup ────────────────────────────────────────────
268
+ const webdav = parent
269
+ .command("webdav")
270
+ .description(
271
+ "WebDAV (Nextcloud / 坚果云 / 群晖) sync provider — credential management",
272
+ );
273
+
274
+ webdav
275
+ .command("configure")
276
+ .description(
277
+ "Save WebDAV credentials to ~/.chainlesschain/sync-credentials.enc",
278
+ )
279
+ .requiredOption("--url <url>", "WebDAV endpoint URL")
280
+ .option("--username <name>", "WebDAV username", "")
281
+ .requiredOption(
282
+ "--password <pw>",
283
+ "WebDAV password (use stdin in v0.2 — for now this WILL hit shell history)",
284
+ )
285
+ .option("--remote-path <p>", "remote directory path", "/")
286
+ .action(async (opts) => {
287
+ try {
288
+ _configureWebDAV(opts);
289
+ } catch (err) {
290
+ console.error(chalk.red(`✗ ${err?.message || err}`));
291
+ process.exitCode = 2;
292
+ }
293
+ });
294
+
295
+ webdav
296
+ .command("status")
297
+ .description("Show sanitized WebDAV credentials + configured flag")
298
+ .action(() => {
299
+ try {
300
+ _printStatus("webdav");
301
+ } catch (err) {
302
+ console.error(chalk.red(`✗ ${err?.message || err}`));
303
+ process.exitCode = 2;
304
+ }
305
+ });
306
+
307
+ webdav
308
+ .command("clear")
309
+ .description("Remove WebDAV credentials from vault")
310
+ .action(() => {
311
+ try {
312
+ _clearProvider("webdav");
313
+ } catch (err) {
314
+ console.error(chalk.red(`✗ ${err?.message || err}`));
315
+ process.exitCode = 2;
316
+ }
317
+ });
318
+
319
+ webdav
320
+ .command("test")
321
+ .description("Probe WebDAV connectivity (PROPFIND on remotePath)")
322
+ .action(async () => {
323
+ try {
324
+ await _testProvider("webdav");
325
+ } catch (err) {
326
+ console.error(chalk.red(`✗ ${err?.message || err}`));
327
+ process.exitCode = 2;
328
+ }
329
+ });
330
+
331
+ webdav
332
+ .command("run")
333
+ .description(
334
+ "Run one full WebDAV sync against ~/.chainlesschain/cli-vault.db",
335
+ )
336
+ .option("-v, --verbose", "show vault path + verbose progress", false)
337
+ .action(async (opts) => {
338
+ try {
339
+ await _runProvider("webdav", opts);
340
+ } catch (err) {
341
+ console.error(chalk.red(`✗ ${err?.message || err}`));
342
+ process.exitCode = 2;
343
+ }
344
+ });
345
+
346
+ // ── oss subgroup ───────────────────────────────────────────────
347
+ const oss = parent
348
+ .command("oss")
349
+ .description(
350
+ "S3 / OSS (AWS / 阿里云 / R2 / B2) sync provider — credential management",
351
+ );
352
+
353
+ oss
354
+ .command("configure")
355
+ .description(
356
+ "Save OSS credentials to ~/.chainlesschain/sync-credentials.enc",
357
+ )
358
+ .requiredOption(
359
+ "--endpoint <url>",
360
+ "S3-compat endpoint URL (e.g. https://oss-cn-hangzhou.aliyuncs.com)",
361
+ )
362
+ .option(
363
+ "--region <r>",
364
+ "region (default: auto for R2 / explicit for AWS+aliyun)",
365
+ "auto",
366
+ )
367
+ .requiredOption("--bucket <name>", "target bucket name")
368
+ .requiredOption("--access-key-id <id>", "access key id")
369
+ .requiredOption(
370
+ "--secret-access-key <secret>",
371
+ "secret access key (use stdin in v0.2 — hits shell history now)",
372
+ )
373
+ .option("--remote-path <p>", "object key prefix", "")
374
+ .option(
375
+ "--force-path-style",
376
+ "use path-style URLs (R2 / MinIO need true)",
377
+ false,
378
+ )
379
+ .action(async (opts) => {
380
+ try {
381
+ _configureOSS(opts);
382
+ } catch (err) {
383
+ console.error(chalk.red(`✗ ${err?.message || err}`));
384
+ process.exitCode = 2;
385
+ }
386
+ });
387
+
388
+ oss
389
+ .command("status")
390
+ .description("Show sanitized OSS credentials + configured flag")
391
+ .action(() => {
392
+ try {
393
+ _printStatus("oss");
394
+ } catch (err) {
395
+ console.error(chalk.red(`✗ ${err?.message || err}`));
396
+ process.exitCode = 2;
397
+ }
398
+ });
399
+
400
+ oss
401
+ .command("clear")
402
+ .description("Remove OSS credentials from vault")
403
+ .action(() => {
404
+ try {
405
+ _clearProvider("oss");
406
+ } catch (err) {
407
+ console.error(chalk.red(`✗ ${err?.message || err}`));
408
+ process.exitCode = 2;
409
+ }
410
+ });
411
+
412
+ oss
413
+ .command("test")
414
+ .description("Probe S3 / OSS connectivity (HeadBucket)")
415
+ .action(async () => {
416
+ try {
417
+ await _testProvider("oss");
418
+ } catch (err) {
419
+ console.error(chalk.red(`✗ ${err?.message || err}`));
420
+ process.exitCode = 2;
421
+ }
422
+ });
423
+
424
+ oss
425
+ .command("run")
426
+ .description("Run one full OSS sync against ~/.chainlesschain/cli-vault.db")
427
+ .option("-v, --verbose", "show vault path + verbose progress", false)
428
+ .action(async (opts) => {
429
+ try {
430
+ await _runProvider("oss", opts);
431
+ } catch (err) {
432
+ console.error(chalk.red(`✗ ${err?.message || err}`));
433
+ process.exitCode = 2;
434
+ }
435
+ });
436
+ }
@@ -21,8 +21,12 @@ import {
21
21
  getHub,
22
22
  close as closeHub,
23
23
  } from "../../lib/personal-data-hub-wiring.js";
24
+ import { getAIChatWizard } from "../../lib/personal-data-hub-aichat-wizard.js";
24
25
  import { existsSync, unlinkSync, readdirSync } from "node:fs";
25
26
  import { join } from "node:path";
27
+ import pdhPkg from "@chainlesschain/personal-data-hub";
28
+
29
+ const { ingestSystemDataAndroidSnapshot } = pdhPkg;
26
30
 
27
31
  async function withHub(fn) {
28
32
  try {
@@ -41,6 +45,22 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
41
45
  return await hub.engine.ask(msg.question, msg.options || {});
42
46
  }),
43
47
 
48
+ // Path Y: prompt context only, no LLM call. Lets web-shell / mobile host
49
+ // its own inference (Volcengine Doubao, OpenRouter, etc.) while keeping
50
+ // vault retrieval centralized.
51
+ "personal-data-hub.retrieve-context": async (msg) =>
52
+ withHub(async (hub) => {
53
+ if (!hub.engine) throw new Error("Analysis engine unavailable");
54
+ return await hub.engine.retrieveContext(msg.question, msg.options || {});
55
+ }),
56
+
57
+ // Path C: phone-collected ContentResolver + PackageManager snapshot →
58
+ // staging file → syncAdapter(system-data-android). Returns SyncReport.
59
+ "personal-data-hub.ingest-system-data-android": async (msg) =>
60
+ withHub(
61
+ async (hub) => await ingestSystemDataAndroidSnapshot(hub, msg.snapshot),
62
+ ),
63
+
44
64
  "personal-data-hub.stats": async () =>
45
65
  withHub((hub) => ({
46
66
  vault: hub.vault.stats(),
@@ -212,6 +232,29 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
212
232
  }),
213
233
  ),
214
234
 
235
+ // ─── Phase 12.6.8 — WeChat env-probe + register / unregister / list ──
236
+
237
+ "personal-data-hub.wechat-env-probe": async () =>
238
+ withHub(async (hub) => await hub.probeWechatEnv()),
239
+
240
+ "personal-data-hub.register-wechat": async (msg) =>
241
+ withHub(
242
+ async (hub) =>
243
+ await hub.registerWechatAdapter({
244
+ account: msg.account,
245
+ dbPath: msg.dbPath,
246
+ wechatDataPath: msg.wechatDataPath,
247
+ fridaOpts: msg.fridaOpts,
248
+ keyProviderOverride: msg.keyProviderOverride,
249
+ }),
250
+ ),
251
+
252
+ "personal-data-hub.unregister-wechat": async (msg) =>
253
+ withHub(async (hub) => await hub.unregisterWechatAdapter(msg.uin)),
254
+
255
+ "personal-data-hub.list-wechat-accounts": async () =>
256
+ withHub((hub) => hub.listWechatAccounts()),
257
+
215
258
  // ─── Phase 8 — EntityResolver review / merge / unmerge ───────────────
216
259
 
217
260
  "personal-data-hub.review-queue-list": async (msg) =>
@@ -264,6 +307,51 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
264
307
 
265
308
  "personal-data-hub.run-skill": async (msg) =>
266
309
  withHub(async (hub) => await hub.runSkill(msg.name, msg.options || {})),
310
+
311
+ // ─── Phase 10.3 — AIChat WebView 鉴权向导 (paste-mode on cc ui) ────────
312
+
313
+ "personal-data-hub.aichat-open-login": async (msg) =>
314
+ withHub(async (hub) => {
315
+ const wiz = getAIChatWizard({ hubDir: hub.hubDir });
316
+ return await wiz.openVendorLogin({
317
+ vendor: msg.vendor,
318
+ opts: msg.opts || {},
319
+ });
320
+ }),
321
+
322
+ "personal-data-hub.aichat-probe-cookies": async (msg) =>
323
+ withHub(async (hub) => {
324
+ const wiz = getAIChatWizard({ hubDir: hub.hubDir });
325
+ return await wiz.probeCookies({
326
+ vendor: msg.vendor,
327
+ cookieHeader: msg.cookieHeader,
328
+ });
329
+ }),
330
+
331
+ "personal-data-hub.aichat-register-vendor": async (msg) =>
332
+ withHub(async (hub) => {
333
+ const wiz = getAIChatWizard({ hubDir: hub.hubDir });
334
+ return await wiz.registerVendor({
335
+ vendor: msg.vendor,
336
+ cookies: msg.cookies,
337
+ opts: msg.opts || {},
338
+ });
339
+ }),
340
+
341
+ "personal-data-hub.aichat-rotate-login": async (msg) =>
342
+ withHub(async (hub) => {
343
+ const wiz = getAIChatWizard({ hubDir: hub.hubDir });
344
+ return await wiz.rotateLoginPartition({ vendor: msg.vendor });
345
+ }),
346
+
347
+ "personal-data-hub.list-aichat-accounts": async () =>
348
+ withHub(async (hub) => await hub.listAIChatAccounts()),
349
+
350
+ "personal-data-hub.unregister-aichat": async (msg) =>
351
+ withHub(async (hub) => await hub.unregisterAIChatVendor(msg.vendor)),
352
+
353
+ "personal-data-hub.aichat-health-check-once": async () =>
354
+ withHub(async (hub) => await hub.runAIChatHealthCheckOnce()),
267
355
  };
268
356
 
269
357
  /**
package/src/index.js CHANGED
@@ -16,6 +16,7 @@ import { registerChatCommand } from "./commands/chat.js";
16
16
  import { registerAskCommand } from "./commands/ask.js";
17
17
  import { registerLlmCommand } from "./commands/llm.js";
18
18
  import { registerHubCommand } from "./commands/hub.js";
19
+ import { registerAndroidCommand } from "./commands/android.js";
19
20
  import {
20
21
  registerAgentCommand,
21
22
  registerSubAgentV2Command,
@@ -68,6 +69,7 @@ import { registerAuthCommand } from "./commands/auth.js";
68
69
  import { registerAuditCommand } from "./commands/audit.js";
69
70
  import { registerP2pCommand } from "./commands/p2p.js";
70
71
  import { registerSyncCommand } from "./commands/sync.js";
72
+ import { registerSyncProviderCommands } from "./commands/sync-providers.js";
71
73
  import { registerWalletCommand } from "./commands/wallet.js";
72
74
  import { registerOrgCommand } from "./commands/org.js";
73
75
  import { registerPluginCommand } from "./commands/plugin.js";
@@ -406,6 +408,7 @@ export function createProgram(opts = {}) {
406
408
  registerAskCommand(program);
407
409
  registerLlmCommand(program);
408
410
  registerHubCommand(program);
411
+ registerAndroidCommand(program);
409
412
  registerAgentCommand(program);
410
413
  registerSubAgentV2Command(program);
411
414
  registerExecBackendV2Command(program);
@@ -466,6 +469,9 @@ export function createProgram(opts = {}) {
466
469
  // Phase 5: P2P, blockchain & enterprise
467
470
  registerP2pCommand(program);
468
471
  registerSyncCommand(program);
472
+ // Phase 3c follow-up — cc sync webdav / cc sync oss subgroups (credential mgmt).
473
+ // Must come AFTER registerSyncCommand so the `sync` parent exists.
474
+ registerSyncProviderCommands(program);
469
475
  registerWalletCommand(program);
470
476
  registerOrgCommand(program);
471
477
  registerPluginCommand(program);