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.
- package/package.json +3 -3
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BnOiVQsQ.js → AIOps-VbMLpnCu.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Tw6tLfY1.js → ActionButton-BR6BrZ2w.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Des59eT3.js → Analytics-DWN2iHDA.js} +2 -2
- package/src/assets/web-panel/assets/AppLayout-CyBXOO_H.js +3 -0
- package/src/assets/web-panel/assets/{AppLayout-BLCe1k8m.css → AppLayout-DleZFgpe.css} +1 -1
- package/src/assets/web-panel/assets/{Audit-JX1upUxG.js → Audit-Cu5a4b5S.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-ByvQLRhY.js → Backup-D0vrJYkS.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DC-h8Hd-.js → BaseInput-DnFk3wDi.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-D9dJ3NKb.js → Chat-DFMa9lEz.js} +3 -3
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CO908iBt.css +1 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CpVazmEP.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-n3tD-95B.js → Checkbox-J23wKgNR.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BV9t0CmU.js → Codegen-Ca6Z4r1p.js} +1 -1
- package/src/assets/web-panel/assets/{Col-4KhPnXFB.js → Col-BZ3XsxN2.js} +1 -1
- package/src/assets/web-panel/assets/{Community-R1hZqHEr.js → Community-DhK5H5dD.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Bo4r1Z3L.js → Compact-DjJMyddV.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dwywk8U2.js → Compliance-Bup3Rk9z.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DTBwVdcR.js → Cowork-BqsPMIpo.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BrveD2Al.js → Cron-Ca69LFf-.js} +1 -1
- package/src/assets/web-panel/assets/{Crosschain-C63oZCeg.js → Crosschain-mTB21YwK.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Cyfo7zh4.js → DID-C1_Eree4.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-_EOI1Ax4.js → Dashboard-L2OWv5io.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BWYHGHO3.js → Dropdown-CpqNwurh.js} +1 -1
- package/src/assets/web-panel/assets/EmailListRenderer-CVJ1j3Ll.css +1 -0
- package/src/assets/web-panel/assets/EmailListRenderer-Mo7D9ADF.js +1 -0
- package/src/assets/web-panel/assets/{Federation-CU03AB2d.js → Federation-COTeKl2R.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DECACp9C.js → FormItemContext-0oTTQ9MI.js} +1 -1
- package/src/assets/web-panel/assets/GenericCardRenderer-DrMs3upM.js +1 -0
- package/src/assets/web-panel/assets/GenericCardRenderer-DtJFcJYl.css +1 -0
- package/src/assets/web-panel/assets/{Git-BhpPR-ck.js → Git-C6eFUBhz.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BtpmvOHi.js → Governance-5ivL10kw.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DfPuEW02.js → Inference-DcERJUS_.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CeA_2NFe.js → KnowledgeGraph-Dm1eQ_Hv.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C_ozF-bn.js → Logs-Cjt-JTuL.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-WgBvu6Ma.js → Marketplace-fNDRN8YJ.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CNIz8liM.js → McpTools-kKgzl9Bb.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-DEN8NgRg.js → Memory-BdJujXCH.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CP0rj-Fx.js → MobileBridge-lmvJfnpK.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-x3zDbPDI.js → MobileProjects-ZM-DVPhi.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CC4PEFJV.js → Mtc-CeoaWgzU.js} +1 -1
- package/src/assets/web-panel/assets/{MtcAudit-BHB0GvyW.js → MtcAudit-CRvKTLqr.js} +1 -1
- package/src/assets/web-panel/assets/{Multisig-BUPfLbde.js → Multisig-DnzFw69O.js} +2 -2
- package/src/assets/web-panel/assets/{NLProgramming-DNOkByM8.js → NLProgramming-0xP2rtGN.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-U-RIv-kE.js → Notes-tJpp3z8e.js} +1 -1
- package/src/assets/web-panel/assets/{NotificationSettings-B-q6tsxf.js → NotificationSettings-CRdpEoHX.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-BEH9lAIb.js +1 -0
- package/src/assets/web-panel/assets/OrderTableRenderer-BnOISpKI.css +1 -0
- package/src/assets/web-panel/assets/{Organization-DJLNuZ2_.js → Organization-Dhwy6dXT.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BxTl0aeE.js → Overflow-COwwTMb-.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Czzalu_0.js → P2P-79YWb-cn.js} +1 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-B9ZGFpn4.css +1 -0
- package/src/assets/web-panel/assets/PdhVaultBrowser-Dhn5S3Vs.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-BBw06EGK.js → Permissions-ELRvDOlY.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-Dvaa8niQ.css → PersonalDataHub-D0ncF92t.css} +1 -1
- package/src/assets/web-panel/assets/PersonalDataHub-DIWbfS5k.js +1 -0
- package/src/assets/web-panel/assets/{Pipeline-qLLWNe2i.js → Pipeline-Dzi1zmAr.js} +1 -1
- package/src/assets/web-panel/assets/Privacy-BYzWkaRt.js +1 -0
- package/src/assets/web-panel/assets/{ProjectInit-CmJ0VPGy.js → ProjectInit-D_5DqLSS.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-D1Xm2EwO.js → ProjectSettings-DrAAYJgR.js} +1 -1
- package/src/assets/web-panel/assets/{Projects-DLN-awqS.js → Projects-BOrF4_X8.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D164DGWo.js → Providers-DYLWZVe4.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BRCH7WgH.js → QuickAsk-k76cZTaF.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BWZhT_-2.js → Recommend-CXM4p6RB.js} +1 -1
- package/src/assets/web-panel/assets/Reputation-DLnLpz8L.js +1 -0
- package/src/assets/web-panel/assets/{Row-BbuTB-ny.js → Row-BavvTUrL.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CLegyrrb.js → RssFeed-CtCarC8_.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Bz41pkvW.js → Search-CJcDGc1x.js} +1 -1
- package/src/assets/web-panel/assets/{Security-D4NWRpgV.js → Security-DB3GmnY9.js} +3 -3
- package/src/assets/web-panel/assets/{Services-CP_6SXST.js → Services-BWEvVHhz.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CdRO3MnV.js → Skeleton-BHbixeGV.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BmghgIL3.js → Skills-DWwIjvjl.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DjAIXxkm.js → Sla-C1Qu9o0j.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DYk-En4R.js → SpeechSettings-BiEysZg1.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CglX98G4.js → SyncSettings-XlOLFUv2.js} +1 -1
- package/src/assets/web-panel/assets/{Tasks-BcLMTSP3.js → Tasks-BKjOcYxW.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BCs5bP8P.js → Templates-BVKjc9j-.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-B5jLtdWR.js → Tenant-C33WmSiJ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CZKKYYaA.js → Terminal-Dl8RJZHg.js} +1 -1
- package/src/assets/web-panel/assets/TimelineRenderer-CFN36N3H.js +1 -0
- package/src/assets/web-panel/assets/TimelineRenderer-DmztdsbF.css +1 -0
- package/src/assets/web-panel/assets/{Tokens-B8aHonMu.js → Tokens-Dy2kxiCA.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D6jDjaX1.js → Trigger-C7bt0leJ.js} +1 -1
- package/src/assets/web-panel/assets/Trust-CVKbWEMH.js +1 -0
- package/src/assets/web-panel/assets/{UkeySign-B1IDXsz6.js → UkeySign-B91QGwbs.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DHvglMzO.js → VideoEditing-C8xBqRiE.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DAUh8j_b.js → Wallet-RW2IBbpH.js} +1 -1
- package/src/assets/web-panel/assets/{WebAuthn-D0Y8wGZt.js → WebAuthn-CZPv5ayn.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BqZgQo4U.js → WorkflowEditor-CFCwic4a.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CtfIYzWq.js → chat-PVfHUaHj.js} +1 -1
- package/src/assets/web-panel/assets/{colors-B6ZfKKgZ.js → colors-C4WA0-Iq.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item--HQOl9D1.js → compact-item-DQfLwjbC.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-Bf-YNOPI.js → createContext-31PSlu0j.js} +1 -1
- package/src/assets/web-panel/assets/{hasIn-D5G7UiYx.js → hasIn-Csltfg47.js} +1 -1
- package/src/assets/web-panel/assets/icons-AILO5ZcK.js +57 -0
- package/src/assets/web-panel/assets/index-3NsH3wNq.js +1 -0
- package/src/assets/web-panel/assets/{index-_ZD6hPvh.js → index-41v9Hflm.js} +1 -1
- package/src/assets/web-panel/assets/{index-B23hk7ZY.js → index-45Iyof95.js} +1 -1
- package/src/assets/web-panel/assets/{index-CcbuseEC.js → index-8IVdEMKr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVTgMzbI.js → index-B-aRUTIJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-OSlN9c4x.js → index-BCxhSOsr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BrJfwd9_.js → index-BCyTEqF7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAPj11l4.js → index-BD-K1g5z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJlTZ7oK.js → index-BLwrQAlK.js} +1 -1
- package/src/assets/web-panel/assets/{index-ByjAzHrC.js → index-Ba6cQs-y.js} +4 -4
- package/src/assets/web-panel/assets/{index-__qol0SM.js → index-BiFRGYGH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZyNnZb9.js → index-BqOmboiA.js} +1 -1
- package/src/assets/web-panel/assets/{index-UppuQXbk.js → index-C4gzD6Ra.js} +2 -2
- package/src/assets/web-panel/assets/{index-2QuOKVo1.js → index-CArRkfYM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWOeC8v6.js → index-CE8i90GF.js} +1 -1
- package/src/assets/web-panel/assets/{index-B75QpKcS.js → index-CEbbRpw2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKsNidiT.js → index-CEtPU50W.js} +1 -1
- package/src/assets/web-panel/assets/{index-g_d5tOWL.js → index-CIeFJLHG.js} +1 -1
- package/src/assets/web-panel/assets/{index-ofgv0VHh.js → index-CQWE2WKS.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRPGyig2.js → index-C_k_btzK.js} +1 -1
- package/src/assets/web-panel/assets/{index-xOVop383.js → index-CbpUjcEf.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIYydwQc.js → index-CdQUx-5Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQIzU6GO.js → index-CfWk9Yzf.js} +1 -1
- package/src/assets/web-panel/assets/{index-CihsW323.js → index-Cgt2_bmM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkoQfJv0.js → index-CmzuBE2G.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPvA_8ed.js → index-CpXm8DBk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtjPgDzA.js → index-DSO9eU_G.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmVrKala.js → index-DUFwsCsD.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dfm65OiJ.js → index-DVHR_To_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGG5O6Zh.js → index-DW-7sqm0.js} +1 -1
- package/src/assets/web-panel/assets/index-DWtc_qRj.js +1 -0
- package/src/assets/web-panel/assets/{index-BBSGKZ-l.js → index-DdrYhK__.js} +3 -3
- package/src/assets/web-panel/assets/{index-XwovMqXr.js → index-DfbOwhkA.js} +1 -1
- package/src/assets/web-panel/assets/{index-OY_eegoA.js → index-DpEj71nk.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ca_5Za9D.js → index-DtUcq8Nn.js} +1 -1
- package/src/assets/web-panel/assets/{index--KnB-1F0.js → index-DuZKKJDi.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOzNKGtD.js → index-Dymm64KM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzvrUpDp.js → index-P9rJg2C1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqJoAOhC.js → index-nAhW-NN4.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DjUNw-1y.js → initDefaultProps-DPk1oFCk.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Cd6xXLlf.js → motion-CzQ1k8MU.js} +1 -1
- package/src/assets/web-panel/assets/{move-B_W-Y6JL.js → move-BCExaQ0x.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BCZBLb_-.js → omit-D71nF5o_.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CjDhGYLm.js → pickAttrs-pvCq8tx4.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CSC2rU9-.js → placementArrow-D8lSLg_0.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DnyswFkD.js → responsiveObserve-ZN6pVHvM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DujNhbuH.js → slide-VHxyZhFr.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-U2lNCQiL.js → statusUtils-B0jFTTFP.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Ch2rQftE.js → styleChecker-Bc6FRYW9.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-5XxNwjTL.js → useFlexGapSupport-D4YDiqxr.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-pv2YfF-X.js → useFs-CQgQ7iah.js} +1 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-LDh_Sq7B.js +1 -0
- package/src/assets/web-panel/assets/{vnode-CU0J2mVX.js → vnode-BwPvBDfI.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-ZII_iqXl.js → zoom-r6u1_Sq8.js} +1 -1
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/__tests__/hub-ask.test.js +136 -0
- package/src/commands/ask.js +110 -43
- package/src/commands/hub.js +260 -26
- package/src/constants.js +7 -0
- package/src/gateways/ws/personal-data-hub-protocol.js +151 -9
- package/src/lib/host-adb-bridge.js +430 -0
- package/src/lib/personal-data-hub-wiring.js +85 -0
- package/src/assets/web-panel/assets/AppLayout-hku5aFqc.js +0 -3
- package/src/assets/web-panel/assets/PersonalDataHub-CmTx090l.js +0 -1
- package/src/assets/web-panel/assets/Privacy-CStpViYX.js +0 -1
- package/src/assets/web-panel/assets/Reputation-DSTNi8ge.js +0 -1
- package/src/assets/web-panel/assets/Trust-DX_BvTA9.js +0 -1
- package/src/assets/web-panel/assets/icons-BOPtEWK4.js +0 -57
- package/src/assets/web-panel/assets/index-B-xjGh0B.js +0 -1
- 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};
|