chainlesschain 0.162.25 → 0.162.27
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 +2 -2
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-CAdsXHkz.js → AIOps-D67bnWOm.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-JsLRBlBP.js → ActionButton-z7o1N942.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DeM96q71.js → Analytics-ygwetD7a.js} +1 -1
- package/src/assets/web-panel/assets/{AppLayout-eb_6mT6V.js → AppLayout-DKIKC0vr.js} +2 -2
- package/src/assets/web-panel/assets/{Audit-BEOY-CQE.js → Audit-RfvwANd0.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-irFD_DBa.js → Backup-CLC0Npju.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Dq7wtv_k.js → BaseInput-Cy955ldQ.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CstRKWdu.js → Chat-Di1G3WpZ.js} +1 -1
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-3BBqk317.js → ChatBubbleRenderer-D2CwVV3N.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-A8D25IT5.js → Checkbox-mM6T49x7.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-1EfMWeRA.js → Codegen-CFRknQ28.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Bc08LzOn.js → Col-Md7VPq32.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BNnNv7xp.js → Community-B75271cm.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-nFjLneHM.js → Compact-BOrAa1JM.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CZpaaHND.js → Compliance-CqgTFpLC.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DzHugH3j.js → Cowork-Bvdzx2lF.js} +1 -1
- package/src/assets/web-panel/assets/{Cron-C7YRyiN-.js → Cron-BP3ZLMIx.js} +1 -1
- package/src/assets/web-panel/assets/{Crosschain-er2h0L0q.js → Crosschain-Dy8IWecD.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DaMdE0A7.js → DID-DxnpBszy.js} +1 -1
- package/src/assets/web-panel/assets/{Dashboard-1z2K_E1B.js → Dashboard-h8TY-9dT.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-B9NIqAXf.js → Dropdown-CfIh_9pn.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CBHLFokz.js → EmailListRenderer-egkHFDB9.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D2fEJEki.js → Federation-iXsC9ljf.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-tmsd70yG.js → FormItemContext-D16LYrK1.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DW4Lnrsr.js → GenericCardRenderer-B2l7qvIp.js} +1 -1
- package/src/assets/web-panel/assets/{Git-D8aBagAp.js → Git-DshuXpeI.js} +1 -1
- package/src/assets/web-panel/assets/{Governance-CKDAHamy.js → Governance-BzgoQvxX.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BLLp118j.js → Inference-CMikYc6i.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Cawx-yfu.js → KnowledgeGraph-DAP_uKkx.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-sWSzp5PY.js → Logs-Zax7aDPt.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BQMX3dSy.js → Marketplace-DC8_c3hX.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DjlFST3o.js → McpTools-CvpCNH6E.js} +1 -1
- package/src/assets/web-panel/assets/{Memory-LZE1wG7m.js → Memory-BVgvCyNB.js} +1 -1
- package/src/assets/web-panel/assets/{MobileBridge-BWG47jQ6.js → MobileBridge-BvffJp-I.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DHVv0tYo.js → MobileProjects-BBEmZ56X.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Di1hrhM3.js → Mtc-D4Lg-E10.js} +1 -1
- package/src/assets/web-panel/assets/{MtcAudit-BowOCi-O.js → MtcAudit-BpuX4w67.js} +1 -1
- package/src/assets/web-panel/assets/{Multisig-CgpR0s8E.js → Multisig-CclH6FTt.js} +1 -1
- package/src/assets/web-panel/assets/{NLProgramming-O4U3Plxd.js → NLProgramming-DPBSg0ot.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Ce_5C6XT.js → Notes-CapzFL8Y.js} +1 -1
- package/src/assets/web-panel/assets/{NotificationSettings-BVVopkxj.js → NotificationSettings-Fxts3vW8.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-XW2G50wt.js → OrderTableRenderer-DexmnSf8.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DaW54kdP.js → Organization-Cx9wnh2C.js} +1 -1
- package/src/assets/web-panel/assets/{Overflow-CVTGMUVt.js → Overflow-uNU3Jy_O.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CpEwrhBx.js → P2P-DZqGX3zP.js} +1 -1
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CDqun-Z9.js → PdhVaultBrowser-BbXlJUmU.js} +2 -2
- package/src/assets/web-panel/assets/{Permissions-BsSU3MaL.js → Permissions-tSlqIXRk.js} +1 -1
- package/src/assets/web-panel/assets/{PersonalDataHub-DmUc89_0.css → PersonalDataHub-CO9-IYDY.css} +1 -1
- package/src/assets/web-panel/assets/PersonalDataHub-DdPngiX0.js +2 -0
- package/src/assets/web-panel/assets/{Pipeline-CPCDpDyd.js → Pipeline-G-YXvU25.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-oZEQvVWA.js → Privacy-BIDsJhkC.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CRu5bDNW.js → ProjectInit-DTGzvgQ9.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectSettings-ComIZ7gQ.js → ProjectSettings-8QjihLTL.js} +1 -1
- package/src/assets/web-panel/assets/{Projects-Djr10qFp.js → Projects-D7S7x7R1.js} +1 -1
- package/src/assets/web-panel/assets/Providers-BNI-WkmA.css +1 -0
- package/src/assets/web-panel/assets/Providers-DpTXneeZ.js +1 -0
- package/src/assets/web-panel/assets/{QuickAsk-C21t1JEf.js → QuickAsk-C83JwW8d.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BjJForJo.js → Recommend-PO0TXid1.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-Cp8Ym-Hk.js → Reputation-pwXhN9Lv.js} +1 -1
- package/src/assets/web-panel/assets/{Row-n8ruyEoT.js → Row-829tJQ3D.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CosaiHvS.js → RssFeed-Btnw67Mk.js} +1 -1
- package/src/assets/web-panel/assets/{Search-DUNSNFJZ.js → Search-olQ94qFA.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Z3WyX_MB.js → Security-C_Vfuu0K.js} +1 -1
- package/src/assets/web-panel/assets/{Services-U0m9Oj8V.js → Services-ByfhJMDp.js} +1 -1
- package/src/assets/web-panel/assets/{Skeleton-B_M5sv2W.js → Skeleton-CWxck8Jk.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-NKU9c6LT.js → Skills-yady6VUJ.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DscfpqF8.js → Sla-Dc_HEsj7.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DP0O84ej.js → SpeechSettings--vhH3ORV.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-P_WEyoH3.js → SyncSettings-GUPyaG2O.js} +1 -1
- package/src/assets/web-panel/assets/{Tasks-C8YAncnj.js → Tasks-Sj1OYuDS.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-F12-SRc3.js → Templates-rdiV_eFo.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CULHbrwu.js → Tenant-N76bdElE.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DdYrQ0n3.js → Terminal-KZ1H0ObH.js} +1 -1
- package/src/assets/web-panel/assets/{TimelineRenderer-C12_BYAe.js → TimelineRenderer-D7nI-o49.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-8MVLlc0s.js → Tokens-c2LL4v7q.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Bl6QmvKw.js → Trigger-B57LuN-B.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BH_aEsWy.js → Trust-BMmdOSoP.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DsX2CeE4.js → UkeySign-CtGUfuxi.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DaRdn6e9.js → VideoEditing-CzrCzzLF.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DO89dzlU.js → Wallet-Ciiwlppn.js} +1 -1
- package/src/assets/web-panel/assets/{WebAuthn-KUKNjImY.js → WebAuthn-BPFoLjnF.js} +1 -1
- package/src/assets/web-panel/assets/{WorkflowEditor-CnSoP-Z9.js → WorkflowEditor-Bf8UZPRx.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Jp0M9E52.js → chat-aoVkknKT.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Bkq4q91x.js → colors-CKv2MZMK.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CCt1byem.js → compact-item-1FPS5mTP.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DwRLi0Uq.js → createContext-o2GXZ1sO.js} +1 -1
- package/src/assets/web-panel/assets/{hasIn-CTVm-2lw.js → hasIn-CMm7HgH-.js} +1 -1
- package/src/assets/web-panel/assets/{index-TqiVFiUf.js → index-866hrngI.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9q3wKEr.js → index-8AzFTShP.js} +1 -1
- package/src/assets/web-panel/assets/index-BHtt98Qo.js +1 -0
- package/src/assets/web-panel/assets/{index-Cvrka2TD.js → index-BQcTgRAZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJegJP2N.js → index-BSqFVnSI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIBi-rGt.js → index-BUWd4FFK.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRwUdk7I.js → index-Bb7YRgoc.js} +1 -1
- package/src/assets/web-panel/assets/{index-hpRtUCjU.js → index-BbJDxap_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DC-8E2CG.js → index-BwA5hOgO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPnSymMN.js → index-CFgWbJuM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDbgmmSF.js → index-CXDN0kh7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhSbNePw.js → index-CXHs9New.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXDSJwDk.js → index-CalorQK0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BziGa10S.js → index-CcfXX0ID.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3irAeY8.js → index-CdDX6sEY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWQ9NRWg.js → index-Ch-sPaT4.js} +1 -1
- package/src/assets/web-panel/assets/{index-MdArO-BF.js → index-Chh-oVTw.js} +1 -1
- package/src/assets/web-panel/assets/{index-zwGGcR7I.js → index-Cr1ZwF59.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtzUDs1M.js → index-Cr2EOK21.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2pkXVOU.js → index-Crp4UcP-.js} +1 -1
- package/src/assets/web-panel/assets/index-Cul_OH-A.js +1 -0
- package/src/assets/web-panel/assets/{index-TL3iHPdE.js → index-D1QEfzq_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BjGcDwb2.js → index-D3aMAQEQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_U_xDvh.js → index-D3bKIme7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjJWQqPG.js → index-DCxs8O-B.js} +1 -1
- package/src/assets/web-panel/assets/{index-Db3R-khd.js → index-DDP25Jlo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFcr_PT2.js → index-DT76REiB.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-UAtktg.js → index-DZ747YY7.js} +1 -1
- package/src/assets/web-panel/assets/{index-C2ovimhG.js → index-De4hAcPZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdlVwys1.js → index-DoVMBKvC.js} +1 -1
- package/src/assets/web-panel/assets/{index-BD2U0Ciz.js → index-JP5LGd1K.js} +3 -3
- package/src/assets/web-panel/assets/{index-BJmiHI2z.js → index-OiF8vib7.js} +1 -1
- package/src/assets/web-panel/assets/{index-C3ZzMEg0.js → index-Y_UOzu30.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFh73FRz.js → index-bJ5UBvQQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-eyVkd-kF.js → index-dXE5uCaT.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLjugrcu.js → index-fyC4Vx7E.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRkGL2HJ.js → index-g4LWpdR7.js} +1 -1
- package/src/assets/web-panel/assets/{index-6OmglXey.js → index-u3FjYN52.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJWYdgmz.js → index-yhq2Pttf.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-9iSe4Eid.js → initDefaultProps-Co0jgVso.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CcUz2pq7.js → motion-Zw-nUuCZ.js} +1 -1
- package/src/assets/web-panel/assets/{move-3Po9fM71.js → move-O_Pya0SD.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BBcRnciw.js → omit-bqQYnuYR.js} +1 -1
- package/src/assets/web-panel/assets/parsers-UEvh_ShA.js +4 -0
- package/src/assets/web-panel/assets/{pickAttrs-UCqcWwOy.js → pickAttrs-PeesUh3N.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-boVtHxA4.js → placementArrow-DoUJMHry.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-V0qPHZOl.js → responsiveObserve-QHPYy6hK.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CZyysA_q.js → slide-H_RDRwbZ.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BLyCU5L3.js → statusUtils-RuUT_noY.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BfXrPW7h.js → styleChecker-DuWlOmft.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Be2wILDi.js → useFlexGapSupport-CJmU3crw.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CzJYoHOI.js → useFs-CBYaEAuH.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-__HEfTF9.js → usePersonalDataHub-B0x06BwX.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-C0XE0aCE.js → vnode-B2BMGDRL.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CphwCBhl.js → zoom-D_OEfpnp.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/__tests__/hub-ask.test.js +104 -1
- package/src/commands/__tests__/hub-kuaishou-adb-sync.test.js +161 -0
- package/src/commands/__tests__/hub-toutiao-adb-sync.test.js +158 -0
- package/src/commands/hub.js +353 -1
- package/src/gateways/ws/personal-data-hub-protocol.js +34 -0
- package/src/lib/personal-data-hub-wiring.js +218 -0
- package/src/assets/web-panel/assets/PersonalDataHub-BafcAH5d.js +0 -1
- package/src/assets/web-panel/assets/Providers-BEakqcO5.css +0 -1
- package/src/assets/web-panel/assets/Providers-CltNzV7e.js +0 -2
- package/src/assets/web-panel/assets/index-CR2wmKfw.js +0 -1
- package/src/assets/web-panel/assets/index-iXk8Oeci.js +0 -1
- package/src/assets/web-panel/assets/parsers-DftYMnlk.js +0 -3
|
@@ -331,12 +331,26 @@ async function initHub() {
|
|
|
331
331
|
// collector (xiaohongshu.com cookies + 4 endpoints with X-S sign).
|
|
332
332
|
const { createXhsCookiesExtension } =
|
|
333
333
|
await import("@chainlesschain/personal-data-hub/adapters/social-xiaohongshu-adb");
|
|
334
|
+
// Phase 6c: register `toutiao.cookies` extension for the Toutiao
|
|
335
|
+
// C-path collector (www.toutiao.com cookies + 4 endpoints, 3 of
|
|
336
|
+
// which need _signature signing — CLI context falls back to -99
|
|
337
|
+
// short-circuit, desktop wiring upgrades via ToutiaoSignBridge).
|
|
338
|
+
const { createToutiaoCookiesExtension } =
|
|
339
|
+
await import("@chainlesschain/personal-data-hub/adapters/social-toutiao-adb");
|
|
340
|
+
// Phase 6d: register `kuaishou.cookies` extension. Profile from
|
|
341
|
+
// cookie's api_ph payload (no HTTP); 3 GraphQL POST endpoints need
|
|
342
|
+
// __NS_sig3 + kpf/kpn — CLI short-circuits, desktop upgrades via
|
|
343
|
+
// KuaishouSignBridge.
|
|
344
|
+
const { createKuaishouCookiesExtension } =
|
|
345
|
+
await import("@chainlesschain/personal-data-hub/adapters/social-kuaishou-adb");
|
|
334
346
|
hostAdbBridge = createHostAdbBridge({
|
|
335
347
|
extensions: {
|
|
336
348
|
"bilibili.cookies": createBilibiliCookiesExtension(),
|
|
337
349
|
"douyin.pull-im-db": createDouyinDbExtension(),
|
|
338
350
|
"weibo.cookies": createWeiboCookiesExtension(),
|
|
339
351
|
"xhs.cookies": createXhsCookiesExtension(),
|
|
352
|
+
"toutiao.cookies": createToutiaoCookiesExtension(),
|
|
353
|
+
"kuaishou.cookies": createKuaishouCookiesExtension(),
|
|
340
354
|
},
|
|
341
355
|
});
|
|
342
356
|
sda._deps.bridgeProvider = () => hostAdbBridge;
|
|
@@ -1072,6 +1086,114 @@ async function initHub() {
|
|
|
1072
1086
|
};
|
|
1073
1087
|
}
|
|
1074
1088
|
},
|
|
1089
|
+
|
|
1090
|
+
// ─── Phase 6c — Toutiao C 路径 one-shot sync ────────────────────────
|
|
1091
|
+
//
|
|
1092
|
+
// Pulls www.toutiao.com cookies via toutiao.cookies extension →
|
|
1093
|
+
// fetchProfile (/passport/account/info/v2 — no _sig) → 3 endpoints
|
|
1094
|
+
// (feed/collection/search, _signature required).
|
|
1095
|
+
//
|
|
1096
|
+
// **CLI context has NO sign bridge** — the 3 _signature endpoints
|
|
1097
|
+
// short-circuit with lastErrorCode=-99 (no HTTP traffic). Profile is
|
|
1098
|
+
// still fetched. Desktop wiring upgrades via ToutiaoSignBridge.
|
|
1099
|
+
//
|
|
1100
|
+
// Typed reason codes: BRIDGE_UNAVAILABLE / MODULE_LOAD_FAILED /
|
|
1101
|
+
// TOUTIAO_NO_ROOT / TOUTIAO_NOT_INSTALLED / TOUTIAO_COOKIES_EMPTY /
|
|
1102
|
+
// TOUTIAO_COOKIES_TRUNCATED / TOUTIAO_NOT_SQLITE /
|
|
1103
|
+
// TOUTIAO_COOKIES_INCOMPLETE / TOUTIAO_BASE64_PARSE / SYNC_FAILED.
|
|
1104
|
+
async toutiaoAdbSync(opts = {}) {
|
|
1105
|
+
if (!hostAdbBridge) {
|
|
1106
|
+
return {
|
|
1107
|
+
ok: false,
|
|
1108
|
+
reason: "BRIDGE_UNAVAILABLE",
|
|
1109
|
+
message:
|
|
1110
|
+
"host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
let collector;
|
|
1114
|
+
try {
|
|
1115
|
+
const mod =
|
|
1116
|
+
await import("@chainlesschain/personal-data-hub/adapters/social-toutiao-adb");
|
|
1117
|
+
collector = mod.default ? mod.default : mod;
|
|
1118
|
+
} catch (err) {
|
|
1119
|
+
return {
|
|
1120
|
+
ok: false,
|
|
1121
|
+
reason: "MODULE_LOAD_FAILED",
|
|
1122
|
+
message: err && err.message ? err.message : String(err),
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
try {
|
|
1126
|
+
const report = await collector.collectAndSync(
|
|
1127
|
+
hostAdbBridge,
|
|
1128
|
+
registry,
|
|
1129
|
+
opts,
|
|
1130
|
+
);
|
|
1131
|
+
return { ok: true, report };
|
|
1132
|
+
} catch (err) {
|
|
1133
|
+
const msg = err && err.message ? err.message : String(err);
|
|
1134
|
+
const m = msg.match(/^(TOUTIAO_[A-Z_]+)/);
|
|
1135
|
+
return {
|
|
1136
|
+
ok: false,
|
|
1137
|
+
reason: m ? m[1] : "SYNC_FAILED",
|
|
1138
|
+
message: msg,
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
},
|
|
1142
|
+
|
|
1143
|
+
// ─── Phase 6d — Kuaishou C 路径 one-shot sync ───────────────────────
|
|
1144
|
+
//
|
|
1145
|
+
// Pulls www.kuaishou.com cookies via kuaishou.cookies extension →
|
|
1146
|
+
// fetchProfile (PURE COOKIE PARSE — reads api_ph payload, no HTTP)
|
|
1147
|
+
// → 3 signed GraphQL POST endpoints (visionFeedRecommend /
|
|
1148
|
+
// visionProfilePhotoList / visionSearchPhoto, __NS_sig3 + kpf/kpn).
|
|
1149
|
+
//
|
|
1150
|
+
// **CLI context has NO sign bridge** — 3 signed endpoints short-
|
|
1151
|
+
// circuit with lastErrorCode=-99 (no HTTP traffic). Profile + uid
|
|
1152
|
+
// still emit from cookie payload. Desktop wiring upgrades via
|
|
1153
|
+
// KuaishouSignBridge.
|
|
1154
|
+
//
|
|
1155
|
+
// Typed reason codes: BRIDGE_UNAVAILABLE / MODULE_LOAD_FAILED /
|
|
1156
|
+
// KUAISHOU_NO_ROOT / KUAISHOU_NOT_INSTALLED / KUAISHOU_COOKIES_EMPTY /
|
|
1157
|
+
// KUAISHOU_COOKIES_TRUNCATED / KUAISHOU_NOT_SQLITE /
|
|
1158
|
+
// KUAISHOU_COOKIES_INCOMPLETE / KUAISHOU_BASE64_PARSE / SYNC_FAILED.
|
|
1159
|
+
async kuaishouAdbSync(opts = {}) {
|
|
1160
|
+
if (!hostAdbBridge) {
|
|
1161
|
+
return {
|
|
1162
|
+
ok: false,
|
|
1163
|
+
reason: "BRIDGE_UNAVAILABLE",
|
|
1164
|
+
message:
|
|
1165
|
+
"host-adb-bridge failed to initialize at hub boot — check `adb` is on PATH or set ADB_PATH env var",
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
let collector;
|
|
1169
|
+
try {
|
|
1170
|
+
const mod =
|
|
1171
|
+
await import("@chainlesschain/personal-data-hub/adapters/social-kuaishou-adb");
|
|
1172
|
+
collector = mod.default ? mod.default : mod;
|
|
1173
|
+
} catch (err) {
|
|
1174
|
+
return {
|
|
1175
|
+
ok: false,
|
|
1176
|
+
reason: "MODULE_LOAD_FAILED",
|
|
1177
|
+
message: err && err.message ? err.message : String(err),
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
try {
|
|
1181
|
+
const report = await collector.collectAndSync(
|
|
1182
|
+
hostAdbBridge,
|
|
1183
|
+
registry,
|
|
1184
|
+
opts,
|
|
1185
|
+
);
|
|
1186
|
+
return { ok: true, report };
|
|
1187
|
+
} catch (err) {
|
|
1188
|
+
const msg = err && err.message ? err.message : String(err);
|
|
1189
|
+
const m = msg.match(/^(KUAISHOU_[A-Z_]+)/);
|
|
1190
|
+
return {
|
|
1191
|
+
ok: false,
|
|
1192
|
+
reason: m ? m[1] : "SYNC_FAILED",
|
|
1193
|
+
message: msg,
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
},
|
|
1075
1197
|
};
|
|
1076
1198
|
}
|
|
1077
1199
|
|
|
@@ -1151,6 +1273,95 @@ export async function getHub() {
|
|
|
1151
1273
|
return _initPromise;
|
|
1152
1274
|
}
|
|
1153
1275
|
|
|
1276
|
+
// ─── Minimal hub bootstrap for read-only / LLM-free commands ────────────
|
|
1277
|
+
//
|
|
1278
|
+
// 2026-05-27 — `cc hub retrieve-context` cold-start was 90s+ on Android
|
|
1279
|
+
// because initHub() wires 50+ adapters + KG sink + RAG sink + EntityResolver
|
|
1280
|
+
// + email accounts auto-load + 6 ADB extension imports — none of which
|
|
1281
|
+
// retrieveContext actually needs. AnalysisEngine.retrieveContext only
|
|
1282
|
+
// touches: vault.queryEvents / queryPersons / queryItems / stats / audit /
|
|
1283
|
+
// searchEvents / searchPersons. No adapters. No LLM call. Skipping the
|
|
1284
|
+
// heavy wiring should cut cold-start from ~90s to <5s in-APK.
|
|
1285
|
+
//
|
|
1286
|
+
// Singleton-cached separately from full hub — if the user later runs a
|
|
1287
|
+
// `cc hub sync-adapter` in the same process, getHub() lazy-builds the
|
|
1288
|
+
// full hub on demand. The minimal hub's vault is closed when full hub
|
|
1289
|
+
// boots to avoid double-open contention (SQLCipher allows single writer).
|
|
1290
|
+
//
|
|
1291
|
+
// Returns the same shape as getHub() for the keys retrieveContext needs:
|
|
1292
|
+
// { hubDir, vault, engine, llm, kgSink:null, ragSink:null, registry:null }.
|
|
1293
|
+
|
|
1294
|
+
let _hubMinimal = null;
|
|
1295
|
+
let _hubMinimalInitPromise = null;
|
|
1296
|
+
|
|
1297
|
+
async function initHubMinimal() {
|
|
1298
|
+
const hubDir = resolveHubDir();
|
|
1299
|
+
mkdirSync(hubDir, { recursive: true });
|
|
1300
|
+
mkdirSync(join(hubDir, "keys"), { recursive: true });
|
|
1301
|
+
|
|
1302
|
+
const keyProvider = new FileKeyProvider(join(hubDir, "keys"));
|
|
1303
|
+
const KEY_NAME = "vault:default";
|
|
1304
|
+
let key = await keyProvider.get(KEY_NAME);
|
|
1305
|
+
if (!key) {
|
|
1306
|
+
key = generateKeyHex();
|
|
1307
|
+
await keyProvider.set(KEY_NAME, key);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
const vault = new LocalVault({ path: join(hubDir, "vault.db"), key });
|
|
1311
|
+
vault.open();
|
|
1312
|
+
|
|
1313
|
+
// No LLM: retrieveContext is LLM-free. AnalysisEngine constructor still
|
|
1314
|
+
// requires a `llm` arg with chat() + isLocal — pass a sentinel that
|
|
1315
|
+
// throws if anyone actually calls it (defense against future code
|
|
1316
|
+
// accidentally invoking ask() via this minimal hub).
|
|
1317
|
+
const sentinelLlm = {
|
|
1318
|
+
isLocal: true,
|
|
1319
|
+
name: "minimal-hub-sentinel",
|
|
1320
|
+
chat: () => {
|
|
1321
|
+
throw new Error(
|
|
1322
|
+
"minimal hub: LLM unavailable — use getHub() for ask() / chat paths",
|
|
1323
|
+
);
|
|
1324
|
+
},
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
const engine = new AnalysisEngine({
|
|
1328
|
+
vault,
|
|
1329
|
+
llm: sentinelLlm,
|
|
1330
|
+
// No ragRetriever — BM25 sink is part of full hub init, skip here.
|
|
1331
|
+
});
|
|
1332
|
+
|
|
1333
|
+
return {
|
|
1334
|
+
hubDir,
|
|
1335
|
+
vault,
|
|
1336
|
+
engine,
|
|
1337
|
+
llm: null,
|
|
1338
|
+
kgSink: null,
|
|
1339
|
+
ragSink: null,
|
|
1340
|
+
registry: null,
|
|
1341
|
+
minimal: true,
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
export async function getHubMinimal() {
|
|
1346
|
+
if (_hubMinimal) return _hubMinimal;
|
|
1347
|
+
// If full hub is already initialized, reuse its vault + engine — opening
|
|
1348
|
+
// a second LocalVault against the same SQLCipher DB would fight for the
|
|
1349
|
+
// file lock.
|
|
1350
|
+
if (_hub) return _hub;
|
|
1351
|
+
if (!_hubMinimalInitPromise) {
|
|
1352
|
+
_hubMinimalInitPromise = initHubMinimal()
|
|
1353
|
+
.then((h) => {
|
|
1354
|
+
_hubMinimal = h;
|
|
1355
|
+
return h;
|
|
1356
|
+
})
|
|
1357
|
+
.catch((err) => {
|
|
1358
|
+
_hubMinimalInitPromise = null;
|
|
1359
|
+
throw err;
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
return _hubMinimalInitPromise;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1154
1365
|
export function close() {
|
|
1155
1366
|
if (_hub && _hub.aichatHealthChecker) {
|
|
1156
1367
|
try {
|
|
@@ -1162,8 +1373,15 @@ export function close() {
|
|
|
1162
1373
|
_hub.vault.close();
|
|
1163
1374
|
} catch (_e) {}
|
|
1164
1375
|
}
|
|
1376
|
+
if (_hubMinimal && _hubMinimal.vault && _hubMinimal !== _hub) {
|
|
1377
|
+
try {
|
|
1378
|
+
_hubMinimal.vault.close();
|
|
1379
|
+
} catch (_e) {}
|
|
1380
|
+
}
|
|
1165
1381
|
_hub = null;
|
|
1166
1382
|
_initPromise = null;
|
|
1383
|
+
_hubMinimal = null;
|
|
1384
|
+
_hubMinimalInitPromise = null;
|
|
1167
1385
|
_bm25 = null;
|
|
1168
1386
|
_kgMod = null;
|
|
1169
1387
|
_bm25Mod = null;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{w as et,L as n,Q as g,N as t,c as o,M as y,R as d,F as ee,Y as re,Z as tt,P as r,O as l,S as p,a1 as at,f as ue,r as S,K as c,a as se,a4 as Bt,o as Rt,u as X,a0 as Tt,$ as Ht}from"./vendor-DhFY8mDK.js";import{u as Me}from"./usePersonalDataHub-__HEfTF9.js";import{_ as Le,d as k}from"./index-BD2U0Ciz.js";import{R as je,aB as zt,O as Ft,al as Wt,h as qt,aC as Kt,Q as Vt,aD as Qt,aE as Gt,y as Yt,q as Xt,aF as jt,a3 as Jt,ad as Zt,aG as ea,m as ta,e as Je}from"./icons-AILO5ZcK.js";const aa={key:0},oa={class:"vendor-head"},la={class:"hint"},na={class:"hint",style:{"margin-top":"4px"}},sa={key:0,class:"hint",style:{"margin-top":"4px",color:"#ff4d4f"}},ia={key:1},ra={class:"hint"},ua=["href"],da={class:"howto"},pa=["href"],ca={key:3,style:{"margin-top":"8px"}},fa={key:2,class:"kv",style:{"margin-top":"4px"}},va={key:3,class:"kv",style:{"margin-top":"4px",color:"#ff4d4f"}},ma={key:2},ya={__name:"AIChatWizard",props:{open:{type:Boolean,default:!1},existingAccounts:{type:Array,default:()=>[]}},emits:["update:open","registered"],setup(me,{emit:_e}){const w=me,L=_e,Q=[{vendor:"deepseek",displayName:"DeepSeek",notes:"手机号 + 验证码登录",requiredCookies:["userToken"],cookieMaxAgeHintDays:30},{vendor:"kimi",displayName:"Kimi",notes:"手机号验证码登录",requiredCookies:["access_token"],cookieMaxAgeHintDays:30},{vendor:"tongyi",displayName:"通义千问",notes:"阿里云账号 SSO(过期较快)",requiredCookies:["login_aliyunid"],cookieMaxAgeHintDays:7},{vendor:"zhipu",displayName:"智谱清言",notes:"手机号 + 验证码",requiredCookies:["chatglm_token"],cookieMaxAgeHintDays:30},{vendor:"hunyuan",displayName:"腾讯混元",notes:"QQ / 微信 / 手机号",requiredCookies:["hy_token"],cookieMaxAgeHintDays:14},{vendor:"qianfan",displayName:"百度文心",notes:"百度账号",requiredCookies:["BDUSS"],cookieMaxAgeHintDays:7},{vendor:"coze",displayName:"字节扣子 Coze",notes:"字节统一 passport",requiredCookies:["sessionid"],cookieMaxAgeHintDays:14},{vendor:"dreamina",displayName:"即梦 Dreamina",notes:"字节图像生成",requiredCookies:["sessionid"],cookieMaxAgeHintDays:14},{vendor:"doubao",displayName:"豆包 Doubao",notes:"字节文本 AI",requiredCookies:["sessionid"],cookieMaxAgeHintDays:14}],h=Me(),m=S(1),b=S(null),U=S(""),O=S(null),B=S(null),V=S(null),M=se({open:!1,probe:!1,register:!1}),ie=ue(()=>Q.find(_=>_.vendor===b.value)||{}),de=ue(()=>m.value===1?"选择一家 AI 服务商":m.value===2?O.value?.fallbackMode==="paste"?"在外部浏览器登录,把 cookie 粘贴到下面":"在内嵌浏览器登录,主进程自动读取 cookie":"校验并写入本地加密 vault"),j=ue(()=>{const _=B.value;return _?_.reason==="UNKNOWN_VENDOR"?"未知厂商 — 请刷新页面或重选":_.reason==="PASTE_REQUIRED"?"请先粘贴 cookie 字符串":_.missingRequired?.length?`缺关键 cookie: ${_.missingRequired.join(", ")}`:_.reason||"cookie 校验失败":""}),R=ue(()=>{const _=V.value;return _?_.reason==="REQUIRED_COOKIES_MISSING"?`缺关键 cookie: ${(_.missingRequired||[]).join(", ")}`:_.reason==="VALIDATE_COOKIE_FAILED"?"厂商拒绝该 cookie(可能已过期或被风控)":_.reason==="ADAPTER_THREW"?`Adapter 抛错: ${_.error||"网络错误"}`:_.reason==="UNKNOWN_VENDOR"?"未知厂商":_.reason||"注册失败":"未知错误"});function v(_){return w.existingAccounts.some(i=>i&&i.vendor===_)}function le(_){return w.existingAccounts.find(i=>i&&i.vendor===_)||null}function q(_){const i=le(_);return i?i.lastHealth?i.lastHealth.ok?"ok":i.lastHealth.reason==="SPEC_VERSION_MISMATCH"?"mismatch":"fail":"unknown":null}function te(_){const i=le(_);if(!i||!i.lastHealth||i.lastHealth.ok)return"";const z=i.lastHealth.reason;return z?z==="SPEC_VERSION_MISMATCH"?"cookie 规格已升级,请重新登录":z==="ADAPTER_THREW"?"上次校验抛错,建议稍后重试":z==="COOKIE_EXPIRED"?"Cookie 已过期,请重新登录":z:"Cookie 校验失败,建议重新登录"}async function J(_){try{(await h.unregisterAichat(_))?.ok&&L("registered",{vendor:_,accountId:null,unregistered:!0})}catch(i){V.value={ok:!1,reason:i?.message||"UNREGISTER_FAILED"}}}function A(_){b.value=_}async function W(){if(b.value){M.open=!0,O.value=null,B.value=null,U.value="";try{if(O.value=await h.openAichatLogin(b.value),!O.value?.ok)return;m.value=2}catch(_){O.value={ok:!1,reason:_?.message||"OPEN_FAILED"}}finally{M.open=!1}}}async function ae(){M.probe=!0,B.value=null;try{const _=U.value.trim(),i=_||void 0;B.value=await h.probeAichatCookies(b.value,i)}catch(_){B.value={ok:!1,reason:_?.message||"PROBE_FAILED"}}finally{M.probe=!1}}async function I(){if(B.value?.ok){M.register=!0;try{V.value=await h.registerAichatVendor(b.value,B.value.cookies),m.value=3,V.value?.ok&&L("registered",{vendor:b.value,accountId:V.value.accountId})}catch(_){V.value={ok:!1,reason:_?.message||"REGISTER_FAILED"},m.value=3}finally{M.register=!1}}}function K(){m.value=1,b.value=null,U.value="",O.value=null,B.value=null,V.value=null}function pe(){K(),L("update:open",!1)}return et(()=>w.open,_=>{_&&K()}),(_,i)=>{const z=c("a-alert"),D=c("a-tag"),G=c("a-button"),Ee=c("a-popconfirm"),ke=c("a-card"),Se=c("a-col"),ye=c("a-row"),T=c("a-collapse-panel"),H=c("a-collapse"),C=c("a-textarea"),f=c("a-form-item"),we=c("a-form"),Ce=c("a-result"),xe=c("a-space"),he=c("a-drawer");return n(),g(he,{open:me.open,title:"添加 AI 对话账号",placement:"right",width:640,"destroy-on-close":!0,"onUpdate:open":i[4]||(i[4]=N=>L("update:open",N)),onClose:pe},{footer:t(()=>[o(xe,{style:{float:"right"}},{default:t(()=>[m.value>1&&m.value<3?(n(),g(G,{key:0,onClick:i[3]||(i[3]=N=>m.value=m.value-1)},{default:t(()=>[...i[22]||(i[22]=[l("上一步",-1)])]),_:1})):p("",!0),o(G,{onClick:pe},{default:t(()=>[...i[23]||(i[23]=[l("取消",-1)])]),_:1}),m.value===1?(n(),g(G,{key:1,type:"primary",disabled:!b.value,loading:M.open,onClick:W},{default:t(()=>[...i[24]||(i[24]=[l(" 下一步 ",-1)])]),_:1},8,["disabled","loading"])):p("",!0),m.value===2&&O.value?.fallbackMode==="paste"?(n(),g(G,{key:2,loading:M.probe,disabled:!U.value.trim(),onClick:ae},{default:t(()=>[...i[25]||(i[25]=[l(" 检测 cookie ",-1)])]),_:1},8,["loading","disabled"])):p("",!0),m.value===2&&O.value?.fallbackMode!=="paste"?(n(),g(G,{key:3,loading:M.probe,onClick:ae},{default:t(()=>[...i[26]||(i[26]=[l(" 检测 cookie ",-1)])]),_:1},8,["loading"])):p("",!0),m.value===2?(n(),g(G,{key:4,type:"primary",loading:M.register,disabled:!B.value?.ok,onClick:I},{default:t(()=>[...i[27]||(i[27]=[l(" 注册 ",-1)])]),_:1},8,["loading","disabled"])):p("",!0)]),_:1})]),default:t(()=>[o(z,{message:`第 ${m.value} / 3 步`,description:de.value,type:"info","show-icon":"",style:{"margin-bottom":"16px"}},null,8,["message","description"]),m.value===1?(n(),y("div",aa,[i[10]||(i[10]=d("p",{class:"hint"}," 选择要接入的 AI 服务商。登录后将本地读取 cookie 同步对话历史;cookie 仅落本机加密文件,不上传任何云端。 ",-1)),o(ye,{gutter:[12,12]},{default:t(()=>[(n(),y(ee,null,re(Q,N=>o(Se,{xs:24,sm:12,md:8,key:N.vendor},{default:t(()=>[o(ke,{size:"small",hoverable:"",class:tt(["vendor-card",{selected:b.value===N.vendor}]),onClick:Pe=>A(N.vendor)},{default:t(()=>[d("div",oa,[d("strong",null,r(N.displayName),1),q(N.vendor)==="fail"?(n(),g(D,{key:0,color:"red"},{default:t(()=>[...i[5]||(i[5]=[l("🔴 重新登录",-1)])]),_:1})):q(N.vendor)==="mismatch"?(n(),g(D,{key:1,color:"orange"},{default:t(()=>[...i[6]||(i[6]=[l("⚠ 规格升级",-1)])]),_:1})):q(N.vendor)==="unknown"?(n(),g(D,{key:2,color:"blue"},{default:t(()=>[...i[7]||(i[7]=[l("已接入·待巡检",-1)])]),_:1})):q(N.vendor)==="ok"?(n(),g(D,{key:3,color:"green"},{default:t(()=>[...i[8]||(i[8]=[l("✓ 已接入",-1)])]),_:1})):p("",!0)]),d("div",la,r(N.notes),1),d("div",na,[o(D,{color:"default"},{default:t(()=>[l(r(N.requiredCookies.length)+" 必需 cookie",1)]),_:2},1024),o(D,{color:"default"},{default:t(()=>[l("过期约 "+r(N.cookieMaxAgeHintDays)+" 天",1)]),_:2},1024)]),v(N.vendor)&&te(N.vendor)?(n(),y("div",sa,r(te(N.vendor)),1)):p("",!0),v(N.vendor)?(n(),y("div",{key:1,class:"vendor-actions",onClick:i[0]||(i[0]=at(()=>{},["stop"]))},[o(Ee,{title:"注销该 AI 对话来源?历史事件仍可在 vault 中查询。","ok-text":"注销","cancel-text":"取消",onConfirm:Pe=>J(N.vendor)},{default:t(()=>[o(G,{size:"small",type:"text",danger:""},{default:t(()=>[...i[9]||(i[9]=[l("注销",-1)])]),_:1})]),_:1},8,["onConfirm"])])):p("",!0)]),_:2},1032,["class","onClick"])]),_:2},1024)),64))]),_:1})])):p("",!0),m.value===2&&O.value?(n(),y("div",ia,[d("p",ra,[d("strong",null,r(ie.value.displayName),1),i[11]||(i[11]=l(" · ",-1)),d("a",{href:O.value.loginUrl,target:"_blank",rel:"noopener noreferrer"},r(O.value.loginUrl),9,ua)]),O.value.fallbackMode==="paste"?(n(),g(z,{key:0,message:O.value.helpText||"请在外部浏览器登录后从开发者工具复制全部 cookie 字符串粘贴到下方。",type:"warning","show-icon":"",style:{"margin-bottom":"12px"}},null,8,["message"])):(n(),g(z,{key:1,message:"桌面端:请在弹出的内嵌浏览器窗口登录后点击 “检测 cookie”。",type:"info","show-icon":"",style:{"margin-bottom":"12px"}})),O.value.fallbackMode==="paste"?(n(),g(H,{key:2,bordered:!1,style:{"margin-bottom":"12px"}},{default:t(()=>[o(T,{key:"howto",header:"如何获取 cookie 字符串?"},{default:t(()=>[d("ol",da,[d("li",null,[i[12]||(i[12]=l("用 Chrome / Edge 打开 ",-1)),d("a",{href:O.value.loginUrl,target:"_blank"},r(O.value.loginUrl),9,pa)]),i[13]||(i[13]=d("li",null,"完成登录,进入对话页",-1)),i[14]||(i[14]=d("li",null,[l("按 "),d("kbd",null,"F12"),l(" 打开开发者工具 → "),d("strong",null,"Application"),l(" → "),d("strong",null,"Cookies")],-1)),i[15]||(i[15]=d("li",null,"选中域名 → 全选所有 cookie 行 → 用扩展(如 EditThisCookie)导出 “name=value; …” 串",-1)),i[16]||(i[16]=d("li",null,[l("或在 Console 执行 "),d("code",null,"document.cookie"),l(" 复制结果(注意:HTTP-Only cookie 取不到,仍需 Application 面板)")],-1)),i[17]||(i[17]=d("li",null,"粘贴到下方文本框,点 “检测 cookie”",-1))])]),_:1})]),_:1})):p("",!0),o(we,{layout:"vertical"},{default:t(()=>[o(f,{label:"Cookie 字符串"},{default:t(()=>[o(C,{value:U.value,"onUpdate:value":i[1]||(i[1]=N=>U.value=N),rows:6,placeholder:"name1=value1; name2=value2; name3=value3 …",autocomplete:"off"},null,8,["value"])]),_:1})]),_:1}),B.value?(n(),y("div",ca,[B.value.ok?(n(),g(z,{key:0,type:"success","show-icon":"",message:`已识别 ${B.value.foundRequired.length} 个必需 cookie + ${B.value.foundOptional.length} 个可选 cookie`},null,8,["message"])):(n(),g(z,{key:1,type:"error","show-icon":"",message:j.value},null,8,["message"])),B.value.foundRequired?.length?(n(),y("div",fa," ✓ "+r(B.value.foundRequired.join(", ")),1)):p("",!0),B.value.missingRequired?.length?(n(),y("div",va," 缺失: "+r(B.value.missingRequired.join(", ")),1)):p("",!0)])):p("",!0)])):p("",!0),m.value===3?(n(),y("div",ma,[V.value?.ok?(n(),g(Ce,{key:0,status:"success",title:`${ie.value.displayName} 已接入`,"sub-title":`accountId: ${V.value.accountId} · userId: ${V.value.validation?.userId||"匿名"}`},{extra:t(()=>[o(G,{type:"primary",onClick:pe},{default:t(()=>[...i[18]||(i[18]=[l("完成",-1)])]),_:1}),o(G,{onClick:K},{default:t(()=>[...i[19]||(i[19]=[l("再加一家",-1)])]),_:1})]),_:1},8,["title","sub-title"])):(n(),g(Ce,{key:1,status:"error",title:"接入失败","sub-title":R.value},{extra:t(()=>[o(G,{type:"primary",onClick:i[2]||(i[2]=N=>m.value=2)},{default:t(()=>[...i[20]||(i[20]=[l("返回粘贴 cookie",-1)])]),_:1}),o(G,{onClick:K},{default:t(()=>[...i[21]||(i[21]=[l("选其他厂商",-1)])]),_:1})]),_:1},8,["sub-title"]))])):p("",!0)]),_:1},8,["open"])}}},ga=Le(ya,[["__scopeId","data-v-a608230c"]]),_a={key:0},ka={key:0,class:"probe-result"},ba={key:0,class:"kv"},Aa={key:0,class:"kv"},wa={key:1},Ca={key:2},Ia={key:2,style:{"margin-top":"12px"}},Da={__name:"WechatWizard",props:{open:{type:Boolean,default:!1}},emits:["update:open","registered"],setup(me,{emit:_e}){const w=me,L=_e,Q=Me(),h=S(1),m=S(null),b=se({uin:"",dbPath:"",wechatDataPath:"",forceProvider:null}),U=S(null),O=se({probe:!1,register:!1}),B=ue(()=>h.value===1?"探测设备 + WeChat 版本,确认可用的 keyProvider":h.value===2?"填 UIN 与已 adb-pull 的本地路径":"bootstrap 注册 + 持久化 wechat-accounts.json"),V=ue(()=>{const R=U.value;return R?R.reason==="ENV_UNSUPPORTED"?R.message||"env-probe 拒绝 — 请回到第 1 步看 reasons":R.reason==="MD5_NEEDS_WECHAT_DATA_PATH"?"MD5 路径需要 wechatDataPath":R.reason==="FRIDA_NEEDS_WXID"?"Frida 路径需要 account.uin / wxid":R.reason==="ADAPTER_CTOR_FAILED"?`Adapter ctor 抛错: ${R.message||""}`:R.reason==="BOOTSTRAP_THREW"?`Bootstrap 抛错: ${R.message||""}`:R.reason==="UIN_REQUIRED"?"UIN 不能为空":R.message||R.reason||"注册失败":"未知错误"});async function M(){O.probe=!0;try{m.value=await Q.probeWechatEnv()}catch(R){m.value={ok:!1,suggestedKeyProvider:"unsupported",reasons:[R?.message||"probe failed"],device:{reachable:!1},root:{detected:!1,magiskInstalled:!1},frida:{serverRunning:!1,port:null},wechat:{installed:!1,versionName:null,majorVersion:null},warnings:[]}}finally{O.probe=!1}}async function ie(){O.register=!0;try{U.value=await Q.registerWechat({account:{uin:b.uin},dbPath:b.dbPath||null,wechatDataPath:b.wechatDataPath||null,keyProviderOverride:b.forceProvider}),h.value=3,U.value?.ok&&L("registered",{uin:b.uin,chosenKeyProvider:U.value.chosenKeyProvider})}catch(R){U.value={ok:!1,reason:"BOOTSTRAP_THREW",message:R?.message||"RPC failed"},h.value=3}finally{O.register=!1}}function de(){h.value=1,m.value=null,b.uin="",b.dbPath="",b.wechatDataPath="",b.forceProvider=null,U.value=null}function j(){de(),L("update:open",!1)}return et(()=>w.open,R=>{R&&de()}),(R,v)=>{const le=c("a-alert"),q=c("a-button"),te=c("a-tag"),J=c("a-descriptions-item"),A=c("a-descriptions"),W=c("a-input"),ae=c("a-form-item"),I=c("a-radio"),K=c("a-radio-group"),pe=c("a-form"),_=c("a-result"),i=c("a-space"),z=c("a-drawer");return n(),g(z,{open:me.open,title:"添加 WeChat 账号",placement:"right",width:640,"destroy-on-close":!0,"onUpdate:open":v[8]||(v[8]=D=>L("update:open",D)),onClose:j},{footer:t(()=>[o(i,{style:{float:"right"}},{default:t(()=>[h.value>1&&h.value<3?(n(),g(q,{key:0,onClick:v[6]||(v[6]=D=>h.value=h.value-1)},{default:t(()=>[...v[21]||(v[21]=[l("上一步",-1)])]),_:1})):p("",!0),o(q,{onClick:j},{default:t(()=>[...v[22]||(v[22]=[l("取消",-1)])]),_:1}),h.value===1?(n(),g(q,{key:1,type:"primary",disabled:!m.value||m.value.suggestedKeyProvider==="unsupported",onClick:v[7]||(v[7]=D=>h.value=2)},{default:t(()=>[...v[23]||(v[23]=[l(" 下一步 ",-1)])]),_:1},8,["disabled"])):p("",!0),h.value===2?(n(),g(q,{key:2,type:"primary",loading:O.register,disabled:!b.uin||m.value?.suggestedKeyProvider==="md5"&&!b.wechatDataPath,onClick:ie},{default:t(()=>[...v[24]||(v[24]=[l(" 注册 ",-1)])]),_:1},8,["loading","disabled"])):p("",!0)]),_:1})]),default:t(()=>[o(le,{message:`第 ${h.value} / 3 步`,description:B.value,type:"info","show-icon":"",style:{"margin-bottom":"16px"}},null,8,["message","description"]),h.value===1?(n(),y("div",_a,[v[11]||(v[11]=d("p",{class:"hint"},[l(" 请用 USB 连接 Android 设备(开启 USB 调试)。WeChat ≥ 8.0 需要 root + frida-server。 探测仅读取 "),d("code",null,"adb shell"),l(" 命令输出,不写入任何东西。 ")],-1)),o(q,{type:"primary",loading:O.probe,onClick:M,style:{"margin-bottom":"12px"}},{default:t(()=>[...v[9]||(v[9]=[l(" 🔍 探测环境 ",-1)])]),_:1},8,["loading"]),m.value?(n(),y("div",ka,[o(A,{column:1,size:"small",bordered:""},{default:t(()=>[o(J,{label:"suggestedKeyProvider"},{default:t(()=>[o(te,{color:m.value.suggestedKeyProvider==="unsupported"?"red":"green"},{default:t(()=>[l(r(m.value.suggestedKeyProvider),1)]),_:1},8,["color"])]),_:1}),o(J,{label:"adb 设备"},{default:t(()=>[o(te,{color:m.value.device.reachable?"green":"red"},{default:t(()=>[l(r(m.value.device.reachable?"已连接":"未连接"),1)]),_:1},8,["color"]),m.value.device.serial?(n(),y("span",ba,r(m.value.device.serial)+" · abi="+r(m.value.device.abi||"?"),1)):p("",!0)]),_:1}),o(J,{label:"root"},{default:t(()=>[o(te,{color:m.value.root.detected?"green":"default"},{default:t(()=>[l(r(m.value.root.detected?"已 root":"未 root"),1)]),_:1},8,["color"]),m.value.root.magiskInstalled?(n(),g(te,{key:0,color:"blue"},{default:t(()=>[...v[10]||(v[10]=[l("Magisk",-1)])]),_:1})):p("",!0)]),_:1}),o(J,{label:"frida-server"},{default:t(()=>[o(te,{color:m.value.frida.serverRunning?"green":"default"},{default:t(()=>[l(r(m.value.frida.serverRunning?"运行中":"未运行"),1)]),_:1},8,["color"]),m.value.frida.port?(n(),y("span",Aa," :"+r(m.value.frida.port),1)):p("",!0)]),_:1}),o(J,{label:"WeChat"},{default:t(()=>[o(te,{color:m.value.wechat.installed?"green":"red"},{default:t(()=>[l(r(m.value.wechat.installed?m.value.wechat.versionName:"未安装"),1)]),_:1},8,["color"])]),_:1})]),_:1}),(n(!0),y(ee,null,re(m.value.reasons||[],D=>(n(),g(le,{key:D,message:D,type:"info","show-icon":"",style:{"margin-top":"8px"}},null,8,["message"]))),128)),(n(!0),y(ee,null,re(m.value.warnings||[],D=>(n(),g(le,{key:D,message:D,type:"warning","show-icon":"",style:{"margin-top":"8px"}},null,8,["message"]))),128))])):p("",!0)])):p("",!0),h.value===2?(n(),y("div",wa,[v[16]||(v[16]=d("p",{class:"hint"},[l(" 填写从 adb pull 拉下来的本地路径。MD5 路径(7.x)需要 "),d("code",null,"wechatDataPath"),l("; Frida 路径(8.0+)需要设备运行 frida-server。 ")],-1)),o(pe,{layout:"vertical"},{default:t(()=>[o(ae,{label:"UIN / wxid",required:""},{default:t(()=>[o(W,{value:b.uin,"onUpdate:value":v[0]||(v[0]=D=>b.uin=D),placeholder:"WeChat 数字 UIN 或 wxid"},null,8,["value"])]),_:1}),o(ae,{label:"dbPath(已拉下的 EnMicroMsg.db 本地路径)"},{default:t(()=>[o(W,{value:b.dbPath,"onUpdate:value":v[1]||(v[1]=D=>b.dbPath=D),placeholder:"C:\\\\users\\\\me\\\\pull\\\\EnMicroMsg.db"},null,8,["value"])]),_:1}),o(ae,{label:"wechatDataPath(已拉下的 /data/data/com.tencent.mm/ 目录)"},{default:t(()=>[o(W,{value:b.wechatDataPath,"onUpdate:value":v[2]||(v[2]=D=>b.wechatDataPath=D),placeholder:"C:\\\\users\\\\me\\\\pull\\\\com.tencent.mm"},null,8,["value"]),v[12]||(v[12]=d("div",{class:"hint"},"MD5 路径必填;Frida 路径可空",-1))]),_:1}),o(ae,{label:"强制 keyProvider(覆盖 env-probe 建议)"},{default:t(()=>[o(K,{value:b.forceProvider,"onUpdate:value":v[3]||(v[3]=D=>b.forceProvider=D)},{default:t(()=>[o(I,{value:null},{default:t(()=>[...v[13]||(v[13]=[l("自动(推荐)",-1)])]),_:1}),o(I,{value:"md5"},{default:t(()=>[...v[14]||(v[14]=[l("md5",-1)])]),_:1}),o(I,{value:"frida"},{default:t(()=>[...v[15]||(v[15]=[l("frida",-1)])]),_:1})]),_:1},8,["value"])]),_:1})]),_:1})])):p("",!0),h.value===3?(n(),y("div",Ca,[U.value?.ok?(n(),g(_,{key:0,status:"success",title:`WeChat 已接入 (uin=${b.uin})`,"sub-title":`provider=${U.value.chosenKeyProvider} · sensitivity=${U.value.sensitivity}`},{extra:t(()=>[o(q,{type:"primary",onClick:j},{default:t(()=>[...v[17]||(v[17]=[l("完成",-1)])]),_:1}),o(q,{onClick:de},{default:t(()=>[...v[18]||(v[18]=[l("再加一个",-1)])]),_:1})]),_:1},8,["title","sub-title"])):(n(),g(_,{key:1,status:"error",title:"接入失败","sub-title":V.value},Bt({_:2},[U.value?.probe?.reasons?.length?{name:"extra",fn:t(()=>[o(q,{onClick:v[4]||(v[4]=D=>h.value=1)},{default:t(()=>[...v[19]||(v[19]=[l("返回检查环境",-1)])]),_:1}),o(q,{onClick:v[5]||(v[5]=D=>h.value=2)},{default:t(()=>[...v[20]||(v[20]=[l("返回修改路径",-1)])]),_:1})]),key:"0"}:void 0]),1032,["sub-title"])),U.value?.probe?.reasons?.length?(n(),y("div",Ia,[(n(!0),y(ee,null,re(U.value.probe.reasons,D=>(n(),g(le,{key:D,message:D,type:"warning","show-icon":"",style:{"margin-bottom":"4px"}},null,8,["message"]))),128))])):p("",!0)])):p("",!0)]),_:1},8,["open"])}}},Ea=Le(Da,[["__scopeId","data-v-c7327e24"]]),Sa={class:"pdh-page"},xa={class:"pdh-header"},ha={class:"kv"},Pa={key:0,class:"kv"},Oa={key:1,class:"kv"},$a={class:"kv"},Ma={key:0,class:"kv hint"},La={style:{"margin-top":"12px",display:"flex","justify-content":"space-between","align-items":"center"}},Ua={key:0,style:{"margin-top":"12px"}},Na={key:1,style:{"margin-top":"12px"}},Ba={class:"answer"},Ra={style:{"margin-top":"8px","font-size":"12px",color:"var(--text-color-secondary, #888)"}},Ta={key:2,style:{"margin-top":"8px"}},Ha={style:{display:"flex","align-items":"center",gap:"8px"}},za={class:"hint",style:{"margin-top":"4px"}},Fa={key:0,style:{"margin-top":"16px"}},Wa={class:"json-pre",style:{"max-height":"300px",overflow:"auto"}},qa={key:0,style:{"margin-top":"8px"}},Ka={style:{"min-width":"220px"}},Va={style:{color:"#999","font-size":"12px","margin-left":"4px"}},Qa={key:2,style:{"margin-top":"12px"}},Ga={class:"kv",style:{"margin-bottom":"4px"}},Ya={key:0,style:{color:"#faad14"}},Xa={key:2,class:"kv hint"},ja={key:3,class:"kv hint",style:{color:"#ff4d4f"}},Ja={key:3,style:{"margin-top":"12px"}},Za={key:2,style:{"margin-top":"8px"}},eo={key:1},to={style:{"margin-left":"8px"}},ao={key:3,class:"json-pre"},oo={style:{"margin-left":"6px"}},lo={key:0,style:{"margin-left":"6px"}},no={key:0,class:"hint",style:{"margin-top":"4px"}},so={key:0,style:{"margin-top":"8px"}},io={style:{"margin-bottom":"12px"}},ro={class:"hint"},uo={class:"kv"},po={class:"kv",style:{"margin-top":"4px"}},co={class:"kv"},fo={key:0,class:"hint",style:{"margin-top":"4px"}},vo={key:1,style:{"font-size":"11px"}},Ze="pdh.syncIncludeOptions.v1",mo={__name:"PersonalDataHub",setup(me,{expose:_e}){const w=Me(),L=S(null),Q=S(null),h=S([]),m=S(""),b=S(null),U=S(""),O=S(!1),B=S(!1),V=S([]),M=S(null),ie={"system-data-android":{contacts:!0,apps:!0,sms:!0,calls:!0}};function de(){try{const a=localStorage.getItem(Ze);if(!a)return JSON.parse(JSON.stringify(ie));const e=JSON.parse(a);return{"system-data-android":{...ie["system-data-android"],...e["system-data-android"]||{}}}}catch{return JSON.parse(JSON.stringify(ie))}}const j=se(de());function R(){try{localStorage.setItem(Ze,JSON.stringify(j)),console.log("[PDH-include] persisted:",JSON.stringify(j))}catch(a){console.warn("[PDH-include] persist failed:",a&&a.message)}}const v=S({}),le={"system-data-android":[{key:"contacts",label:"联系人",hint:"~767 条"},{key:"apps",label:"已安装应用",hint:"~176 个"},{key:"sms",label:"短信内容",hint:"~2400 条 · 高敏感",sensitive:!0},{key:"calls",label:"通话记录",hint:"~18000 条 · 包含号码",sensitive:!0}]};function q(a){return Object.prototype.hasOwnProperty.call(le,a)}function te(a,e,u){const E=u&&u.target?!!u.target.checked:!!u;console.log("[PDH-include] toggle",a,e,"=>",E),j[a]||(j[a]={}),j[a][e]=E,R()}const J=S(!1),A=se({provider:"qq",email:"",authCode:"",host:"",port:993,pdfPasswordHints:{idCardLast6:"",phoneLast6:"",cardLast6:""}}),W=S(null),ae=S(!1),I=S(null),K=S(null),pe=[{name:"analysis.spending",label:"消费分析",icon:Kt,description:"总支出 / 商家排行 / 月度趋势"},{name:"analysis.relations",label:"人际关系",icon:Vt,description:"与每个人的互动频率 / 主动比例"},{name:"analysis.footprint",label:"足迹",icon:Qt,description:"常去地点 / 出行模式"},{name:"analysis.interests",label:"兴趣画像",icon:Gt,description:"从购买 / 浏览 / 收藏抽兴趣"},{name:"analysis.timeline",label:"时间线",icon:Yt,description:"跨源事件串成故事"}],_=S(!1),i=S([]),z=se({queue:{pending:0},mergeGroups:0,reviewQueue:0}),D=S(!1),G=S([]);function Ee(a){a?.unregistered?k.success(`已注销 ${a.vendor}`):k.success(`已接入 ${a.vendor}`),Y()}const ke=S(!1);function Se(a){k.success(`WeChat 已接入 (uin=${a.uin}, provider=${a.chosenKeyProvider})`),Y()}const ye=S(!1),T=se({email:"",zipPassword:"",filePath:""}),H=S(null),C=se({active:!1,adapter:"",phase:"",mailbox:"",current:0,total:0,attempt:1,errorMessage:""}),f=se({refresh:!1,ask:!1,addMock:!1,syncAll:!1,sync:{},audit:!1,testEmail:!1,saveEmail:!1,eventDetail:!1,importAlipay:!1,reviewQueue:!1,resolverDrain:!1,skill:!1,bilibiliAdbSync:!1,bilibiliAdbDoctor:!1,douyinAdbSync:!1,weiboAdbSync:!1,xhsAdbSync:!1});function we(a){switch(a){case"BRIDGE_UNAVAILABLE":return"adb 未安装或不在 PATH — 请安装 Android Platform Tools 或设置 ADB_PATH 环境变量";case"MODULE_LOAD_FAILED":return"PDH adapter 模块缺失 — 请重装 cc";case"BILIBILI_NO_ROOT":return"手机未 root — Bilibili 正式版 APK 不是 debuggable,需 Magisk root 才能读 Cookies DB";case"BILIBILI_NOT_INSTALLED_OR_NEVER_LOGGED_IN":return"请在手机上安装 Bilibili App 并登录一次,然后重试";case"BILIBILI_COOKIES_INCOMPLETE":return"Cookie 缺关键字段 — 请在手机 Bilibili App 上重新登录";case"BILIBILI_COOKIES_TRUNCATED":return"ADB 流被截断 — 拔插 USB 重试,或检查 `adb logcat` 是否有 MIUI ROM 干扰";case"BILIBILI_NOT_SQLITE":return"ADB 拉回的文件不是 sqlite — 可能 base64 stream 被 MIUI/HyperOS 干扰,拔插 USB 重试";case"BILIBILI_INVALID_UID":return"Cookie 中 DedeUserID 不是正整数 — 请重新登录";default:return"同步失败 — 详见 message 字段"}}function Ce(a){switch(a){case"BRIDGE_UNAVAILABLE":return"adb 未安装或不在 PATH — 请安装 Android Platform Tools 或设置 ADB_PATH 环境变量";case"MODULE_LOAD_FAILED":return"PDH adapter 模块缺失 — 请重装 cc";case"DOUYIN_NO_ROOT":return"手机未 root — 抖音正式版 APK 不是 debuggable,需 Magisk root 才能读 IM 数据库";case"DOUYIN_NOT_INSTALLED":return"请在手机上安装抖音 App,然后重试";case"DOUYIN_NO_IM_DB":return"抖音 App 已装但未生成 IM 数据库 — 请登录抖音并打开任一聊天会话后重试";case"DOUYIN_MULTIPLE_USERS":return"此手机登录了多个抖音账号 — 请加 --uid <19位数字> 选一个";case"DOUYIN_UID_NOT_FOUND":return"指定的 uid 不在设备上的抖音账号列表里";case"DOUYIN_PULL_FAILED":return"ADB 流传输失败 — 拔插 USB 重试,或检查 `adb logcat` 是否有 MIUI ROM 干扰";case"DOUYIN_NOT_SQLITE":return"拉回的文件不是 sqlite — 可能 base64 stream 被 MIUI/HyperOS 干扰,拔插 USB 重试";default:return"同步失败 — 详见 message 字段"}}function xe(a){switch(a){case"BRIDGE_UNAVAILABLE":return"adb 未安装或不在 PATH — 请安装 Android Platform Tools 或设置 ADB_PATH 环境变量";case"MODULE_LOAD_FAILED":return"PDH adapter 模块缺失 — 请重装 cc";case"WEIBO_NO_ROOT":return"手机未 root — 微博正式版 APK 不是 debuggable,需 Magisk root 才能读 Cookies DB";case"WEIBO_NOT_INSTALLED":return"请在手机上安装微博 App 并登录一次,然后重试 (或微博使用了非默认 WebView 数据目录)";case"WEIBO_COOKIES_EMPTY":return"ADB 流返 0 字节 — MIUI/HyperOS silent 失败?拔插 USB 重试";case"WEIBO_COOKIES_TRUNCATED":return"ADB 流被截断 — 拔插 USB 重试,或检查 `adb logcat` 是否有 MIUI ROM 干扰";case"WEIBO_NOT_SQLITE":return"拉回的文件不是 sqlite — 可能 base64 stream 被 MIUI 干扰,拔插 USB 重试";case"WEIBO_BASE64_PARSE":return"base64 解码失败 — adb 终端编码问题,请检查 `chcp 65001`";case"WEIBO_COOKIES_INCOMPLETE":return"SUB cookie 缺失 — 请在手机微博 App 上重新登录";default:return"同步失败 — 详见 message 字段"}}function he(a){switch(a){case"BRIDGE_UNAVAILABLE":return"adb 未安装或不在 PATH — 请安装 Android Platform Tools 或设置 ADB_PATH 环境变量";case"MODULE_LOAD_FAILED":return"PDH adapter 模块缺失 — 请重装 cc";case"XHS_NO_ROOT":return"手机未 root — 小红书正式版 APK 不是 debuggable,需 Magisk root 才能读 Cookies DB";case"XHS_NOT_INSTALLED":return"请在手机上安装小红书 App 并登录一次,然后重试";case"XHS_COOKIES_EMPTY":return"ADB 流返 0 字节 — MIUI/HyperOS silent 失败?拔插 USB 重试";case"XHS_COOKIES_TRUNCATED":return"ADB 流被截断 — 拔插 USB 重试,或检查 `adb logcat` 是否有 MIUI ROM 干扰";case"XHS_NOT_SQLITE":return"拉回的文件不是 sqlite — 可能 base64 stream 被 MIUI 干扰,拔插 USB 重试";case"XHS_BASE64_PARSE":return"base64 解码失败 — adb 终端编码问题,请检查 `chcp 65001`";case"XHS_COOKIES_INCOMPLETE":return"a1 或 web_session cookie 缺失 — 请在手机小红书 App 上重新登录 (X-S 签名需要 a1 字段)";default:return"同步失败 — 详见 message 字段"}}async function N(){if(!f.xhsAdbSync){f.xhsAdbSync=!0;try{const a=await w.xhsAdbSync({});if(!a||!a.ok){const P=a&&a.reason||"SYNC_FAILED",$=he(P),F=a&&a.message||"";k.error({content:`Xhs ADB 同步失败:${$}`,description:F,duration:8});return}const e=a.report||{},u=e.xhs||{},E=u.eventCounts||{};u.meFetchFailed?k.warning({content:"Xhs 同步未拉到 user_id — /user/me 返空 data",description:`lastErrorCode=${u.lastErrorCode}, ${u.lastErrorMessage||""}。可能 cookie 已过期或 web_session 缺失,请在手机重新登录。`,duration:10}):u.lastErrorCode===461?k.warning({content:"Xhs X-S 签名被拒 (461) — 部分接口未抓到",description:`命中 ${E.total||0} events。我们的 X-S 算法 best-effort (~60% GET / <30% POST hit),461 在 POST 较常见。稍后重试 (X-S 算法可能 4-8 周 rotate)。`,duration:10}):u.lastErrorCode?k.warning({content:`Xhs 同步部分完成 (${E.total||0} events)`,description:`lastErrorCode=${u.lastErrorCode}, ${u.lastErrorMessage||""}`,duration:8}):k.success(`Xhs 同步成功:notes=${E.note||0} / liked=${E.liked||0} / follow=${E.follow||0} (total=${E.total||0})${u.nickname?" ["+u.nickname+"]":""}`),M.value=e,Y()}catch(a){k.error({content:"Xhs ADB 同步异常",description:a&&a.message?a.message:String(a),duration:8})}finally{f.xhsAdbSync=!1}}}async function Pe(){if(!f.weiboAdbSync){f.weiboAdbSync=!0;try{const a=await w.weiboAdbSync({});if(!a||!a.ok){const P=a&&a.reason||"SYNC_FAILED",$=xe(P),F=a&&a.message||"";k.error({content:`Weibo ADB 同步失败:${$}`,description:F,duration:8});return}const e=a.report||{},u=e.weibo||{},E=u.eventCounts||{};u.uidFetchFailed?k.warning({content:"Weibo 同步未拉到 UID — /api/config 返 login=false",description:`lastErrorCode=${u.lastErrorCode}, ${u.lastErrorMessage||""}。可能 cookie 已过期 (请在手机重新登录) 或微博触发 anti-bot redirect。事件数 0,未入 vault。`,duration:10}):u.lastErrorCode?k.warning({content:`Weibo 同步部分完成 (${E.total||0} events)`,description:`lastErrorCode=${u.lastErrorCode}, ${u.lastErrorMessage||""} — 部分接口受反爬限制,稍后重试可补齐`,duration:8}):k.success(`Weibo 同步成功:posts=${E.post||0} / fav=${E.favourite||0} / follow=${E.follow||0} (total=${E.total||0})`),M.value=e,Y()}catch(a){k.error({content:"Weibo ADB 同步异常",description:a&&a.message?a.message:String(a),duration:8})}finally{f.weiboAdbSync=!1}}}async function ot(){if(!f.douyinAdbSync){f.douyinAdbSync=!0;try{const a=await w.douyinAdbSync({});if(!a||!a.ok){const $=a&&a.reason||"SYNC_FAILED",F=Ce($),ce=a&&a.message||"";k.error({content:`Douyin ADB 同步失败:${F}`,description:ce,duration:8});return}const e=a.report||{},u=e.douyin||{},E=u.eventCounts||{},P=u.parserDiagnostic||{};if(!P.hadMsgTable&&!P.hadSimpleUserTable)k.warning({content:"Douyin 同步完成但 0 events",description:"msg 和 SIMPLE_USER 表都未在 IM 数据库中找到 — 抖音 App 版本可能用了不同 schema",duration:10});else if(!P.hadMsgTable||!P.hadSimpleUserTable){const $=[];P.hadMsgTable||$.push("msg (私信)"),P.hadSimpleUserTable||$.push("SIMPLE_USER (联系人)"),k.warning({content:`Douyin 部分同步:msg=${E.message||0} contacts=${E.contact||0}`,description:`${$.join("、")} 表未找到,未入库部分数据`,duration:8})}else k.success(`Douyin 同步成功:messages=${E.message||0} contacts=${E.contact||0} (total=${E.total||0})`);M.value=e,Y()}catch(a){k.error({content:"Douyin ADB 同步异常",description:a&&a.message?a.message:String(a),duration:8})}finally{f.douyinAdbSync=!1}}}async function lt(){if(!f.bilibiliAdbDoctor){f.bilibiliAdbDoctor=!0;try{const a=await w.bilibiliAdbDoctor();if(!a||!a.ok){const u=a&&a.reason||"PROBE_FAILED",E=we(u),P=a&&a.message||"";k.error({content:`Bilibili 诊断失败:${E}`,description:P,duration:8});return}const e=a.cookieDiagnostic||{};e.hadEncrypted?k.warning({content:`Bilibili 环境就绪 (uid=${a.uid}) — 但发现 Keystore 加密 cookie`,description:`cookies 数=${e.cookieCount||"?"}; 部分行使用 Android Keystore 加密 (跳过)。可能是较新 Bilibili App + Android 14+。可继续同步,但可能数据不全。`,duration:10}):k.success(`Bilibili 环境就绪 — uid=${a.uid}, 找到 ${e.cookieCount||"?"} 个 cookie,可以同步`)}catch(a){k.error({content:"Bilibili 诊断异常",description:a&&a.message?a.message:String(a),duration:8})}finally{f.bilibiliAdbDoctor=!1}}}async function nt(){if(!f.bilibiliAdbSync){f.bilibiliAdbSync=!0;try{const a=await w.bilibiliAdbSync({});if(!a||!a.ok){const P=a&&a.reason||"SYNC_FAILED",$=we(P),F=a&&a.message||"";k.error({content:`Bilibili ADB 同步失败:${$}`,description:F,duration:8});return}const e=a.report||{},u=e.bilibili||{},E=u.eventCounts||{};u.lastErrorCode?k.warning({content:`Bilibili 同步部分完成 (${E.total||0} events)`,description:`lastErrorCode=${u.lastErrorCode}, ${u.lastErrorMessage||""} — 部分接口受反爬限制,稍后重试可补齐`,duration:8}):k.success(`Bilibili 同步成功:history=${E.history||0} / fav=${E.favourite||0} / dyn=${E.dynamic||0} / follow=${E.follow||0} (total=${E.total||0})`),M.value=e,Y()}catch(a){k.error({content:"Bilibili ADB 同步异常",description:a&&a.message?a.message:String(a),duration:8})}finally{f.bilibiliAdbSync=!1}}}const st=[{title:"名称",dataIndex:"name",key:"name",width:140},{title:"版本",dataIndex:"version",key:"version",width:80},{title:"能力",key:"capabilities"},{title:"敏感度",key:"sensitivity",width:140},{title:"操作",key:"actions",width:160,align:"right"}],it=[{title:"时间",key:"at",dataIndex:"at",width:170},{title:"动作",dataIndex:"action",key:"action",width:200},{title:"详情",key:"details"}],rt=[{title:"日期",key:"occurredAt",width:100},{title:"描述",dataIndex:"description",key:"description"},{title:"金额",key:"amount",width:140,align:"right"}];function ut(a){return a==="high"?"red":a==="medium"?"orange":"default"}function dt(a){if(!a)return"";const e=a.entityCounts||{},u=`events=${e.events??0} persons=${e.persons??0} | raw=${a.rawCount??0} invalid=${a.invalidCount??0} | KG triples=${a.kgTripleCount??0} RAG docs=${a.ragDocCount??0} | ${a.durationMs??0}ms`;return a.error?`${u} · 错误: ${a.error}`:u}async function Y(){f.refresh=!0;try{L.value=await w.health(),Q.value=await w.stats(),h.value=await w.listAdapters();try{G.value=await w.listAichatAccounts()}catch{}}catch(a){k.error("刷新失败: "+a.message)}finally{f.refresh=!1}}async function Ue(){if(m.value.trim()){f.ask=!0,U.value="",b.value=null;try{b.value=await w.ask(m.value.trim(),{acceptNonLocal:O.value})}catch(a){U.value=a.message}finally{f.ask=!1}}}async function pt(){f.addMock=!0;try{await w.registerMock({count:30,seed:Date.now()%1e3}),await Y(),k.success("MockAdapter 已注册(30 条 mock 数据 ready 同步)")}catch(a){k.error("注册失败: "+a.message)}finally{f.addMock=!1}}function Ne(a=""){C.active=!0,C.adapter=a,C.phase="starting",C.mailbox="",C.current=0,C.total=0,C.attempt=1,C.errorMessage=""}function Be(a){a&&(a.adapter&&(C.adapter=a.adapter),a.phase&&(C.phase=a.phase),typeof a.current=="number"&&(C.current=a.current),typeof a.total=="number"&&(C.total=a.total),typeof a.attempt=="number"&&(C.attempt=a.attempt),a.mailbox&&(C.mailbox=a.mailbox),a.phase==="error"&&(C.errorMessage=a.message||"sync error"))}async function ct(a){f.sync[a]=!0,Ne(a);try{const e=j[a],u=e?{include:{...e}}:{};typeof w.syncAdapterStream=="function"?M.value=await w.syncAdapterStream(a,u,Be):M.value=await w.syncAdapter(a,u),await Y()}catch(e){k.error(`同步 ${a} 失败: ${e.message}`)}finally{f.sync[a]=!1,C.active=!1}}async function ft(){f.syncAll=!0,Ne("(all)");try{const a=typeof w.syncAllStream=="function"?await w.syncAllStream({},Be):await w.syncAll();M.value=a?.[a.length-1]||null,await Y(),k.success(`已同步 ${a?.length||0} 个 adapter`)}catch(a){k.error("同步失败: "+a.message)}finally{f.syncAll=!1,C.active=!1}}async function vt(a){try{await w.unregister(a),await Y()}catch(e){k.error("移除失败: "+e.message)}}async function mt(a){if(a){f.audit=!0;try{V.value=await w.recentAudit({limit:200})}catch(e){k.error("审计日志加载失败: "+e.message)}finally{f.audit=!1}}}const Ie=ue(()=>!(!A.email||!A.email.includes("@")||!A.authCode||A.authCode.length<4||A.provider==="custom"&&!A.host));function yt(a){return{qq:"QQ: 邮箱 → 设置 → 账户 → IMAP/SMTP → 开启 → 生成授权码",163:"163: 邮箱 → 设置 → POP3/SMTP/IMAP → 开启 IMAP/SMTP 服务 → 授权密码",189:"189: 设置 → 第三方客户端授权码",outlook:"Outlook: account.microsoft.com/security → App password",gmail:"Gmail: myaccount.google.com/apppasswords (需开启 2FA)",custom:"联系你的邮箱管理员获取 IMAP 端点 + app-password"}[a]||"请输入服务商授权码(不是登录密码)"}function Re(){A.provider="qq",A.email="",A.authCode="",A.host="",A.port=993,A.pdfPasswordHints={idCardLast6:"",phoneLast6:"",cardLast6:""},W.value=null}function Te(){const a={provider:A.provider,email:A.email.trim(),authCode:A.authCode};return A.provider==="custom"&&(a.host=A.host.trim(),a.port=A.port||993,a.secure=!0),a}function gt(){const a={};for(const e of Object.keys(A.pdfPasswordHints)){const u=A.pdfPasswordHints[e];typeof u=="string"&&u.trim().length>0&&(a[e]=u.trim())}return Object.keys(a).length>0?a:null}async function _t(){if(Ie.value){f.testEmail=!0,W.value=null;try{W.value=await w.testEmailAuth(Te())}catch(a){W.value={ok:!1,error:a.message}}finally{f.testEmail=!1}}}async function kt(){if(!(!Ie.value||!W.value?.ok)){f.saveEmail=!0;try{const a={},e=gt();e&&(a.pdfPasswordHints=e),await w.registerEmail(Te(),a),k.success("邮箱账号已注册"),J.value=!1,Re(),await Y()}catch(a){k.error("保存失败: "+a.message)}finally{f.saveEmail=!1}}}const He=ue(()=>!(!T.email||!T.email.includes("@")||!T.filePath||T.filePath.length<3));function bt(){T.email="",T.zipPassword="",T.filePath="",H.value=null}async function At(){if(He.value){f.importAlipay=!0,H.value=null;try{await w.registerAlipay({email:T.email.trim(),zipPassword:T.zipPassword||void 0});const e=/\.zip$/i.test(T.filePath)?{zipPath:T.filePath,zipPassword:T.zipPassword||void 0}:{csvPath:T.filePath};H.value=await w.importAlipayBill(e),H.value?.status==="ok"?(k.success(`导入成功 — ${H.value.entityCounts?.events||0} 笔交易`),await Y()):k.error("导入失败: "+(H.value?.error||H.value?.status))}catch(a){H.value={status:"error",error:a.message},k.error("导入失败: "+a.message)}finally{f.importAlipay=!1}}}async function ze(a){if(a){f.eventDetail=!0,ae.value=!0;try{I.value=await w.eventDetail(a)}catch(e){I.value=null,k.error("事件详情加载失败: "+e.message)}finally{f.eventDetail=!1}}}_e({showEventDetail:ze});async function wt(a){f.skill=!0,K.value=null;try{K.value=await w.runSkill(a,{})}catch(e){k.error(`${a} 失败: ${e.message}`)}finally{f.skill=!1}}async function De(){f.reviewQueue=!0;try{i.value=await w.reviewQueueList(50);const a=await w.resolverStats();Object.assign(z,a)}catch(a){k.error("待消歧加载失败: "+a.message)}finally{f.reviewQueue=!1}}async function Ct(){_.value=!0,await De()}async function Oe(a,e){try{await w.reviewDecision(a,e),k.success(`已记录决策: ${e}`),await De()}catch(u){k.error("决策失败: "+u.message)}}async function It(){f.resolverDrain=!0;try{const a=await w.resolverDrain(20);k.success(`drain 完成 — same=${a.same} different=${a.different} review=${a.review}`),await De()}catch(a){k.error("drain 失败: "+a.message)}finally{f.resolverDrain=!1}}async function Dt(){try{const a=await w.resolverStats();Object.assign(z,a)}catch{}}return Rt(()=>{Y(),Dt()}),(a,e)=>{const u=c("a-button"),E=c("a-badge"),P=c("a-space"),$=c("a-tag"),F=c("a-card"),ce=c("a-col"),Fe=c("a-row"),Et=c("a-textarea"),We=c("a-checkbox"),ne=c("a-alert"),fe=c("a-divider"),St=c("a-spin"),xt=c("a-popover"),ht=c("a-popconfirm"),$e=c("a-table"),qe=c("a-empty"),Ke=c("a-progress"),ge=c("a-select-option"),Pt=c("a-select"),oe=c("a-form-item"),ve=c("a-input"),Ve=c("a-tooltip"),Qe=c("a-input-password"),Ot=c("a-input-number"),Ge=c("a-form"),be=c("a-drawer"),Ae=c("a-descriptions-item"),$t=c("a-descriptions"),Mt=c("a-list-item-meta"),Ye=c("a-list-item"),Xe=c("a-list"),Lt=c("a-collapse-panel"),Ut=c("a-collapse");return n(),y("div",Sa,[d("div",xa,[e[30]||(e[30]=d("div",null,[d("h2",{class:"page-title"},"个人数据中台"),d("p",{class:"page-sub"}," 让数据回归个人 — 各 app 数据本地加密落盘,本地 LLM 跨源分析,零云端外传。 ")],-1)),o(P,null,{default:t(()=>[o(u,{loading:f.refresh,onClick:Y},{icon:t(()=>[o(X(je))]),default:t(()=>[e[27]||(e[27]=l(" 刷新 ",-1))]),_:1},8,["loading"]),o(E,{count:z.reviewQueue,offset:[0,0]},{default:t(()=>[o(u,{type:"primary",ghost:"",onClick:Ct},{icon:t(()=>[o(X(zt))]),default:t(()=>[e[28]||(e[28]=l(" 待消歧 ",-1))]),_:1})]),_:1},8,["count"]),o(u,{type:"primary",ghost:"",onClick:e[0]||(e[0]=s=>B.value=!0)},{icon:t(()=>[o(X(Ft))]),default:t(()=>[e[29]||(e[29]=l(" 审计日志 ",-1))]),_:1})]),_:1})]),o(Fe,{gutter:16,style:{"margin-bottom":"16px"}},{default:t(()=>[o(ce,{xs:24,sm:12,md:6},{default:t(()=>[o(F,{size:"small",title:"Vault"},{extra:t(()=>[o($,{color:L.value?.vault?.ok?"green":"red"},{default:t(()=>[l(r(L.value?.vault?.ok?"正常":"未就绪"),1)]),_:1},8,["color"])]),default:t(()=>[d("div",ha,"schema v"+r(L.value?.vault?.schemaVersion??"?"),1),Q.value?.vault?(n(),y("div",Pa," 事件 "+r(Q.value.vault.events)+" · 联系人 "+r(Q.value.vault.persons),1)):p("",!0),Q.value?.vault?(n(),y("div",Oa," 地点 "+r(Q.value.vault.places)+" · 商品 "+r(Q.value.vault.items)+" · 主题 "+r(Q.value.vault.topics),1)):p("",!0)]),_:1})]),_:1}),o(ce,{xs:24,sm:12,md:6},{default:t(()=>[o(F,{size:"small",title:"本地 LLM"},{extra:t(()=>[o($,{color:L.value?.llm?.ok?L.value.llm.isLocal?"green":"orange":"red"},{default:t(()=>[l(r(L.value?.llm?.ok?L.value.llm.isLocal?"本地":"非本地":"未就绪"),1)]),_:1},8,["color"])]),default:t(()=>[d("div",$a,r(L.value?.llm?.name||"—"),1),L.value?.llm?.ok&&!L.value.llm.isLocal?(n(),y("div",Ma," ⚠️ 非本地 — ask 会被隐私 gate 拒绝,除非显式 acceptNonLocal ")):p("",!0)]),_:1})]),_:1}),o(ce,{xs:24,sm:12,md:6},{default:t(()=>[o(F,{size:"small",title:"KG 索引"},{extra:t(()=>[o($,{color:L.value?.kgSink?.ok?"green":"default"},{default:t(()=>[l(r(L.value?.kgSink?.ok?"已连接":"不可用"),1)]),_:1},8,["color"])]),default:t(()=>[e[31]||(e[31]=d("div",{class:"kv"},"events / persons → cc knowledge-graph 实体 + 关系",-1))]),_:1})]),_:1}),o(ce,{xs:24,sm:12,md:6},{default:t(()=>[o(F,{size:"small",title:"RAG 索引"},{extra:t(()=>[o($,{color:L.value?.ragSink?.ok?"green":"default"},{default:t(()=>[l(r(L.value?.ragSink?.ok?"已连接":"不可用"),1)]),_:1},8,["color"])]),default:t(()=>[e[32]||(e[32]=d("div",{class:"kv"},"文本 → BM25(vector 留待后续 phase)",-1))]),_:1})]),_:1})]),_:1}),o(F,{style:{"margin-bottom":"16px"}},{title:t(()=>[o(P,null,{default:t(()=>[o(X(qt)),e[33]||(e[33]=d("span",null,"问我数据",-1))]),_:1})]),default:t(()=>[o(Et,{value:m.value,"onUpdate:value":e[1]||(e[1]=s=>m.value=s),rows:2,placeholder:"例:上个月在淘宝总共花了多少?/我妈生日那周买了啥送哪儿?",onKeydown:Tt(at(Ue,["exact","prevent"]),["enter"])},null,8,["value","onKeydown"]),d("div",La,[o(We,{checked:O.value,"onUpdate:checked":e[2]||(e[2]=s=>O.value=s)},{default:t(()=>[...e[34]||(e[34]=[l("允许非本地 LLM (volcengine / anthropic 等)",-1)])]),_:1},8,["checked"]),o(u,{type:"primary",loading:f.ask,disabled:!m.value.trim(),onClick:Ue},{icon:t(()=>[o(X(Wt))]),default:t(()=>[e[35]||(e[35]=l(" 提问 ",-1))]),_:1},8,["loading","disabled"])]),U.value?(n(),y("div",Ua,[o(ne,{type:"error","show-icon":"",message:U.value},null,8,["message"])])):p("",!0),b.value?(n(),y("div",Na,[b.value.warning==="no-facts"?(n(),g(ne,{key:0,type:"warning","show-icon":"",message:"vault 里没找到匹配的事件('no-facts')—— 先同步几个 adapter 让数据进 vault",style:{"margin-bottom":"12px"}})):b.value.warning==="hallucinated-citations"?(n(),g(ne,{key:1,type:"warning","show-icon":"",message:`LLM 引用了 ${b.value.hallucinatedCitations?.length||0} 个不存在的 event id —— 模型在编造`,style:{"margin-bottom":"12px"}},null,8,["message"])):p("",!0),d("div",Ba,r(b.value.answer),1),d("div",Ra," 引用 "+r(b.value.citations?.length||0)+" 条事实 · "+r(b.value.facts?.length||0)+" facts 入 prompt · "+r(b.value.durationMs)+"ms · "+r(b.value.model),1),b.value.citations?.length?(n(),y("div",Ta,[e[36]||(e[36]=d("span",{style:{"font-size":"12px",color:"var(--text-color-secondary, #888)"}},"事件链接(点击查看明细 / PDF 解密结果):",-1)),o(P,{style:{"margin-top":"4px"},wrap:""},{default:t(()=>[(n(!0),y(ee,null,re(b.value.citations,s=>(n(),g($,{key:s,color:"blue",style:{cursor:"pointer"},onClick:x=>ze(s)},{default:t(()=>[l(r(s),1)]),_:2},1032,["onClick"]))),128))]),_:1})])):p("",!0)])):p("",!0)]),_:1}),o(F,{style:{"margin-bottom":"16px"}},{title:t(()=>[o(P,null,{default:t(()=>[o(X(Xt)),e[37]||(e[37]=d("span",null,"分析 skill (Phase 11)",-1))]),_:1})]),extra:t(()=>[o($,{color:"purple"},{default:t(()=>[...e[38]||(e[38]=[l("5 内置",-1)])]),_:1})]),default:t(()=>[o(Fe,{gutter:[12,12]},{default:t(()=>[(n(),y(ee,null,re(pe,s=>o(ce,{xs:24,sm:12,md:8,key:s.name},{default:t(()=>[o(F,{size:"small",hoverable:"",onClick:x=>wt(s.name)},{default:t(()=>[d("div",Ha,[(n(),g(Ht(s.icon),{style:{"font-size":"18px",color:"#722ed1"}})),d("strong",null,r(s.label),1)]),d("div",za,r(s.description),1)]),_:2},1032,["onClick"])]),_:2},1024)),64))]),_:1}),K.value?(n(),y("div",Fa,[o(fe,{plain:"",orientation:"left"},{default:t(()=>[l(r(K.value.skill)+" 结果",1)]),_:1}),o(St,{spinning:f.skill},{default:t(()=>[d("pre",Wa,r(JSON.stringify(K.value,null,2)),1),K.value.llm_commentary||K.value.llm_narrative?(n(),y("div",qa,[o(ne,{type:"info",message:K.value.llm_commentary||K.value.llm_narrative},null,8,["message"])])):p("",!0)]),_:1},8,["spinning"])])):p("",!0)]),_:1}),o(F,{style:{"margin-bottom":"16px"}},{title:t(()=>[o(P,null,{default:t(()=>[o(X(ta)),e[39]||(e[39]=d("span",null,"Adapters",-1))]),_:1})]),extra:t(()=>[o(P,null,{default:t(()=>[o(u,{onClick:e[3]||(e[3]=s=>J.value=!0)},{icon:t(()=>[o(X(jt))]),default:t(()=>[e[40]||(e[40]=l(" 添加邮箱账号 ",-1))]),_:1}),o(u,{onClick:e[4]||(e[4]=s=>ye.value=!0)},{icon:t(()=>[o(X(Jt))]),default:t(()=>[e[41]||(e[41]=l(" 导入支付宝账单 ",-1))]),_:1}),o(u,{onClick:e[5]||(e[5]=s=>D.value=!0)},{icon:t(()=>[o(X(Zt))]),default:t(()=>[e[42]||(e[42]=l(" 添加 AI 对话账号 ",-1))]),_:1}),o(u,{onClick:e[6]||(e[6]=s=>ke.value=!0)},{icon:t(()=>[o(X(ea))]),default:t(()=>[e[43]||(e[43]=l(" 添加 WeChat ",-1))]),_:1}),o(u,{onClick:lt,loading:f.bilibiliAdbDoctor},{default:t(()=>[...e[44]||(e[44]=[l(" 诊断 Bilibili ADB ",-1)])]),_:1},8,["loading"]),o(u,{onClick:nt,loading:f.bilibiliAdbSync},{default:t(()=>[...e[45]||(e[45]=[l(" 通过 PC ADB 同步 Bilibili ",-1)])]),_:1},8,["loading"]),o(u,{onClick:Pe,loading:f.weiboAdbSync},{default:t(()=>[...e[46]||(e[46]=[l(" 通过 PC ADB 同步 Weibo ",-1)])]),_:1},8,["loading"]),o(u,{onClick:N,loading:f.xhsAdbSync},{default:t(()=>[...e[47]||(e[47]=[l(" 通过 PC ADB 同步 Xhs ",-1)])]),_:1},8,["loading"]),o(u,{onClick:ot,loading:f.douyinAdbSync},{default:t(()=>[...e[48]||(e[48]=[l(" 通过 PC ADB 同步 Douyin ",-1)])]),_:1},8,["loading"]),o(u,{onClick:pt,loading:f.addMock},{default:t(()=>[...e[49]||(e[49]=[l(" 注册 MockAdapter(开发) ",-1)])]),_:1},8,["loading"]),o(u,{type:"primary",onClick:ft,loading:f.syncAll,disabled:!h.value.length},{default:t(()=>[...e[50]||(e[50]=[l(" 同步全部 ",-1)])]),_:1},8,["loading","disabled"])]),_:1})]),default:t(()=>[h.value.length?(n(),g($e,{key:0,columns:st,"data-source":h.value,pagination:!1,"row-key":s=>s.name,size:"middle"},{bodyCell:t(({column:s,record:x})=>[s.key==="sensitivity"?(n(),y(ee,{key:0},[o($,{color:ut(x.sensitivity)},{default:t(()=>[l(r(x.sensitivity),1)]),_:2},1032,["color"]),x.legalGate?(n(),g($,{key:0,color:"red",style:{"margin-left":"4px"}},{default:t(()=>[...e[51]||(e[51]=[l("需法律确认",-1)])]),_:1})):p("",!0)],64)):s.key==="capabilities"?(n(!0),y(ee,{key:1},re(x.capabilities,Z=>(n(),g($,{key:Z,style:{"margin-right":"4px"}},{default:t(()=>[l(r(Z),1)]),_:2},1024))),128)):s.key==="actions"?(n(),g(P,{key:2},{default:t(()=>[o(u,{size:"small",loading:f.sync[x.name],onClick:Z=>ct(x.name)},{default:t(()=>[...e[52]||(e[52]=[l(" 同步 ",-1)])]),_:1},8,["loading","onClick"]),q(x.name)?(n(),g(xt,{key:0,open:v.value[x.name],"onUpdate:open":Z=>v.value[x.name]=Z,trigger:"click",placement:"left",title:`${x.name} 采集范围`},{content:t(()=>[d("div",Ka,[(n(!0),y(ee,null,re(le[x.name],Z=>(n(),y("div",{key:Z.key,style:{margin:"6px 0"}},[o(We,{checked:j[x.name][Z.key]!==!1,onChange:Nt=>te(x.name,Z.key,Nt)},{default:t(()=>[l(r(Z.label)+" ",1),d("span",Va,r(Z.hint),1),Z.sensitive?(n(),g($,{key:0,color:"orange",size:"small",style:{"margin-left":"4px"}},{default:t(()=>[...e[53]||(e[53]=[l("敏感",-1)])]),_:1})):p("",!0)]),_:2},1032,["checked","onChange"])]))),128)),e[54]||(e[54]=d("div",{style:{"margin-top":"8px","font-size":"11px",color:"#999"}}," 取消勾选的数据本次同步不会拉取入库 ",-1))])]),default:t(()=>[o(u,{size:"small",title:"选择采集范围"},{default:t(()=>[...e[55]||(e[55]=[l("⚙",-1)])]),_:1})]),_:2},1032,["open","onUpdate:open","title"])):p("",!0),o(ht,{title:`从注册表移除 ${x.name}?(vault 数据不会删除)`,onConfirm:Z=>vt(x.name)},{default:t(()=>[o(u,{size:"small",danger:""},{default:t(()=>[...e[56]||(e[56]=[l("移除",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)):p("",!0)]),_:1},8,["data-source","row-key"])):(n(),g(qe,{key:1,description:"无已注册 adapter — 点上方按钮注册 MockAdapter 看效果"})),C.active?(n(),y("div",Qa,[o(F,{size:"small",bordered:!0},{default:t(()=>[d("div",Ga,[e[57]||(e[57]=d("strong",null,"同步进行中",-1)),l(" · "+r(C.adapter)+" · "+r(C.phase||"...")+" ",1),C.attempt&&C.attempt>1?(n(),y("span",Ya," (重试 #"+r(C.attempt)+") ",1)):p("",!0)]),C.total>0?(n(),g(Ke,{key:0,percent:Math.round(C.current/C.total*100),status:C.errorMessage?"exception":"active",size:"small"},null,8,["percent","status"])):(n(),g(Ke,{key:1,percent:0,status:"active",size:"small"})),C.mailbox?(n(),y("div",Xa," 邮箱 "+r(C.mailbox)+" · "+r(C.current)+" / "+r(C.total),1)):p("",!0),C.errorMessage?(n(),y("div",ja,r(C.errorMessage),1)):p("",!0)]),_:1})])):p("",!0),M.value?(n(),y("div",Ja,[o(ne,{type:M.value.status==="ok"?"success":"error","show-icon":"",message:`同步 ${M.value.adapter}: ${M.value.status}`,description:dt(M.value)},null,8,["type","message","description"])])):p("",!0)]),_:1}),o(be,{open:J.value,"onUpdate:open":e[16]||(e[16]=s=>J.value=s),title:"添加邮箱账号",placement:"right",width:"560","destroy-on-close":!0,onClose:Re},{footer:t(()=>[o(P,null,{default:t(()=>[o(u,{onClick:e[15]||(e[15]=s=>J.value=!1)},{default:t(()=>[...e[67]||(e[67]=[l("取消",-1)])]),_:1}),o(u,{loading:f.testEmail,disabled:!Ie.value,onClick:_t},{default:t(()=>[...e[68]||(e[68]=[l(" 测试连接 ",-1)])]),_:1},8,["loading","disabled"]),o(u,{type:"primary",loading:f.saveEmail,disabled:!Ie.value||!W.value?.ok,onClick:kt},{default:t(()=>[...e[69]||(e[69]=[l(" 保存并注册 ",-1)])]),_:1},8,["loading","disabled"])]),_:1})]),default:t(()=>[o(ne,{message:"数据回归个人 — 凭证落本地加密文件(与 vault 主密钥同目录),同步动作 100% 本地。",type:"info","show-icon":"",style:{"margin-bottom":"16px"}}),o(Ge,{layout:"vertical",model:A},{default:t(()=>[o(oe,{label:"邮箱服务商",required:""},{default:t(()=>[o(Pt,{value:A.provider,"onUpdate:value":e[7]||(e[7]=s=>A.provider=s),placeholder:"选择服务商"},{default:t(()=>[o(ge,{value:"qq"},{default:t(()=>[...e[58]||(e[58]=[l("QQ 邮箱 (imap.qq.com)",-1)])]),_:1}),o(ge,{value:"163"},{default:t(()=>[...e[59]||(e[59]=[l("网易邮箱 163/126",-1)])]),_:1}),o(ge,{value:"189"},{default:t(()=>[...e[60]||(e[60]=[l("189 邮箱",-1)])]),_:1}),o(ge,{value:"outlook"},{default:t(()=>[...e[61]||(e[61]=[l("Outlook / Hotmail",-1)])]),_:1}),o(ge,{value:"gmail"},{default:t(()=>[...e[62]||(e[62]=[l("Gmail",-1)])]),_:1}),o(ge,{value:"custom"},{default:t(()=>[...e[63]||(e[63]=[l("自定义 IMAP",-1)])]),_:1})]),_:1},8,["value"])]),_:1}),o(oe,{label:"邮箱地址",required:""},{default:t(()=>[o(ve,{value:A.email,"onUpdate:value":e[8]||(e[8]=s=>A.email=s),placeholder:"you@qq.com",autocomplete:"off"},null,8,["value"])]),_:1}),o(oe,{required:""},{label:t(()=>[o(P,null,{default:t(()=>[e[64]||(e[64]=d("span",null,"授权码(非登录密码)",-1)),o(Ve,{title:yt(A.provider)},{default:t(()=>[o(X(Je),{style:{color:"#888"}})]),_:1},8,["title"])]),_:1})]),default:t(()=>[o(Qe,{value:A.authCode,"onUpdate:value":e[9]||(e[9]=s=>A.authCode=s),placeholder:"例:QQ 邮箱 设置 → 账户 → 开启 IMAP/SMTP → 生成的授权码",autocomplete:"off"},null,8,["value"])]),_:1}),A.provider==="custom"?(n(),g(oe,{key:0,label:"IMAP host"},{default:t(()=>[o(ve,{value:A.host,"onUpdate:value":e[10]||(e[10]=s=>A.host=s),placeholder:"mail.example.com"},null,8,["value"])]),_:1})):p("",!0),A.provider==="custom"?(n(),g(oe,{key:1,label:"端口"},{default:t(()=>[o(Ot,{value:A.port,"onUpdate:value":e[11]||(e[11]=s=>A.port=s),min:1,max:65535,"default-value":993},null,8,["value"])]),_:1})):p("",!0),o(fe,{orientation:"left",plain:""},{default:t(()=>[...e[65]||(e[65]=[l("PDF 账单解密提示(可选)",-1)])]),_:1}),e[66]||(e[66]=d("p",{class:"hint"},"银行 PDF 月结大多加密;提供几个常用候选项让 Phase 5.5 自动解锁:",-1)),o(oe,{label:"身份证后 6 位"},{default:t(()=>[o(ve,{value:A.pdfPasswordHints.idCardLast6,"onUpdate:value":e[12]||(e[12]=s=>A.pdfPasswordHints.idCardLast6=s),placeholder:"123456",autocomplete:"off"},null,8,["value"])]),_:1}),o(oe,{label:"手机后 6 位"},{default:t(()=>[o(ve,{value:A.pdfPasswordHints.phoneLast6,"onUpdate:value":e[13]||(e[13]=s=>A.pdfPasswordHints.phoneLast6=s),placeholder:"123456",autocomplete:"off"},null,8,["value"])]),_:1}),o(oe,{label:"信用卡尾 6 位"},{default:t(()=>[o(ve,{value:A.pdfPasswordHints.cardLast6,"onUpdate:value":e[14]||(e[14]=s=>A.pdfPasswordHints.cardLast6=s),placeholder:"123456",autocomplete:"off"},null,8,["value"])]),_:1}),W.value?(n(),y("div",Za,[o(ne,{type:W.value.ok?"success":"error","show-icon":"",message:W.value.ok?"凭证有效 — 可以保存":`认证失败: ${W.value.reason||W.value.error}`},null,8,["type","message"])])):p("",!0)]),_:1},8,["model"])]),_:1},8,["open"]),o(be,{open:ae.value,"onUpdate:open":e[17]||(e[17]=s=>ae.value=s),title:I.value?`事件 ${I.value.event.id}`:"加载中...",placement:"right",width:"640","destroy-on-close":!0},{default:t(()=>[I.value?(n(),y(ee,{key:0},[o($t,{column:1,size:"small",bordered:""},{default:t(()=>[o(Ae,{label:"类型"},{default:t(()=>[l(r(I.value.event.subtype),1)]),_:1}),o(Ae,{label:"发生于"},{default:t(()=>[l(r(new Date(I.value.event.occurredAt).toLocaleString()),1)]),_:1}),o(Ae,{label:"actor"},{default:t(()=>[l(r(I.value.event.actor),1)]),_:1}),I.value.event.content?.title?(n(),g(Ae,{key:0,label:"标题"},{default:t(()=>[l(r(I.value.event.content.title),1)]),_:1})):p("",!0),I.value.event.source?.adapter?(n(),g(Ae,{key:1,label:"来源 adapter"},{default:t(()=>[l(r(I.value.event.source.adapter)+" @ v"+r(I.value.event.source.adapterVersion),1)]),_:1})):p("",!0)]),_:1}),I.value.classification?(n(),g(fe,{key:0,orientation:"left",plain:""},{default:t(()=>[...e[70]||(e[70]=[l("分类",-1)])]),_:1})):p("",!0),I.value.classification?(n(),y("div",eo,[o($,{color:"blue"},{default:t(()=>[l(r(I.value.classification.category),1)]),_:1}),o($,null,{default:t(()=>[l(r(I.value.classification.layer),1)]),_:1}),d("span",to,"置信 "+r(Math.round((I.value.classification.confidence||0)*100))+"%",1)])):p("",!0),I.value.extraction?(n(),g(fe,{key:2,orientation:"left",plain:""},{default:t(()=>[l("结构化字段("+r(I.value.extraction.template)+")",1)]),_:1})):p("",!0),I.value.extraction?(n(),y("pre",ao,r(JSON.stringify(I.value.extraction.fields,null,2)),1)):p("",!0),I.value.extraction?.pdfExtraction?(n(),g(fe,{key:4,orientation:"left",plain:""},{default:t(()=>[...e[71]||(e[71]=[l("PDF 解密 / 解析",-1)])]),_:1})):p("",!0),I.value.extraction?.pdfExtraction?(n(),g(Xe,{key:5,"data-source":I.value.extraction.pdfExtraction,size:"small"},{renderItem:t(({item:s})=>[o(Ye,null,{default:t(()=>[o(Mt,{title:s.filename},{description:t(()=>[d("div",null,[o($,{color:s.decrypted?"green":"red"},{default:t(()=>[l(r(s.decrypted?"已解密":"解密失败"),1)]),_:2},1032,["color"]),d("span",oo,"尝试 "+r(s.attempted)+" 次",1),s.transactionsExtracted!=null?(n(),y("span",lo," · 提取 "+r(s.transactionsExtracted)+" 条交易 ",1)):p("",!0)]),s.error?(n(),y("div",no,r(s.error),1)):p("",!0)]),_:2},1032,["title"])]),_:2},1024)]),_:1},8,["data-source"])):p("",!0),I.value.extraction?.fields?.transactions?.length?(n(),y(ee,{key:6},[o(fe,{orientation:"left",plain:""},{default:t(()=>[...e[72]||(e[72]=[l("交易明细",-1)])]),_:1}),o($e,{columns:rt,"data-source":I.value.extraction.fields.transactions,pagination:{pageSize:10,size:"small"},"row-key":(s,x)=>x,size:"small"},{bodyCell:t(({column:s,record:x})=>[s.key==="occurredAt"?(n(),y(ee,{key:0},[l(r(new Date(x.occurredAtMs).toLocaleDateString()),1)],64)):s.key==="amount"?(n(),y("span",{key:1,class:tt(x.amount.direction==="in"?"amount-in":"amount-out")},r(x.amount.direction==="in"?"+":"-")+r(x.amount.value.toFixed(2))+" "+r(x.amount.currency),3)):p("",!0)]),_:1},8,["data-source","row-key"])],64)):p("",!0)],64)):(n(),g(qe,{key:1,description:"无事件数据"}))]),_:1},8,["open","title"]),o(be,{open:ye.value,"onUpdate:open":e[22]||(e[22]=s=>ye.value=s),title:"导入支付宝账单",placement:"right",width:"560","destroy-on-close":!0,onClose:bt},{footer:t(()=>[o(P,null,{default:t(()=>[o(u,{onClick:e[21]||(e[21]=s=>ye.value=!1)},{default:t(()=>[...e[78]||(e[78]=[l("关闭",-1)])]),_:1}),o(u,{type:"primary",loading:f.importAlipay,disabled:!He.value,onClick:At},{default:t(()=>[...e[79]||(e[79]=[l(" 注册账户 + 导入 ",-1)])]),_:1},8,["loading","disabled"])]),_:1})]),default:t(()=>[o(ne,{message:"支付宝官方导出 CSV — 服务器侧全量、稳定无风控。3 分钟拿到 12 个月流水。",type:"info","show-icon":"",style:{"margin-bottom":"16px"}}),o(Ut,{bordered:!1,style:{"margin-bottom":"12px"}},{default:t(()=>[o(Lt,{header:"如何导出账单(首次必看)"},{default:t(()=>[...e[73]||(e[73]=[d("ol",{style:{"padding-left":"18px","font-size":"13px"}},[d("li",null,"支付宝 app → 我的 → 账单 → 右上角 ⋯"),d("li",null,'点 "开具交易流水证明"'),d("li",null,"选月份范围(最长 12 个月)"),d("li",null,'用途选 "个人对账"'),d("li",null,"发送到你的绑定邮箱"),d("li",null,[l("从邮箱下载 "),d("code",null,"alipay_record_*.zip")]),d("li",null,"解压密码 = 你的身份证后 6 位")],-1)])]),_:1})]),_:1}),o(Ge,{layout:"vertical",model:T},{default:t(()=>[o(oe,{label:"支付宝绑定邮箱(账户标识)",required:""},{default:t(()=>[o(ve,{value:T.email,"onUpdate:value":e[18]||(e[18]=s=>T.email=s),placeholder:"alipay-bound@example.com",autocomplete:"off"},null,8,["value"])]),_:1}),o(oe,null,{label:t(()=>[o(P,null,{default:t(()=>[e[74]||(e[74]=d("span",null,"ZIP 密码(身份证后 6 位)",-1)),o(Ve,{title:"支付宝 ZIP 默认密码 = 身份证号后 6 位。也支持自定义密码。"},{default:t(()=>[o(X(Je),{style:{color:"#888"}})]),_:1})]),_:1})]),default:t(()=>[o(Qe,{value:T.zipPassword,"onUpdate:value":e[19]||(e[19]=s=>T.zipPassword=s),placeholder:"例:123456",autocomplete:"off"},null,8,["value"]),e[75]||(e[75]=d("div",{class:"hint",style:{"margin-top":"4px"}}," 空白则解析时再问,或导入的 ZIP 未加密。 ",-1))]),_:1}),o(fe,{orientation:"left",plain:""},{default:t(()=>[...e[76]||(e[76]=[l("选择文件",-1)])]),_:1}),o(oe,{label:"ZIP 或 CSV 文件路径"},{default:t(()=>[o(ve,{value:T.filePath,"onUpdate:value":e[20]||(e[20]=s=>T.filePath=s),placeholder:"C:\\\\Users\\\\you\\\\Downloads\\\\alipay_record_xxx.zip","allow-clear":""},null,8,["value"]),e[77]||(e[77]=d("div",{class:"hint",style:{"margin-top":"4px"}}," 桌面版可通过 Electron 文件选择器自动填充;web-shell 复制完整路径。 ",-1))]),_:1}),H.value?(n(),y("div",so,[o(ne,{type:H.value.status==="ok"?"success":"error","show-icon":"",message:H.value.status==="ok"?`导入成功 — ${H.value.entityCounts?.events||0} 笔交易`:`导入失败: ${H.value.error||H.value.status}`,description:H.value.status==="ok"?`${H.value.entityCounts?.persons||0} 个交易对方 · ${H.value.kgTripleCount||0} KG triples · ${H.value.durationMs||0}ms`:null},null,8,["type","message","description"])])):p("",!0)]),_:1},8,["model"])]),_:1},8,["open"]),o(be,{open:_.value,"onUpdate:open":e[23]||(e[23]=s=>_.value=s),title:"待消歧(EntityResolver 模糊判定)",placement:"right",width:"640","destroy-on-close":!0},{default:t(()=>[i.value.length===0&&!f.reviewQueue?(n(),g(ne,{key:0,type:"success","show-icon":"",message:"无待消歧 pair — 所有跨源 Person 已确定。",style:{"margin-bottom":"12px"}})):p("",!0),d("div",io,[o(P,null,{default:t(()=>[o(u,{loading:f.reviewQueue,onClick:De},{icon:t(()=>[o(X(je))]),default:t(()=>[e[80]||(e[80]=l(" 刷新 ",-1))]),_:1},8,["loading"]),o(u,{loading:f.resolverDrain,onClick:It},{default:t(()=>[...e[81]||(e[81]=[l(" 手动 drain 队列 ",-1)])]),_:1},8,["loading"]),d("span",ro," queue: "+r(z.queue?.pending||0)+" pending · "+r(z.mergeGroups||0)+" groups ",1)]),_:1})]),o(Xe,{"data-source":i.value,pagination:{pageSize:5,size:"small"},size:"small"},{renderItem:t(({item:s})=>[o(Ye,null,{default:t(()=>[o(F,{size:"small",style:{width:"100%"}},{default:t(()=>[d("div",uo,[d("strong",null,"Pair #"+r(s.id),1),s.embed_sim?(n(),g($,{key:0,color:"blue",style:{"margin-left":"8px"}},{default:t(()=>[l(" sim "+r(Number(s.embed_sim).toFixed(2)),1)]),_:2},1024)):p("",!0),s.llm_verdict?(n(),g($,{key:1,color:s.llm_verdict==="yes"?"green":s.llm_verdict==="no"?"red":"orange",style:{"margin-left":"4px"}},{default:t(()=>[l(" LLM: "+r(s.llm_verdict),1)]),_:2},1032,["color"])):p("",!0)]),d("div",po,"A: "+r(s.a_person_id),1),d("div",co,"B: "+r(s.b_person_id),1),s.llm_reason?(n(),y("div",fo," LLM 理由: "+r(s.llm_reason),1)):p("",!0),o(P,{style:{"margin-top":"8px"}},{default:t(()=>[o(u,{size:"small",type:"primary",onClick:x=>Oe(s.id,"same")},{default:t(()=>[...e[82]||(e[82]=[l("同一人",-1)])]),_:1},8,["onClick"]),o(u,{size:"small",danger:"",onClick:x=>Oe(s.id,"different")},{default:t(()=>[...e[83]||(e[83]=[l("不同人",-1)])]),_:1},8,["onClick"]),o(u,{size:"small",onClick:x=>Oe(s.id,"skip")},{default:t(()=>[...e[84]||(e[84]=[l("跳过",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),_:2},1024)]),_:2},1024)]),_:1},8,["data-source"])]),_:1},8,["open"]),o(be,{open:B.value,"onUpdate:open":e[24]||(e[24]=s=>B.value=s),title:"审计日志(数据 lineage)",placement:"right",width:"600",onAfterOpenChange:mt},{default:t(()=>[o($e,{columns:it,"data-source":V.value,pagination:{pageSize:20,size:"small"},"row-key":s=>s.id,size:"small"},{bodyCell:t(({column:s,record:x})=>[s.key==="at"?(n(),y(ee,{key:0},[l(r(new Date(x.at).toLocaleString()),1)],64)):s.key==="details"?(n(),y("code",vo,r(x.details||"—"),1)):p("",!0)]),_:1},8,["data-source","row-key"])]),_:1},8,["open"]),o(ga,{open:D.value,"onUpdate:open":e[25]||(e[25]=s=>D.value=s),"existing-accounts":G.value,onRegistered:Ee},null,8,["open","existing-accounts"]),o(Ea,{open:ke.value,"onUpdate:open":e[26]||(e[26]=s=>ke.value=s),onRegistered:Se},null,8,["open"])])}}},bo=Le(mo,[["__scopeId","data-v-3b29f69d"]]);export{bo as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.providers-grid[data-v-38d68389]{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.provider-card[data-v-38d68389]{border:1px solid var(--border-color)!important;transition:border-color .2s}.provider-card[data-v-38d68389]:hover{border-color:var(--text-muted)!important}.provider-card.active[data-v-38d68389]{border-color:#52c41a!important;background:#29a27014!important}.section-title[data-v-38d68389]{color:var(--text-primary, #ccc);font-size:16px;font-weight:500;margin:0}.config-card[data-v-38d68389]{border-radius:8px}.config-card[data-v-38d68389] .ant-card-body{padding:24px}.config-form[data-v-38d68389] .ant-form-item-label>label{color:var(--text-secondary, #aaa);font-size:13px}.config-form[data-v-38d68389] .ant-input,.config-form[data-v-38d68389] .ant-input-password input,.config-form[data-v-38d68389] .ant-input-number,.config-form[data-v-38d68389] .ant-select-selector{background:var(--bg-card-hover, #1a1a1a)!important;border-color:var(--border-color, #333)!important;color:var(--text-primary, #e0e0e0)!important}.config-form[data-v-38d68389] .ant-input::placeholder,.config-form[data-v-38d68389] .ant-input-password input::placeholder{color:var(--text-muted, #555)!important}.config-form[data-v-38d68389] .ant-input-number-input,.config-form[data-v-38d68389] .ant-select-selection-item{color:var(--text-primary, #e0e0e0)!important}.config-form[data-v-38d68389] .ant-select-arrow{color:var(--text-muted, #555)}.config-form[data-v-38d68389] .ant-slider-rail{background:var(--border-color, #333)}.config-form[data-v-38d68389] .ant-slider-track{background:#1890ff}.config-form[data-v-38d68389] .ant-slider-handle{border-color:#1890ff}.config-form[data-v-38d68389] .ant-input-password-icon{color:var(--text-muted, #555)}.config-grid[data-v-38d68389]{display:grid;grid-template-columns:repeat(2,1fr);gap:0 24px}@media(max-width:640px){.config-grid[data-v-38d68389]{grid-template-columns:1fr}}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{E as Z,r as P,o as H,M as N,R as n,c as s,N as l,u as g,Q as K,S as B,F as X,Y as ee,K as u,a as te,L as y,O as x,P as M,Z as oe}from"./vendor-DhFY8mDK.js";import{u as A,_ as ae,d as _}from"./index-BD2U0Ciz.js";import{a as se,b as le}from"./parsers-DftYMnlk.js";import{R as q}from"./icons-AILO5ZcK.js";const re=Z("providers",()=>{const O=P(!1),i=P(null),m=P([]),T=P([]),c=P(null);async function t(){const v=A();O.value=!0;try{const{output:k}=await v.execute("llm providers",15e3);m.value=se(k);const b=m.value.find(C=>C.active);b&&(c.value=b.name);const{output:w}=await v.execute("llm models",15e3);T.value=le(w)}catch(k){console.error("Failed to load providers:",k)}finally{O.value=!1}}async function d(v){await A().execute(`llm switch ${v}`,1e4),m.value.forEach(b=>b.active=b.name===v),c.value=v}async function F(v){const k=A();i.value=v;try{const{output:b,exitCode:w}=await k.execute("llm test",3e4),C=m.value.find(S=>S.name===v);return C&&(C.status=w===0?"ok":"error"),w===0}catch{const b=m.value.find(w=>w.name===v);return b&&(b.status="error"),!1}finally{i.value=null}}return{loading:O,testing:i,providers:m,localModels:T,activeProvider:c,loadProviders:t,switchProvider:d,testProvider:F}}),ne={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},ie={key:1,style:{"text-align":"center",padding:"60px"}},de={key:2},ue={class:"providers-grid"},ce={style:{display:"flex","align-items":"center",gap:"12px","margin-bottom":"12px"}},pe={style:{"font-size":"24px"}},me={style:{flex:"1"}},ve={style:{color:"#e0e0e0","font-weight":"500"}},fe={style:{color:"var(--text-secondary)","font-size":"11px","font-family":"monospace"}},ge={style:{display:"flex",gap:"8px","justify-content":"flex-end"}},ye={key:0,style:{"margin-top":"24px"}},be={style:{color:"#ccc","font-family":"monospace","font-size":"13px"}},xe={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"16px"}},_e={class:"config-grid"},ke={style:{display:"flex","align-items":"center",gap:"12px"}},we={style:{display:"flex",gap:"12px","justify-content":"flex-end","margin-top":"16px"}},he={__name:"Providers",setup(O){const i=re(),m=A(),T=P(!1),c=P(!1),t=te({provider:void 0,model:"",apiKey:"",baseUrl:"",temperature:.7,maxTokens:4096});let d={};const F=["ollama","openai","anthropic","volcengine","deepseek","gemini","groq","mistral","custom","zhipu"],v={ollama:"Ollama(本地)",openai:"OpenAI",anthropic:"Anthropic",volcengine:"火山引擎(豆包)",deepseek:"DeepSeek",gemini:"Google Gemini",groq:"Groq",mistral:"Mistral",custom:"Custom(自定义)",zhipu:"智谱 AI"},k=F.map(a=>({value:a,label:v[a]||a}));async function b(a){try{await i.switchProvider(a),_.success(`已切换到 ${a}`)}catch(e){_.error(`切换失败: ${e.message}`)}}async function w(a){await i.testProvider(a)?_.success(`${a} 连接正常`):_.warning(`${a} 连接失败,请检查配置`)}function C(a){const e={};if(!a)return e;try{const U=JSON.parse(a.trim()),p=U.llm||U;return p.provider&&(e.provider=p.provider),p.model&&(e.model=p.model),p.apiKey&&(e.apiKey=p.apiKey),p.baseUrl&&(e.baseUrl=p.baseUrl),p.temperature!==void 0&&(e.temperature=Number(p.temperature)),p.maxTokens!==void 0&&(e.maxTokens=Number(p.maxTokens)),e}catch{}const r=a.split(`
|
|
2
|
-
`);for(const U of r){const z=U.trim().match(/^(?:llm\.)?(\w+)\s*[=:]\s*(.+)$/i);if(!z)continue;const[,I,j]=z,f=j.trim(),h=I.toLowerCase();if(h==="provider"&&f)e.provider=f;else if(h==="model"&&f)e.model=f;else if(h==="apikey"&&f)f.includes("***")||(e.apiKey=f);else if(h==="baseurl")e.baseUrl=f;else if(h==="temperature"){const $=parseFloat(f);isNaN($)||(e.temperature=$)}else if(h==="maxtokens"){const $=parseInt(f,10);isNaN($)||(e.maxTokens=$)}}return e}async function S(){T.value=!0;try{const{output:a}=await m.execute("config list",15e3),e=C(a);e.provider&&(t.provider=e.provider),e.model&&(t.model=e.model),e.apiKey&&(t.apiKey=e.apiKey),e.baseUrl&&(t.baseUrl=e.baseUrl),e.temperature!==void 0&&(t.temperature=e.temperature),e.maxTokens!==void 0&&(t.maxTokens=e.maxTokens),d={...t},_.success("配置已加载")}catch(a){_.error(`加载配置失败: ${a.message}`)}finally{T.value=!1}}async function E(){c.value=!0;const a=[],e=[];try{if(t.provider&&t.provider!==d.provider)try{await m.execute(`config set llm.provider ${t.provider}`,1e4),e.push("provider")}catch(r){a.push(`provider: ${r.message}`)}if(t.model&&t.model!==d.model)try{await m.execute(`config set llm.model ${t.model}`,1e4),e.push("model")}catch(r){a.push(`model: ${r.message}`)}if(t.apiKey&&t.apiKey!==d.apiKey)try{await m.execute(`config set llm.apiKey ${t.apiKey}`,1e4),e.push("apiKey")}catch(r){a.push(`apiKey: ${r.message}`)}if(t.baseUrl!==void 0&&t.baseUrl!==d.baseUrl)try{await m.execute(`config set llm.baseUrl ${t.baseUrl}`,1e4),e.push("baseUrl")}catch(r){a.push(`baseUrl: ${r.message}`)}if(t.temperature!==d.temperature)try{await m.execute(`config set llm.temperature ${t.temperature}`,1e4),e.push("temperature")}catch(r){a.push(`temperature: ${r.message}`)}if(t.maxTokens!==d.maxTokens)try{await m.execute(`config set llm.maxTokens ${t.maxTokens}`,1e4),e.push("maxTokens")}catch(r){a.push(`maxTokens: ${r.message}`)}a.length>0?_.warning(`部分配置保存失败: ${a.join("; ")}`):e.length>0?(_.success(`已保存 ${e.length} 项配置`),d={...t},e.includes("provider")&&i.loadProviders()):_.info("没有检测到配置变更")}catch(r){_.error(`保存配置失败: ${r.message}`)}finally{c.value=!1}}function G(){t.provider=d.provider||void 0,t.model=d.model||"",t.apiKey=d.apiKey||"",t.baseUrl=d.baseUrl||"",t.temperature=d.temperature??.7,t.maxTokens=d.maxTokens??4096}return H(()=>{i.loadProviders(),S()}),(a,e)=>{const r=u("a-button"),U=u("a-alert"),p=u("a-spin"),z=u("a-tag"),I=u("a-badge"),j=u("a-card"),f=u("a-list-item"),h=u("a-list"),$=u("a-divider"),D=u("a-select"),L=u("a-form-item"),R=u("a-input"),J=u("a-input-password"),Q=u("a-slider"),V=u("a-input-number"),W=u("a-form");return y(),N("div",null,[n("div",ne,[e[9]||(e[9]=n("div",null,[n("h2",{class:"page-title"},"LLM 配置"),n("p",{class:"page-sub"},"管理 AI 服务提供商")],-1)),s(r,{type:"primary",ghost:"",loading:g(i).loading,onClick:e[0]||(e[0]=o=>g(i).loadProviders())},{icon:l(()=>[s(g(q))]),default:l(()=>[e[8]||(e[8]=x(" 刷新 ",-1))]),_:1},8,["loading"])]),g(i).activeProvider?(y(),K(U,{key:0,type:"success",style:{"margin-bottom":"20px",background:"rgba(41,162,112,.08)","border-color":"rgba(41,162,112,.3)"},"show-icon":""},{message:l(()=>[n("span",null,[e[10]||(e[10]=x("当前激活:",-1)),n("strong",null,M(g(i).activeProvider),1)])]),_:1})):B("",!0),g(i).loading?(y(),N("div",ie,[s(p,{size:"large"}),e[11]||(e[11]=n("div",{style:{color:"var(--text-muted)","margin-top":"12px"}},"加载 LLM 信息中...",-1))])):(y(),N("div",de,[n("div",ue,[(y(!0),N(X,null,ee(g(i).providers,o=>(y(),K(j,{key:o.name,class:oe(["provider-card",{active:o.active}]),style:{background:"var(--bg-card)"},size:"small"},{default:l(()=>[n("div",ce,[n("span",pe,M(o.icon),1),n("div",me,[n("div",ve,M(o.label),1),n("div",fe,M(o.name),1)]),n("div",null,[o.active?(y(),K(z,{key:0,color:"green"},{default:l(()=>[...e[12]||(e[12]=[x("活跃",-1)])]),_:1})):o.status==="ok"?(y(),K(I,{key:1,status:"success",text:""})):o.status==="error"?(y(),K(I,{key:2,status:"error",text:""})):B("",!0)])]),n("div",ge,[s(r,{size:"small",style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"},loading:g(i).testing===o.name,onClick:Y=>w(o.name)},{default:l(()=>[...e[13]||(e[13]=[x(" 测试 ",-1)])]),_:1},8,["loading","onClick"]),o.active?(y(),K(z,{key:1,color:"green",style:{margin:"0","line-height":"24px"}},{default:l(()=>[...e[15]||(e[15]=[x("当前",-1)])]),_:1})):(y(),K(r,{key:0,size:"small",type:"primary",ghost:"",onClick:Y=>b(o.name)},{default:l(()=>[...e[14]||(e[14]=[x(" 切换 ",-1)])]),_:1},8,["onClick"]))])]),_:2},1032,["class"]))),128))]),g(i).localModels.length?(y(),N("div",ye,[e[16]||(e[16]=n("h3",{style:{color:"#ccc","font-size":"15px","margin-bottom":"12px"}}," 本地模型(Ollama) ",-1)),s(h,{"data-source":g(i).localModels,size:"small",style:{background:"var(--bg-card)","border-radius":"8px",border:"1px solid var(--border-color)"}},{renderItem:l(({item:o})=>[s(f,{style:{padding:"10px 16px","border-color":"#252525"}},{actions:l(()=>[s(z,{color:"cyan",style:{"font-size":"10px"}},{default:l(()=>[x(M(o.size||"local"),1)]),_:2},1024)]),default:l(()=>[n("span",be,M(o.name),1)]),_:2},1024)]),_:1},8,["data-source"])])):B("",!0),s($,{style:{"border-color":"var(--border-color)",margin:"32px 0 24px"}}),n("div",xe,[e[18]||(e[18]=n("h3",{class:"section-title"},"LLM 参数设置",-1)),s(r,{size:"small",loading:T.value,onClick:S,style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{icon:l(()=>[s(g(q))]),default:l(()=>[e[17]||(e[17]=x(" 加载配置 ",-1))]),_:1},8,["loading"])]),s(j,{class:"config-card",style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:l(()=>[s(W,{model:t,layout:"vertical",class:"config-form"},{default:l(()=>[n("div",_e,[s(L,{label:"Provider(提供商)"},{default:l(()=>[s(D,{value:t.provider,"onUpdate:value":e[1]||(e[1]=o=>t.provider=o),placeholder:"选择 LLM 提供商",options:g(k),style:{width:"100%"},disabled:c.value},null,8,["value","options","disabled"])]),_:1}),s(L,{label:"Model(模型名称)"},{default:l(()=>[s(R,{value:t.model,"onUpdate:value":e[2]||(e[2]=o=>t.model=o),placeholder:"例如 doubao-seed-1-6-251015","allow-clear":"",disabled:c.value},null,8,["value","disabled"])]),_:1}),s(L,{label:"API Key"},{default:l(()=>[s(J,{value:t.apiKey,"onUpdate:value":e[3]||(e[3]=o=>t.apiKey=o),placeholder:"输入 API Key",disabled:c.value},null,8,["value","disabled"])]),_:1}),s(L,{label:"Base URL"},{default:l(()=>[s(R,{value:t.baseUrl,"onUpdate:value":e[4]||(e[4]=o=>t.baseUrl=o),placeholder:"例如 https://ark.cn-beijing.volces.com/api/v3","allow-clear":"",disabled:c.value},null,8,["value","disabled"])]),_:1}),s(L,{label:"Temperature(温度)"},{default:l(()=>[n("div",ke,[s(Q,{value:t.temperature,"onUpdate:value":e[5]||(e[5]=o=>t.temperature=o),min:0,max:2,step:.1,style:{flex:"1"},disabled:c.value},null,8,["value","disabled"]),s(V,{value:t.temperature,"onUpdate:value":e[6]||(e[6]=o=>t.temperature=o),min:0,max:2,step:.1,precision:1,style:{width:"80px"},disabled:c.value},null,8,["value","disabled"])])]),_:1}),s(L,{label:"Max Tokens(最大输出长度)"},{default:l(()=>[s(V,{value:t.maxTokens,"onUpdate:value":e[7]||(e[7]=o=>t.maxTokens=o),min:256,max:128e3,step:256,style:{width:"100%"},placeholder:"4096",disabled:c.value},null,8,["value","disabled"])]),_:1})]),n("div",we,[s(r,{onClick:G,disabled:c.value,style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{default:l(()=>[...e[19]||(e[19]=[x(" 重置 ",-1)])]),_:1},8,["disabled"]),s(r,{type:"primary",loading:c.value,onClick:E},{default:l(()=>[...e[20]||(e[20]=[x(" 保存配置 ",-1)])]),_:1},8,["loading"])])]),_:1},8,["model"])]),_:1})]))])}}},Te=ae(he,[["__scopeId","data-v-38d68389"]]);export{Te as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-n8ruyEoT.js";import{S as t}from"./index-BD2U0Ciz.js";import"./responsiveObserve-V0qPHZOl.js";import"./vendor-DhFY8mDK.js";import"./useFlexGapSupport-Be2wILDi.js";import"./styleChecker-BfXrPW7h.js";import"./index-CFh73FRz.js";import"./icons-AILO5ZcK.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-Bc08LzOn.js";import{S as t}from"./index-BD2U0Ciz.js";import"./index-CFh73FRz.js";import"./vendor-DhFY8mDK.js";import"./icons-AILO5ZcK.js";const s=t(o);export{s as default};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
function p(a){const e=a.split(`
|
|
2
|
-
`),n=[];let i="built-in";for(const l of e){const t=l.trim();if(!t||t.startsWith("─")||t.startsWith("="))continue;const r=t.match(/^([a-z][a-z0-9-]+)\s+\(\d+\)$/);if(r){i=r[1];continue}const s=t.match(/^[●•]\s+([a-z][a-z0-9-]+)\s+(.+)$/);if(s){let c=s[2].trim();const m=c.match(/\s+\[(bundled|project|managed|workspace|marketplace)\]$/);m&&(c=c.slice(0,-m[0].length).trim());const u=i.includes("agent")?"agent":i.includes("llm")?"llm-query":i==="cli-direct"||i.includes("cli")?"cli-direct":"built-in";n.push({name:s[1],description:c,category:i,executionMode:u});continue}const o=t.match(/^([a-z][a-z0-9-]+)\s+[-–]\s+(.+)/)||t.match(/^([a-z][a-z0-9-]+)\s{2,}(.+)/);o&&n.push({name:o[1],description:o[2],category:i,executionMode:i.includes("agent")?"agent":i.includes("llm")?"llm-query":i.includes("cli")?"cli-direct":"built-in"})}return n}const d=[{name:"anthropic",label:"Anthropic (Claude)",icon:"🤖"},{name:"openai",label:"OpenAI (GPT)",icon:"🧠"},{name:"ollama",label:"Ollama (本地)",icon:"🦙"},{name:"deepseek",label:"DeepSeek",icon:"🔍"},{name:"gemini",label:"Google Gemini",icon:"✨"},{name:"volcengine",label:"火山引擎 (豆包)",icon:"🌋"},{name:"dashscope",label:"通义千问 (DashScope)",icon:"🌊"},{name:"kimi",label:"Kimi (月之暗面)",icon:"🌙"},{name:"minimax",label:"MiniMax (海螺AI)",icon:"🐚"},{name:"mistral",label:"Mistral AI",icon:"💨"}];function h(a){const e=[];for(const n of d)e.push({...n,configured:a.toLowerCase().includes(n.name),active:a.match(new RegExp(`\\*\\s*${n.name}`,"i"))!==null,status:"unknown"});if(!e.find(n=>n.active)){const n=a.match(/active[:\s]+(\w+)/i);if(n){const i=e.find(l=>l.name===n[1].toLowerCase());i&&(i.active=!0)}}return e}function f(a){return a.split(`
|
|
3
|
-
`).map(e=>e.trim()).filter(e=>e&&!e.startsWith("#")&&!e.startsWith("─")&&e.includes(":")).map(e=>({name:e,size:""})).slice(0,20)}export{h as a,f as b,p};
|