chainlesschain 0.162.17 → 0.162.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/package.json +3 -3
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-BnOiVQsQ.js → AIOps-VbMLpnCu.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-Tw6tLfY1.js → ActionButton-BR6BrZ2w.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Des59eT3.js → Analytics-DWN2iHDA.js} +2 -2
  6. package/src/assets/web-panel/assets/AppLayout-CyBXOO_H.js +3 -0
  7. package/src/assets/web-panel/assets/{AppLayout-BLCe1k8m.css → AppLayout-DleZFgpe.css} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-JX1upUxG.js → Audit-Cu5a4b5S.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-ByvQLRhY.js → Backup-D0vrJYkS.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-DC-h8Hd-.js → BaseInput-DnFk3wDi.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-D9dJ3NKb.js → Chat-DFMa9lEz.js} +3 -3
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-CO908iBt.css +1 -0
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-CpVazmEP.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-n3tD-95B.js → Checkbox-J23wKgNR.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-BV9t0CmU.js → Codegen-Ca6Z4r1p.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-4KhPnXFB.js → Col-BZ3XsxN2.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-R1hZqHEr.js → Community-DhK5H5dD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-Bo4r1Z3L.js → Compact-DjJMyddV.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-Dwywk8U2.js → Compliance-Bup3Rk9z.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DTBwVdcR.js → Cowork-BqsPMIpo.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-BrveD2Al.js → Cron-Ca69LFf-.js} +1 -1
  22. package/src/assets/web-panel/assets/{Crosschain-C63oZCeg.js → Crosschain-mTB21YwK.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-Cyfo7zh4.js → DID-C1_Eree4.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-_EOI1Ax4.js → Dashboard-L2OWv5io.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BWYHGHO3.js → Dropdown-CpqNwurh.js} +1 -1
  26. package/src/assets/web-panel/assets/EmailListRenderer-CVJ1j3Ll.css +1 -0
  27. package/src/assets/web-panel/assets/EmailListRenderer-Mo7D9ADF.js +1 -0
  28. package/src/assets/web-panel/assets/{Federation-CU03AB2d.js → Federation-COTeKl2R.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-DECACp9C.js → FormItemContext-0oTTQ9MI.js} +1 -1
  30. package/src/assets/web-panel/assets/GenericCardRenderer-DrMs3upM.js +1 -0
  31. package/src/assets/web-panel/assets/GenericCardRenderer-DtJFcJYl.css +1 -0
  32. package/src/assets/web-panel/assets/{Git-BhpPR-ck.js → Git-C6eFUBhz.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-BtpmvOHi.js → Governance-5ivL10kw.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-DfPuEW02.js → Inference-DcERJUS_.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-CeA_2NFe.js → KnowledgeGraph-Dm1eQ_Hv.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-C_ozF-bn.js → Logs-Cjt-JTuL.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-WgBvu6Ma.js → Marketplace-fNDRN8YJ.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-CNIz8liM.js → McpTools-kKgzl9Bb.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-DEN8NgRg.js → Memory-BdJujXCH.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-CP0rj-Fx.js → MobileBridge-lmvJfnpK.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-x3zDbPDI.js → MobileProjects-ZM-DVPhi.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-CC4PEFJV.js → Mtc-CeoaWgzU.js} +1 -1
  43. package/src/assets/web-panel/assets/{MtcAudit-BHB0GvyW.js → MtcAudit-CRvKTLqr.js} +1 -1
  44. package/src/assets/web-panel/assets/{Multisig-BUPfLbde.js → Multisig-DnzFw69O.js} +2 -2
  45. package/src/assets/web-panel/assets/{NLProgramming-DNOkByM8.js → NLProgramming-0xP2rtGN.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-U-RIv-kE.js → Notes-tJpp3z8e.js} +1 -1
  47. package/src/assets/web-panel/assets/{NotificationSettings-B-q6tsxf.js → NotificationSettings-CRdpEoHX.js} +1 -1
  48. package/src/assets/web-panel/assets/OrderTableRenderer-BEH9lAIb.js +1 -0
  49. package/src/assets/web-panel/assets/OrderTableRenderer-BnOISpKI.css +1 -0
  50. package/src/assets/web-panel/assets/{Organization-DJLNuZ2_.js → Organization-Dhwy6dXT.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-BxTl0aeE.js → Overflow-COwwTMb-.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-Czzalu_0.js → P2P-79YWb-cn.js} +1 -1
  53. package/src/assets/web-panel/assets/PdhVaultBrowser-B9ZGFpn4.css +1 -0
  54. package/src/assets/web-panel/assets/PdhVaultBrowser-Dhn5S3Vs.js +7 -0
  55. package/src/assets/web-panel/assets/{Permissions-BBw06EGK.js → Permissions-ELRvDOlY.js} +3 -3
  56. package/src/assets/web-panel/assets/{PersonalDataHub-Dvaa8niQ.css → PersonalDataHub-D0ncF92t.css} +1 -1
  57. package/src/assets/web-panel/assets/PersonalDataHub-DIWbfS5k.js +1 -0
  58. package/src/assets/web-panel/assets/{Pipeline-qLLWNe2i.js → Pipeline-Dzi1zmAr.js} +1 -1
  59. package/src/assets/web-panel/assets/Privacy-BYzWkaRt.js +1 -0
  60. package/src/assets/web-panel/assets/{ProjectInit-CmJ0VPGy.js → ProjectInit-D_5DqLSS.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-D1Xm2EwO.js → ProjectSettings-DrAAYJgR.js} +1 -1
  62. package/src/assets/web-panel/assets/{Projects-DLN-awqS.js → Projects-BOrF4_X8.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-D164DGWo.js → Providers-DYLWZVe4.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-BRCH7WgH.js → QuickAsk-k76cZTaF.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-BWZhT_-2.js → Recommend-CXM4p6RB.js} +1 -1
  66. package/src/assets/web-panel/assets/Reputation-DLnLpz8L.js +1 -0
  67. package/src/assets/web-panel/assets/{Row-BbuTB-ny.js → Row-BavvTUrL.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-CLegyrrb.js → RssFeed-CtCarC8_.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-Bz41pkvW.js → Search-CJcDGc1x.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-D4NWRpgV.js → Security-DB3GmnY9.js} +3 -3
  71. package/src/assets/web-panel/assets/{Services-CP_6SXST.js → Services-BWEvVHhz.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-CdRO3MnV.js → Skeleton-BHbixeGV.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-BmghgIL3.js → Skills-DWwIjvjl.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-DjAIXxkm.js → Sla-C1Qu9o0j.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-DYk-En4R.js → SpeechSettings-BiEysZg1.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-CglX98G4.js → SyncSettings-XlOLFUv2.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tasks-BcLMTSP3.js → Tasks-BKjOcYxW.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-BCs5bP8P.js → Templates-BVKjc9j-.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-B5jLtdWR.js → Tenant-C33WmSiJ.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-CZKKYYaA.js → Terminal-Dl8RJZHg.js} +1 -1
  81. package/src/assets/web-panel/assets/TimelineRenderer-CFN36N3H.js +1 -0
  82. package/src/assets/web-panel/assets/TimelineRenderer-DmztdsbF.css +1 -0
  83. package/src/assets/web-panel/assets/{Tokens-B8aHonMu.js → Tokens-Dy2kxiCA.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-D6jDjaX1.js → Trigger-C7bt0leJ.js} +1 -1
  85. package/src/assets/web-panel/assets/Trust-CVKbWEMH.js +1 -0
  86. package/src/assets/web-panel/assets/{UkeySign-B1IDXsz6.js → UkeySign-B91QGwbs.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-DHvglMzO.js → VideoEditing-C8xBqRiE.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-DAUh8j_b.js → Wallet-RW2IBbpH.js} +1 -1
  89. package/src/assets/web-panel/assets/{WebAuthn-D0Y8wGZt.js → WebAuthn-CZPv5ayn.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-BqZgQo4U.js → WorkflowEditor-CFCwic4a.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-CtfIYzWq.js → chat-PVfHUaHj.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-B6ZfKKgZ.js → colors-C4WA0-Iq.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item--HQOl9D1.js → compact-item-DQfLwjbC.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-Bf-YNOPI.js → createContext-31PSlu0j.js} +1 -1
  95. package/src/assets/web-panel/assets/{hasIn-D5G7UiYx.js → hasIn-Csltfg47.js} +1 -1
  96. package/src/assets/web-panel/assets/icons-AILO5ZcK.js +57 -0
  97. package/src/assets/web-panel/assets/index-3NsH3wNq.js +1 -0
  98. package/src/assets/web-panel/assets/{index-_ZD6hPvh.js → index-41v9Hflm.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-B23hk7ZY.js → index-45Iyof95.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CcbuseEC.js → index-8IVdEMKr.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CVTgMzbI.js → index-B-aRUTIJ.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-OSlN9c4x.js → index-BCxhSOsr.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BrJfwd9_.js → index-BCyTEqF7.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CAPj11l4.js → index-BD-K1g5z.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DJlTZ7oK.js → index-BLwrQAlK.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-ByjAzHrC.js → index-Ba6cQs-y.js} +4 -4
  107. package/src/assets/web-panel/assets/{index-__qol0SM.js → index-BiFRGYGH.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DZyNnZb9.js → index-BqOmboiA.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-UppuQXbk.js → index-C4gzD6Ra.js} +2 -2
  110. package/src/assets/web-panel/assets/{index-2QuOKVo1.js → index-CArRkfYM.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BWOeC8v6.js → index-CE8i90GF.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-B75QpKcS.js → index-CEbbRpw2.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BKsNidiT.js → index-CEtPU50W.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-g_d5tOWL.js → index-CIeFJLHG.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-ofgv0VHh.js → index-CQWE2WKS.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BRPGyig2.js → index-C_k_btzK.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-xOVop383.js → index-CbpUjcEf.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DIYydwQc.js → index-CdQUx-5Z.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CQIzU6GO.js → index-CfWk9Yzf.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CihsW323.js → index-Cgt2_bmM.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CkoQfJv0.js → index-CmzuBE2G.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BPvA_8ed.js → index-CpXm8DBk.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BtjPgDzA.js → index-DSO9eU_G.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CmVrKala.js → index-DUFwsCsD.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Dfm65OiJ.js → index-DVHR_To_.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CGG5O6Zh.js → index-DW-7sqm0.js} +1 -1
  127. package/src/assets/web-panel/assets/index-DWtc_qRj.js +1 -0
  128. package/src/assets/web-panel/assets/{index-BBSGKZ-l.js → index-DdrYhK__.js} +3 -3
  129. package/src/assets/web-panel/assets/{index-XwovMqXr.js → index-DfbOwhkA.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-OY_eegoA.js → index-DpEj71nk.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Ca_5Za9D.js → index-DtUcq8Nn.js} +1 -1
  132. package/src/assets/web-panel/assets/{index--KnB-1F0.js → index-DuZKKJDi.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BOzNKGtD.js → index-Dymm64KM.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-DzvrUpDp.js → index-P9rJg2C1.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-DqJoAOhC.js → index-nAhW-NN4.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-DjUNw-1y.js → initDefaultProps-DPk1oFCk.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-Cd6xXLlf.js → motion-CzQ1k8MU.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-B_W-Y6JL.js → move-BCExaQ0x.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-BCZBLb_-.js → omit-D71nF5o_.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-CjDhGYLm.js → pickAttrs-pvCq8tx4.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-CSC2rU9-.js → placementArrow-D8lSLg_0.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-DnyswFkD.js → responsiveObserve-ZN6pVHvM.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-DujNhbuH.js → slide-VHxyZhFr.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-U2lNCQiL.js → statusUtils-B0jFTTFP.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-Ch2rQftE.js → styleChecker-Bc6FRYW9.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-5XxNwjTL.js → useFlexGapSupport-D4YDiqxr.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-pv2YfF-X.js → useFs-CQgQ7iah.js} +1 -1
  148. package/src/assets/web-panel/assets/usePersonalDataHub-LDh_Sq7B.js +1 -0
  149. package/src/assets/web-panel/assets/{vnode-CU0J2mVX.js → vnode-BwPvBDfI.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-ZII_iqXl.js → zoom-r6u1_Sq8.js} +1 -1
  151. package/src/assets/web-panel/index.html +2 -2
  152. package/src/commands/__tests__/hub-ask.test.js +136 -0
  153. package/src/commands/ask.js +110 -43
  154. package/src/commands/hub.js +260 -26
  155. package/src/constants.js +7 -0
  156. package/src/gateways/ws/personal-data-hub-protocol.js +151 -9
  157. package/src/lib/host-adb-bridge.js +430 -0
  158. package/src/lib/personal-data-hub-wiring.js +85 -0
  159. package/src/assets/web-panel/assets/AppLayout-hku5aFqc.js +0 -3
  160. package/src/assets/web-panel/assets/PersonalDataHub-CmTx090l.js +0 -1
  161. package/src/assets/web-panel/assets/Privacy-CStpViYX.js +0 -1
  162. package/src/assets/web-panel/assets/Reputation-DSTNi8ge.js +0 -1
  163. package/src/assets/web-panel/assets/Trust-DX_BvTA9.js +0 -1
  164. package/src/assets/web-panel/assets/icons-BOPtEWK4.js +0 -57
  165. package/src/assets/web-panel/assets/index-B-xjGh0B.js +0 -1
  166. package/src/assets/web-panel/assets/index-B9RskCJ5.js +0 -1
