chainlesschain 0.162.13 → 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 (145) hide show
  1. package/README.md +1 -1
  2. package/package.json +2 -2
  3. package/src/assets/web-panel/assets/{AIOps-Bq_zxhCr.js → AIOps-D34d_Nh1.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CaevDm9t.js → ActionButton-Br7HxCnl.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-B0gOmwPw.js → Analytics-bVKq79Xd.js} +1 -1
  6. package/src/assets/web-panel/assets/{AppLayout-DWhZiV0Q.js → AppLayout-CWSLIbAz.js} +2 -2
  7. package/src/assets/web-panel/assets/{Audit-ZuZJBCxo.js → Audit-Cmnu1qqa.js} +1 -1
  8. package/src/assets/web-panel/assets/{Backup-CX7jhH5l.js → Backup-Rok20-TL.js} +1 -1
  9. package/src/assets/web-panel/assets/{BaseInput-CVLx7HVq.js → BaseInput-BJzs_ZtT.js} +1 -1
  10. package/src/assets/web-panel/assets/{Chat-C6yL5tRD.js → Chat-CSYapbcq.js} +1 -1
  11. package/src/assets/web-panel/assets/{Checkbox-BePhbqVq.js → Checkbox-BEa7Sr7e.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-B5E4x1Lm.js → Codegen-C9M4e7ne.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-CWhNU6A7.js → Col-DU9NoUIi.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-mSEAuJhp.js → Community-DA9uz_jP.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-DSudHzX3.js → Compact-3_bEraVw.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-CxJLYjyn.js → Compliance-BtF8jWUQ.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-C-trppQj.js → Cowork-BqvA7oaM.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cron-_Ij4v5fY.js → Cron-CxZy7Mzg.js} +1 -1
  19. package/src/assets/web-panel/assets/{Crosschain-eLHXzp5T.js → Crosschain-1DB-XRGu.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-BP04AUUB.js → DID-B6Ezp1pt.js} +1 -1
  21. package/src/assets/web-panel/assets/{Dashboard-CzEeQv62.js → Dashboard-QDJ6VVsn.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-C_SGOB22.js → Dropdown-CovsWjxG.js} +1 -1
  23. package/src/assets/web-panel/assets/{Federation-BgaP4BOv.js → Federation-DbRxS4Y4.js} +1 -1
  24. package/src/assets/web-panel/assets/{FormItemContext-BxGLLt9r.js → FormItemContext-9E9dNGtx.js} +1 -1
  25. package/src/assets/web-panel/assets/{Git-Bt_uM_Gw.js → Git-CqEpyxRZ.js} +1 -1
  26. package/src/assets/web-panel/assets/{Governance-N2-0RG_o.js → Governance-On47KtGq.js} +1 -1
  27. package/src/assets/web-panel/assets/{Inference-eS3g-CzP.js → Inference-RZcjcyaq.js} +1 -1
  28. package/src/assets/web-panel/assets/{KnowledgeGraph-CUuvNVah.js → KnowledgeGraph-C-1rRAM9.js} +1 -1
  29. package/src/assets/web-panel/assets/{Logs-wPbwEt2r.js → Logs-BuunmG_r.js} +1 -1
  30. package/src/assets/web-panel/assets/{Marketplace-DH91kTwo.js → Marketplace-CromymyA.js} +1 -1
  31. package/src/assets/web-panel/assets/{McpTools-D-GyyBrI.js → McpTools-5XlFExh7.js} +1 -1
  32. package/src/assets/web-panel/assets/{Memory-BOtUy-tw.js → Memory-DjnUT7YM.js} +1 -1
  33. package/src/assets/web-panel/assets/{MobileBridge-DIP__XQd.js → MobileBridge-BrYIgLg6.js} +1 -1
  34. package/src/assets/web-panel/assets/{MobileProjects-1nqr1UsU.js → MobileProjects-CL5V3fTm.js} +1 -1
  35. package/src/assets/web-panel/assets/{Mtc-CCE0x7h2.js → Mtc-CHYJq6zK.js} +1 -1
  36. package/src/assets/web-panel/assets/{MtcAudit-BBkz0XUO.js → MtcAudit-BZxUO0qt.js} +1 -1
  37. package/src/assets/web-panel/assets/{Multisig-CIKSJvTY.js → Multisig-FZTmJgW1.js} +1 -1
  38. package/src/assets/web-panel/assets/{NLProgramming-BDkgeFcq.js → NLProgramming-C9Mhefph.js} +1 -1
  39. package/src/assets/web-panel/assets/{Notes-ONiUxfN1.js → Notes-W7usj-Ar.js} +1 -1
  40. package/src/assets/web-panel/assets/{NotificationSettings-CGcyKEIe.js → NotificationSettings-PBuYv_Bh.js} +1 -1
  41. package/src/assets/web-panel/assets/{Organization-BZtMYBJt.js → Organization-CuYCE-rF.js} +1 -1
  42. package/src/assets/web-panel/assets/{Overflow-C4LfFZAI.js → Overflow-Dojx-kzE.js} +1 -1
  43. package/src/assets/web-panel/assets/{P2P-D71Cpk-m.js → P2P-BgIaSrLX.js} +1 -1
  44. package/src/assets/web-panel/assets/{Permissions-DRGYF29v.js → Permissions-Byj2dkF_.js} +1 -1
  45. package/src/assets/web-panel/assets/{PersonalDataHub-CfRYoIua.js → PersonalDataHub-CMOOI13-.js} +1 -1
  46. package/src/assets/web-panel/assets/{Pipeline-BOyp0_Qo.js → Pipeline-CWwEOF09.js} +1 -1
  47. package/src/assets/web-panel/assets/{Privacy-a_AcphvF.js → Privacy-VT7gldcN.js} +1 -1
  48. package/src/assets/web-panel/assets/{ProjectInit-CFu1grYt.js → ProjectInit-7UH3c3p7.js} +1 -1
  49. package/src/assets/web-panel/assets/{ProjectSettings-p54Eivhh.js → ProjectSettings-DqLp-72a.js} +1 -1
  50. package/src/assets/web-panel/assets/{Projects-DkB88XAu.js → Projects-B_54eDhH.js} +1 -1
  51. package/src/assets/web-panel/assets/{Providers-EK7f8DEd.js → Providers-BIrNfNpc.js} +1 -1
  52. package/src/assets/web-panel/assets/{QuickAsk-CpO0w3iP.js → QuickAsk-BbYPwCso.js} +1 -1
  53. package/src/assets/web-panel/assets/{Recommend-BUJVQdv9.js → Recommend-BF4qBssF.js} +1 -1
  54. package/src/assets/web-panel/assets/{Reputation-kU2fOuZt.js → Reputation-DPEzlC2V.js} +1 -1
  55. package/src/assets/web-panel/assets/{Row-oGWRbk6g.js → Row-DjHxhH1L.js} +1 -1
  56. package/src/assets/web-panel/assets/{RssFeed-saC_46Yo.js → RssFeed-D0_j678P.js} +1 -1
  57. package/src/assets/web-panel/assets/{Search-CjtRqFUu.js → Search-DctfGehu.js} +1 -1
  58. package/src/assets/web-panel/assets/{Security-BX0NBVfQ.js → Security-BFHggeYM.js} +1 -1
  59. package/src/assets/web-panel/assets/{Services-Bgxsnei_.js → Services-CmrFMukV.js} +1 -1
  60. package/src/assets/web-panel/assets/{Skeleton-CwBb3k2a.js → Skeleton-DR4vn_nS.js} +1 -1
  61. package/src/assets/web-panel/assets/{Skills-CZCMYH6Z.js → Skills-DlXG2yyV.js} +1 -1
  62. package/src/assets/web-panel/assets/{Sla-Djy1uHnZ.js → Sla-4PPGL3SE.js} +1 -1
  63. package/src/assets/web-panel/assets/{SpeechSettings-CGUI_Uyh.js → SpeechSettings-D9EhJOqm.js} +1 -1
  64. package/src/assets/web-panel/assets/{SyncSettings-DK2CKHRD.js → SyncSettings-Dasmbi0p.js} +1 -1
  65. package/src/assets/web-panel/assets/{Tasks-BKiOzeIO.js → Tasks-vilEiuPA.js} +1 -1
  66. package/src/assets/web-panel/assets/{Templates-CnQpleXj.js → Templates-Ca9Rvktn.js} +1 -1
  67. package/src/assets/web-panel/assets/{Tenant-DwKz0cjm.js → Tenant-CEZb9gfK.js} +1 -1
  68. package/src/assets/web-panel/assets/{Terminal-A7t_wsR8.js → Terminal-DanCBdbD.js} +1 -1
  69. package/src/assets/web-panel/assets/{Tokens-BqYY9l44.js → Tokens-SPkClW2d.js} +1 -1
  70. package/src/assets/web-panel/assets/{Trigger-BI4bXFmi.js → Trigger-B645yL7g.js} +1 -1
  71. package/src/assets/web-panel/assets/{Trust-yMynKTRG.js → Trust-D9sM_Ig0.js} +1 -1
  72. package/src/assets/web-panel/assets/{UkeySign-Br4IScM6.js → UkeySign-B_Nr2K-u.js} +1 -1
  73. package/src/assets/web-panel/assets/{VideoEditing-CWcThGsP.js → VideoEditing-U01Lea8j.js} +1 -1
  74. package/src/assets/web-panel/assets/{Wallet-CZcAtjxj.js → Wallet-6xBySVV8.js} +1 -1
  75. package/src/assets/web-panel/assets/{WebAuthn-BnTZFMA0.js → WebAuthn-DbgMoBu6.js} +1 -1
  76. package/src/assets/web-panel/assets/{WorkflowEditor-N7gGz3_n.js → WorkflowEditor-Bz-Y6IR2.js} +1 -1
  77. package/src/assets/web-panel/assets/{chat-D175ZIO0.js → chat-BC_O9hag.js} +1 -1
  78. package/src/assets/web-panel/assets/{colors-LKhZyttv.js → colors-ChlOGOvr.js} +1 -1
  79. package/src/assets/web-panel/assets/{compact-item-CsJSebxT.js → compact-item-BSbAYGGF.js} +1 -1
  80. package/src/assets/web-panel/assets/{createContext-BJ_CPYFC.js → createContext-CFcZly5M.js} +1 -1
  81. package/src/assets/web-panel/assets/{hasIn-CzD3IqH8.js → hasIn-BomYwwYE.js} +1 -1
  82. package/src/assets/web-panel/assets/{index-BSNibAqz.js → index-5Ewm6KZA.js} +1 -1
  83. package/src/assets/web-panel/assets/{index-D8kltMTW.js → index-B6LJHQoE.js} +1 -1
  84. package/src/assets/web-panel/assets/{index-BvF2tC6C.js → index-BEJ6YiLI.js} +1 -1
  85. package/src/assets/web-panel/assets/{index-BjOrt4vw.js → index-BGUbtM3R.js} +1 -1
  86. package/src/assets/web-panel/assets/{index-Dm-3kvtD.js → index-BHGsFwYW.js} +1 -1
  87. package/src/assets/web-panel/assets/{index-D401L3yx.js → index-BHi69MHF.js} +1 -1
  88. package/src/assets/web-panel/assets/{index-R1cFADfk.js → index-BI1jAWcc.js} +1 -1
  89. package/src/assets/web-panel/assets/index-BIRYt1of.js +1 -0
  90. package/src/assets/web-panel/assets/{index-Dd7dICwB.js → index-BYDvb1pi.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-Kn-Of5ew.js → index-BZGdjNLA.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-uTEVWPYA.js → index-BwFykZ5U.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-JTX9A7w0.js → index-ByZQNO0A.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-BmJdof_c.js → index-C0rr1X9W.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BsirlkJ0.js → index-CBhoZhCO.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-6qPbrYF7.js → index-CCRSz2cR.js} +1 -1
  97. package/src/assets/web-panel/assets/index-CZfySmWX.js +1 -0
  98. package/src/assets/web-panel/assets/{index-DJVkBmSc.js → index-Cj47XwJQ.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DOO73rHE.js → index-Cmzh8gKL.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BNVLVzN5.js → index-CnxlKTDK.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CTIkCKav.js → index-CoF95pYK.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-RIO4JKMP.js → index-Ctx97mH-.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BEDFHKO3.js → index-D0vX9jQA.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CRGNuUIM.js → index-DNkth8dM.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DnPt5OdD.js → index-DRp5_Xns.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-E7t1hAnk.js → index-DW-Ji07y.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BhiZDGg7.js → index-DXgE2VW6.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-B7UYymse.js → index-D_0B3CiU.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CyHdYUeZ.js → index-Dbf5YmDX.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CKjBAdm0.js → index-DsNQ2hqI.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-C2HBKw07.js → index-EY733h9z.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DM3uBEWD.js → index-QD_n54XT.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DXp1jVsK.js → index-T5Y_9IPv.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BDSZDDb2.js → index-b8GbH2Yi.js} +3 -3
  115. package/src/assets/web-panel/assets/{index-BZluCuTH.js → index-gUACAWbM.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-D7ZcBI5s.js → index-onW325hZ.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-D5IZCkZG.js → index-ozVPr1gj.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BMvdoiFr.js → index-slYX2rCE.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BXH9ujMW.js → index-t9u2bHpH.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BV-__mlC.js → index-za1GUJBG.js} +1 -1
  121. package/src/assets/web-panel/assets/{initDefaultProps-CBW0okek.js → initDefaultProps-DnadEaxu.js} +1 -1
  122. package/src/assets/web-panel/assets/{motion-DGAffQ0Z.js → motion-CC_Na0Tl.js} +1 -1
  123. package/src/assets/web-panel/assets/{move-DFJ0-5IW.js → move-C2d9Mkk9.js} +1 -1
  124. package/src/assets/web-panel/assets/{omit-AvrDghg1.js → omit-QvpKbF8p.js} +1 -1
  125. package/src/assets/web-panel/assets/{pickAttrs-D7csw9i1.js → pickAttrs-Dm8r3X1_.js} +1 -1
  126. package/src/assets/web-panel/assets/{placementArrow-hZ6Lg6kG.js → placementArrow-DaqaVfoX.js} +1 -1
  127. package/src/assets/web-panel/assets/{responsiveObserve-DLLx5VvS.js → responsiveObserve-Iida9fIn.js} +1 -1
  128. package/src/assets/web-panel/assets/{slide-BaRIT3ev.js → slide-YqHexXQD.js} +1 -1
  129. package/src/assets/web-panel/assets/{statusUtils-Cdjyuhrz.js → statusUtils-BGKLoeEt.js} +1 -1
  130. package/src/assets/web-panel/assets/{styleChecker-CbrNybTt.js → styleChecker-aI-gsQO8.js} +1 -1
  131. package/src/assets/web-panel/assets/{useFlexGapSupport-B8gAhiRC.js → useFlexGapSupport-BiOsz4rc.js} +1 -1
  132. package/src/assets/web-panel/assets/{useFs-BZPy4ICP.js → useFs-CZy7Zo2X.js} +1 -1
  133. package/src/assets/web-panel/assets/{vnode-6Y0NDMVv.js → vnode-B6WqjmE4.js} +1 -1
  134. package/src/assets/web-panel/assets/{zoom-DTbMGsSH.js → zoom-DTeTrJ2z.js} +1 -1
  135. package/src/assets/web-panel/index.html +1 -1
  136. package/src/commands/__tests__/android.test.js +260 -0
  137. package/src/commands/android.js +284 -0
  138. package/src/commands/hub.js +57 -17
  139. package/src/gateways/ws/personal-data-hub-protocol.js +28 -8
  140. package/src/index.js +2 -0
  141. package/src/lib/cc-android-bridge.js +162 -0
  142. package/src/lib/personal-data-hub-wiring.js +74 -18
  143. package/src/lib/web-ui-server.js +2 -1
  144. package/src/assets/web-panel/assets/index-CY1mQA2I.js +0 -1
  145. package/src/assets/web-panel/assets/index-D9nXHfUB.js +0 -1
