chainlesschain 0.162.17 → 0.162.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BnOiVQsQ.js → AIOps-VbMLpnCu.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Tw6tLfY1.js → ActionButton-BR6BrZ2w.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Des59eT3.js → Analytics-DWN2iHDA.js} +2 -2
- package/src/assets/web-panel/assets/AppLayout-CyBXOO_H.js +3 -0
- package/src/assets/web-panel/assets/{AppLayout-BLCe1k8m.css → AppLayout-DleZFgpe.css} +1 -1
- package/src/assets/web-panel/assets/{Audit-JX1upUxG.js → Audit-Cu5a4b5S.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-ByvQLRhY.js → Backup-D0vrJYkS.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DC-h8Hd-.js → BaseInput-DnFk3wDi.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-D9dJ3NKb.js → Chat-DFMa9lEz.js} +3 -3
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CO908iBt.css +1 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CpVazmEP.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-n3tD-95B.js → Checkbox-J23wKgNR.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BV9t0CmU.js → Codegen-Ca6Z4r1p.js} +1 -1
- package/src/assets/web-panel/assets/{Col-4KhPnXFB.js → Col-BZ3XsxN2.js} +1 -1
- package/src/assets/web-panel/assets/{Community-R1hZqHEr.js → Community-DhK5H5dD.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Bo4r1Z3L.js → Compact-DjJMyddV.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dwywk8U2.js → Compliance-Bup3Rk9z.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DTBwVdcR.js → Cowork-BqsPMIpo.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BrveD2Al.js → Cron-Ca69LFf-.js} +1 -1
- package/src/assets/web-panel/assets/{Crosschain-C63oZCeg.js → Crosschain-mTB21YwK.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Cyfo7zh4.js → DID-C1_Eree4.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-_EOI1Ax4.js → Dashboard-L2OWv5io.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BWYHGHO3.js → Dropdown-CpqNwurh.js} +1 -1
- package/src/assets/web-panel/assets/EmailListRenderer-CVJ1j3Ll.css +1 -0
- package/src/assets/web-panel/assets/EmailListRenderer-Mo7D9ADF.js +1 -0
- package/src/assets/web-panel/assets/{Federation-CU03AB2d.js → Federation-COTeKl2R.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DECACp9C.js → FormItemContext-0oTTQ9MI.js} +1 -1
- package/src/assets/web-panel/assets/GenericCardRenderer-DrMs3upM.js +1 -0
- package/src/assets/web-panel/assets/GenericCardRenderer-DtJFcJYl.css +1 -0
- package/src/assets/web-panel/assets/{Git-BhpPR-ck.js → Git-C6eFUBhz.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BtpmvOHi.js → Governance-5ivL10kw.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DfPuEW02.js → Inference-DcERJUS_.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CeA_2NFe.js → KnowledgeGraph-Dm1eQ_Hv.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C_ozF-bn.js → Logs-Cjt-JTuL.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-WgBvu6Ma.js → Marketplace-fNDRN8YJ.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CNIz8liM.js → McpTools-kKgzl9Bb.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-DEN8NgRg.js → Memory-BdJujXCH.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CP0rj-Fx.js → MobileBridge-lmvJfnpK.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-x3zDbPDI.js → MobileProjects-ZM-DVPhi.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CC4PEFJV.js → Mtc-CeoaWgzU.js} +1 -1
- package/src/assets/web-panel/assets/{MtcAudit-BHB0GvyW.js → MtcAudit-CRvKTLqr.js} +1 -1
- package/src/assets/web-panel/assets/{Multisig-BUPfLbde.js → Multisig-DnzFw69O.js} +2 -2
- package/src/assets/web-panel/assets/{NLProgramming-DNOkByM8.js → NLProgramming-0xP2rtGN.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-U-RIv-kE.js → Notes-tJpp3z8e.js} +1 -1
- package/src/assets/web-panel/assets/{NotificationSettings-B-q6tsxf.js → NotificationSettings-CRdpEoHX.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-BEH9lAIb.js +1 -0
- package/src/assets/web-panel/assets/OrderTableRenderer-BnOISpKI.css +1 -0
- package/src/assets/web-panel/assets/{Organization-DJLNuZ2_.js → Organization-Dhwy6dXT.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BxTl0aeE.js → Overflow-COwwTMb-.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Czzalu_0.js → P2P-79YWb-cn.js} +1 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-B9ZGFpn4.css +1 -0
- package/src/assets/web-panel/assets/PdhVaultBrowser-Dhn5S3Vs.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-BBw06EGK.js → Permissions-ELRvDOlY.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-Dvaa8niQ.css → PersonalDataHub-D0ncF92t.css} +1 -1
- package/src/assets/web-panel/assets/PersonalDataHub-DIWbfS5k.js +1 -0
- package/src/assets/web-panel/assets/{Pipeline-qLLWNe2i.js → Pipeline-Dzi1zmAr.js} +1 -1
- package/src/assets/web-panel/assets/Privacy-BYzWkaRt.js +1 -0
- package/src/assets/web-panel/assets/{ProjectInit-CmJ0VPGy.js → ProjectInit-D_5DqLSS.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-D1Xm2EwO.js → ProjectSettings-DrAAYJgR.js} +1 -1
- package/src/assets/web-panel/assets/{Projects-DLN-awqS.js → Projects-BOrF4_X8.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D164DGWo.js → Providers-DYLWZVe4.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BRCH7WgH.js → QuickAsk-k76cZTaF.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BWZhT_-2.js → Recommend-CXM4p6RB.js} +1 -1
- package/src/assets/web-panel/assets/Reputation-DLnLpz8L.js +1 -0
- package/src/assets/web-panel/assets/{Row-BbuTB-ny.js → Row-BavvTUrL.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CLegyrrb.js → RssFeed-CtCarC8_.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Bz41pkvW.js → Search-CJcDGc1x.js} +1 -1
- package/src/assets/web-panel/assets/{Security-D4NWRpgV.js → Security-DB3GmnY9.js} +3 -3
- package/src/assets/web-panel/assets/{Services-CP_6SXST.js → Services-BWEvVHhz.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CdRO3MnV.js → Skeleton-BHbixeGV.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BmghgIL3.js → Skills-DWwIjvjl.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DjAIXxkm.js → Sla-C1Qu9o0j.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DYk-En4R.js → SpeechSettings-BiEysZg1.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CglX98G4.js → SyncSettings-XlOLFUv2.js} +1 -1
- package/src/assets/web-panel/assets/{Tasks-BcLMTSP3.js → Tasks-BKjOcYxW.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BCs5bP8P.js → Templates-BVKjc9j-.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-B5jLtdWR.js → Tenant-C33WmSiJ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CZKKYYaA.js → Terminal-Dl8RJZHg.js} +1 -1
- package/src/assets/web-panel/assets/TimelineRenderer-CFN36N3H.js +1 -0
- package/src/assets/web-panel/assets/TimelineRenderer-DmztdsbF.css +1 -0
- package/src/assets/web-panel/assets/{Tokens-B8aHonMu.js → Tokens-Dy2kxiCA.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D6jDjaX1.js → Trigger-C7bt0leJ.js} +1 -1
- package/src/assets/web-panel/assets/Trust-CVKbWEMH.js +1 -0
- package/src/assets/web-panel/assets/{UkeySign-B1IDXsz6.js → UkeySign-B91QGwbs.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DHvglMzO.js → VideoEditing-C8xBqRiE.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DAUh8j_b.js → Wallet-RW2IBbpH.js} +1 -1
- package/src/assets/web-panel/assets/{WebAuthn-D0Y8wGZt.js → WebAuthn-CZPv5ayn.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BqZgQo4U.js → WorkflowEditor-CFCwic4a.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CtfIYzWq.js → chat-PVfHUaHj.js} +1 -1
- package/src/assets/web-panel/assets/{colors-B6ZfKKgZ.js → colors-C4WA0-Iq.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item--HQOl9D1.js → compact-item-DQfLwjbC.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-Bf-YNOPI.js → createContext-31PSlu0j.js} +1 -1
- package/src/assets/web-panel/assets/{hasIn-D5G7UiYx.js → hasIn-Csltfg47.js} +1 -1
- package/src/assets/web-panel/assets/icons-AILO5ZcK.js +57 -0
- package/src/assets/web-panel/assets/index-3NsH3wNq.js +1 -0
- package/src/assets/web-panel/assets/{index-_ZD6hPvh.js → index-41v9Hflm.js} +1 -1
- package/src/assets/web-panel/assets/{index-B23hk7ZY.js → index-45Iyof95.js} +1 -1
- package/src/assets/web-panel/assets/{index-CcbuseEC.js → index-8IVdEMKr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVTgMzbI.js → index-B-aRUTIJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-OSlN9c4x.js → index-BCxhSOsr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BrJfwd9_.js → index-BCyTEqF7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAPj11l4.js → index-BD-K1g5z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJlTZ7oK.js → index-BLwrQAlK.js} +1 -1
- package/src/assets/web-panel/assets/{index-ByjAzHrC.js → index-Ba6cQs-y.js} +4 -4
- package/src/assets/web-panel/assets/{index-__qol0SM.js → index-BiFRGYGH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZyNnZb9.js → index-BqOmboiA.js} +1 -1
- package/src/assets/web-panel/assets/{index-UppuQXbk.js → index-C4gzD6Ra.js} +2 -2
- package/src/assets/web-panel/assets/{index-2QuOKVo1.js → index-CArRkfYM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWOeC8v6.js → index-CE8i90GF.js} +1 -1
- package/src/assets/web-panel/assets/{index-B75QpKcS.js → index-CEbbRpw2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKsNidiT.js → index-CEtPU50W.js} +1 -1
- package/src/assets/web-panel/assets/{index-g_d5tOWL.js → index-CIeFJLHG.js} +1 -1
- package/src/assets/web-panel/assets/{index-ofgv0VHh.js → index-CQWE2WKS.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRPGyig2.js → index-C_k_btzK.js} +1 -1
- package/src/assets/web-panel/assets/{index-xOVop383.js → index-CbpUjcEf.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIYydwQc.js → index-CdQUx-5Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQIzU6GO.js → index-CfWk9Yzf.js} +1 -1
- package/src/assets/web-panel/assets/{index-CihsW323.js → index-Cgt2_bmM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkoQfJv0.js → index-CmzuBE2G.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPvA_8ed.js → index-CpXm8DBk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtjPgDzA.js → index-DSO9eU_G.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmVrKala.js → index-DUFwsCsD.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dfm65OiJ.js → index-DVHR_To_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGG5O6Zh.js → index-DW-7sqm0.js} +1 -1
- package/src/assets/web-panel/assets/index-DWtc_qRj.js +1 -0
- package/src/assets/web-panel/assets/{index-BBSGKZ-l.js → index-DdrYhK__.js} +3 -3
- package/src/assets/web-panel/assets/{index-XwovMqXr.js → index-DfbOwhkA.js} +1 -1
- package/src/assets/web-panel/assets/{index-OY_eegoA.js → index-DpEj71nk.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ca_5Za9D.js → index-DtUcq8Nn.js} +1 -1
- package/src/assets/web-panel/assets/{index--KnB-1F0.js → index-DuZKKJDi.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOzNKGtD.js → index-Dymm64KM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzvrUpDp.js → index-P9rJg2C1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqJoAOhC.js → index-nAhW-NN4.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DjUNw-1y.js → initDefaultProps-DPk1oFCk.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Cd6xXLlf.js → motion-CzQ1k8MU.js} +1 -1
- package/src/assets/web-panel/assets/{move-B_W-Y6JL.js → move-BCExaQ0x.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BCZBLb_-.js → omit-D71nF5o_.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CjDhGYLm.js → pickAttrs-pvCq8tx4.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CSC2rU9-.js → placementArrow-D8lSLg_0.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DnyswFkD.js → responsiveObserve-ZN6pVHvM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DujNhbuH.js → slide-VHxyZhFr.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-U2lNCQiL.js → statusUtils-B0jFTTFP.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Ch2rQftE.js → styleChecker-Bc6FRYW9.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-5XxNwjTL.js → useFlexGapSupport-D4YDiqxr.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-pv2YfF-X.js → useFs-CQgQ7iah.js} +1 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-LDh_Sq7B.js +1 -0
- package/src/assets/web-panel/assets/{vnode-CU0J2mVX.js → vnode-BwPvBDfI.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-ZII_iqXl.js → zoom-r6u1_Sq8.js} +1 -1
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/__tests__/hub-ask.test.js +136 -0
- package/src/commands/ask.js +110 -43
- package/src/commands/hub.js +260 -26
- package/src/constants.js +7 -0
- package/src/gateways/ws/personal-data-hub-protocol.js +151 -9
- package/src/lib/host-adb-bridge.js +430 -0
- package/src/lib/personal-data-hub-wiring.js +85 -0
- package/src/assets/web-panel/assets/AppLayout-hku5aFqc.js +0 -3
- package/src/assets/web-panel/assets/PersonalDataHub-CmTx090l.js +0 -1
- package/src/assets/web-panel/assets/Privacy-CStpViYX.js +0 -1
- package/src/assets/web-panel/assets/Reputation-DSTNi8ge.js +0 -1
- package/src/assets/web-panel/assets/Trust-DX_BvTA9.js +0 -1
- package/src/assets/web-panel/assets/icons-BOPtEWK4.js +0 -57
- package/src/assets/web-panel/assets/index-B-xjGh0B.js +0 -1
- package/src/assets/web-panel/assets/index-B9RskCJ5.js +0 -1
package/src/commands/hub.js
CHANGED
|
@@ -25,6 +25,34 @@ function printJson(obj) {
|
|
|
25
25
|
console.log(JSON.stringify(obj, null, 2));
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Drain-then-exit. console.log → process.stdout.write is async for pipes;
|
|
30
|
+
* exiting immediately can truncate output to the parent. Use this in
|
|
31
|
+
* commands that must terminate even when getHub() left libuv handles
|
|
32
|
+
* registered (aichat-health setInterval, sidecar supervisor, etc.) — sync
|
|
33
|
+
* + read commands are all-done after the report, no reason to keep idling.
|
|
34
|
+
* Real-device repro on Xiaomi 24115RA8EC 2026-05-23.
|
|
35
|
+
*/
|
|
36
|
+
function jsonAndExit(obj) {
|
|
37
|
+
process.stdout.write(JSON.stringify(obj, null, 2) + "\n", () =>
|
|
38
|
+
process.exit(0),
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Coerce a Commander string option to a positive integer, returning null if
|
|
44
|
+
* unset / blank / non-numeric / ≤0. Used by `--max-facts` / `--max-query-limit`
|
|
45
|
+
* on `cc hub ask` so on-device callers can pass smaller budgets without
|
|
46
|
+
* silent fallback to constructor defaults on a typo (`--max-facts abc`
|
|
47
|
+
* should not silently use 80).
|
|
48
|
+
*/
|
|
49
|
+
function parsePositiveInt(raw) {
|
|
50
|
+
if (raw === undefined || raw === null || raw === "") return null;
|
|
51
|
+
const n = Number.parseInt(raw, 10);
|
|
52
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
53
|
+
return n;
|
|
54
|
+
}
|
|
55
|
+
|
|
28
56
|
function fail(spinner, err, asJson) {
|
|
29
57
|
if (spinner) spinner.stop();
|
|
30
58
|
const msg = err && err.message ? err.message : String(err);
|
|
@@ -41,7 +69,9 @@ function fail(spinner, err, asJson) {
|
|
|
41
69
|
async function cmdAsk(question, options) {
|
|
42
70
|
const spinner = options.json ? null : ora("Asking hub...").start();
|
|
43
71
|
try {
|
|
44
|
-
|
|
72
|
+
// _getHub injection mirrors other handlers — lets unit tests stub the
|
|
73
|
+
// engine without standing up a real vault.
|
|
74
|
+
const hub = await (options._getHub || getHub)();
|
|
45
75
|
if (!hub.engine) throw new Error("Analysis engine unavailable");
|
|
46
76
|
// 推文 §三道锁第二把 "默认不许问云端" — acceptNonLocal 默认 false (拒云)。
|
|
47
77
|
// 优先 --accept-non-local CLI 旗,其次 env CC_HUB_ALLOW_NON_LOCAL (Android UI
|
|
@@ -50,10 +80,19 @@ async function cmdAsk(question, options) {
|
|
|
50
80
|
process.env.CC_HUB_ALLOW_NON_LOCAL === "1" ||
|
|
51
81
|
process.env.CC_HUB_ALLOW_NON_LOCAL === "true";
|
|
52
82
|
const acceptNonLocal = !!options.acceptNonLocal || envAllow;
|
|
53
|
-
|
|
83
|
+
// Per-call budget overrides for small-model callers (Android Qwen2.5-1.5B
|
|
84
|
+
// passes --max-facts 20 --max-query-limit 50 to keep prompt ~1.5K tokens
|
|
85
|
+
// and stay under the model's effective instruction-following window).
|
|
86
|
+
// Commander parses --max-facts <n> as string — coerce + drop invalid.
|
|
87
|
+
const maxFacts = parsePositiveInt(options.maxFacts);
|
|
88
|
+
const maxQueryLimit = parsePositiveInt(options.maxQueryLimit);
|
|
89
|
+
const askOptions = {
|
|
54
90
|
useRag: options.useRag !== false,
|
|
55
91
|
acceptNonLocal,
|
|
56
|
-
}
|
|
92
|
+
};
|
|
93
|
+
if (maxFacts !== null) askOptions.maxFacts = maxFacts;
|
|
94
|
+
if (maxQueryLimit !== null) askOptions.maxQueryLimit = maxQueryLimit;
|
|
95
|
+
const result = await hub.engine.ask(question, askOptions);
|
|
57
96
|
if (spinner) spinner.stop();
|
|
58
97
|
if (options.json) {
|
|
59
98
|
printJson(result);
|
|
@@ -203,13 +242,34 @@ async function cmdSyncAdapter(name, options) {
|
|
|
203
242
|
if (options.input) opts.inputPath = String(options.input);
|
|
204
243
|
const report = await hub.registry.syncAdapter(name, opts);
|
|
205
244
|
if (spinner) spinner.succeed(`synced ${name}`);
|
|
245
|
+
// 2026-05-24 in-APK Android exit + flush-race fix. Real-device repro on
|
|
246
|
+
// Xiaomi 24115RA8EC:
|
|
247
|
+
//
|
|
248
|
+
// (1) cc subprocess sits idle in epoll_wait for the full 240s budget
|
|
249
|
+
// after the report is fully written, then gets destroyForcibly'd
|
|
250
|
+
// by Kotlin LocalCcRunner → false "timeout after 240000ms" UI
|
|
251
|
+
// error even though vault writes committed. Root cause: a
|
|
252
|
+
// lingering libuv handle in getHub() wiring (suspect: aichat-
|
|
253
|
+
// health setInterval or sidecar supervisor health ping) keeps
|
|
254
|
+
// the event loop alive forever. Long-run fix is to close those
|
|
255
|
+
// cleanly; until then we force-exit here.
|
|
256
|
+
//
|
|
257
|
+
// (2) First-pass force-exit landed `process.exit(0)` after a normal
|
|
258
|
+
// `printJson(report) = console.log(...)`. But console.log →
|
|
259
|
+
// process.stdout.write is ASYNC for pipes (only sync for TTY),
|
|
260
|
+
// so process.exit fires before the JSON buffer drains → Kotlin
|
|
261
|
+
// parent reads truncated/empty stdout → "parse-failed" reason
|
|
262
|
+
// in CcResult.Failed → UI "写入本地数据库失败".
|
|
263
|
+
//
|
|
264
|
+
// Fix: explicit drain-then-exit (jsonAndExit helper at top of file).
|
|
206
265
|
if (options.json) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
logger.log(
|
|
210
|
-
`ingested=${report.ingested} kgTriples=${report.kgTriples} ragDocs=${report.ragDocs} durationMs=${report.durationMs}`,
|
|
211
|
-
);
|
|
266
|
+
jsonAndExit(report);
|
|
267
|
+
return;
|
|
212
268
|
}
|
|
269
|
+
logger.log(
|
|
270
|
+
`ingested=${report.ingested} kgTriples=${report.kgTriples} ragDocs=${report.ragDocs} durationMs=${report.durationMs}`,
|
|
271
|
+
);
|
|
272
|
+
process.exit(0);
|
|
213
273
|
} catch (err) {
|
|
214
274
|
fail(spinner, err, options.json);
|
|
215
275
|
}
|
|
@@ -239,6 +299,46 @@ async function cmdSyncAll(options) {
|
|
|
239
299
|
}
|
|
240
300
|
}
|
|
241
301
|
|
|
302
|
+
// ─── rederive ────────────────────────────────────────────────────────
|
|
303
|
+
|
|
304
|
+
async function cmdRederive(options) {
|
|
305
|
+
const spinner = options.json
|
|
306
|
+
? null
|
|
307
|
+
: ora(
|
|
308
|
+
options.adapter
|
|
309
|
+
? `re-deriving ${options.adapter} from raw_events...`
|
|
310
|
+
: "re-deriving all adapters from raw_events...",
|
|
311
|
+
).start();
|
|
312
|
+
try {
|
|
313
|
+
const hub = await getHub();
|
|
314
|
+
const opts = {};
|
|
315
|
+
if (options.adapter) opts.adapter = String(options.adapter);
|
|
316
|
+
if (options.batchSize) opts.batchSize = Number(options.batchSize);
|
|
317
|
+
const report = await hub.registry.rederive(opts);
|
|
318
|
+
if (spinner) {
|
|
319
|
+
spinner.succeed(
|
|
320
|
+
`re-derived ${report.rawSeen} raw → events:${report.entityCounts.events} ` +
|
|
321
|
+
`persons:${report.entityCounts.persons} items:${report.entityCounts.items} ` +
|
|
322
|
+
`(invalid:${report.invalidCount} missing:${report.adapterMissing} ` +
|
|
323
|
+
`${report.durationMs}ms)`,
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
if (options.json) {
|
|
327
|
+
jsonAndExit(report);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (report.errors.length > 0) {
|
|
331
|
+
logger.log(chalk.red(`errors: ${report.errors.length}`));
|
|
332
|
+
for (const e of report.errors) {
|
|
333
|
+
logger.log(` ${chalk.red(e.adapter)}: ${e.error}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
process.exit(0);
|
|
337
|
+
} catch (err) {
|
|
338
|
+
fail(spinner, err, options.json);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
242
342
|
// ─── query-events / recent-audit ─────────────────────────────────────
|
|
243
343
|
|
|
244
344
|
async function cmdQueryEvents(options) {
|
|
@@ -253,16 +353,93 @@ async function cmdQueryEvents(options) {
|
|
|
253
353
|
if (options.limit) q.limit = Number(options.limit);
|
|
254
354
|
const events = hub.vault.queryEvents(q);
|
|
255
355
|
if (options.json) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
)
|
|
264
|
-
|
|
356
|
+
jsonAndExit(events);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
logger.log(`${events.length} events:`);
|
|
360
|
+
for (const ev of events) {
|
|
361
|
+
const at = new Date(ev.at).toISOString();
|
|
362
|
+
logger.log(
|
|
363
|
+
` ${chalk.gray(at)} ${chalk.cyan(ev.subtype)} ${ev.summary || ev.id}`,
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
process.exit(0);
|
|
367
|
+
} catch (err) {
|
|
368
|
+
fail(null, err, options.json);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// ─── search / facet-counts (Phase 16 Vault Browser) ──────────────────
|
|
373
|
+
//
|
|
374
|
+
// Surfaces vault.searchEvents + vault.facetCounts for headless use
|
|
375
|
+
// (Android LocalCcRunner.searchEvents calls this; CI smoke too).
|
|
376
|
+
async function cmdSearchEvents(options) {
|
|
377
|
+
try {
|
|
378
|
+
const hub = await getHub();
|
|
379
|
+
const q = {};
|
|
380
|
+
if (options.q) q.q = String(options.q);
|
|
381
|
+
if (options.adapter) q.adapter = options.adapter;
|
|
382
|
+
if (options.category) q.category = options.category;
|
|
383
|
+
if (options.subtype) q.subtype = options.subtype;
|
|
384
|
+
if (options.since) q.since = Number(options.since);
|
|
385
|
+
if (options.until) q.until = Number(options.until);
|
|
386
|
+
if (options.limit) q.limit = Number(options.limit);
|
|
387
|
+
// cursor passed as `--cursor "<occurredAt>:<id>"` (cli-friendly)
|
|
388
|
+
if (options.cursor) {
|
|
389
|
+
const m = String(options.cursor).match(/^(\d+):(.+)$/);
|
|
390
|
+
if (m) q.cursor = { occurredAt: Number(m[1]), id: m[2] };
|
|
265
391
|
}
|
|
392
|
+
const result = hub.vault.searchEvents(q);
|
|
393
|
+
if (options.json) {
|
|
394
|
+
jsonAndExit(result);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
logger.log(
|
|
398
|
+
`${result.rows.length} events (mode=${result.mode}${result.shortQuery ? " shortQuery!" : ""})` +
|
|
399
|
+
(result.nextCursor
|
|
400
|
+
? ` nextCursor=${result.nextCursor.occurredAt}:${result.nextCursor.id}`
|
|
401
|
+
: ""),
|
|
402
|
+
);
|
|
403
|
+
for (const ev of result.rows) {
|
|
404
|
+
const at = new Date(ev.occurredAt).toISOString();
|
|
405
|
+
const summary =
|
|
406
|
+
(ev.content &&
|
|
407
|
+
(ev.content.text || ev.content.title || ev.content.subject)) ||
|
|
408
|
+
ev.id;
|
|
409
|
+
logger.log(
|
|
410
|
+
` ${chalk.gray(at)} ${chalk.cyan(ev.source.adapter)} ${chalk.dim(ev.subtype)} ${summary}`,
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
process.exit(0);
|
|
414
|
+
} catch (err) {
|
|
415
|
+
fail(null, err, options.json);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
async function cmdFacetCounts(options) {
|
|
420
|
+
try {
|
|
421
|
+
const hub = await getHub();
|
|
422
|
+
const q = {};
|
|
423
|
+
if (options.q) q.q = String(options.q);
|
|
424
|
+
if (options.since) q.since = Number(options.since);
|
|
425
|
+
if (options.until) q.until = Number(options.until);
|
|
426
|
+
const result = hub.vault.facetCounts(q);
|
|
427
|
+
if (options.json) {
|
|
428
|
+
jsonAndExit(result);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
logger.log(
|
|
432
|
+
`total=${result.total} mode=${result.mode}${result.shortQuery ? " shortQuery!" : ""}`,
|
|
433
|
+
);
|
|
434
|
+
logger.log(chalk.bold("by category:"));
|
|
435
|
+
for (const [k, n] of Object.entries(result.byCategory)) {
|
|
436
|
+
logger.log(` ${chalk.cyan(k.padEnd(10))} ${n}`);
|
|
437
|
+
}
|
|
438
|
+
logger.log(chalk.bold("by adapter:"));
|
|
439
|
+
for (const [k, n] of Object.entries(result.byAdapter)) {
|
|
440
|
+
logger.log(` ${chalk.cyan(k.padEnd(24))} ${n}`);
|
|
441
|
+
}
|
|
442
|
+
process.exit(0);
|
|
266
443
|
} catch (err) {
|
|
267
444
|
fail(null, err, options.json);
|
|
268
445
|
}
|
|
@@ -277,16 +454,17 @@ async function cmdRecentAudit(options) {
|
|
|
277
454
|
if (options.limit) q.limit = Number(options.limit);
|
|
278
455
|
const rows = hub.vault.queryAudit(q);
|
|
279
456
|
if (options.json) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
logger.log(`${rows.length} audit rows:`);
|
|
283
|
-
for (const r of rows) {
|
|
284
|
-
const at = new Date(r.at).toISOString();
|
|
285
|
-
logger.log(
|
|
286
|
-
` ${chalk.gray(at)} ${chalk.cyan(r.action)} ${r.adapter || ""} ${r.eventId || ""}`,
|
|
287
|
-
);
|
|
288
|
-
}
|
|
457
|
+
jsonAndExit(rows);
|
|
458
|
+
return;
|
|
289
459
|
}
|
|
460
|
+
logger.log(`${rows.length} audit rows:`);
|
|
461
|
+
for (const r of rows) {
|
|
462
|
+
const at = new Date(r.at).toISOString();
|
|
463
|
+
logger.log(
|
|
464
|
+
` ${chalk.gray(at)} ${chalk.cyan(r.action)} ${r.adapter || ""} ${r.eventId || ""}`,
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
process.exit(0);
|
|
290
468
|
} catch (err) {
|
|
291
469
|
fail(null, err, options.json);
|
|
292
470
|
}
|
|
@@ -1044,6 +1222,14 @@ export function registerHubCommand(program) {
|
|
|
1044
1222
|
"--accept-non-local",
|
|
1045
1223
|
"Allow non-local LLM (sends data off device — required when provider is not Ollama/vLLM)",
|
|
1046
1224
|
)
|
|
1225
|
+
.option(
|
|
1226
|
+
"--max-facts <n>",
|
|
1227
|
+
"Cap facts in prompt (default 80; on-device small models e.g. Qwen2.5-1.5B should pass 20)",
|
|
1228
|
+
)
|
|
1229
|
+
.option(
|
|
1230
|
+
"--max-query-limit <n>",
|
|
1231
|
+
"Cap vault queryEvents limit (default 200; small-model callers should pass 50)",
|
|
1232
|
+
)
|
|
1047
1233
|
.option("--json", "Output JSON")
|
|
1048
1234
|
.action(cmdAsk);
|
|
1049
1235
|
|
|
@@ -1087,6 +1273,24 @@ export function registerHubCommand(program) {
|
|
|
1087
1273
|
.option("--json", "Output JSON")
|
|
1088
1274
|
.action(cmdSyncAll);
|
|
1089
1275
|
|
|
1276
|
+
hub
|
|
1277
|
+
.command("rederive")
|
|
1278
|
+
.description(
|
|
1279
|
+
"Re-derive canonical events from raw_events without re-fetching " +
|
|
1280
|
+
"from source (recovers orphan raws from a past sync where putBatch " +
|
|
1281
|
+
"silently failed, e.g. trap #25 partial-index drift).",
|
|
1282
|
+
)
|
|
1283
|
+
.option(
|
|
1284
|
+
"--adapter <name>",
|
|
1285
|
+
"Filter to one adapter; default = all registered",
|
|
1286
|
+
)
|
|
1287
|
+
.option(
|
|
1288
|
+
"--batch-size <n>",
|
|
1289
|
+
"Raws per partitionBatch+putBatch tx (default 100)",
|
|
1290
|
+
)
|
|
1291
|
+
.option("--json", "Output JSON")
|
|
1292
|
+
.action(cmdRederive);
|
|
1293
|
+
|
|
1090
1294
|
hub
|
|
1091
1295
|
.command("query-events")
|
|
1092
1296
|
.description("Query vault events with filters")
|
|
@@ -1099,6 +1303,34 @@ export function registerHubCommand(program) {
|
|
|
1099
1303
|
.option("--json", "Output JSON")
|
|
1100
1304
|
.action(cmdQueryEvents);
|
|
1101
1305
|
|
|
1306
|
+
hub
|
|
1307
|
+
.command("search")
|
|
1308
|
+
.description("Vault Browser search — events_fts (FTS5) + faceted filters")
|
|
1309
|
+
.option("--q <text>", "Keyword (FTS5 phrase match if mode=fts5)")
|
|
1310
|
+
.option("--adapter <name>", "Filter by exact adapter")
|
|
1311
|
+
.option(
|
|
1312
|
+
"--category <cat>",
|
|
1313
|
+
"Filter by category (chat/social/email/shopping/travel/system/ai-chat/other)",
|
|
1314
|
+
)
|
|
1315
|
+
.option("--subtype <t>", "Filter by event subtype")
|
|
1316
|
+
.option("--since <ms>", "Start of time window (unix-ms)")
|
|
1317
|
+
.option("--until <ms>", "End of time window (unix-ms)")
|
|
1318
|
+
.option("--cursor <occurredAt:id>", "Page cursor from previous response")
|
|
1319
|
+
.option("--limit <n>", "Page size (max 500)", "50")
|
|
1320
|
+
.option("--json", "Output JSON")
|
|
1321
|
+
.action(cmdSearchEvents);
|
|
1322
|
+
|
|
1323
|
+
hub
|
|
1324
|
+
.command("facet-counts")
|
|
1325
|
+
.description(
|
|
1326
|
+
"Sidebar / chip counts — events grouped by category / adapter / subtype",
|
|
1327
|
+
)
|
|
1328
|
+
.option("--q <text>", "Keyword filter (same semantics as `cc hub search`)")
|
|
1329
|
+
.option("--since <ms>", "Start of time window (unix-ms)")
|
|
1330
|
+
.option("--until <ms>", "End of time window (unix-ms)")
|
|
1331
|
+
.option("--json", "Output JSON")
|
|
1332
|
+
.action(cmdFacetCounts);
|
|
1333
|
+
|
|
1102
1334
|
hub
|
|
1103
1335
|
.command("recent-audit")
|
|
1104
1336
|
.description("Recent audit log entries")
|
|
@@ -1270,6 +1502,8 @@ export function registerHubCommand(program) {
|
|
|
1270
1502
|
// `_wizard` / `_factoryDeps` / `_knownVendors` injected, bypassing the
|
|
1271
1503
|
// real `getHub()` call. The commander wiring above is the runtime path.
|
|
1272
1504
|
export const _internal = {
|
|
1505
|
+
cmdAsk,
|
|
1506
|
+
parsePositiveInt,
|
|
1273
1507
|
cmdAIChatList,
|
|
1274
1508
|
cmdAIChatLogin,
|
|
1275
1509
|
cmdAIChatProbe,
|
package/src/constants.js
CHANGED
|
@@ -145,6 +145,13 @@ export const DEFAULT_CONFIG = {
|
|
|
145
145
|
apiKey: null,
|
|
146
146
|
baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
|
|
147
147
|
model: "doubao-seed-1-6-251015",
|
|
148
|
+
// When true, `cc ask` (provider=ollama only) overrides baseUrl to point at
|
|
149
|
+
// the Android LocalLlmServer (127.0.0.1:18484). User opt-in toggle:
|
|
150
|
+
// cc config set llm.preferAndroidLocal true
|
|
151
|
+
// Resolution priority in ask.js:
|
|
152
|
+
// --base-url > CC_HUB_OLLAMA_URL env > --prefer-android-local flag >
|
|
153
|
+
// this config > config.llm.baseUrl > hardcoded localhost:11434
|
|
154
|
+
preferAndroidLocal: false,
|
|
148
155
|
},
|
|
149
156
|
enterprise: {
|
|
150
157
|
serverUrl: null,
|
|
@@ -22,12 +22,103 @@ import {
|
|
|
22
22
|
close as closeHub,
|
|
23
23
|
} from "../../lib/personal-data-hub-wiring.js";
|
|
24
24
|
import { getAIChatWizard } from "../../lib/personal-data-hub-aichat-wizard.js";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
existsSync,
|
|
27
|
+
unlinkSync,
|
|
28
|
+
readdirSync,
|
|
29
|
+
mkdirSync,
|
|
30
|
+
writeFileSync,
|
|
31
|
+
} from "node:fs";
|
|
26
32
|
import { join } from "node:path";
|
|
27
33
|
import pdhPkg from "@chainlesschain/personal-data-hub";
|
|
28
34
|
|
|
29
35
|
const { ingestSystemDataAndroidSnapshot } = pdhPkg;
|
|
30
36
|
|
|
37
|
+
/**
|
|
38
|
+
* If the caller didn't pass `inputPath`, try to pull a snapshot for
|
|
39
|
+
* this adapter off the attached Android phone via `adb shell run-as
|
|
40
|
+
* <pkg.debug> cat files/.chainlesschain/staging/<name>.json`. On
|
|
41
|
+
* success, write the JSON to `hub.hubDir/staging/` and return an
|
|
42
|
+
* `options` object with `inputPath` set so the adapter's _syncViaSnapshot
|
|
43
|
+
* picks it up.
|
|
44
|
+
*
|
|
45
|
+
* Why this is needed: every social adapter (bilibili, weibo, douyin,
|
|
46
|
+
* xiaohongshu, toutiao, kuaishou, qq, wechat, baidu-map, tencent-map,
|
|
47
|
+
* jd, meituan, pinduoduo) is snapshot-only and the Android in-app
|
|
48
|
+
* collectors write their JSON into the app's filesDir/.chainlesschain/
|
|
49
|
+
* staging/. Without an auto-pull, the desktop 同步 button can never
|
|
50
|
+
* reach a working state for these adapters — it just throws "needs
|
|
51
|
+
* opts.inputPath".
|
|
52
|
+
*
|
|
53
|
+
* Best-effort: if anything fails (no device, package not debuggable,
|
|
54
|
+
* snapshot file missing for that adapter, bridge module unavailable),
|
|
55
|
+
* return the original options unchanged so the adapter's normal error
|
|
56
|
+
* path fires and the UI banner shows a meaningful message.
|
|
57
|
+
*/
|
|
58
|
+
async function _tryAdbAutoPullInputPath(hub, name, options) {
|
|
59
|
+
if (
|
|
60
|
+
options &&
|
|
61
|
+
typeof options.inputPath === "string" &&
|
|
62
|
+
options.inputPath.length > 0
|
|
63
|
+
) {
|
|
64
|
+
return options; // caller already supplied a path
|
|
65
|
+
}
|
|
66
|
+
// Skip auto-pull for adapters that have a live bridge mode — pulling
|
|
67
|
+
// a stale snapshot file would short-circuit the bridge path which
|
|
68
|
+
// yields fresher / richer data (e.g. system-data-android's bridge
|
|
69
|
+
// mode pulls contacts + apps + sms + call_log live via ADB, while
|
|
70
|
+
// an Android-collected snapshot only contains contacts + apps).
|
|
71
|
+
// Keep this list in sync with adapters whose _syncViaBridge is
|
|
72
|
+
// strictly richer than their snapshot output.
|
|
73
|
+
// browser-history-* and vscode read desktop-local files (browser History
|
|
74
|
+
// SQLite + Bookmarks JSON, or VS Code workspaceStorage + state.vscdb);
|
|
75
|
+
// ADB snapshot is meaningless for them.
|
|
76
|
+
const BRIDGE_PREFERRED = new Set([
|
|
77
|
+
"system-data-android",
|
|
78
|
+
"browser-history-chrome",
|
|
79
|
+
"browser-history-edge",
|
|
80
|
+
"vscode",
|
|
81
|
+
"win-recent",
|
|
82
|
+
"git-activity",
|
|
83
|
+
"shell-history",
|
|
84
|
+
"local-files",
|
|
85
|
+
]);
|
|
86
|
+
if (BRIDGE_PREFERRED.has(name)) {
|
|
87
|
+
return options || {};
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const { createHostAdbBridge } =
|
|
91
|
+
await import("../../lib/host-adb-bridge.js");
|
|
92
|
+
const bridge = createHostAdbBridge();
|
|
93
|
+
const content = await bridge.invoke("snapshot.read", {
|
|
94
|
+
fileName: `${name}.json`,
|
|
95
|
+
});
|
|
96
|
+
// Sanity: must be parseable JSON. If not, the adapter would fail
|
|
97
|
+
// with a confusing parse error — surface a clearer one here.
|
|
98
|
+
try {
|
|
99
|
+
JSON.parse(content);
|
|
100
|
+
} catch (_e) {
|
|
101
|
+
return options; // leave to adapter — it'll report parse error
|
|
102
|
+
}
|
|
103
|
+
const stagingDir = join(hub.hubDir, "staging");
|
|
104
|
+
mkdirSync(stagingDir, { recursive: true });
|
|
105
|
+
const stagingPath = join(
|
|
106
|
+
stagingDir,
|
|
107
|
+
`${name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`,
|
|
108
|
+
);
|
|
109
|
+
writeFileSync(stagingPath, content, "utf-8");
|
|
110
|
+
return {
|
|
111
|
+
...(options || {}),
|
|
112
|
+
inputPath: stagingPath,
|
|
113
|
+
_autoPulledViaAdb: true,
|
|
114
|
+
};
|
|
115
|
+
} catch (_e) {
|
|
116
|
+
// Bridge unavailable / device not attached / file missing — let the
|
|
117
|
+
// adapter throw its normal error so the banner explains.
|
|
118
|
+
return options || {};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
31
122
|
async function withHub(fn) {
|
|
32
123
|
try {
|
|
33
124
|
const hub = await getHub();
|
|
@@ -83,10 +174,26 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
|
|
|
83
174
|
withHub((hub) => hub.registry.list()),
|
|
84
175
|
|
|
85
176
|
"personal-data-hub.sync-adapter": async (msg) =>
|
|
86
|
-
withHub(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
177
|
+
withHub(async (hub) => {
|
|
178
|
+
const options = await _tryAdbAutoPullInputPath(
|
|
179
|
+
hub,
|
|
180
|
+
msg.name,
|
|
181
|
+
msg.options,
|
|
182
|
+
);
|
|
183
|
+
try {
|
|
184
|
+
return await hub.registry.syncAdapter(msg.name, options);
|
|
185
|
+
} finally {
|
|
186
|
+
// Best-effort cleanup of staging file we just wrote (don't shadow
|
|
187
|
+
// a real adapter error with cleanup noise).
|
|
188
|
+
if (options && options._autoPulledViaAdb && options.inputPath) {
|
|
189
|
+
try {
|
|
190
|
+
if (existsSync(options.inputPath)) unlinkSync(options.inputPath);
|
|
191
|
+
} catch (_e) {
|
|
192
|
+
/* ignore */
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}),
|
|
90
197
|
|
|
91
198
|
"personal-data-hub.sync-all": async (msg) =>
|
|
92
199
|
withHub(async (hub) => await hub.registry.syncAll(msg.options || {})),
|
|
@@ -116,6 +223,36 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
|
|
|
116
223
|
}),
|
|
117
224
|
),
|
|
118
225
|
|
|
226
|
+
// Phase 16 Vault Browser — full-text + faceted search over events.
|
|
227
|
+
// See packages/personal-data-hub/lib/vault.js#searchEvents for the
|
|
228
|
+
// query/result shape. The desktop browser view + Android "我的数据" tab
|
|
229
|
+
// both consume this topic.
|
|
230
|
+
"personal-data-hub.search-events": async (msg) =>
|
|
231
|
+
withHub((hub) =>
|
|
232
|
+
hub.vault.searchEvents({
|
|
233
|
+
q: msg.q,
|
|
234
|
+
adapter: msg.adapter,
|
|
235
|
+
category: msg.category,
|
|
236
|
+
subtype: msg.subtype,
|
|
237
|
+
since: msg.since,
|
|
238
|
+
until: msg.until,
|
|
239
|
+
cursor: msg.cursor,
|
|
240
|
+
limit: msg.limit,
|
|
241
|
+
}),
|
|
242
|
+
),
|
|
243
|
+
|
|
244
|
+
// Phase 16 Vault Browser — counts grouped by category/adapter/subtype,
|
|
245
|
+
// honoring the same q + since/until filters as search-events. Powers
|
|
246
|
+
// the sidebar badges + adapter chip counts in the browser UI.
|
|
247
|
+
"personal-data-hub.facet-counts": async (msg) =>
|
|
248
|
+
withHub((hub) =>
|
|
249
|
+
hub.vault.facetCounts({
|
|
250
|
+
q: msg.q,
|
|
251
|
+
since: msg.since,
|
|
252
|
+
until: msg.until,
|
|
253
|
+
}),
|
|
254
|
+
),
|
|
255
|
+
|
|
119
256
|
"personal-data-hub.recent-audit": async (msg) =>
|
|
120
257
|
withHub((hub) =>
|
|
121
258
|
hub.vault.queryAudit({
|
|
@@ -379,14 +516,19 @@ export const PERSONAL_DATA_HUB_STREAMING_HANDLERS = {
|
|
|
379
516
|
} catch (_e) {}
|
|
380
517
|
}
|
|
381
518
|
};
|
|
519
|
+
const options = await _tryAdbAutoPullInputPath(hub, msg.name, msg.options);
|
|
382
520
|
try {
|
|
383
|
-
const report = await hub.registry.syncAdapter(
|
|
384
|
-
msg.name,
|
|
385
|
-
msg.options || {},
|
|
386
|
-
);
|
|
521
|
+
const report = await hub.registry.syncAdapter(msg.name, options);
|
|
387
522
|
return { result: report };
|
|
388
523
|
} finally {
|
|
389
524
|
hub.registry.onSyncEvent = original;
|
|
525
|
+
if (options && options._autoPulledViaAdb && options.inputPath) {
|
|
526
|
+
try {
|
|
527
|
+
if (existsSync(options.inputPath)) unlinkSync(options.inputPath);
|
|
528
|
+
} catch (_e) {
|
|
529
|
+
/* ignore */
|
|
530
|
+
}
|
|
531
|
+
}
|
|
390
532
|
}
|
|
391
533
|
},
|
|
392
534
|
|