chainlesschain 0.162.102 → 0.162.103
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/README.md +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.mjs +33 -3
- package/src/assets/web-panel/assets/{AIOps-C1k00Gsz.js → AIOps-BpJ5yCcV.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BinI6ZDq.js → ActionButton-B1uBfxnA.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Cg0jo_cd.js → Analytics-0ubw5quf.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CClMs_AA.js → AppLayout-go-GyyM_.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-BtQgvFdM.js → Audit-CdUfoUnM.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-43FRi7ZI.js → Backup-CBn0xtsa.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Cfza-FZU.js → BaseInput-a9fqTkvL.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-7AjHSiSC.js → Chat-D-d_IatD.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Bh1YNdtx.js → ChatBubbleRenderer-Co9h0SbA.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DgjfqlWW.js → Checkbox-CiKEjtXm.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CkwOBThj.js → Codegen-OQxW_9Z2.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Cohk5WYM.js → Col-BZHXUEnZ.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D3LMGh3F.js → Community-D3xno9fj.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DqoMJmh0.js → Compact-D62jpZk_.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BVjWZlEj.js → Compliance-D4jFTAcQ.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-C0lqQPqu.js → Cowork-BOU_wir4.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DHd_PJZS.js → Cron-Cr9BlJA7.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BphK2Q9u.js → Crosschain-L9M--CXb.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CWIw0aG4.js → DID-xFu3-VWT.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CKgDU9U6.js → Dashboard--ax48T3j.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DkIlDUXF.js → Dropdown-CTOS8daR.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-5sXA9hwZ.js → EmailListRenderer-CNLSX81U.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CgcdJLH7.js → FamilyGuardDashboard-5EjFynBc.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DPOcJISA.js → Federation-CoPyIWIu.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DxOutBMJ.js → FormItemContext-BbzCNbYy.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BYVNtkcd.js → GenericCardRenderer-8_9_uXY0.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B37LKxOu.js → Git-Bz_qlVPg.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CnKcx5un.js → Governance-7eepNCeD.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CbRAWN3_.js → Inference-DlBx5l1g.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-D0w6RfE_.js → KnowledgeGraph-BPkc--rM.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DxBDKpzq.js → Logs-BQw4nPvS.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-DNLi6O_3.js → Marketplace-Cil3SdgN.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-s0sBCPXw.js → McpTools-Bnch7KrG.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-BdSEgpmP.js → Memory-assQ3Suc.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Dz7nz4K9.js → MobileBridge-D5mE8c-z.js} +2 -2
- package/src/assets/web-panel/assets/{MobileProjects-DakdA2PC.js → MobileProjects-C4MiDXw1.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Be9OBypk.js → Mtc-CumojeLk.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-KI2ih4Tl.js → MtcAudit-3tTBc_fw.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-Cg3jHFjL.js → Multisig-Dl4IJBsl.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BepHx8fU.js → NLProgramming-DHN_cV9x.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-2f05HyqN.js → Notes-DeyTvwYk.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-Blwio_G5.js → NotificationSettings-BUkj8mTj.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-D7HJfvo_.js → OrderTableRenderer-BMpEXTki.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Uihlz1cI.js → Organization-B6Ogmkpz.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-gZx8kADL.js → Overflow-DRUE-2Wz.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DqEEGqba.js → P2P-CnMUkd64.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-B3nFxT3b.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-ERF2ZQ3G.js → Permissions-CyG1FR7v.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CzDy9CFB.js → PersonalDataHub-BmN6YMb5.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-Dy4x9Ejw.js → Pipeline-BZcamAnH.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-C6UJys52.js → Privacy-D7_zsaY3.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Bmi027fa.js → ProjectInit-DNa7XQjg.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-NinSZmGA.js → ProjectSettings-KH2Dm09G.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DeW-p-hT.js → Projects-T-WqR3D6.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-4hxrBTLo.js → Providers-8GtQ6GgR.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-B5inZlW8.js → QuickAsk-BuBM5Zpg.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-7lpBm00-.js → Recommend-DvH95W1b.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-QfdGZxYO.js → Reputation-BHCpMEP6.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DqHC7BCT.js → Row-BnMPysBm.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B3F1aGP6.js → RssFeed-C-T8B5VU.js} +2 -2
- package/src/assets/web-panel/assets/{Search-BXtjuoYO.js → Search-CioiZGkX.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Iy0MOV-A.js → Security-zSApKqdd.js} +4 -4
- package/src/assets/web-panel/assets/{Services-C_puMp_6.js → Services-CQh0UDXC.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Bg6mTVZU.js → Skeleton-C0dRaEVG.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-D4wXhanR.js → Skills-BgQRArsa.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Cgr2B9R6.js → Sla-BNn7F3jc.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-ctYqZEY5.js → SpeechSettings-kvVfKfqv.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-C3qWh9y4.js → SyncSettings-BwIkkX1E.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-D3AAgUx1.js → Tasks-BkcvhBZw.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Bm_Dyz8T.js → Templates-COK0o2pL.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DOSrOw9X.js → Tenant-DpK87fqo.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-2g2-XPT_.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-BB8Qq6Cx.js → TimelineRenderer-B4SJqyqf.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DqyF_Flh.js → Tokens-C3iSR8fH.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-ClwQC2hP.js → Trigger-D1Oo58Yo.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DGQSLPQ0.js → Trust-CUhy4DDc.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BAkeYsUO.js → UkeySign-r-kTqSw8.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-WyUxS65Y.js → VideoEditing-B8MyBfCX.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Br7GdjEg.js → Wallet-CquTfSv0.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-bKs1dahj.js → WebAuthn-BC7TP1H3.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-CVqAALYe.js → WorkflowEditor-CELBSNbP.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BDGDRbab.js → chat-d66mbO2i.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DIUxZwT8.js → colors-D0WRCg20.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-C2iM4GmN.js → compact-item-4__-8TIi.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D27NeHwO.js → createContext-Dqsf52js.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DUAmX0aE.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D1lXdsFj.js → hasIn-ClTZOS8I.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cgf3zMwq.js → index-0Axwx1nN.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8POWlbO.js → index-81SaeU6t.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoygRreE.js → index-B1TGSkBt.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dc4k4V1u.js → index-B3vrmn5v.js} +1 -1
- package/src/assets/web-panel/assets/{index-ET5LYk9B.js → index-BCOpbfAH.js} +1 -1
- package/src/assets/web-panel/assets/index-BLCwqv8j.js +1 -0
- package/src/assets/web-panel/assets/{index-HZGu1woY.js → index-BNKECBZm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAnMUhHO.js → index-BwozLU75.js} +1 -1
- package/src/assets/web-panel/assets/{index-yIM-KxVm.js → index-C4_XhCJS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Do13fQ5W.js → index-C5l6tSky.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiA-L5ld.js → index-CFwkeSun.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIVYPlpl.js → index-CGf3oqM0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkOu8er7.js → index-CJKyF-y8.js} +1 -1
- package/src/assets/web-panel/assets/{index-Y1rkRas5.js → index-Cg8Qw3Jw.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEO9vhv7.js → index-Cops66s2.js} +3 -3
- package/src/assets/web-panel/assets/{index-DfSav-yQ.js → index-Ct5SJenr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CfR3Pvsu.js → index-CxoWS8hl.js} +1 -1
- package/src/assets/web-panel/assets/{index-BE9bNvdn.js → index-D-ya3Ohe.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnCVI295.js → index-D68tyHYa.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5ZB5lsV.js → index-D9x6i7iV.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cbqr8kW6.js → index-DDLjwgva.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsIw-YQF.js → index-DORg0Hps.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNk98bb1.js → index-DQaGurrQ.js} +1 -1
- package/src/assets/web-panel/assets/index-Db5JRQ6E.js +1 -0
- package/src/assets/web-panel/assets/{index-CKMDgjfh.js → index-DbY1lv1z.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDzSUTpa.js → index-Dm7CYK3j.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFEwtE3q.js → index-DpLhC0nx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTedVe_v.js → index-P4X9zSF2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi8u5GsP.js → index-PAiWA2un.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTUFhfHs.js → index-PMJ4tBAA.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqbjsJcS.js → index-Yi5Lr63I.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFhdJm7M.js → index-ZZpfHd4J.js} +1 -1
- package/src/assets/web-panel/assets/{index-DrS-Mrm-.js → index-b7a5aEX9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CFY1KjB1.js → index-e5zJLrJQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cb9u9MMo.js → index-fi2ikHoc.js} +1 -1
- package/src/assets/web-panel/assets/{index-DK0jgmJg.js → index-jAPphbJL.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6kc4-nD.js → index-leuwRsbf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bil9t91t.js → index-luisYDBz.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ca8n97h9.js → index-we9-1IbF.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C0Yrc6yY.js → initDefaultProps-zqDf7qWv.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DnOI85ek.js → motion-DRqTooll.js} +1 -1
- package/src/assets/web-panel/assets/{move-DT9zQPZp.js → move-N8tkRqS4.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DFtDi5Wd.js → omit-Cy01f2vw.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Cobkb_rd.js → pickAttrs-C2ycNXNi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DWQDu4i-.js → placementArrow-D60Xb1j9.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-daoQcWcX.js → responsiveObserve-BF8Y-1HQ.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BLkzd2OV.js → slide-DDi6zYZf.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Uyxi81M0.js → statusUtils-CWPq6UzA.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Dtw5lUcs.js → styleChecker-D4zVyb4w.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-_JpMgpdt.js → useFlexGapSupport-BEMNO3oR.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-huwAlPD-.js → useFs-DBLO8VR7.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-7cafj8_f.js → usePersonalDataHub-C83ZIrPY.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DYUSfRt7.js → vnode-Dcfyve-7.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-B-tjvmer.js → zoom-Dg6uoWSc.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/__tests__/hub-health.test.js +105 -0
- package/src/commands/__tests__/hub-stats.test.js +106 -0
- package/src/commands/hub.js +111 -32
- package/src/gateways/ws/personal-data-hub-protocol.js +16 -3
- package/src/lib/personal-data-hub-wiring.js +135 -7
- package/src/assets/web-panel/assets/PdhVaultBrowser-BHUi1nb5.js +0 -7
- package/src/assets/web-panel/assets/Terminal-DrG0bEOS.js +0 -3
- package/src/assets/web-panel/assets/devWarning-Daz0PHhS.js +0 -1
- package/src/assets/web-panel/assets/index-Cbe_eJAR.js +0 -1
- package/src/assets/web-panel/assets/index-DgcPjW1c.js +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc hub health` — focused unit tests for the --quick (minimal hub) path.
|
|
3
|
+
*
|
|
4
|
+
* Why this test exists: `cc hub health` defaults to the FULL hub because its
|
|
5
|
+
* job is to verify hub init wired every component (llm / kgSink / ragSink) —
|
|
6
|
+
* a minimal hub leaves those null on purpose, so reporting them as down would
|
|
7
|
+
* be a false negative, not a faster check. `--quick` opts into a vault-only
|
|
8
|
+
* probe on the minimal hub (skips the 77-adapter registry + sink wiring) and
|
|
9
|
+
* must mark the other components "not probed" rather than failing them. If
|
|
10
|
+
* that distinction regresses, `--quick` would either go slow again or start
|
|
11
|
+
* lying about component health. This suite is the canary.
|
|
12
|
+
*
|
|
13
|
+
* Uses the `_getHub` injection seam — no real vault / no spinner side effects.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
17
|
+
import { _internal } from "../hub.js";
|
|
18
|
+
|
|
19
|
+
const { cmdHealth } = _internal;
|
|
20
|
+
|
|
21
|
+
let exitSpy, logSpy, out;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {});
|
|
25
|
+
out = [];
|
|
26
|
+
logSpy = vi.spyOn(console, "log").mockImplementation((...args) => {
|
|
27
|
+
out.push(args.join(" "));
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
exitSpy.mockRestore();
|
|
33
|
+
logSpy.mockRestore();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
function fullHub() {
|
|
37
|
+
return {
|
|
38
|
+
minimal: false,
|
|
39
|
+
vault: { db: {}, schemaVersion: () => 4 },
|
|
40
|
+
llm: { name: "ollama:qwen2.5", isLocal: true },
|
|
41
|
+
kgSink: {},
|
|
42
|
+
ragSink: {},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function minimalHub() {
|
|
47
|
+
return {
|
|
48
|
+
minimal: true,
|
|
49
|
+
vault: { db: {}, schemaVersion: () => 4 },
|
|
50
|
+
llm: null,
|
|
51
|
+
kgSink: null,
|
|
52
|
+
ragSink: null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function parseJson() {
|
|
57
|
+
return JSON.parse(out.join("\n"));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe("cc hub health — default (full) vs --quick (minimal)", () => {
|
|
61
|
+
it("default probes all four components with real ok states", async () => {
|
|
62
|
+
const stub = vi.fn(async () => fullHub());
|
|
63
|
+
await cmdHealth({ json: true, _getHub: stub });
|
|
64
|
+
const o = parseJson();
|
|
65
|
+
expect(stub).toHaveBeenCalledTimes(1);
|
|
66
|
+
expect(o.quick).toBe(false);
|
|
67
|
+
expect(o.vault.ok).toBe(true);
|
|
68
|
+
expect(o.vault.schemaVersion).toBe(4);
|
|
69
|
+
expect(o.llm).toEqual({ ok: true, isLocal: true, name: "ollama:qwen2.5" });
|
|
70
|
+
expect(o.kgSink).toEqual({ ok: true });
|
|
71
|
+
expect(o.ragSink).toEqual({ ok: true });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("--quick reports vault only; llm/kgSink/ragSink marked not probed (NOT down)", async () => {
|
|
75
|
+
await cmdHealth({
|
|
76
|
+
json: true,
|
|
77
|
+
quick: true,
|
|
78
|
+
_getHub: async () => minimalHub(),
|
|
79
|
+
});
|
|
80
|
+
const o = parseJson();
|
|
81
|
+
expect(o.quick).toBe(true);
|
|
82
|
+
expect(o.vault.ok).toBe(true);
|
|
83
|
+
// The key correctness property: not-probed, never { ok: false }.
|
|
84
|
+
expect(o.llm).toEqual({ probed: false });
|
|
85
|
+
expect(o.kgSink).toEqual({ probed: false });
|
|
86
|
+
expect(o.ragSink).toEqual({ probed: false });
|
|
87
|
+
expect(o.llm.ok).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("--quick human output notes the skipped components", async () => {
|
|
91
|
+
await cmdHealth({ quick: true, _getHub: async () => minimalHub() });
|
|
92
|
+
const text = out.join("\n");
|
|
93
|
+
expect(text).toMatch(/vault\s+schema=4/);
|
|
94
|
+
expect(text).toContain("not probed");
|
|
95
|
+
expect(text).toContain("--quick");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("default human output lists llm/kgSink/ragSink", async () => {
|
|
99
|
+
await cmdHealth({ _getHub: async () => fullHub() });
|
|
100
|
+
const text = out.join("\n");
|
|
101
|
+
expect(text).toContain("llm");
|
|
102
|
+
expect(text).toContain("kgSink");
|
|
103
|
+
expect(text).toContain("ragSink");
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc hub stats` — focused unit tests for the minimal-vs-full hub selection.
|
|
3
|
+
*
|
|
4
|
+
* Why this test exists: `cc hub stats` defaults to the MINIMAL hub so a quick
|
|
5
|
+
* "how many rows do I have" check doesn't pay to instantiate the full
|
|
6
|
+
* 77-adapter registry + KG/RAG sinks + email-account auto-load. The adapter
|
|
7
|
+
* list + resolved LLM are only built when the caller passes `--full` (or via
|
|
8
|
+
* the standalone `cc hub list-adapters`). If that wiring regresses, every
|
|
9
|
+
* `cc hub stats` call silently goes back to a slow full-hub init. This suite
|
|
10
|
+
* is the canary.
|
|
11
|
+
*
|
|
12
|
+
* Uses the `_getHub` injection seam — no real vault / no spinner side effects.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
16
|
+
import { _internal } from "../hub.js";
|
|
17
|
+
|
|
18
|
+
const { cmdStats } = _internal;
|
|
19
|
+
|
|
20
|
+
let exitSpy, logSpy, jsonOut;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {});
|
|
24
|
+
jsonOut = [];
|
|
25
|
+
logSpy = vi.spyOn(console, "log").mockImplementation((...args) => {
|
|
26
|
+
jsonOut.push(args.join(" "));
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
exitSpy.mockRestore();
|
|
32
|
+
logSpy.mockRestore();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
function minimalHub() {
|
|
36
|
+
return {
|
|
37
|
+
minimal: true,
|
|
38
|
+
hubDir: "/tmp/hub",
|
|
39
|
+
vault: {
|
|
40
|
+
stats: () => ({ events: 3, persons: 1, places: 0, items: 6, topics: 2 }),
|
|
41
|
+
},
|
|
42
|
+
registry: null,
|
|
43
|
+
llm: null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function fullHub() {
|
|
48
|
+
return {
|
|
49
|
+
minimal: false,
|
|
50
|
+
hubDir: "/tmp/hub",
|
|
51
|
+
vault: {
|
|
52
|
+
stats: () => ({ events: 3, persons: 1, places: 0, items: 6, topics: 2 }),
|
|
53
|
+
},
|
|
54
|
+
registry: {
|
|
55
|
+
list: () => [
|
|
56
|
+
{ name: "wechat", version: "0.1.0" },
|
|
57
|
+
{ name: "email-imap", version: "0.2.0" },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
llm: { name: "ollama:qwen2.5", isLocal: true },
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function parseJson() {
|
|
65
|
+
return JSON.parse(jsonOut.join("\n"));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
describe("cc hub stats — minimal vs full hub selection", () => {
|
|
69
|
+
it("default (no --full) builds the MINIMAL hub: null adapters, minimal flag", async () => {
|
|
70
|
+
const stub = vi.fn(async () => minimalHub());
|
|
71
|
+
await cmdStats({ json: true, _getHub: stub });
|
|
72
|
+
const out = parseJson();
|
|
73
|
+
expect(stub).toHaveBeenCalledTimes(1);
|
|
74
|
+
expect(out.minimal).toBe(true);
|
|
75
|
+
expect(out.adapters).toBeNull();
|
|
76
|
+
expect(out.llm).toBeNull();
|
|
77
|
+
expect(out.vault.items).toBe(6);
|
|
78
|
+
expect(out.hubDir).toBe("/tmp/hub");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("--full builds the full hub: adapters listed, llm resolved, minimal false", async () => {
|
|
82
|
+
const stub = vi.fn(async () => fullHub());
|
|
83
|
+
await cmdStats({ json: true, full: true, _getHub: stub });
|
|
84
|
+
const out = parseJson();
|
|
85
|
+
expect(out.minimal).toBe(false);
|
|
86
|
+
expect(Array.isArray(out.adapters)).toBe(true);
|
|
87
|
+
expect(out.adapters).toHaveLength(2);
|
|
88
|
+
expect(out.llm).toEqual({ name: "ollama:qwen2.5", isLocal: true });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("human (non-JSON) minimal output points to --full / list-adapters", async () => {
|
|
92
|
+
await cmdStats({ _getHub: async () => minimalHub() });
|
|
93
|
+
const text = jsonOut.join("\n");
|
|
94
|
+
expect(text).toMatch(/events:\s+3/);
|
|
95
|
+
expect(text).toContain("cc hub list-adapters");
|
|
96
|
+
expect(text).toContain("cc hub stats --full");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("human full output lists adapter names + versions", async () => {
|
|
100
|
+
await cmdStats({ full: true, _getHub: async () => fullHub() });
|
|
101
|
+
const text = jsonOut.join("\n");
|
|
102
|
+
expect(text).toContain("adapters (2)");
|
|
103
|
+
expect(text).toContain("wechat");
|
|
104
|
+
expect(text).toContain("email-imap");
|
|
105
|
+
});
|
|
106
|
+
});
|
package/src/commands/hub.js
CHANGED
|
@@ -173,12 +173,28 @@ async function cmdRetrieveContext(question, options) {
|
|
|
173
173
|
|
|
174
174
|
async function cmdStats(options) {
|
|
175
175
|
try {
|
|
176
|
-
|
|
176
|
+
// Default to the minimal hub: stats' core payload (vault row counts +
|
|
177
|
+
// hubDir) only needs the vault, so the full 77-adapter registry + KG/RAG
|
|
178
|
+
// sinks + email-account auto-load is wasted work for a quick `cc hub
|
|
179
|
+
// stats`. Pass --full to also list registered adapters and the resolved
|
|
180
|
+
// LLM, which require the full hub init. (The adapter list is also
|
|
181
|
+
// available standalone via `cc hub list-adapters`.) getHubMinimal()
|
|
182
|
+
// transparently returns the full hub if one was already built this
|
|
183
|
+
// process, so --full is only needed on a cold stats call. Tests stub
|
|
184
|
+
// via _getHub.
|
|
185
|
+
const wantFull = options.full === true;
|
|
186
|
+
const hub = options._getHub
|
|
187
|
+
? await options._getHub()
|
|
188
|
+
: wantFull
|
|
189
|
+
? await getHub()
|
|
190
|
+
: await getHubMinimal();
|
|
191
|
+
const adapters = hub.registry ? hub.registry.list() : null;
|
|
177
192
|
const out = {
|
|
178
193
|
vault: hub.vault.stats(),
|
|
179
|
-
adapters
|
|
194
|
+
adapters,
|
|
180
195
|
hubDir: hub.hubDir,
|
|
181
196
|
llm: hub.llm ? { name: hub.llm.name, isLocal: hub.llm.isLocal } : null,
|
|
197
|
+
minimal: !!hub.minimal,
|
|
182
198
|
};
|
|
183
199
|
if (options.json) {
|
|
184
200
|
printJson(out);
|
|
@@ -190,9 +206,17 @@ async function cmdStats(options) {
|
|
|
190
206
|
logger.log(` places: ${v.places}`);
|
|
191
207
|
logger.log(` items: ${v.items}`);
|
|
192
208
|
logger.log(` topics: ${v.topics}`);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
209
|
+
if (out.adapters) {
|
|
210
|
+
logger.log(chalk.bold(`\nadapters (${out.adapters.length}):`));
|
|
211
|
+
for (const a of out.adapters) {
|
|
212
|
+
logger.log(` ${chalk.cyan(a.name)} v${a.version}`);
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
logger.log(
|
|
216
|
+
chalk.gray(
|
|
217
|
+
"\nadapters: (run `cc hub stats --full` or `cc hub list-adapters`)",
|
|
218
|
+
),
|
|
219
|
+
);
|
|
196
220
|
}
|
|
197
221
|
logger.log(chalk.gray(`\nhubDir: ${out.hubDir}`));
|
|
198
222
|
if (out.llm) {
|
|
@@ -200,6 +224,8 @@ async function cmdStats(options) {
|
|
|
200
224
|
? chalk.green("[local]")
|
|
201
225
|
: chalk.yellow("[remote]");
|
|
202
226
|
logger.log(chalk.gray(`llm: ${out.llm.name} ${tag}`));
|
|
227
|
+
} else if (out.minimal) {
|
|
228
|
+
logger.log(chalk.gray("llm: (run `cc hub stats --full` to resolve)"));
|
|
203
229
|
} else {
|
|
204
230
|
logger.log(chalk.yellow("llm: (none)"));
|
|
205
231
|
}
|
|
@@ -213,18 +239,39 @@ async function cmdStats(options) {
|
|
|
213
239
|
|
|
214
240
|
async function cmdHealth(options) {
|
|
215
241
|
try {
|
|
216
|
-
|
|
242
|
+
// Full hub is the default: health's whole job is verifying that hub init
|
|
243
|
+
// wired every component (llm / kgSink / ragSink), which a minimal hub
|
|
244
|
+
// deliberately leaves null — reporting those as ✗ would be a false
|
|
245
|
+
// negative, not a faster check. `--quick` opts into a vault-only probe
|
|
246
|
+
// on the minimal hub (skips the 77-adapter registry + sink wiring) for
|
|
247
|
+
// when you just need "is the vault openable / what schema". Tests stub
|
|
248
|
+
// via _getHub.
|
|
249
|
+
const quick = options.quick === true;
|
|
250
|
+
const hub = options._getHub
|
|
251
|
+
? await options._getHub()
|
|
252
|
+
: quick
|
|
253
|
+
? await getHubMinimal()
|
|
254
|
+
: await getHub();
|
|
217
255
|
const out = {
|
|
256
|
+
quick,
|
|
218
257
|
vault: {
|
|
219
258
|
ok: !!hub.vault.db,
|
|
220
259
|
schemaVersion: hub.vault.schemaVersion(),
|
|
221
260
|
},
|
|
222
|
-
llm: hub.llm
|
|
223
|
-
? { ok: true, isLocal: hub.llm.isLocal, name: hub.llm.name }
|
|
224
|
-
: { ok: false, reason: "LLM unavailable" },
|
|
225
|
-
kgSink: { ok: !!hub.kgSink },
|
|
226
|
-
ragSink: { ok: !!hub.ragSink },
|
|
227
261
|
};
|
|
262
|
+
if (quick) {
|
|
263
|
+
// Minimal hub intentionally has no llm / kgSink / ragSink — mark them
|
|
264
|
+
// "not probed" rather than reporting a misleading down state.
|
|
265
|
+
out.llm = { probed: false };
|
|
266
|
+
out.kgSink = { probed: false };
|
|
267
|
+
out.ragSink = { probed: false };
|
|
268
|
+
} else {
|
|
269
|
+
out.llm = hub.llm
|
|
270
|
+
? { ok: true, isLocal: hub.llm.isLocal, name: hub.llm.name }
|
|
271
|
+
: { ok: false, reason: "LLM unavailable" };
|
|
272
|
+
out.kgSink = { ok: !!hub.kgSink };
|
|
273
|
+
out.ragSink = { ok: !!hub.ragSink };
|
|
274
|
+
}
|
|
228
275
|
if (options.json) {
|
|
229
276
|
printJson(out);
|
|
230
277
|
} else {
|
|
@@ -232,17 +279,25 @@ async function cmdHealth(options) {
|
|
|
232
279
|
logger.log(
|
|
233
280
|
`${mark(out.vault.ok)} vault schema=${out.vault.schemaVersion}`,
|
|
234
281
|
);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
282
|
+
if (quick) {
|
|
283
|
+
logger.log(
|
|
284
|
+
chalk.gray(
|
|
285
|
+
"· llm / kgSink / ragSink not probed (run without --quick)",
|
|
286
|
+
),
|
|
287
|
+
);
|
|
288
|
+
} else {
|
|
289
|
+
logger.log(
|
|
290
|
+
`${mark(out.llm.ok)} llm ${out.llm.name || out.llm.reason}${
|
|
291
|
+
out.llm.ok
|
|
292
|
+
? out.llm.isLocal
|
|
293
|
+
? chalk.green(" [local]")
|
|
294
|
+
: chalk.yellow(" [remote]")
|
|
295
|
+
: ""
|
|
296
|
+
}`,
|
|
297
|
+
);
|
|
298
|
+
logger.log(`${mark(out.kgSink.ok)} kgSink`);
|
|
299
|
+
logger.log(`${mark(out.ragSink.ok)} ragSink`);
|
|
300
|
+
}
|
|
246
301
|
}
|
|
247
302
|
} catch (err) {
|
|
248
303
|
fail(null, err, options.json);
|
|
@@ -468,7 +523,11 @@ async function cmdRederive(options) {
|
|
|
468
523
|
|
|
469
524
|
async function cmdQueryEvents(options) {
|
|
470
525
|
try {
|
|
471
|
-
|
|
526
|
+
// Read-only vault query — needs no adapters / sinks / llm. Minimal hub
|
|
527
|
+
// skips the 77-adapter registry build (and is crash-resilient to a
|
|
528
|
+
// partial pdh install). getHubMinimal() returns the full hub if one was
|
|
529
|
+
// already built this process, so the vault instance is identical.
|
|
530
|
+
const hub = await getHubMinimal();
|
|
472
531
|
const q = {};
|
|
473
532
|
if (options.subtype) q.subtype = options.subtype;
|
|
474
533
|
if (options.since) q.since = Number(options.since);
|
|
@@ -528,7 +587,8 @@ function importEventsInto(vault, events) {
|
|
|
528
587
|
imported += 1;
|
|
529
588
|
} catch (e) {
|
|
530
589
|
failed += 1;
|
|
531
|
-
if (errors.length < 10)
|
|
590
|
+
if (errors.length < 10)
|
|
591
|
+
errors.push({ id: ev && ev.id, error: e.message });
|
|
532
592
|
}
|
|
533
593
|
}
|
|
534
594
|
return { ok: failed === 0, imported, failed, errors };
|
|
@@ -536,7 +596,8 @@ function importEventsInto(vault, events) {
|
|
|
536
596
|
|
|
537
597
|
async function cmdExportEvents(options) {
|
|
538
598
|
try {
|
|
539
|
-
|
|
599
|
+
// Vault-only raw-event export — no adapters needed, use the minimal hub.
|
|
600
|
+
const hub = await (options._getHub || getHubMinimal)();
|
|
540
601
|
const all = exportAllEvents(hub.vault);
|
|
541
602
|
if (options.output) {
|
|
542
603
|
require("fs").writeFileSync(options.output, JSON.stringify(all), "utf-8");
|
|
@@ -566,7 +627,8 @@ async function cmdImportEvents(options) {
|
|
|
566
627
|
if (!Array.isArray(events)) {
|
|
567
628
|
throw new Error("import-events: expected a JSON array of events");
|
|
568
629
|
}
|
|
569
|
-
|
|
630
|
+
// Vault-only idempotent upsert — no adapters needed, use the minimal hub.
|
|
631
|
+
const hub = await (options._getHub || getHubMinimal)();
|
|
570
632
|
const result = importEventsInto(hub.vault, events);
|
|
571
633
|
if (options.json) {
|
|
572
634
|
jsonAndExit(result);
|
|
@@ -585,7 +647,8 @@ async function cmdImportEvents(options) {
|
|
|
585
647
|
// (Android LocalCcRunner.searchEvents calls this; CI smoke too).
|
|
586
648
|
async function cmdSearchEvents(options) {
|
|
587
649
|
try {
|
|
588
|
-
|
|
650
|
+
// Read-only vault FTS search — vault-only, use the minimal hub.
|
|
651
|
+
const hub = await getHubMinimal();
|
|
589
652
|
const q = {};
|
|
590
653
|
if (options.q) q.q = String(options.q);
|
|
591
654
|
if (options.adapter) q.adapter = options.adapter;
|
|
@@ -628,7 +691,8 @@ async function cmdSearchEvents(options) {
|
|
|
628
691
|
|
|
629
692
|
async function cmdFacetCounts(options) {
|
|
630
693
|
try {
|
|
631
|
-
|
|
694
|
+
// Read-only vault facet aggregation — vault-only, use the minimal hub.
|
|
695
|
+
const hub = await getHubMinimal();
|
|
632
696
|
const q = {};
|
|
633
697
|
if (options.q) q.q = String(options.q);
|
|
634
698
|
if (options.since) q.since = Number(options.since);
|
|
@@ -657,7 +721,8 @@ async function cmdFacetCounts(options) {
|
|
|
657
721
|
|
|
658
722
|
async function cmdRecentAudit(options) {
|
|
659
723
|
try {
|
|
660
|
-
|
|
724
|
+
// Read-only vault audit log query — vault-only, use the minimal hub.
|
|
725
|
+
const hub = await getHubMinimal();
|
|
661
726
|
const q = {};
|
|
662
727
|
if (options.since) q.since = Number(options.since);
|
|
663
728
|
if (options.action) q.action = options.action;
|
|
@@ -722,7 +787,8 @@ async function cmdEventDetail(eventId, options) {
|
|
|
722
787
|
process.exit(1);
|
|
723
788
|
}
|
|
724
789
|
try {
|
|
725
|
-
|
|
790
|
+
// Read-only single-event lookup — vault-only, use the minimal hub.
|
|
791
|
+
const hub = await getHubMinimal();
|
|
726
792
|
const event = hub.vault.getEvent(eventId);
|
|
727
793
|
if (!event) {
|
|
728
794
|
const result = { found: false, eventId };
|
|
@@ -774,7 +840,8 @@ async function cmdExport(options) {
|
|
|
774
840
|
try {
|
|
775
841
|
const fs = await import("node:fs");
|
|
776
842
|
const path = await import("node:path");
|
|
777
|
-
|
|
843
|
+
// Vault-file snapshot copy — vault-only, use the minimal hub.
|
|
844
|
+
const hub = await getHubMinimal();
|
|
778
845
|
const src = hub.vault.path;
|
|
779
846
|
if (!src) throw new Error("vault path unavailable (hub not initialized?)");
|
|
780
847
|
|
|
@@ -2606,14 +2673,24 @@ export function registerHubCommand(program) {
|
|
|
2606
2673
|
|
|
2607
2674
|
hub
|
|
2608
2675
|
.command("stats")
|
|
2609
|
-
.description(
|
|
2676
|
+
.description(
|
|
2677
|
+
"Vault row counts + hub paths (use --full to also list adapters + LLM)",
|
|
2678
|
+
)
|
|
2610
2679
|
.option("--json", "Output JSON")
|
|
2680
|
+
.option(
|
|
2681
|
+
"--full",
|
|
2682
|
+
"Include registered adapter list + resolved LLM (loads the full hub)",
|
|
2683
|
+
)
|
|
2611
2684
|
.action(cmdStats);
|
|
2612
2685
|
|
|
2613
2686
|
hub
|
|
2614
2687
|
.command("health")
|
|
2615
2688
|
.description("Component health: vault / llm / kgSink / ragSink")
|
|
2616
2689
|
.option("--json", "Output JSON")
|
|
2690
|
+
.option(
|
|
2691
|
+
"--quick",
|
|
2692
|
+
"Vault-only probe via the minimal hub (skips llm/kgSink/ragSink wiring)",
|
|
2693
|
+
)
|
|
2617
2694
|
.action(cmdHealth);
|
|
2618
2695
|
|
|
2619
2696
|
hub
|
|
@@ -3175,6 +3252,8 @@ export function registerHubCommand(program) {
|
|
|
3175
3252
|
export const _internal = {
|
|
3176
3253
|
cmdAsk,
|
|
3177
3254
|
cmdRetrieveContext,
|
|
3255
|
+
cmdStats,
|
|
3256
|
+
cmdHealth,
|
|
3178
3257
|
parsePositiveInt,
|
|
3179
3258
|
cmdAIChatList,
|
|
3180
3259
|
cmdAIChatLogin,
|
|
@@ -30,9 +30,22 @@ import {
|
|
|
30
30
|
writeFileSync,
|
|
31
31
|
} from "node:fs";
|
|
32
32
|
import { join } from "node:path";
|
|
33
|
-
import
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
// Lazily import the pdh package the first time the system-data-android
|
|
34
|
+
// ingest topic is actually used. This module is pulled in by the
|
|
35
|
+
// agent/chat/serve/ui runtime chain at startup (ws-server →
|
|
36
|
+
// message-dispatcher → here), so a top-level static import would force the
|
|
37
|
+
// whole pdh graph to load on every `cc` invocation — and a partial/corrupt
|
|
38
|
+
// pdh install would brick unrelated commands. See the matching rationale in
|
|
39
|
+
// personal-data-hub-wiring.js.
|
|
40
|
+
let _ingestSnapshotFn = null;
|
|
41
|
+
async function ingestSystemDataAndroidSnapshot(hub, snapshot) {
|
|
42
|
+
if (!_ingestSnapshotFn) {
|
|
43
|
+
const pdhMod = await import("@chainlesschain/personal-data-hub");
|
|
44
|
+
const pdhPkg = pdhMod.default || pdhMod;
|
|
45
|
+
_ingestSnapshotFn = pdhPkg.ingestSystemDataAndroidSnapshot;
|
|
46
|
+
}
|
|
47
|
+
return _ingestSnapshotFn(hub, snapshot);
|
|
48
|
+
}
|
|
36
49
|
|
|
37
50
|
/**
|
|
38
51
|
* If the caller didn't pass `inputPath`, try to pull a snapshot for
|
|
@@ -29,11 +29,20 @@ import { mkdirSync } from "node:fs";
|
|
|
29
29
|
// Hub package is CJS; in ESM we default-import then destructure (Node 22
|
|
30
30
|
// won't let us name-import a CJS module unless it ships a separate ESM
|
|
31
31
|
// shim, which we don't).
|
|
32
|
-
import
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
// PDH is loaded LAZILY (not a top-level static import) so that merely
|
|
33
|
+
// importing this wiring module — which happens on EVERY `cc` invocation,
|
|
34
|
+
// because index.js statically pulls in commands/hub.js (getHub) AND the
|
|
35
|
+
// agent/chat/serve/ui runtime chain (ws pdh-protocol → this wiring) — does
|
|
36
|
+
// NOT eagerly evaluate the entire personal-data-hub adapter graph. Wins:
|
|
37
|
+
// • Robustness: a partial/corrupt pdh install (e.g. an interrupted
|
|
38
|
+
// `npm i -g` that left adapter files unwritten) no longer bricks
|
|
39
|
+
// unrelated commands like `cc -v` with a cryptic ERR_MODULE_NOT_FOUND.
|
|
40
|
+
// pdh only loads when a `cc hub …` / web-shell hub topic actually runs.
|
|
41
|
+
// • Startup cost: non-hub commands skip loading 50+ adapter modules.
|
|
42
|
+
// The bindings below are populated by ensurePdhLoaded(), which initHub() and
|
|
43
|
+
// initHubMinimal() await before touching any of them.
|
|
44
|
+
let bootstrapWechatAdapter, probeWeChatEnv;
|
|
45
|
+
let LocalVault,
|
|
37
46
|
AdapterRegistry,
|
|
38
47
|
AnalysisEngine,
|
|
39
48
|
MockAdapter,
|
|
@@ -124,8 +133,125 @@ const {
|
|
|
124
133
|
EntityResolverEmbeddingStage,
|
|
125
134
|
EntityResolverLLMStage,
|
|
126
135
|
runAnalysisSkill,
|
|
127
|
-
ANALYSIS_SKILL_NAMES
|
|
128
|
-
|
|
136
|
+
ANALYSIS_SKILL_NAMES;
|
|
137
|
+
|
|
138
|
+
let _pdhLoadPromise = null;
|
|
139
|
+
/**
|
|
140
|
+
* Lazily import the personal-data-hub package + wechat adapter and populate
|
|
141
|
+
* the module-level binding holders above. Memoized so concurrent
|
|
142
|
+
* getHub()/getHubMinimal() callers share one load. Must be awaited by any
|
|
143
|
+
* code path that uses a pdh binding (initHub / initHubMinimal).
|
|
144
|
+
*/
|
|
145
|
+
function ensurePdhLoaded() {
|
|
146
|
+
if (!_pdhLoadPromise) {
|
|
147
|
+
_pdhLoadPromise = (async () => {
|
|
148
|
+
const hubMod = await import("@chainlesschain/personal-data-hub");
|
|
149
|
+
const hub = hubMod.default || hubMod;
|
|
150
|
+
// Composed specifier dodges vite/vitest static import-analysis of
|
|
151
|
+
// subpath exports (same trick as loadAIChatHealthChecker below).
|
|
152
|
+
const wechatSpec =
|
|
153
|
+
"@chainlesschain/personal-data-hub" + "/adapters/wechat";
|
|
154
|
+
const waMod = await import(wechatSpec);
|
|
155
|
+
const wechatAdapterModule = waMod.default || waMod;
|
|
156
|
+
({ bootstrapWechatAdapter, probeWeChatEnv } = wechatAdapterModule);
|
|
157
|
+
({
|
|
158
|
+
LocalVault,
|
|
159
|
+
AdapterRegistry,
|
|
160
|
+
AnalysisEngine,
|
|
161
|
+
MockAdapter,
|
|
162
|
+
OllamaClient,
|
|
163
|
+
CcKgSink,
|
|
164
|
+
CcRagSink,
|
|
165
|
+
FileKeyProvider,
|
|
166
|
+
generateKeyHex,
|
|
167
|
+
EmailAdapter,
|
|
168
|
+
AlipayBillAdapter,
|
|
169
|
+
SystemDataAndroidAdapter,
|
|
170
|
+
BrowserHistoryChromeAdapter,
|
|
171
|
+
BrowserHistoryEdgeAdapter,
|
|
172
|
+
VSCodeAdapter,
|
|
173
|
+
WinRecentAdapter,
|
|
174
|
+
GitActivityAdapter,
|
|
175
|
+
ShellHistoryAdapter,
|
|
176
|
+
LocalFilesAdapter,
|
|
177
|
+
BilibiliAdapter,
|
|
178
|
+
WeiboAdapter,
|
|
179
|
+
ZhihuAdapter,
|
|
180
|
+
DoubanAdapter,
|
|
181
|
+
BossZhipinAdapter,
|
|
182
|
+
CsdnAdapter,
|
|
183
|
+
DongchediAdapter,
|
|
184
|
+
TianyanchaAdapter,
|
|
185
|
+
DouyinAdapter,
|
|
186
|
+
XiaohongshuAdapter,
|
|
187
|
+
ToutiaoAdapter,
|
|
188
|
+
KuaishouAdapter,
|
|
189
|
+
GenshinAdapter,
|
|
190
|
+
HonorOfKingsAdapter,
|
|
191
|
+
ZuoyebangAdapter,
|
|
192
|
+
AlipayAdapter,
|
|
193
|
+
HuaweiLearningAdapter,
|
|
194
|
+
QQAdapter,
|
|
195
|
+
WeChatPcAdapter,
|
|
196
|
+
QQPcAdapter,
|
|
197
|
+
AppleHealthAdapter,
|
|
198
|
+
NeteaseMusicAdapter,
|
|
199
|
+
KugouMusicAdapter,
|
|
200
|
+
QQMusicAdapter,
|
|
201
|
+
XimalayaAdapter,
|
|
202
|
+
FanqieReadingAdapter,
|
|
203
|
+
QimaoReadingAdapter,
|
|
204
|
+
JoyrunAdapter,
|
|
205
|
+
KeepAdapter,
|
|
206
|
+
DidiConsumerAdapter,
|
|
207
|
+
MercedesMeAdapter,
|
|
208
|
+
IqiyiVideoAdapter,
|
|
209
|
+
TencentVideoAdapter,
|
|
210
|
+
XiguaVideoAdapter,
|
|
211
|
+
WeReadAdapter,
|
|
212
|
+
WpsDocAdapter,
|
|
213
|
+
TencentDocsAdapter,
|
|
214
|
+
BaiduNetdiskAdapter,
|
|
215
|
+
CamScannerDocAdapter,
|
|
216
|
+
IXiamenAdapter,
|
|
217
|
+
MeiyouAdapter,
|
|
218
|
+
TaxAdapter,
|
|
219
|
+
CmbcBankAdapter,
|
|
220
|
+
BocBankAdapter,
|
|
221
|
+
BankcommBankAdapter,
|
|
222
|
+
IcbcBankAdapter,
|
|
223
|
+
DcepAdapter,
|
|
224
|
+
Tmri12123Adapter,
|
|
225
|
+
DingTalkPcAdapter,
|
|
226
|
+
FeishuPcAdapter,
|
|
227
|
+
WeWorkPcAdapter,
|
|
228
|
+
BaiduMapAdapter,
|
|
229
|
+
TencentMapAdapter,
|
|
230
|
+
JdAdapter,
|
|
231
|
+
MeituanAdapter,
|
|
232
|
+
ElemeAdapter,
|
|
233
|
+
PinduoduoAdapter,
|
|
234
|
+
DianpingAdapter,
|
|
235
|
+
XianyuAdapter,
|
|
236
|
+
VipshopAdapter,
|
|
237
|
+
Train12306Adapter,
|
|
238
|
+
TaobaoAdapter,
|
|
239
|
+
CtripAdapter,
|
|
240
|
+
TongchengAdapter,
|
|
241
|
+
DidiAdapter,
|
|
242
|
+
AmapAdapter,
|
|
243
|
+
TelegramAdapter,
|
|
244
|
+
WhatsAppAdapter,
|
|
245
|
+
EntityResolver,
|
|
246
|
+
EntityResolverEmbeddingStage,
|
|
247
|
+
EntityResolverLLMStage,
|
|
248
|
+
runAnalysisSkill,
|
|
249
|
+
ANALYSIS_SKILL_NAMES,
|
|
250
|
+
} = hub);
|
|
251
|
+
})();
|
|
252
|
+
}
|
|
253
|
+
return _pdhLoadPromise;
|
|
254
|
+
}
|
|
129
255
|
import {
|
|
130
256
|
readFileSync,
|
|
131
257
|
writeFileSync,
|
|
@@ -209,6 +335,7 @@ export function resolveHubDir() {
|
|
|
209
335
|
}
|
|
210
336
|
|
|
211
337
|
async function initHub() {
|
|
338
|
+
await ensurePdhLoaded();
|
|
212
339
|
// Phase 1c: hoisted so the hub-level `bilibiliAdbSync` method can reuse
|
|
213
340
|
// the same bridge instance the system-data-android adapter wires below.
|
|
214
341
|
// Single bridge per hub keeps `bilibili.cookies` extension state /
|
|
@@ -1490,6 +1617,7 @@ let _hubMinimal = null;
|
|
|
1490
1617
|
let _hubMinimalInitPromise = null;
|
|
1491
1618
|
|
|
1492
1619
|
async function initHubMinimal() {
|
|
1620
|
+
await ensurePdhLoaded();
|
|
1493
1621
|
const hubDir = resolveHubDir();
|
|
1494
1622
|
mkdirSync(hubDir, { recursive: true });
|
|
1495
1623
|
mkdirSync(join(hubDir, "keys"), { recursive: true });
|