@@ -24,6 +24,9 @@ import {
24
24
  import { getAIChatWizard } from "../../lib/personal-data-hub-aichat-wizard.js";
25
25
  import { existsSync, unlinkSync, readdirSync } from "node:fs";
26
26
  import { join } from "node:path";
27
+ import pdhPkg from "@chainlesschain/personal-data-hub";
28
+
29
+ const { ingestSystemDataAndroidSnapshot } = pdhPkg;
27
30
 
28
31
  async function withHub(fn) {
29
32
  try {
@@ -42,6 +45,22 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
42
45
  return await hub.engine.ask(msg.question, msg.options || {});
43
46
  }),
44
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
+
45
64
  "personal-data-hub.stats": async () =>
46
65
  withHub((hub) => ({
47
66
  vault: hub.vault.stats(),
@@ -219,14 +238,15 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
219
238
  withHub(async (hub) => await hub.probeWechatEnv()),
220
239
 
221
240
  "personal-data-hub.register-wechat": async (msg) =>
222
- withHub(async (hub) =>
223
- await hub.registerWechatAdapter({
224
- account: msg.account,
225
- dbPath: msg.dbPath,
226
- wechatDataPath: msg.wechatDataPath,
227
- fridaOpts: msg.fridaOpts,
228
- keyProviderOverride: msg.keyProviderOverride,
229
- }),
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
+ }),
230
250
  ),
231
251
 
232
252
  "personal-data-hub.unregister-wechat": async (msg) =>
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,
@@ -407,6 +408,7 @@ export function createProgram(opts = {}) {
407
408
  registerAskCommand(program);
408
409
  registerLlmCommand(program);
409
410
  registerHubCommand(program);
411
+ registerAndroidCommand(program);
410
412
  registerAgentCommand(program);
411
413
  registerSubAgentV2Command(program);
412
414
  registerExecBackendV2Command(program);
@@ -0,0 +1,162 @@
1
+ /**
2
+ * cc-android-bridge — Node-side facade for the Android JNI bridge.
3
+ *
4
+ * Plan A Sub-Phase A6/A7 scaffold (see `docs/design/Personal_Data_Hub_Android_Standalone_Cc.md`
5
+ * §4.2 + §6.1). The eventual native binding (`cc-android-bridge.node`,
6
+ * loaded from `android-app/app/src/main/cpp/`) exposes Java/Kotlin APIs to
7
+ * the in-APK Node runtime: ContentResolver query, PackageManager listings,
8
+ * Runtime.exec / Shizuku / Magisk su, Accessibility node tree, SAF DocumentFile
9
+ * read.
10
+ *
11
+ * **v0.1 status**: the native .node binding is NOT yet shipped. This file is
12
+ * a pure stub — every `invoke()` call rejects with ANDROID_BRIDGE_NOT_AVAILABLE.
13
+ * It exists so the `cc android …` commands and `system-data-android` adapter
14
+ * (A7 / A8) can land + be unit-tested ahead of the JNI work. When A6 ships
15
+ * the .node binding, this file's `loadNativeBinding()` will resolve the real
16
+ * module; method dispatch is already wired.
17
+ *
18
+ * Detection precedence (highest first):
19
+ * 1. process.env.CC_ANDROID_BRIDGE_OVERRIDE === "1" — test override; bridge
20
+ * reports "available" and routes through `_deps.testInvoke` (which tests
21
+ * replace with a mock). Lets us exercise the command code paths without
22
+ * a real device.
23
+ * 2. process.platform === "android"
24
+ * 3. process.env.PREFIX startsWith "/data/data/com.chainlesschain.android/"
25
+ * (Termux $PREFIX pattern in the bundled cc).
26
+ *
27
+ * Method names are kebab-case to match the `cc android <verb>` CLI surface,
28
+ * not the underlying JNI signatures (those use Java camelCase). Mapping
29
+ * happens in the future native binding.
30
+ */
31
+
32
+ import { createRequire } from "node:module";
33
+
34
+ const ANDROID_PREFIX = "/data/data/com.chainlesschain.android/";
35
+ const nodeRequire = createRequire(import.meta.url);
36
+
37
+ export function detectAndroid() {
38
+ if (process.env.CC_ANDROID_BRIDGE_OVERRIDE === "1") return true;
39
+ if (process.platform === "android") return true;
40
+ if (
41
+ typeof process.env.PREFIX === "string" &&
42
+ process.env.PREFIX.startsWith(ANDROID_PREFIX)
43
+ ) {
44
+ return true;
45
+ }
46
+ return false;
47
+ }
48
+
49
+ /**
50
+ * Lazy-load the native .node binding when we're actually on Android. Stays
51
+ * null elsewhere. The binding is expected at:
52
+ * $APK/lib/<abi>/cc-android-bridge.node
53
+ * resolved via require.resolve("cc-android-bridge").
54
+ *
55
+ * Wrapped in try so a missing binding (current state pre-A6) doesn't crash
56
+ * the CLI on import — `invoke()` reports it as a runtime error instead.
57
+ */
58
+ export function loadNativeBinding() {
59
+ if (!detectAndroid()) return null;
60
+ if (process.env.CC_ANDROID_BRIDGE_OVERRIDE === "1") return null;
61
+ try {
62
+ return nodeRequire("cc-android-bridge");
63
+ } catch (_e) {
64
+ return null;
65
+ }
66
+ }
67
+
68
+ export class AndroidBridgeUnavailableError extends Error {
69
+ constructor(reason) {
70
+ super(`ANDROID_BRIDGE_NOT_AVAILABLE: ${reason}`);
71
+ this.code = "ANDROID_BRIDGE_NOT_AVAILABLE";
72
+ this.reason = reason;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Invoke a bridge method.
78
+ *
79
+ * @param {string} method — kebab-case method name (e.g. "contacts.query",
80
+ * "fs.read", "a11y.query", "app.list").
81
+ * @param {object} [params]
82
+ * @returns {Promise<any>}
83
+ *
84
+ * Rejects with AndroidBridgeUnavailableError when:
85
+ * - Not running on Android (and CC_ANDROID_BRIDGE_OVERRIDE != 1)
86
+ * - Running on Android but native binding failed to load
87
+ * - Method is not registered in the native binding
88
+ */
89
+ export async function invoke(method, params = {}) {
90
+ if (typeof method !== "string" || method.length === 0) {
91
+ throw new TypeError(
92
+ "cc-android-bridge.invoke: method must be non-empty string",
93
+ );
94
+ }
95
+
96
+ // Test path — _deps.testInvoke replaced by harness.
97
+ if (
98
+ process.env.CC_ANDROID_BRIDGE_OVERRIDE === "1" &&
99
+ typeof _deps.testInvoke === "function"
100
+ ) {
101
+ return await _deps.testInvoke(method, params);
102
+ }
103
+
104
+ if (!_deps.detectAndroid()) {
105
+ throw new AndroidBridgeUnavailableError(
106
+ `not running on Android (platform=${process.platform})`,
107
+ );
108
+ }
109
+
110
+ const native = _deps.loadNativeBinding();
111
+ if (!native) {
112
+ throw new AndroidBridgeUnavailableError(
113
+ "native binding cc-android-bridge.node missing — A6 JNI module not yet bundled",
114
+ );
115
+ }
116
+ if (typeof native.invoke !== "function") {
117
+ throw new AndroidBridgeUnavailableError(
118
+ "native binding loaded but does not export invoke()",
119
+ );
120
+ }
121
+ return await native.invoke(method, params);
122
+ }
123
+
124
+ /**
125
+ * Check whether the bridge is usable right now without throwing.
126
+ * Returns `{ available: boolean, reason?: string }`.
127
+ */
128
+ export function caps() {
129
+ if (process.env.CC_ANDROID_BRIDGE_OVERRIDE === "1") {
130
+ return { available: true, reason: "test-override" };
131
+ }
132
+ if (!_deps.detectAndroid()) {
133
+ return {
134
+ available: false,
135
+ reason: `not-on-android (platform=${process.platform})`,
136
+ };
137
+ }
138
+ const native = _deps.loadNativeBinding();
139
+ if (!native) {
140
+ return {
141
+ available: false,
142
+ reason: "native-binding-missing (A6 pending)",
143
+ };
144
+ }
145
+ return { available: true };
146
+ }
147
+
148
+ // _deps injection seam (per [[feedback-vi-mock-cjs-interop]]). Tests reach in
149
+ // and replace these to exercise both success + error paths without needing
150
+ // a real Android device or the unloaded native binding.
151
+ export const _deps = {
152
+ detectAndroid,
153
+ loadNativeBinding,
154
+ testInvoke: null,
155
+ };
156
+
157
+ export default {
158
+ invoke,
159
+ caps,
160
+ AndroidBridgeUnavailableError,
161
+ _deps,
162
+ };
@@ -44,6 +44,7 @@ const {
44
44
  generateKeyHex,
45
45
  EmailAdapter,
46
46
  AlipayBillAdapter,
47
+ SystemDataAndroidAdapter,
47
48
  EntityResolver,
48
49
  EntityResolverEmbeddingStage,
49
50
  EntityResolverLLMStage,
@@ -95,6 +96,28 @@ let _hub = null;
95
96
  let _initPromise = null;
96
97
  let _bm25 = null;
97
98
 
99
+ // LLM override — see file header. Default cli-side hub uses a direct
100
+ // OllamaClient; when the desktop main process embeds this wiring via
101
+ // ws-cli-loader it can inject a CcLLMAdapter (wrapping LLMManager) so the
102
+ // SAME wiring honors the user's active provider (volcengine / anthropic /
103
+ // etc.) instead of hard-binding Ollama. Must be set BEFORE the first
104
+ // getHub() call — initHub() reads it synchronously at the LLM-wiring step.
105
+ let _llmOverride = null;
106
+
107
+ /**
108
+ * Override the default cli-side OllamaClient with a caller-supplied LLM
109
+ * client conforming to the hub's LLMClient contract ({ chat, name, isLocal }).
110
+ *
111
+ * Used by desktop-app-vue web-shell's ws-cli-loader bootstrap: see
112
+ * desktop-app-vue/src/main/web-shell/ws-cli-loader.js. Calling this on
113
+ * an already-initialized hub does NOT swap the live LLM — the override only
114
+ * applies on the next fresh initHub(). Restart the process if you need to
115
+ * change provider mid-session.
116
+ */
117
+ export function setHubLLMOverride(llm) {
118
+ _llmOverride = llm || null;
119
+ }
120
+
98
121
  export function resolveHubDir() {
99
122
  return join(getElectronUserDataDir(), ".chainlesschain", "hub");
100
123
  }
@@ -115,12 +138,16 @@ async function initHub() {
115
138
  const vault = new LocalVault({ path: join(hubDir, "vault.db"), key });
116
139
  vault.open();
117
140
 
118
- // LLM: standalone OllamaClient connects to localhost:11434.
119
- // Override via env CC_HUB_OLLAMA_URL / CC_HUB_OLLAMA_MODEL.
120
- const llm = new OllamaClient({
121
- baseUrl: process.env.CC_HUB_OLLAMA_URL || "http://localhost:11434",
122
- model: process.env.CC_HUB_OLLAMA_MODEL || "qwen2.5:7b-instruct",
123
- });
141
+ // LLM: prefer caller-injected override (desktop web-shell wires CcLLMAdapter
142
+ // wrapping LLMManager so PDH honors the user's saved active provider).
143
+ // Fallback to standalone OllamaClient — connects to localhost:11434.
144
+ // Override the fallback via env CC_HUB_OLLAMA_URL / CC_HUB_OLLAMA_MODEL.
145
+ const llm =
146
+ _llmOverride ||
147
+ new OllamaClient({
148
+ baseUrl: process.env.CC_HUB_OLLAMA_URL || "http://localhost:11434",
149
+ model: process.env.CC_HUB_OLLAMA_MODEL || "qwen2.5:7b-instruct",
150
+ });
124
151
 
125
152
  // KG sink — direct ESM import works here.
126
153
  let kgSink = null;
@@ -147,20 +174,33 @@ async function initHub() {
147
174
 
148
175
  // Phase 8 — EntityResolver pipeline
149
176
  const entityResolver = new EntityResolver({ vault });
177
+ // Plan A v0.1 — in-APK Android cc has no Ollama on localhost:11434.
178
+ // Every embedding call would TCP-timeout (measured: ~60s extra per sync
179
+ // on Xiaomi 24115RA8EC 2026-05-21). Detect Termux $PREFIX for our APK
180
+ // and skip embedding+LLM stages entirely. Rule-stage still runs; the
181
+ // resolve_queue picks up enqueued pairs later if a host with Ollama is
182
+ // ever attached (e.g. desktop-side replay).
183
+ const isInAppAndroidCc =
184
+ typeof process.env.PREFIX === "string" &&
185
+ process.env.PREFIX.startsWith("/data/data/com.chainlesschain.android");
186
+ const skipEmbeddings =
187
+ isInAppAndroidCc || process.env.CC_HUB_DISABLE_EMBEDDINGS === "1";
150
188
  try {
151
- if (llm) {
189
+ if (llm && !skipEmbeddings) {
152
190
  const llmStage = new EntityResolverLLMStage({
153
191
  llm,
154
192
  acceptNonLocal: false,
155
193
  });
156
194
  entityResolver._llmStage = llmStage.asStageFn();
157
195
  }
158
- const embeddingStage = new EntityResolverEmbeddingStage({
159
- ollamaUrl: process.env.CC_HUB_OLLAMA_URL || "http://localhost:11434",
160
- model: process.env.CC_HUB_OLLAMA_EMBED_MODEL || "nomic-embed-text",
161
- vault,
162
- });
163
- entityResolver._embeddingStage = embeddingStage.asStageFn();
196
+ if (!skipEmbeddings) {
197
+ const embeddingStage = new EntityResolverEmbeddingStage({
198
+ ollamaUrl: process.env.CC_HUB_OLLAMA_URL || "http://localhost:11434",
199
+ model: process.env.CC_HUB_OLLAMA_EMBED_MODEL || "nomic-embed-text",
200
+ vault,
201
+ });
202
+ entityResolver._embeddingStage = embeddingStage.asStageFn();
203
+ }
164
204
  } catch (_err) {
165
205
  // Fall back to rule-only — registry still works
166
206
  }
@@ -210,6 +250,19 @@ async function initHub() {
210
250
  }
211
251
  }
212
252
 
253
+ // Plan A v0.1 — Android on-device system-data adapter. Stateless: the UI
254
+ // produces a snapshot JSON via ContentResolver/PackageManager and passes
255
+ // its path through opts.inputPath at sync-time, so registration is a
256
+ // one-shot wire here. Safe to register on every host (no-op until a sync
257
+ // call provides inputPath); future hosts may filter by platform if useful.
258
+ try {
259
+ const sda = new SystemDataAndroidAdapter();
260
+ if (!registry.has(sda.name)) registry.register(sda);
261
+ } catch (_err) {
262
+ // Boot must continue even if the adapter fails to register; cc hub will
263
+ // surface the absence via list-adapters.
264
+ }
265
+
213
266
  // Phase 6: auto-register persisted Alipay accounts.
214
267
  const alipayAccountsPath = join(hubDir, "alipay-accounts.json");
215
268
  const alipayAccounts = loadAlipayAccounts(alipayAccountsPath);
@@ -442,7 +495,11 @@ async function initHub() {
442
495
 
443
496
  async registerWechatAdapter(opts = {}) {
444
497
  if (!opts || !opts.account || !opts.account.uin) {
445
- return { ok: false, reason: "UIN_REQUIRED", message: "opts.account.uin required" };
498
+ return {
499
+ ok: false,
500
+ reason: "UIN_REQUIRED",
501
+ message: "opts.account.uin required",
502
+ };
446
503
  }
447
504
  let r;
448
505
  try {
@@ -476,7 +533,8 @@ async function initHub() {
476
533
  account: { uin: opts.account.uin },
477
534
  dbPath: opts.dbPath || null,
478
535
  wechatDataPath: opts.wechatDataPath || null,
479
- chosenKeyProvider: r.keyProvider && r.keyProvider.name ? r.keyProvider.name : null,
536
+ chosenKeyProvider:
537
+ r.keyProvider && r.keyProvider.name ? r.keyProvider.name : null,
480
538
  registeredAt: Date.now(),
481
539
  lastSyncAt: null,
482
540
  });
@@ -500,9 +558,7 @@ async function initHub() {
500
558
  }
501
559
  const wechatAccountsPath = join(hubDir, "wechat-accounts.json");
502
560
  const accounts = loadWechatAccounts(wechatAccountsPath);
503
- const target = accounts.find(
504
- (c) => c.account && c.account.uin === uin,
505
- );
561
+ const target = accounts.find((c) => c.account && c.account.uin === uin);
506
562
  const next = accounts.filter(
507
563
  (c) => !(c.account && c.account.uin === uin),
508
564
  );
@@ -1211,7 +1211,8 @@ function findWebPanelDist(staticDir) {
1211
1211
  return fs.existsSync(path.join(staticDir, "index.html")) ? staticDir : null;
1212
1212
  }
1213
1213
  // 1. Source tree: packages/web-panel/dist/
1214
- const sourceDist = path.resolve(__dirname, "../../web-panel/dist");
1214
+ // __dirname = packages/cli/src/lib/ so we need three "../" to reach packages/.
1215
+ const sourceDist = path.resolve(__dirname, "../../../web-panel/dist");
1215
1216
  if (fs.existsSync(path.join(sourceDist, "index.html"))) {
1216
1217
  return sourceDist;
1217
1218
  }
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-oGWRbk6g.js";import{S as t}from"./index-BDSZDDb2.js";import"./responsiveObserve-DLLx5VvS.js";import"./vendor-DhFY8mDK.js";import"./useFlexGapSupport-B8gAhiRC.js";import"./styleChecker-CbrNybTt.js";import"./index-BZluCuTH.js";import"./icons-BOPtEWK4.js";const l=t(o);export{l as default};
@@ -1 +0,0 @@
1
- import{C as o}from"./Col-CWhNU6A7.js";import{S as t}from"./index-BDSZDDb2.js";import"./index-BZluCuTH.js";import"./vendor-DhFY8mDK.js";import"./icons-BOPtEWK4.js";const s=t(o);export{s as default};