@@ -0,0 +1,430 @@
1
+ /**
2
+ * host-adb-bridge — host-side `bridgeProvider` for the
3
+ * system-data-android PDH adapter (ESM mirror of the CJS module at
4
+ * desktop-app-vue/src/main/personal-data-hub/desktop-adb-bridge.js).
5
+ *
6
+ * The packaged `cc-android-bridge.js` only works INSIDE the Android cc
7
+ * subprocess (it dials a localhost HTTP server the Android app exposes).
8
+ * That path requires the user to launch the in-APK cc, which most
9
+ * users never do. This shim implements the same `invoke(method,
10
+ * params) → Promise<result>` surface but runs commands via the system
11
+ * `adb` (developer-mode USB debugging) instead.
12
+ *
13
+ * Lives in packages/cli because both `cc serve` / `cc ui` AND the
14
+ * desktop web-shell embed of the CLI WS server use this CLI's wiring
15
+ * (personal-data-hub-wiring.js) — putting the bridge here means both
16
+ * paths get the auto-engage behavior. The desktop-app-vue CJS copy is
17
+ * still used for the V5/V6 IPC code path (separate hub singleton).
18
+ *
19
+ * Methods implemented (only what system-data-android consumes):
20
+ * - `contacts.query({since?})` →
21
+ * [{ lookupKey, displayName }, ...]
22
+ * - `app.list({includeSystem?})` →
23
+ * [{ packageName }, ...]
24
+ *
25
+ * Caveats (cross-checked against the sjqz reference at C:\code\sjqz):
26
+ * - No root required for the two methods above.
27
+ * - User must approve "USB 调试授权" on the phone the first time.
28
+ * - 0 or >1 devices attached → clear typed error (UI surfaces it via
29
+ * the new SyncReport.error rendering).
30
+ * - Windows CRLF trap: JS `$` does NOT match before `\r`, only
31
+ * `\n` / EOS — every parse routine strips `\r+$` first.
32
+ */
33
+
34
+ import { execFile } from "node:child_process";
35
+ import { promisify } from "node:util";
36
+
37
+ const execFileP = promisify(execFile);
38
+
39
+ export class HostAdbBridgeUnavailableError extends Error {
40
+ constructor(reason) {
41
+ super(`HOST_ADB_BRIDGE_NOT_AVAILABLE: ${reason}`);
42
+ this.code = "HOST_ADB_BRIDGE_NOT_AVAILABLE";
43
+ this.reason = reason;
44
+ }
45
+ }
46
+
47
+ async function adb(args, opts = {}) {
48
+ const adbPath = opts.adbPath || process.env.ADB_PATH || "adb";
49
+ const fullArgs = opts.serial ? ["-s", opts.serial, ...args] : args;
50
+ try {
51
+ const { stdout, stderr } = await execFileP(adbPath, fullArgs, {
52
+ timeout: opts.timeoutMs || 30_000,
53
+ maxBuffer: 32 * 1024 * 1024,
54
+ encoding: "utf8",
55
+ });
56
+ if (stderr && /error:|failed:|protocol fault/i.test(stderr)) {
57
+ throw new HostAdbBridgeUnavailableError(stderr.trim().split("\n")[0]);
58
+ }
59
+ return stdout;
60
+ } catch (e) {
61
+ if (e.code === "ENOENT") {
62
+ throw new HostAdbBridgeUnavailableError(
63
+ "adb binary not found on PATH (install Android Platform Tools, or set ADB_PATH)",
64
+ );
65
+ }
66
+ if (e instanceof HostAdbBridgeUnavailableError) {
67
+ throw e;
68
+ }
69
+ throw new HostAdbBridgeUnavailableError(e.message);
70
+ }
71
+ }
72
+
73
+ async function listDevices(opts = {}) {
74
+ const stdout = await adb(["devices"], opts);
75
+ const lines = stdout.split("\n").slice(1);
76
+ const serials = [];
77
+ for (const rawLine of lines) {
78
+ const line = rawLine.replace(/\r+$/, "").trim();
79
+ if (!line) continue;
80
+ const [serial, state] = line.split(/\s+/);
81
+ if (state === "device") serials.push(serial);
82
+ }
83
+ return serials;
84
+ }
85
+
86
+ async function pickDevice(opts = {}) {
87
+ if (opts.serial) return opts.serial;
88
+ if (process.env.ADB_SERIAL) return process.env.ADB_SERIAL;
89
+ const serials = await listDevices(opts);
90
+ if (serials.length === 0) {
91
+ throw new HostAdbBridgeUnavailableError(
92
+ "no Android device attached (enable USB debugging + plug in cable + approve 'USB 调试授权' on phone)",
93
+ );
94
+ }
95
+ if (serials.length > 1) {
96
+ throw new HostAdbBridgeUnavailableError(
97
+ `multiple devices attached (${serials.join(", ")}); set ADB_SERIAL=<serial> to disambiguate`,
98
+ );
99
+ }
100
+ return serials[0];
101
+ }
102
+
103
+ function parseContentQueryRows(stdout) {
104
+ const rows = [];
105
+ for (const rawLine of stdout.split("\n")) {
106
+ const line = rawLine.replace(/\r+$/, "");
107
+ const m = line.match(/^Row:\s+\d+\s+(.*)$/);
108
+ if (!m) continue;
109
+ const fields = {};
110
+ const fieldRe =
111
+ /([A-Za-z_][A-Za-z0-9_]*)=([^,]*?)(?=,\s+[A-Za-z_][A-Za-z0-9_]*=|$)/g;
112
+ let fm;
113
+ while ((fm = fieldRe.exec(m[1])) !== null) {
114
+ const key = fm[1];
115
+ const val = fm[2];
116
+ fields[key] = val === "NULL" ? null : val;
117
+ }
118
+ rows.push(fields);
119
+ }
120
+ return rows;
121
+ }
122
+
123
+ async function queryContacts(_params, opts) {
124
+ const serial = await pickDevice(opts);
125
+ const stdout = await adb(
126
+ [
127
+ "shell",
128
+ "content",
129
+ "query",
130
+ "--uri",
131
+ "content://com.android.contacts/contacts",
132
+ "--projection",
133
+ "lookup:display_name",
134
+ ],
135
+ { ...opts, serial },
136
+ );
137
+ const rows = parseContentQueryRows(stdout);
138
+ return rows
139
+ .map((r) => ({
140
+ lookupKey: r.lookup || null,
141
+ displayName: r.display_name || null,
142
+ }))
143
+ .filter((c) => c.displayName);
144
+ }
145
+
146
+ async function listApps(params, opts) {
147
+ const serial = await pickDevice(opts);
148
+ const includeSystem = params && params.includeSystem === true;
149
+ const flag = includeSystem ? "" : "-3";
150
+ const argv = ["shell", "pm", "list", "packages"];
151
+ if (flag) argv.push(flag);
152
+ const stdout = await adb(argv, { ...opts, serial });
153
+ const apps = [];
154
+ for (const rawLine of stdout.split("\n")) {
155
+ const line = rawLine.replace(/\r+$/, "");
156
+ const m = line.match(/^package:(.+)$/);
157
+ if (m) apps.push({ packageName: m[1].trim() });
158
+ }
159
+ return apps;
160
+ }
161
+
162
+ /**
163
+ * Query SMS via the system content provider. No root, no permissions
164
+ * declared by host — ADB shell user already has READ_SMS-equivalent
165
+ * access. Returns one row per message. The body can contain commas;
166
+ * parseContentQueryRows treats `, <ident>=` as the field boundary so
167
+ * naturally-written text doesn't break the parse (only adversarial
168
+ * SMS containing `, X=` would).
169
+ *
170
+ * @returns {Promise<Array<{id, address, body, date, dateSent, type, threadId, read, subject}>>}
171
+ */
172
+ async function querySms(params, opts) {
173
+ const serial = await pickDevice(opts);
174
+ const stdout = await adb(
175
+ ["shell", "content", "query", "--uri", "content://sms"],
176
+ { ...opts, serial, timeoutMs: opts.timeoutMs || 120_000 },
177
+ );
178
+ const rows = parseContentQueryRows(stdout);
179
+ return rows
180
+ .map((r) => ({
181
+ id: r._id ? String(r._id) : null,
182
+ address: r.address || null,
183
+ body: r.body || null,
184
+ date: r.date ? parseInt(r.date, 10) : null,
185
+ dateSent: r.date_sent ? parseInt(r.date_sent, 10) : null,
186
+ // SMS type: 1=inbox, 2=sent, 3=draft, 4=outbox, 5=failed, 6=queued
187
+ type: r.type ? parseInt(r.type, 10) : null,
188
+ threadId: r.thread_id ? parseInt(r.thread_id, 10) : null,
189
+ read: r.read === "1" ? true : r.read === "0" ? false : null,
190
+ subject: r.subject || null,
191
+ }))
192
+ .filter((m) => m.id); // drop rows with no _id (malformed)
193
+ }
194
+
195
+ /**
196
+ * Query call log via the system content provider. Same access model
197
+ * as SMS. Returns one row per call.
198
+ *
199
+ * @returns {Promise<Array<{id, number, name, duration, date, type, geocoded}>>}
200
+ */
201
+ async function queryCallLog(params, opts) {
202
+ const serial = await pickDevice(opts);
203
+ const stdout = await adb(
204
+ ["shell", "content", "query", "--uri", "content://call_log/calls"],
205
+ { ...opts, serial, timeoutMs: opts.timeoutMs || 120_000 },
206
+ );
207
+ const rows = parseContentQueryRows(stdout);
208
+ return rows
209
+ .map((r) => ({
210
+ id: r._id ? String(r._id) : null,
211
+ number: r.number || null,
212
+ name: r.name || null,
213
+ // Call duration in seconds
214
+ duration: r.duration ? parseInt(r.duration, 10) : null,
215
+ date: r.date ? parseInt(r.date, 10) : null,
216
+ // Call type: 1=incoming, 2=outgoing, 3=missed, 4=voicemail, 5=rejected, 6=blocked
217
+ type: r.type ? parseInt(r.type, 10) : null,
218
+ geocoded: r.geocoded_location || null,
219
+ }))
220
+ .filter((c) => c.id);
221
+ }
222
+
223
+ /**
224
+ * Lists media files in well-known /sdcard subdirectories. Returns metadata
225
+ * only — file CONTENT is never read off the device through this method.
226
+ * Pure ADB shell, no root, no permissions declared (adb shell user already
227
+ * has READ_EXTERNAL_STORAGE-equivalent access).
228
+ *
229
+ * Category → directory mapping:
230
+ * photos /sdcard/DCIM/Camera
231
+ * pictures /sdcard/Pictures (screenshots, downloaded images, etc.)
232
+ * videos /sdcard/Movies
233
+ * downloads /sdcard/Download
234
+ * documents /sdcard/Documents
235
+ *
236
+ * Uses `find -printf "%s\t%T@\t%p\n"` which is supported by Android toybox.
237
+ * One subprocess per category — concurrent isn't worth it; even ~5000-file
238
+ * Pictures listings finish in <2s.
239
+ *
240
+ * @param {{category: string, since?: number}} params
241
+ * - category: one of the keys above (required)
242
+ * - since: epoch-ms; files with mtime < since are skipped
243
+ * @returns {Promise<Array<{path, size, mtimeMs, ext, category}>>}
244
+ */
245
+ const MEDIA_DIRS = {
246
+ photos: "/sdcard/DCIM/Camera",
247
+ pictures: "/sdcard/Pictures",
248
+ videos: "/sdcard/Movies",
249
+ downloads: "/sdcard/Download",
250
+ documents: "/sdcard/Documents",
251
+ };
252
+ async function listMedia(params, opts) {
253
+ const cat = params && params.category;
254
+ const dir = MEDIA_DIRS[cat];
255
+ if (!dir) {
256
+ throw new HostAdbBridgeUnavailableError(
257
+ `media.list: unknown category "${cat}". Valid: ${Object.keys(MEDIA_DIRS).join(", ")}`,
258
+ );
259
+ }
260
+ const serial = await pickDevice(opts);
261
+ const stdout = await adb(
262
+ [
263
+ "shell",
264
+ // Suppress "Permission denied" stderr noise on a few system-protected
265
+ // subdirs (e.g. .trashed). 2>/dev/null hides those rows from output.
266
+ `find ${dir} -type f -printf '%s\\t%T@\\t%p\\n' 2>/dev/null`,
267
+ ],
268
+ { ...opts, serial, timeoutMs: opts.timeoutMs || 180_000 },
269
+ );
270
+ const sinceMs = Number.isInteger(params?.since) ? params.since : 0;
271
+ const out = [];
272
+ for (const rawLine of stdout.split("\n")) {
273
+ const line = rawLine.replace(/\r+$/, "");
274
+ if (!line) continue;
275
+ // tab-separated: <size>\t<mtime_epoch_fractional>\t<path>
276
+ const tab1 = line.indexOf("\t");
277
+ const tab2 = line.indexOf("\t", tab1 + 1);
278
+ if (tab1 < 0 || tab2 < 0) continue;
279
+ const size = parseInt(line.substring(0, tab1), 10);
280
+ const mtimeSec = parseFloat(line.substring(tab1 + 1, tab2));
281
+ const path = line.substring(tab2 + 1);
282
+ if (!Number.isFinite(size) || !Number.isFinite(mtimeSec) || !path) continue;
283
+ // Filter out hidden / system files — any path segment starts with "."
284
+ // catches .thumbnails/, .trashed-*/, .nomedia, etc.
285
+ if (path.split("/").some((seg) => seg.startsWith("."))) continue;
286
+ const mtimeMs = Math.floor(mtimeSec * 1000);
287
+ if (sinceMs > 0 && mtimeMs < sinceMs) continue;
288
+ const lastDot = path.lastIndexOf(".");
289
+ const ext = lastDot >= 0 ? path.substring(lastDot + 1).toLowerCase() : "";
290
+ out.push({ path, size, mtimeMs, ext, category: cat });
291
+ }
292
+ return out;
293
+ }
294
+
295
+ /**
296
+ * List snapshot JSON files in the Android app's staging directory.
297
+ * Uses `adb shell run-as` so only works on debuggable builds (which is
298
+ * always true for `<pkg>.debug` variants). Production builds will
299
+ * surface `package not debuggable` — UI can fall back to a manual
300
+ * upload path.
301
+ *
302
+ * @param {{packageName?: string}} params
303
+ * - packageName: defaults to `com.chainlesschain.android.debug`. The
304
+ * release variant `com.chainlesschain.android` is NOT readable via
305
+ * run-as.
306
+ * @returns {Promise<Array<{name, sizeBytes}>>}
307
+ */
308
+ async function listSnapshots(params, opts) {
309
+ const serial = await pickDevice(opts);
310
+ const pkg =
311
+ (params && params.packageName) || "com.chainlesschain.android.debug";
312
+ const stdout = await adb(
313
+ ["shell", "run-as", pkg, "ls", "-la", "files/.chainlesschain/staging/"],
314
+ { ...opts, serial },
315
+ );
316
+ if (/run-as: package not debuggable/.test(stdout)) {
317
+ throw new HostAdbBridgeUnavailableError(
318
+ `${pkg} is not debuggable — only debug-variant packages expose staging via run-as`,
319
+ );
320
+ }
321
+ const out = [];
322
+ for (const rawLine of stdout.split("\n")) {
323
+ const line = rawLine.replace(/\r+$/, "").trim();
324
+ if (!line || line.startsWith("total ") || line.startsWith("d")) continue;
325
+ // ls -la row: `-rw------- 1 u0_a395 u0_a395 204110 2026-05-23 13:47 system-data-android.json`
326
+ const m = line.match(
327
+ /^[-l]\S*\s+\d+\s+\S+\s+\S+\s+(\d+)\s+\S+\s+\S+\s+(.+\.json)$/,
328
+ );
329
+ if (m) out.push({ name: m[2], sizeBytes: parseInt(m[1], 10) });
330
+ }
331
+ return out;
332
+ }
333
+
334
+ /**
335
+ * Read a snapshot file's content from the Android app's staging directory.
336
+ * Returns the raw UTF-8 text (the JSON the adapter's _syncViaSnapshot
337
+ * expects). Same debuggable-only constraint as listSnapshots.
338
+ *
339
+ * @param {{packageName?: string, fileName: string}} params
340
+ * @returns {Promise<string>}
341
+ */
342
+ async function readSnapshot(params, opts) {
343
+ if (
344
+ !params ||
345
+ typeof params.fileName !== "string" ||
346
+ !params.fileName.endsWith(".json")
347
+ ) {
348
+ throw new HostAdbBridgeUnavailableError(
349
+ "readSnapshot: params.fileName must be a .json filename inside the staging dir",
350
+ );
351
+ }
352
+ // Defense-in-depth: reject path traversal — fileName must be a bare
353
+ // basename, no slashes / dots-leading.
354
+ if (params.fileName.includes("/") || params.fileName.startsWith(".")) {
355
+ throw new HostAdbBridgeUnavailableError(
356
+ `readSnapshot: refusing suspicious fileName "${params.fileName}"`,
357
+ );
358
+ }
359
+ const serial = await pickDevice(opts);
360
+ const pkg = params.packageName || "com.chainlesschain.android.debug";
361
+ const stdout = await adb(
362
+ [
363
+ "shell",
364
+ "run-as",
365
+ pkg,
366
+ "cat",
367
+ `files/.chainlesschain/staging/${params.fileName}`,
368
+ ],
369
+ { ...opts, serial, timeoutMs: opts.timeoutMs || 60_000 },
370
+ );
371
+ if (/run-as: package not debuggable/.test(stdout)) {
372
+ throw new HostAdbBridgeUnavailableError(
373
+ `${pkg} is not debuggable — only debug variant exposes staging via run-as`,
374
+ );
375
+ }
376
+ if (/No such file or directory/.test(stdout)) {
377
+ throw new HostAdbBridgeUnavailableError(
378
+ `snapshot ${params.fileName} not found in ${pkg}'s staging dir (collector probably never ran for this adapter)`,
379
+ );
380
+ }
381
+ return stdout;
382
+ }
383
+
384
+ export function createHostAdbBridge(opts = {}) {
385
+ return {
386
+ /**
387
+ * SystemDataAndroidAdapter._bridgeAvailable() reads this; must be
388
+ * sync. We report available:true optimistically — invoke() will
389
+ * throw a typed error if ADB / device isn't usable, which the
390
+ * registry surfaces via SyncReport.error (rendered by
391
+ * PersonalDataHub.vue syncSummary).
392
+ */
393
+ caps() {
394
+ return { available: true };
395
+ },
396
+ async invoke(method, params = {}) {
397
+ switch (method) {
398
+ case "contacts.query":
399
+ return await queryContacts(params, opts);
400
+ case "app.list":
401
+ return await listApps(params, opts);
402
+ case "sms.query":
403
+ return await querySms(params, opts);
404
+ case "call.query":
405
+ return await queryCallLog(params, opts);
406
+ case "media.list":
407
+ return await listMedia(params, opts);
408
+ case "snapshot.list":
409
+ return await listSnapshots(params, opts);
410
+ case "snapshot.read":
411
+ return await readSnapshot(params, opts);
412
+ default:
413
+ throw new HostAdbBridgeUnavailableError(
414
+ `method "${method}" not implemented by host-adb-bridge`,
415
+ );
416
+ }
417
+ },
418
+ };
419
+ }
420
+
421
+ // Exposed for unit testing without spawning real adb.
422
+ export const _internals = {
423
+ parseContentQueryRows,
424
+ listDevices,
425
+ pickDevice,
426
+ queryContacts,
427
+ listApps,
428
+ listSnapshots,
429
+ readSnapshot,
430
+ };
@@ -45,6 +45,13 @@ const {
45
45
  EmailAdapter,
46
46
  AlipayBillAdapter,
47
47
  SystemDataAndroidAdapter,
48
+ BrowserHistoryChromeAdapter,
49
+ BrowserHistoryEdgeAdapter,
50
+ VSCodeAdapter,
51
+ WinRecentAdapter,
52
+ GitActivityAdapter,
53
+ ShellHistoryAdapter,
54
+ LocalFilesAdapter,
48
55
  BilibiliAdapter,
49
56
  WeiboAdapter,
50
57
  DouyinAdapter,
@@ -274,12 +281,90 @@ async function initHub() {
274
281
  // call provides inputPath); future hosts may filter by platform if useful.
275
282
  try {
276
283
  const sda = new SystemDataAndroidAdapter();
284
+ // Auto-engage host-side ADB bridge: when the UI clicks 同步 with no
285
+ // inputPath, the adapter falls back to bridge mode and pulls
286
+ // contacts + app.list via `adb shell` against the
287
+ // developer-mode-attached phone. The adapter's constructor hardcodes
288
+ // `_deps.bridgeProvider = () => null`, so we mutate after construction.
289
+ // See packages/cli/src/lib/host-adb-bridge.js for the bridge surface
290
+ // + caveats (Windows CRLF parse trap, 0/multi device, ENOENT).
291
+ try {
292
+ const { createHostAdbBridge } = await import("./host-adb-bridge.js");
293
+ const hostAdbBridge = createHostAdbBridge();
294
+ sda._deps.bridgeProvider = () => hostAdbBridge;
295
+ } catch (_e) {
296
+ // Bridge module missing or failed to load — leave snapshot-only.
297
+ }
277
298
  if (!registry.has(sda.name)) registry.register(sda);
278
299
  } catch (_err) {
279
300
  // Boot must continue even if the adapter fails to register; cc hub will
280
301
  // surface the absence via list-adapters.
281
302
  }
282
303
 
304
+ // Phase 17 (2026-05-24) — desktop Chrome history + bookmarks. Reads
305
+ // %LOCALAPPDATA%\Google\Chrome\User Data\Default\{History,Bookmarks}
306
+ // (Win) / equivalent on macOS/Linux. No bridge, no extension, no
307
+ // network. authenticate() reports PROFILE_NOT_FOUND when Chrome isn't
308
+ // installed; sync() throws same. opts.profilePath overrides default.
309
+ try {
310
+ const chrome = new BrowserHistoryChromeAdapter();
311
+ if (!registry.has(chrome.name)) registry.register(chrome);
312
+ } catch (_err) {
313
+ // Continue boot
314
+ }
315
+
316
+ try {
317
+ const edge = new BrowserHistoryEdgeAdapter();
318
+ if (!registry.has(edge.name)) registry.register(edge);
319
+ } catch (_err) {
320
+ // Continue boot
321
+ }
322
+
323
+ // VS Code workspace history + global terminal history. Reads
324
+ // %APPDATA%\Code\User\workspaceStorage and \globalStorage\state.vscdb
325
+ // on Win; equivalents on macOS/Linux.
326
+ try {
327
+ const vscode = new VSCodeAdapter();
328
+ if (!registry.has(vscode.name)) registry.register(vscode);
329
+ } catch (_err) {
330
+ // Continue boot
331
+ }
332
+
333
+ // Windows Recent — cross-application "what did I open" .lnk timeline.
334
+ // Win-only adapter; authenticate() fails on macOS/Linux with
335
+ // PLATFORM_UNSUPPORTED, which surfaces nicely in the UI.
336
+ try {
337
+ const winRecent = new WinRecentAdapter();
338
+ if (!registry.has(winRecent.name)) registry.register(winRecent);
339
+ } catch (_err) {
340
+ // Continue boot
341
+ }
342
+
343
+ // Phase 18 — git activity (commit timeline via local `git log`) +
344
+ // shell history (PSReadLine / bash / zsh history files). Both pure
345
+ // file-import, no network. authenticate() degrades gracefully when
346
+ // no code roots / no history files exist on the host.
347
+ try {
348
+ const git = new GitActivityAdapter();
349
+ if (!registry.has(git.name)) registry.register(git);
350
+ } catch (_err) {
351
+ // Continue boot
352
+ }
353
+
354
+ try {
355
+ const shell = new ShellHistoryAdapter();
356
+ if (!registry.has(shell.name)) registry.register(shell);
357
+ } catch (_err) {
358
+ // Continue boot
359
+ }
360
+
361
+ try {
362
+ const localFiles = new LocalFilesAdapter();
363
+ if (!registry.has(localFiles.name)) registry.register(localFiles);
364
+ } catch (_err) {
365
+ // Continue boot
366
+ }
367
+
283
368
  // A8 v0.1 (2026-05-22) — social adapters in snapshot mode. Stateless: the
284
369
  // Android UI captures a cookie via in-app WebView, runs OkHttp against the
285
370
  // platform's HTTP API, parses the JSON response, writes a snapshot JSON to
@@ -1,3 +0,0 @@
1
- import{f as O,r as K,o as _e,x as yt,K as p,L as u,M as g,c as e,N as t,u as a,R as l,O as i,P as s,Q as C,F as V,Y as nt,Z as J,S as P,I as st,e as mt,_ as ft,w as _t,H as kt,$ as gt}from"./vendor-DhFY8mDK.js";import{u as ke,_ as ge,E as vt,a as ht,b as bt,T as wt,c as $t,d as G}from"./index-ByjAzHrC.js";import{u as q}from"./useShellMode-CgR0wCYM.js";import{B as fe,R as Lt,M as ce,F as Y,G as ee,D as te,h as he,i as ae,j as be,k as oe,A as we,N as $e,l as Le,m as Oe,n as Se,o as Ce,S as Ee,p as Re,q as Ae,r as ne,s as Ne,t as je,u as Te,v as Be,w as Me,x as Pe,y as De,z as Ie,P as Ue,H as se,K as ie,J as U,O as Ke,Q as le,U as ze,V as Fe,W as Ve,X as me,Y as re,Z as qe,_ as We,$ as ue,a0 as He,a1 as Je,a2 as Ge,a3 as Ye,a4 as Ze,a5 as Qe,a6 as Xe,a7 as xe,a8 as et,a9 as tt,aa as Ot,ab as at,e as St}from"./icons-BOPtEWK4.js";import Ct from"./index-BtjPgDzA.js";import"./KeyCode-D63Tfrq7.js";import"./omit-BCZBLb_-.js";import"./pickAttrs-CjDhGYLm.js";import"./initDefaultProps-DjUNw-1y.js";import"./motion-Cd6xXLlf.js";import"./raf-Deuc0E8-.js";import"./index-CAPj11l4.js";import"./index-DIYydwQc.js";import"./isVisible-C7tPsqfj.js";import"./useState-DGS1NOyn.js";import"./devWarning-CNIS3FrJ.js";import"./warning-Pq00owYb.js";import"./compact-item--HQOl9D1.js";import"./createContext-Bf-YNOPI.js";import"./Compact-Bo4r1Z3L.js";import"./_getTag-BVc6NQ_K.js";import"./styleChecker-Ch2rQftE.js";import"./zoom-ZII_iqXl.js";import"./ActionButton-Tw6tLfY1.js";import"./vnode-CU0J2mVX.js";const Et=""+new URL("logo-DBCYUiWP.png",import.meta.url).href,L={notifications:K([]),unreadCount:K(0)};function Z(h){if(h&&h.ok===!1)throw new Error(h.error||"notification handler failed");return h?.result??h}function Rt(){const h=ke();async function T({limit:r=50,offset:c=0,isRead:_}={}){if(!q().isEmbedded)return L.notifications.value=[],L.unreadCount.value=0,L.notifications.value;const y=await h.sendRaw({type:"notification.list",limit:r,offset:c,isRead:_},15e3),w=Z(y);if(w?.success===!1)throw new Error(w.error||"notification.list failed");return L.notifications.value=Array.isArray(w?.notifications)?w.notifications:[],await E(),L.notifications.value}async function E(){if(!q().isEmbedded)return L.unreadCount.value=0,0;const r=await h.sendRaw({type:"notification.unread-count"},1e4),c=Z(r);return L.unreadCount.value=Number(c?.count)||0,L.unreadCount.value}async function k(r){if(r==null||r==="")throw new Error("id is required");if(!q().isEmbedded)return;const c=await h.sendRaw({type:"notification.mark-read",id:r},1e4),_=Z(c);if(_?.success===!1)throw new Error(_.error||"notification.mark-read failed");const y=L.notifications.value.find(w=>w.id===r);y&&(y.is_read=1),await E()}async function S(){if(!q().isEmbedded)return;const r=await h.sendRaw({type:"notification.mark-all-read"},1e4),c=Z(r);if(c?.success===!1)throw new Error(c.error||"notification.mark-all-read failed");for(const _ of L.notifications.value)_.is_read=1;L.unreadCount.value=0}async function b(r,c=""){if(!q().isEmbedded)throw new Error("桌面通知仅在嵌入式 web-shell 中可用");const _=await h.sendRaw({type:"notification.send-desktop",title:r,body:c},1e4),y=Z(_);if(y?.success===!1)throw new Error(y.error||"notification.send-desktop failed")}return{notifications:O(()=>L.notifications.value),unreadCount:O(()=>L.unreadCount.value),refresh:T,refreshUnreadCount:E,markRead:k,markAllRead:S,sendDesktop:b}}const At={class:"notif-toolbar"},Nt={class:"notif-body"},jt={key:2,class:"notif-list"},Tt=["onClick"],Bt={class:"notif-row"},Mt={class:"notif-title"},Pt={class:"notif-time"},Dt={key:0,class:"notif-message"},It={__name:"NotificationBell",setup(h){const T=K(!1),E=K("all"),k=K(!1),{notifications:S,unreadCount:b,refresh:r,markRead:c,markAllRead:_}=Rt();function y(){N()}_e(()=>{window.addEventListener("cc:open-notification-drawer",y)}),yt(()=>{window.removeEventListener("cc:open-notification-drawer",y)});const w=O(()=>E.value==="unread"?S.value.filter(m=>!m.is_read):S.value);async function R(){if(q().isEmbedded){k.value=!0;try{await r({limit:100})}catch{}finally{k.value=!1}}}async function N(){T.value=!0,await R()}async function j(m){if(!m.is_read)try{await c(m.id)}catch{}}async function $(){try{await _()}catch(m){console.warn("[NotificationBell] markAllRead failed:",m?.message||m)}}function A(m){if(!m)return"";const f=typeof m=="string"?Date.parse(m):Number(m);if(!Number.isFinite(f))return String(m);const B=Date.now()-f,z=6e4,D=60*z,W=24*D;return B<z?"刚刚":B<D?`${Math.floor(B/z)} 分钟前`:B<W?`${Math.floor(B/D)} 小时前`:new Date(f).toLocaleDateString()}return(m,f)=>{const B=p("a-badge"),z=p("a-tooltip"),D=p("a-radio-button"),W=p("a-radio-group"),H=p("a-space"),Q=p("a-button"),de=p("a-empty"),pe=p("a-spin"),ye=p("a-drawer");return u(),g(V,null,[e(z,{title:"通知"},{default:t(()=>[e(B,{count:a(b),"overflow-count":99,offset:[-4,4]},{default:t(()=>[l("button",{type:"button",class:"notif-bell-btn","aria-label":"通知",onClick:N},[e(a(fe))])]),_:1},8,["count"])]),_:1}),e(ye,{open:T.value,"onUpdate:open":f[1]||(f[1]=v=>T.value=v),title:"通知中心",placement:"right",width:400,"body-style":{padding:0}},{default:t(()=>[l("div",At,[e(H,null,{default:t(()=>[e(W,{value:E.value,"onUpdate:value":f[0]||(f[0]=v=>E.value=v),size:"small","button-style":"solid"},{default:t(()=>[e(D,{value:"all"},{default:t(()=>[i("全部 ("+s(a(S).length)+")",1)]),_:1}),e(D,{value:"unread"},{default:t(()=>[i("未读 ("+s(a(b))+")",1)]),_:1})]),_:1},8,["value"])]),_:1}),e(H,null,{default:t(()=>[e(Q,{size:"small",loading:k.value,onClick:R},{icon:t(()=>[e(a(Lt))]),_:1},8,["loading"]),e(Q,{size:"small",disabled:a(b)===0,onClick:$},{default:t(()=>[...f[2]||(f[2]=[i(" 全部已读 ",-1)])]),_:1},8,["disabled"])]),_:1})]),l("div",Nt,[!k.value&&w.value.length===0?(u(),C(de,{key:0,description:"暂无通知",image:a(vt).PRESENTED_IMAGE_SIMPLE,style:{padding:"60px 0"}},null,8,["image"])):k.value?(u(),C(pe,{key:1,style:{display:"block",padding:"60px"}})):(u(),g("ul",jt,[(u(!0),g(V,null,nt(w.value,v=>(u(),g("li",{key:v.id,class:J(["notif-item",{unread:!v.is_read}]),onClick:n=>j(v)},[l("div",Bt,[l("div",Mt,s(v.title||v.message||"(无标题)"),1),l("span",Pt,s(A(v.created_at)),1)]),v.message&&v.title?(u(),g("div",Dt,s(v.message),1)):P("",!0)],10,Tt))),128))]))])]),_:1},8,["open"])],64)}}},Ut=ge(It,[["__scopeId","data-v-af539070"]]),Kt={key:0,class:"mbh-count"},zt={__name:"MobileBridgeHeaderStatus",setup(h){function T(R){if(!R)return[];try{return JSON.parse(R)}catch{}const N=String(R).split(`
2
- `),j=N.findIndex($=>{const A=$.trim();if(!A)return!1;const m=A[0];if(m!=="["&&m!=="{")return!1;if(A.length===1)return!0;const f=A[1];return!(f>="A"&&f<="Z"||f>="a"&&f<="z")});if(j<0)return[];for(let $=N.length-1;$>=j;$--){const A=N[$].trim();if(/^[\]\}]/.test(A)&&!/^[\]\}][A-Za-z]/.test(A))try{return JSON.parse(N.slice(j,$+1).join(`
3
- `))}catch{return[]}}return[]}const E=st(),k=ke(),S=K([]);let b=null;const r=O(()=>S.value.length),c=O(()=>r.value===0?"var(--text-muted, #999)":"#52c41a"),_=O(()=>r.value===0?"尚未配对任何手机 — 点击进入配对":`已配对 ${r.value} 台手机 — 点击进入管理`);async function y(){if(k.status==="connected")try{const{output:R}=await k.execute("p2p devices --type mobile --json",1e4);S.value=T(R)||[]}catch{}}function w(){E.push("/mobile-bridge")}return _e(()=>{y(),b=setInterval(y,5e3)}),mt(()=>{b&&(clearInterval(b),b=null)}),(R,N)=>{const j=p("a-badge"),$=p("a-tooltip");return u(),C($,{title:_.value},{default:t(()=>[e(j,{count:r.value,"show-zero":!1,"overflow-count":9,offset:[-2,4]},{default:t(()=>[l("button",{type:"button",class:J(["mbh-btn",{"mbh-btn--active":r.value>0}]),onClick:w},[e(a(ce),{style:ft({color:c.value,fontSize:"14px"})},null,8,["style"]),r.value>0?(u(),g("span",Kt,s(r.value),1)):P("",!0)],2)]),_:1},8,["count"])]),_:1},8,["title"])}}},Ft=ge(zt,[["__scopeId","data-v-05eb475d"]]),Vt=["src"],qt={key:0,class:"logo-text"},Wt={key:0,class:"mode-banner project"},Ht={class:"banner-info"},Jt={class:"banner-name"},Gt={class:"banner-sub"},Yt={key:1,class:"mode-banner global"},Zt={class:"banner-name"},Qt=["title"],Xt={class:"group-label"},xt={class:"group-label"},ea={class:"group-label"},ta={class:"group-label"},aa={class:"group-label"},oa={class:"group-label"},na={class:"group-label"},sa={class:"group-label"},ia={class:"group-label"},la={key:0,class:"footer-text"},ra={class:"header-left"},ua={class:"header-right"},ca={class:"theme-switcher"},da=["data-theme-key","onClick"],pa=["data-locale"],ya={class:"lang-switch-label"},ma={class:"version-tag"},ot="cc.web-panel.sidebar.openKeys",fa={__name:"AppLayout",setup(h){const T=st(),E=kt(),k=ke(),S=ht(),{t:b}=bt(),r=q(),c=K(!1),_=window.__CC_CONFIG__||{},y=O(()=>_.mode==="project"),w="v5.0.3.84",R=O(()=>S.current),N=O(()=>S.config.vars["--menu-mode"]),j=O(()=>{const n=E.name?.toLowerCase()||"dashboard";return[{mcptools:"mcp",quickask:"quick-ask",ukeysign:"ukey-sign"}[n]||n]}),$=["g-overview","g-config","g-data","g-advanced","g-enterprise","g-social","g-media","g-extension"];function A(){try{const n=localStorage.getItem(ot);if(n){const d=JSON.parse(n);if(Array.isArray(d))return d.filter(o=>$.includes(o))}}catch{}return[...$]}const m=K(A());_t(m,n=>{try{localStorage.setItem(ot,JSON.stringify(n))}catch{}},{deep:!0});const f=O(()=>k.status),B=O(()=>({connected:"success",connecting:"processing",error:"error",disconnected:"default"})[k.status]||"default"),z=O(()=>{const n=`appLayout.footerStatus.${k.status}`,d=b(n);return d===n?b("appLayout.footerStatus.unknown"):d});function D(n){S.setTheme(n)}const{current:W,supported:H,setLocale:Q}=$t();function de(){const n=H[(H.indexOf(W.value)+1)%H.length];Q(n)}async function pe(n){try{const d=await k.sendRaw({type:"window.open",role:n},1e4);if(d?.ok===!1){G.error(`打开失败:${d.error||"未知"}`);return}const o=d?.result??d;o?.reason==="role_reserved"?G.warning("该窗口角色被保留"):o?.reason}catch(d){G.error(`打开桌面窗口失败:${d.message||d}`)}}async function ye(){Ct.confirm({title:"切换到桌面壳?",content:"回到 V5/V6 桌面壳。完整 electronAPI 表面(UKey 硬件 / 原生对话框 / 系统设置等)会重新可用,但失去 web-panel 的 SPA 体验。保存后需要重启应用才生效。",okText:"切换并重启",cancelText:"取消",centered:!0,async onOk(){try{const n=await k.sendRaw({type:"shell.switch",target:"desktop"},5e3);if(n?.ok===!1)throw new Error(n.error||"shell.switch returned failure");G.loading({content:"正在重启…",duration:0})}catch(n){const d=n instanceof Error?n.message:String(n);G.error("切换失败:"+d)}}})}function v({key:n}){if(typeof n=="string"&&n.startsWith("desktop:")){pe(n);return}T.push({mcp:"/mcp"}[n]||`/${n}`)}return _e(()=>k.connect()),(n,d)=>{const o=p("a-menu-item"),M=p("a-sub-menu"),F=p("a-menu-divider"),it=p("a-menu"),lt=p("a-badge"),rt=p("a-layout-sider"),X=p("a-tooltip"),ut=p("a-tag"),ct=p("a-layout-header"),dt=p("router-view"),pt=p("a-layout-content"),ve=p("a-layout");return u(),C(ve,{class:"app-root"},{default:t(()=>[e(rt,{collapsed:c.value,"onUpdate:collapsed":d[2]||(d[2]=I=>c.value=I),collapsible:"","collapsed-width":56,width:216,class:"sidebar"},{default:t(()=>[l("div",{class:J(["logo",{collapsed:c.value}])},[l("img",{src:a(Et),alt:"ChainlessChain",class:"logo-icon"},null,8,Vt),c.value?P("",!0):(u(),g("span",qt,"ChainlessChain"))],2),c.value?(u(),g("div",{key:1,class:"mode-icon-sm",title:y.value?a(_).projectName:n.$t("appLayout.scope.global")},[y.value?(u(),C(a(Y),{key:0,style:{color:"#1677ff"}})):(u(),C(a(ee),{key:1,style:{color:"#722ed1"}}))],8,Qt)):(u(),g(V,{key:0},[y.value?(u(),g("div",Wt,[e(a(Y),{class:"banner-icon"}),l("div",Ht,[l("div",Jt,s(a(_).projectName||n.$t("appLayout.scope.fallbackProject")),1),l("div",Gt,s(n.$t("appLayout.scope.projectPanel")),1)])])):(u(),g("div",Yt,[e(a(ee),{class:"banner-icon"}),l("span",Zt,s(n.$t("appLayout.scope.global")),1)]))],64)),e(it,{selectedKeys:j.value,"onUpdate:selectedKeys":d[0]||(d[0]=I=>j.value=I),openKeys:m.value,"onUpdate:openKeys":d[1]||(d[1]=I=>m.value=I),theme:N.value,mode:"inline","inline-collapsed":c.value,class:"side-menu",onClick:v},{default:t(()=>[c.value?(u(),g(V,{key:1},[e(o,{key:"dashboard"},{icon:t(()=>[e(a(te))]),_:1}),e(o,{key:"chat"},{icon:t(()=>[e(a(he))]),_:1}),e(o,{key:"quick-ask"},{icon:t(()=>[e(a(ae))]),_:1}),e(o,{key:"cowork"},{icon:t(()=>[e(a(be))]),_:1}),e(o,{key:"services"},{icon:t(()=>[e(a(oe))]),_:1}),e(o,{key:"aiops"},{icon:t(()=>[e(a(we))]),_:1}),e(o,{key:"tokens"},{icon:t(()=>[e(a($e))]),_:1}),e(o,{key:"logs"},{icon:t(()=>[e(a(Le))]),_:1}),e(F,{class:"divider-sm"}),e(o,{key:"skills"},{icon:t(()=>[e(a(Oe))]),_:1}),e(o,{key:"providers"},{icon:t(()=>[e(a(Se))]),_:1}),e(o,{key:"mcp"},{icon:t(()=>[e(a(Ce))]),_:1}),e(o,{key:"project-settings"},{icon:t(()=>[e(a(Y))]),_:1}),e(o,{key:"speech-settings"},{icon:t(()=>[e(a(Ee))]),_:1}),e(o,{key:"notification-settings"},{icon:t(()=>[e(a(fe))]),_:1}),e(o,{key:"sync-settings"},{icon:t(()=>[e(a(Re))]),_:1}),e(o,{key:"nlprog"},{icon:t(()=>[e(a(Ae))]),_:1}),e(o,{key:"codegen"},{icon:t(()=>[e(a(ne))]),_:1}),e(F,{class:"divider-sm"}),e(o,{key:"notes"},{icon:t(()=>[e(a(Ne))]),_:1}),e(o,{key:"search"},{icon:t(()=>[e(a(je))]),_:1}),e(o,{key:"memory"},{icon:t(()=>[e(a(Te))]),_:1}),e(o,{key:"knowledge"},{icon:t(()=>[e(a(Be))]),_:1}),e(o,{key:"personal-data-hub"},{icon:t(()=>[e(a(Me))]),_:1}),e(o,{key:"marketplace"},{icon:t(()=>[e(a(Pe))]),_:1}),e(o,{key:"cron"},{icon:t(()=>[e(a(De))]),_:1}),e(o,{key:"workflow"},{icon:t(()=>[e(a(Ie))]),_:1}),e(o,{key:"pipeline"},{icon:t(()=>[e(a(Ue))]),_:1}),e(o,{key:"tasks"},{icon:t(()=>[e(a(ae))]),_:1}),e(F,{class:"divider-sm"}),e(o,{key:"security"},{icon:t(()=>[e(a(se))]),_:1}),e(o,{key:"ukey-sign"},{icon:t(()=>[e(a(ie))]),_:1}),e(o,{key:"trust"},{icon:t(()=>[e(a(U))]),_:1}),e(o,{key:"audit"},{icon:t(()=>[e(a(Ke))]),_:1}),e(o,{key:"mtc"},{icon:t(()=>[e(a(U))]),_:1}),e(o,{key:"mtc-audit"},{icon:t(()=>[e(a(U))]),_:1}),e(o,{key:"multisig"},{icon:t(()=>[e(a(le))]),_:1}),e(o,{key:"did"},{icon:t(()=>[e(a(ze))]),_:1}),e(o,{key:"permissions"},{icon:t(()=>[e(a(Fe))]),_:1}),e(o,{key:"p2p"},{icon:t(()=>[e(a(Ve))]),_:1}),e(o,{key:"mobile-bridge"},{icon:t(()=>[e(a(ce))]),_:1}),e(o,{key:"terminal"},{icon:t(()=>[e(a(me))]),_:1}),e(o,{key:"backup"},{icon:t(()=>[e(a(re))]),_:1}),e(o,{key:"git"},{icon:t(()=>[e(a(ne))]),_:1}),e(o,{key:"projects"},{icon:t(()=>[e(a(qe))]),_:1}),e(o,{key:"crosschain"},{icon:t(()=>[e(a(We))]),_:1}),e(o,{key:"compliance"},{icon:t(()=>[e(a(U))]),_:1}),e(o,{key:"privacy"},{icon:t(()=>[e(a(ue))]),_:1}),e(o,{key:"inference"},{icon:t(()=>[e(a(He))]),_:1}),e(o,{key:"federation"},{icon:t(()=>[e(a(Je))]),_:1}),e(F,{class:"divider-sm"}),e(o,{key:"wallet"},{icon:t(()=>[e(a(Ge))]),_:1}),e(o,{key:"organization"},{icon:t(()=>[e(a(le))]),_:1}),e(o,{key:"tenant"},{icon:t(()=>[e(a(Ye))]),_:1}),e(o,{key:"sla"},{icon:t(()=>[e(a(te))]),_:1}),e(o,{key:"analytics"},{icon:t(()=>[e(a(Ze))]),_:1}),e(o,{key:"templates"},{icon:t(()=>[e(a(Qe))]),_:1}),e(F,{class:"divider-sm"}),e(o,{key:"community"},{icon:t(()=>[e(a(Xe))]),_:1}),e(o,{key:"governance"},{icon:t(()=>[e(a(xe))]),_:1}),e(o,{key:"reputation"},{icon:t(()=>[e(a(et))]),_:1}),e(o,{key:"recommend"},{icon:t(()=>[e(a(tt))]),_:1}),e(F,{class:"divider-sm"}),e(o,{key:"rssfeed"},{icon:t(()=>[e(a(at))]),_:1}),e(o,{key:"webauthn"},{icon:t(()=>[e(a(ie))]),_:1}),a(r).isEmbedded?(u(),g(V,{key:0},[e(F,{class:"divider-sm"}),e(o,{key:"desktop:hardware-wallet"},{icon:t(()=>[e(a(se))]),_:1}),e(o,{key:"desktop:backup-dashboard"},{icon:t(()=>[e(a(re))]),_:1}),e(o,{key:"desktop:llm-test-chat"},{icon:t(()=>[e(a(ue))]),_:1}),e(o,{key:"desktop:settings"},{icon:t(()=>[e(a(oe))]),_:1})],64)):P("",!0)],64)):(u(),g(V,{key:0},[e(M,{key:"g-overview"},{title:t(()=>[l("span",Xt,s(n.$t("appLayout.groups.overview")),1)]),default:t(()=>[e(o,{key:"dashboard"},{icon:t(()=>[e(a(te))]),default:t(()=>[i(s(n.$t("appLayout.items.dashboard")),1)]),_:1}),e(o,{key:"chat"},{icon:t(()=>[e(a(he))]),default:t(()=>[i(s(n.$t("appLayout.items.chat")),1)]),_:1}),e(o,{key:"quick-ask"},{icon:t(()=>[e(a(ae))]),default:t(()=>[i(s(n.$t("appLayout.items.quickAsk")),1)]),_:1}),e(o,{key:"cowork"},{icon:t(()=>[e(a(be))]),default:t(()=>[i(s(n.$t("appLayout.items.cowork")),1)]),_:1}),e(o,{key:"services"},{icon:t(()=>[e(a(oe))]),default:t(()=>[i(s(n.$t("appLayout.items.services")),1)]),_:1}),e(o,{key:"aiops"},{icon:t(()=>[e(a(we))]),default:t(()=>[i(s(n.$t("appLayout.items.aiops")),1)]),_:1}),e(o,{key:"tokens"},{icon:t(()=>[e(a($e))]),default:t(()=>[i(s(n.$t("appLayout.items.tokens")),1)]),_:1}),e(o,{key:"logs"},{icon:t(()=>[e(a(Le))]),default:t(()=>[i(s(n.$t("appLayout.items.logs")),1)]),_:1})]),_:1}),e(M,{key:"g-config"},{title:t(()=>[l("span",xt,s(n.$t("appLayout.groups.config")),1)]),default:t(()=>[e(o,{key:"skills"},{icon:t(()=>[e(a(Oe))]),default:t(()=>[i(s(n.$t("appLayout.items.skills")),1)]),_:1}),e(o,{key:"providers"},{icon:t(()=>[e(a(Se))]),default:t(()=>[i(s(n.$t("appLayout.items.providers")),1)]),_:1}),e(o,{key:"mcp"},{icon:t(()=>[e(a(Ce))]),default:t(()=>[i(s(n.$t("appLayout.items.mcp")),1)]),_:1}),e(o,{key:"project-settings"},{icon:t(()=>[e(a(Y))]),default:t(()=>[i(s(n.$t("appLayout.items.projectSettings")),1)]),_:1}),e(o,{key:"speech-settings"},{icon:t(()=>[e(a(Ee))]),default:t(()=>[i(s(n.$t("appLayout.items.speechSettings")),1)]),_:1}),e(o,{key:"notification-settings"},{icon:t(()=>[e(a(fe))]),default:t(()=>[i(s(n.$t("appLayout.items.notificationSettings")),1)]),_:1}),e(o,{key:"sync-settings"},{icon:t(()=>[e(a(Re))]),default:t(()=>[i(s(n.$t("appLayout.items.syncSettings")),1)]),_:1}),e(o,{key:"nlprog"},{icon:t(()=>[e(a(Ae))]),default:t(()=>[i(s(n.$t("appLayout.items.nlprog")),1)]),_:1}),e(o,{key:"codegen"},{icon:t(()=>[e(a(ne))]),default:t(()=>[i(s(n.$t("appLayout.items.codegen")),1)]),_:1})]),_:1}),e(M,{key:"g-data"},{title:t(()=>[l("span",ea,s(n.$t("appLayout.groups.data")),1)]),default:t(()=>[e(o,{key:"notes"},{icon:t(()=>[e(a(Ne))]),default:t(()=>[i(s(n.$t("appLayout.items.notes")),1)]),_:1}),e(o,{key:"search"},{icon:t(()=>[e(a(je))]),default:t(()=>[i(s(n.$t("appLayout.items.search")),1)]),_:1}),e(o,{key:"memory"},{icon:t(()=>[e(a(Te))]),default:t(()=>[i(s(n.$t("appLayout.items.memory")),1)]),_:1}),e(o,{key:"knowledge"},{icon:t(()=>[e(a(Be))]),default:t(()=>[i(s(n.$t("appLayout.items.knowledge")),1)]),_:1}),e(o,{key:"personal-data-hub"},{icon:t(()=>[e(a(Me))]),default:t(()=>[d[3]||(d[3]=i("个人数据中台",-1))]),_:1}),e(o,{key:"marketplace"},{icon:t(()=>[e(a(Pe))]),default:t(()=>[i(s(n.$t("appLayout.items.marketplace")),1)]),_:1}),e(o,{key:"cron"},{icon:t(()=>[e(a(De))]),default:t(()=>[i(s(n.$t("appLayout.items.cron")),1)]),_:1}),e(o,{key:"workflow"},{icon:t(()=>[e(a(Ie))]),default:t(()=>[i(s(n.$t("appLayout.items.workflow")),1)]),_:1}),e(o,{key:"pipeline"},{icon:t(()=>[e(a(Ue))]),default:t(()=>[i(s(n.$t("appLayout.items.pipeline")),1)]),_:1}),e(o,{key:"tasks"},{icon:t(()=>[e(a(ae))]),default:t(()=>[i(s(n.$t("appLayout.items.tasks")),1)]),_:1})]),_:1}),e(M,{key:"g-advanced"},{title:t(()=>[l("span",ta,s(n.$t("appLayout.groups.advanced")),1)]),default:t(()=>[e(o,{key:"security"},{icon:t(()=>[e(a(se))]),default:t(()=>[i(s(n.$t("appLayout.items.security")),1)]),_:1}),e(o,{key:"ukey-sign"},{icon:t(()=>[e(a(ie))]),default:t(()=>[i(s(n.$t("appLayout.items.ukeySign")),1)]),_:1}),e(o,{key:"trust"},{icon:t(()=>[e(a(U))]),default:t(()=>[i(s(n.$t("appLayout.items.trust")),1)]),_:1}),e(o,{key:"audit"},{icon:t(()=>[e(a(Ke))]),default:t(()=>[i(s(n.$t("appLayout.items.audit")),1)]),_:1}),e(o,{key:"mtc"},{icon:t(()=>[e(a(U))]),default:t(()=>[i(s(n.$t("appLayout.items.mtc")),1)]),_:1}),e(o,{key:"mtc-audit"},{icon:t(()=>[e(a(U))]),default:t(()=>[i(s(n.$t("appLayout.items.mtcAudit","MTC 审计")),1)]),_:1}),e(o,{key:"multisig"},{icon:t(()=>[e(a(le))]),default:t(()=>[i(s(n.$t("appLayout.items.multisig","M-of-N 多签")),1)]),_:1}),e(o,{key:"did"},{icon:t(()=>[e(a(ze))]),default:t(()=>[i(s(n.$t("appLayout.items.did")),1)]),_:1}),e(o,{key:"permissions"},{icon:t(()=>[e(a(Fe))]),default:t(()=>[i(s(n.$t("appLayout.items.permissions")),1)]),_:1}),e(o,{key:"p2p"},{icon:t(()=>[e(a(Ve))]),default:t(()=>[i(s(n.$t("appLayout.items.p2p")),1)]),_:1}),e(o,{key:"mobile-bridge"},{icon:t(()=>[e(a(ce))]),default:t(()=>[i(s(n.$t("appLayout.items.mobileBridge","移动桥")),1)]),_:1}),e(o,{key:"mobile-projects"},{icon:t(()=>[e(a(ce))]),default:t(()=>[i(s(n.$t("appLayout.items.mobileProjects","手机项目 (v0.2)")),1)]),_:1}),e(o,{key:"terminal"},{icon:t(()=>[e(a(me))]),default:t(()=>[i(s(n.$t("appLayout.items.terminal","远程终端")),1)]),_:1}),e(o,{key:"backup"},{icon:t(()=>[e(a(re))]),default:t(()=>[i(s(n.$t("appLayout.items.backup")),1)]),_:1}),e(o,{key:"git"},{icon:t(()=>[e(a(ne))]),default:t(()=>[i(s(n.$t("appLayout.items.git")),1)]),_:1}),e(o,{key:"projects"},{icon:t(()=>[e(a(qe))]),default:t(()=>[i(s(n.$t("appLayout.items.projects")),1)]),_:1}),e(o,{key:"crosschain"},{icon:t(()=>[e(a(We))]),default:t(()=>[i(s(n.$t("appLayout.items.crosschain")),1)]),_:1}),e(o,{key:"compliance"},{icon:t(()=>[e(a(U))]),default:t(()=>[i(s(n.$t("appLayout.items.compliance")),1)]),_:1}),e(o,{key:"privacy"},{icon:t(()=>[e(a(ue))]),default:t(()=>[i(s(n.$t("appLayout.items.privacy")),1)]),_:1}),e(o,{key:"inference"},{icon:t(()=>[e(a(He))]),default:t(()=>[i(s(n.$t("appLayout.items.inference")),1)]),_:1}),e(o,{key:"federation"},{icon:t(()=>[e(a(Je))]),default:t(()=>[i(s(n.$t("appLayout.items.federation")),1)]),_:1})]),_:1}),e(M,{key:"g-enterprise"},{title:t(()=>[l("span",aa,s(n.$t("appLayout.groups.enterprise")),1)]),default:t(()=>[e(o,{key:"wallet"},{icon:t(()=>[e(a(Ge))]),default:t(()=>[i(s(n.$t("appLayout.items.wallet")),1)]),_:1}),e(o,{key:"organization"},{icon:t(()=>[e(a(le))]),default:t(()=>[i(s(n.$t("appLayout.items.organization")),1)]),_:1}),e(o,{key:"tenant"},{icon:t(()=>[e(a(Ye))]),default:t(()=>[i(s(n.$t("appLayout.items.tenant")),1)]),_:1}),e(o,{key:"sla"},{icon:t(()=>[e(a(te))]),default:t(()=>[i(s(n.$t("appLayout.items.sla")),1)]),_:1}),e(o,{key:"analytics"},{icon:t(()=>[e(a(Ze))]),default:t(()=>[i(s(n.$t("appLayout.items.analytics")),1)]),_:1}),e(o,{key:"templates"},{icon:t(()=>[e(a(Qe))]),default:t(()=>[i(s(n.$t("appLayout.items.templates")),1)]),_:1})]),_:1}),e(M,{key:"g-social"},{title:t(()=>[l("span",oa,s(n.$t("appLayout.groups.social")),1)]),default:t(()=>[e(o,{key:"community"},{icon:t(()=>[e(a(Xe))]),default:t(()=>[i(s(n.$t("appLayout.items.community")),1)]),_:1}),e(o,{key:"governance"},{icon:t(()=>[e(a(xe))]),default:t(()=>[i(s(n.$t("appLayout.items.governance")),1)]),_:1}),e(o,{key:"reputation"},{icon:t(()=>[e(a(et))]),default:t(()=>[i(s(n.$t("appLayout.items.reputation")),1)]),_:1}),e(o,{key:"recommend"},{icon:t(()=>[e(a(tt))]),default:t(()=>[i(s(n.$t("appLayout.items.recommend")),1)]),_:1})]),_:1}),e(M,{key:"g-media"},{title:t(()=>[l("span",na,s(n.$t("appLayout.groups.media")),1)]),default:t(()=>[e(o,{key:"video"},{icon:t(()=>[e(a(Ot))]),default:t(()=>[i(s(n.$t("appLayout.items.video")),1)]),_:1})]),_:1}),e(M,{key:"g-extension"},{title:t(()=>[l("span",sa,s(n.$t("appLayout.groups.extension")),1)]),default:t(()=>[e(o,{key:"rssfeed"},{icon:t(()=>[e(a(at))]),default:t(()=>[i(s(n.$t("appLayout.items.rssfeed")),1)]),_:1}),e(o,{key:"webauthn"},{icon:t(()=>[e(a(ie))]),default:t(()=>[i(s(n.$t("appLayout.items.webauthn")),1)]),_:1})]),_:1}),a(r).isEmbedded?(u(),C(M,{key:"g-desktop"},{title:t(()=>[l("span",ia,s(n.$t("appLayout.groups.desktop")),1)]),default:t(()=>[e(o,{key:"desktop:hardware-wallet"},{icon:t(()=>[e(a(se))]),default:t(()=>[i(s(n.$t("appLayout.items.desktopHardware")),1)]),_:1}),e(o,{key:"desktop:backup-dashboard"},{icon:t(()=>[e(a(re))]),default:t(()=>[i(s(n.$t("appLayout.items.desktopBackup")),1)]),_:1}),e(o,{key:"desktop:llm-test-chat"},{icon:t(()=>[e(a(ue))]),default:t(()=>[i(s(n.$t("appLayout.items.desktopLlmTest")),1)]),_:1}),e(o,{key:"desktop:settings"},{icon:t(()=>[e(a(oe))]),default:t(()=>[i(s(n.$t("appLayout.items.desktopSettings")),1)]),_:1})]),_:1})):P("",!0)],64))]),_:1},8,["selectedKeys","openKeys","theme","inline-collapsed"]),l("div",{class:J(["sidebar-footer",{collapsed:c.value}])},[e(lt,{status:B.value},null,8,["status"]),c.value?P("",!0):(u(),g("span",la,s(z.value),1))],2)]),_:1},8,["collapsed"]),e(ve,{class:"main-area"},{default:t(()=>[e(ct,{class:"app-header"},{default:t(()=>[l("div",ra,[l("div",{class:J(["scope-tag",y.value?"project":"global"])},[(u(),C(gt(y.value?a(Y):a(ee)))),l("span",null,s(y.value?a(_).projectName||n.$t("appLayout.scope.fallbackProject"):n.$t("appLayout.scope.global")),1),y.value&&a(_).projectRoot?(u(),C(X,{key:0,title:a(_).projectRoot},{default:t(()=>[e(a(St),{class:"info-icon"})]),_:1},8,["title"])):P("",!0)],2)]),l("div",ua,[l("div",ca,[(u(!0),g(V,null,nt(a(wt),(I,x)=>(u(),C(X,{key:x,title:I.label},{default:t(()=>[l("button",{class:J(["theme-btn",{active:R.value===x}]),"data-theme-key":x,onClick:_a=>D(x)},s(I.icon),11,da)]),_:2},1032,["title"]))),128))]),e(X,{title:n.$t("language.label")},{default:t(()=>[l("button",{class:"lang-switch-btn","data-locale":a(W),onClick:de},[e(a(ee),{class:"lang-switch-icon"}),l("span",ya,s(n.$t("language.switch")),1)],8,pa)]),_:1},8,["title"]),e(Ft),a(r).isEmbedded?(u(),C(Ut,{key:0})):P("",!0),l("span",ma,s(a(w)),1),a(r).isEmbedded?(u(),C(X,{key:1,title:n.$t("appLayout.shellSwitch")},{default:t(()=>[l("button",{type:"button",class:"shell-switch-btn",onClick:ye},[e(a(me))])]),_:1},8,["title"])):P("",!0),e(ut,{color:f.value==="connected"?"green":f.value==="connecting"?"orange":"red",class:"ws-tag"},{default:t(()=>[i(s(f.value==="connected"?n.$t("appLayout.wsStatus.connected"):f.value==="connecting"?n.$t("appLayout.wsStatus.connecting"):n.$t("appLayout.wsStatus.disconnected")),1)]),_:1},8,["color"])])]),_:1}),e(pt,{class:"page-content"},{default:t(()=>[e(dt)]),_:1})]),_:1})]),_:1})}}},Fa=ge(fa,[["__scopeId","data-v-1e9db429"]]);export{Fa as default};