chainlesschain 0.162.106 → 0.162.108
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 +1 -1
- package/src/assets/web-panel/assets/{AIOps-Dv4GUrHi.js → AIOps-B8T7xeuV.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C11GYZaf.js → ActionButton-BDxBsVYw.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CAqU4i6d.js → Analytics-5cYrjLzN.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B6iRYx37.js → AppLayout-DkanJ7a5.js} +4 -4
- package/src/assets/web-panel/assets/{Audit-Da0ixyIA.js → Audit-8r3yG5R0.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-YnfhBosV.js → Backup-DmdJpAwc.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BuIUclOL.js → BaseInput-CCTC_ROJ.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-ssBAsMhu.js → Chat-BE4xBoCH.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-C5PQbIce.js → ChatBubbleRenderer-ita18CO8.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-BbWH0SgQ.js → Checkbox-DVUDDyL5.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Dq0LbS-8.js → Codegen-C07Q688Z.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CZ8DawUj.js → Col-Bfmb67bb.js} +1 -1
- package/src/assets/web-panel/assets/{Community-C-4RVVBn.js → Community-DvUS6LOy.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BzAr-qm-.js → Compact-B2jvuCf2.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-D8wHCcwg.js → Compliance-B4VnGZOX.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-B3QMCVBt.js → Cowork-Bf1UR9uf.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-4w6DhJyQ.js → Cron-BYU0OhXx.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Ctlzq9uc.js → Crosschain-DhtbpJ8Y.js} +1 -1
- package/src/assets/web-panel/assets/{DID-FdDbrHQA.js → DID-DFtdsXjV.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DQSb46zq.js → Dashboard-BOqMlucS.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CT4M3kjL.js → Dropdown-DWcGi1lU.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BtTH_9Bp.js → EmailListRenderer-smcpeq18.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-D31xtzUB.js → FamilyGuardDashboard-_qKQM8YZ.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BNfmfO2p.js → Federation-DxaaO_Pn.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C3kmm4nv.js → FormItemContext-Bijk4-hV.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BW1P7ZdH.js → GenericCardRenderer-CXs5JGAs.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DcSEl0Ah.js → Git-vopq_XAi.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Cb8D9qqe.js → Governance-D6lEr1e2.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DTpGkMXl.js → Inference-D716knRp.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-wQuzZA4b.js → KnowledgeGraph-Mt7L5B8p.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C3S78_e6.js → Logs-BmY4Aozy.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-D0utQC7f.js → Marketplace-Bk7yghOV.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CEZolkxe.js → McpTools-BdEGNK8B.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-DkBzSUv5.js → Memory-DaGxWezP.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Dz-Bg3K9.js → MobileBridge-D2QqiIXV.js} +2 -2
- package/src/assets/web-panel/assets/{MobileProjects-YMh4rmVJ.js → MobileProjects-JQQ60jth.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-DQyn5PRr.js → Mtc-DHp0q17f.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-DY1t-cQ3.js → MtcAudit-RWrCriuc.js} +6 -6
- package/src/assets/web-panel/assets/{Multisig-DdzGB5qb.js → Multisig-BR_5j51g.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D5Jrv_7S.js → NLProgramming-MF3ZkPYq.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Wxg8M_jp.js → Notes-BDWwfQ-t.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BOLm3krj.js → NotificationSettings-Xk8BtRL5.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DXgWKvKG.js → OrderTableRenderer-DaVlfAsv.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DpH01k8R.js → Organization-CNdU6Jxx.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Cy2EGsg8.js → Overflow-DOf8iK6T.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BF606jDo.js → P2P-DvOwefeB.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DPmsKIL7.js → PdhVaultBrowser-BmrU5B5U.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-B5SjhtW_.js → Permissions-DM_Cha_-.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CjSBOSps.js → PersonalDataHub-DGOiN1md.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-CLKKF03d.js → Pipeline-BMZcrOpC.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BD9kj_AO.js → Privacy-CcBD3ZJ_.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-1wPQe32f.js → ProjectInit-BQmkVkFp.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-ae1Zvm29.js → ProjectSettings-BL0iqE5h.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-D9mVKxrM.js → Projects-7iyoLF6T.js} +1 -1
- package/src/assets/web-panel/assets/Providers-IQqLZ_11.js +1 -0
- package/src/assets/web-panel/assets/{QuickAsk-Cd5DPpgw.js → QuickAsk-Cp0Lpic1.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BYhtuWo3.js → Recommend-DN-26aef.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-ComyY4bA.js → Reputation-ChdhhVGu.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Dut8pwo9.js → Row-2RBgBLEz.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-xMhor0Fn.js → RssFeed-CfogWRiS.js} +3 -3
- package/src/assets/web-panel/assets/Search-CrREUZpz.js +1 -0
- package/src/assets/web-panel/assets/{Security-KeHoIe_R.js → Security-CcDdV-6d.js} +4 -4
- package/src/assets/web-panel/assets/{Services-C7smnFpg.js → Services-qG5L2PHE.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-PTR3fGUI.js → Skeleton-7CVgHJwr.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DHa51QLm.js → Skills-BEbdNS7s.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BS6ktlUr.js → Sla-C4ENvrVM.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-bfol0gns.js → SpeechSettings-DuvM2AsQ.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-6jRuuFeW.js → SyncSettings-Bm9Np5Yt.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CnC1__IG.js → Tasks-K2ZtJ47C.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DpCAWZlL.js → Templates-C3GJa4ya.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-D3LAKar5.js → Tenant-BLQnLb8K.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DErDY8_S.js → Terminal-BGgZIwb0.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-DlzM7nlo.js → TimelineRenderer-BD8NwNAK.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DNNr3xhM.js → Tokens-BIsO2iiX.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-CHcYxpwE.js → Trigger-FJv5zeym.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-3AYExgaT.js → Trust-9FRFEAhW.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-ZQ_TDiO7.js → UkeySign-aOdZVwgi.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Czq0TJsH.js → VideoEditing-C1KyY7ZB.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DUktui_z.js → Wallet-CH5edY0l.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-fmISWw5b.js → WebAuthn-BUPlkFe0.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-C_CaijGN.js → WorkflowEditor-BoH8bG7y.js} +1 -1
- package/src/assets/web-panel/assets/{chat-MEgPH75-.js → chat-DRS34SZq.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DDL36J3G.js → colors-DxdhROQh.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BkJXaF65.js → compact-item-C5f4y3lM.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DlB8u_7c.js → createContext-DkyzEt2y.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-vwZx8E0a.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Bg2nafvH.js → hasIn-CIRkRQ69.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7C9LYKH.js → index-1Vd3bgPH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKpVxinm.js → index-2uQYIxL1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DI5UpGuc.js → index-5Mph6K8H.js} +1 -1
- package/src/assets/web-panel/assets/{index-UPBfu9WY.js → index-B5r9kCHD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BF_sEVw4.js → index-BHACYX-h.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHSFsKwc.js → index-BLLkL7YU.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bu-Dg9gm.js → index-BStiYEJX.js} +1 -1
- package/src/assets/web-panel/assets/{index--PGD56d7.js → index-B_ytTrAE.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dl2INE9h.js → index-Bc59VV8o.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cl3aP187.js → index-BdzFfdXs.js} +1 -1
- package/src/assets/web-panel/assets/{index-nBzHyZw4.js → index-BfZal2SO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPBU8am-.js → index-BrNCtBLG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbcZ6gjd.js → index-Bskk24yp.js} +1 -1
- package/src/assets/web-panel/assets/{index-3HYiKj6K.js → index-BzC5O6l6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CroGv8Er.js → index-C0VYKzdU.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2N4eCU-.js → index-CLjIL9vZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfTKct1S.js → index-CO4PAGWX.js} +1 -1
- package/src/assets/web-panel/assets/{index-4ysKKyCt.js → index-CSHsX3UZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW6WKVTN.js → index-CXE4fjlC.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9Nf7l-4.js → index-Cv9YEv3M.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCV5a_eZ.js → index-CyMVWOwq.js} +1 -1
- package/src/assets/web-panel/assets/{index-E9fKdmZS.js → index-D3WhDg1s.js} +3 -3
- package/src/assets/web-panel/assets/{index-C5qRqnra.js → index-DR_uUG6x.js} +1 -1
- package/src/assets/web-panel/assets/{index-COiErcgq.js → index-DSpV3T2E.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW_thoFO.js → index-DV5W06OY.js} +1 -1
- package/src/assets/web-panel/assets/{index-rc1sOE1s.js → index-DdLAPzIl.js} +1 -1
- package/src/assets/web-panel/assets/{index-BF8tpZiI.js → index-DgJf60U0.js} +1 -1
- package/src/assets/web-panel/assets/index-Dhn6EWMQ.js +1 -0
- package/src/assets/web-panel/assets/{index-DzslfpyE.js → index-DnAbauX-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DxJe_2Ra.js → index-DpHZisZn.js} +1 -1
- package/src/assets/web-panel/assets/{index-K_8c8jDD.js → index-DtOM1jbe.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHHhMoP4.js → index-Dz-Xl9WT.js} +1 -1
- package/src/assets/web-panel/assets/{index-HwM0KYuJ.js → index-Kyd48UEO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dm36uPhy.js → index-X7QcpsDO.js} +1 -1
- package/src/assets/web-panel/assets/{index-JJaXdXuF.js → index-btOwnCpT.js} +1 -1
- package/src/assets/web-panel/assets/index-dGvDljur.js +1 -0
- package/src/assets/web-panel/assets/{index-BQcBGn2e.js → index-dtUUXiuv.js} +1 -1
- package/src/assets/web-panel/assets/{index-B23ECixr.js → index-fgBegFCK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEhi2NON.js → index-wdXKonKr.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DF4WRyT3.js → initDefaultProps-4uTrrqjb.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DYt7yuUl.js → motion-gkRvxGHW.js} +1 -1
- package/src/assets/web-panel/assets/{move-A2vu17_O.js → move-CIgnaWNe.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BE4gHEDC.js → omit-DB-Ux8Gg.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DZPGMH7O.js → pickAttrs-ree-Itb0.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-C314MZpn.js → placementArrow-EdAP6bCf.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BnImSTAx.js → responsiveObserve-B1DqSgFh.js} +1 -1
- package/src/assets/web-panel/assets/{slide-lhFfg292.js → slide-D_9NP_KE.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-NMoQTkOw.js → statusUtils-CAytzvoR.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-tp7AHEoi.js → styleChecker-zb3gob1_.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CPCXJDFA.js → useFlexGapSupport-BQWuGrL0.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CCZ-ENkG.js → useFs-QMEsYkGX.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-SYhI2gMH.js → usePersonalDataHub-Ccrz7-au.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CwS9FORj.js → vnode-DZVY4QM-.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Dx1C3oM8.js → zoom-Dii_0V_X.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/__tests__/hub-query-events.test.js +134 -0
- package/src/commands/hub.js +33 -8
- package/src/commands/pdh.js +188 -1
- package/src/lib/pdh-egress.js +210 -0
- package/src/lib/repl-completer.js +48 -9
- package/src/repl/agent-repl.js +12 -0
- package/src/runtime/diagnostics.js +48 -0
- package/src/runtime/headless-stream.js +37 -1
- package/src/assets/web-panel/assets/Providers-Bz6n7iqv.js +0 -1
- package/src/assets/web-panel/assets/Search-D4_Od-8S.js +0 -1
- package/src/assets/web-panel/assets/devWarning-7FEuHryT.js +0 -1
- package/src/assets/web-panel/assets/index-1EaBTuZ5.js +0 -1
- package/src/assets/web-panel/assets/index-DkuCcuSQ.js +0 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDH egress classification (design module 101 §3.5.18 — 出境台账 / "what left
|
|
3
|
+
* the device").
|
|
4
|
+
*
|
|
5
|
+
* The personal-data chat's single source of truth for egress is the Android,
|
|
6
|
+
* on-device, *encrypted* TransparencyLedger (§3.5.18, line 962). But the cc
|
|
7
|
+
* agent makes the actual cloud-LLM call — where conversation context that may
|
|
8
|
+
* contain personal data is sent to a cloud provider — entirely inside the cc
|
|
9
|
+
* subprocess, invisible to the Android app (the emitted token_usage carries no
|
|
10
|
+
* provider). Egress-classed tools (send / export / cross-device sync /
|
|
11
|
+
* remote-API fetch) likewise run inside cc.
|
|
12
|
+
*
|
|
13
|
+
* This module classifies cc-side egress so headless-stream.js can EMIT a
|
|
14
|
+
* structured `egress` stream-json event the Android ledger records. cc only
|
|
15
|
+
* REPORTS egress (emit-only); it never writes its own ledger file, so the
|
|
16
|
+
* ledger stays the single on-device encrypted store the design mandates.
|
|
17
|
+
*
|
|
18
|
+
* Honest-by-default (§3.5.18 line 963 "不隐藏任何出境" — never hide an egress):
|
|
19
|
+
* an unknown, non-empty provider is treated as cloud, i.e. we over-report
|
|
20
|
+
* rather than under-report. A local/on-device turn reports nothing — the
|
|
21
|
+
* truthful "0 条出境".
|
|
22
|
+
*
|
|
23
|
+
* Pure CLI, no Android dependency, fully unit-testable.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { BUILT_IN_PROVIDERS } from "./llm-providers.js";
|
|
27
|
+
|
|
28
|
+
// Providers that run on the device (or the user's own LAN box) and so never
|
|
29
|
+
// send conversation context off the device.
|
|
30
|
+
const LOCAL_PROVIDERS = new Set([
|
|
31
|
+
"ollama",
|
|
32
|
+
"llamacpp",
|
|
33
|
+
"llama-cpp",
|
|
34
|
+
"llama.cpp",
|
|
35
|
+
"mediapipe",
|
|
36
|
+
"on-device",
|
|
37
|
+
"ondevice",
|
|
38
|
+
"local",
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
// Known cloud APIs, derived from the provider registry (single source of truth)
|
|
42
|
+
// — ollama is `free:true` (local); every other built-in is a cloud endpoint.
|
|
43
|
+
// For these the provider NAME is authoritative: classify as cloud regardless of
|
|
44
|
+
// a possibly-default/stale baseUrl. New providers added to the registry are
|
|
45
|
+
// picked up automatically.
|
|
46
|
+
const CLOUD_PROVIDERS = new Set(
|
|
47
|
+
Object.values(BUILT_IN_PROVIDERS)
|
|
48
|
+
.filter((d) => d && d.free !== true && d.name)
|
|
49
|
+
.map((d) => String(d.name).toLowerCase()),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
/** True when a baseUrl points at the local device or the user's own LAN. */
|
|
53
|
+
function isLocalBaseUrl(baseUrl) {
|
|
54
|
+
const u = String(baseUrl || "").toLowerCase();
|
|
55
|
+
if (!u) return false;
|
|
56
|
+
if (
|
|
57
|
+
u.includes("localhost") ||
|
|
58
|
+
u.includes("127.0.0.1") ||
|
|
59
|
+
u.includes("0.0.0.0") ||
|
|
60
|
+
u.includes("[::1]") ||
|
|
61
|
+
u.includes("//::1")
|
|
62
|
+
) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
// Private LAN ranges (RFC 1918): the user's own box, not a cloud egress.
|
|
66
|
+
return /\/\/(?:10\.|192\.168\.|172\.(?:1[6-9]|2\d|3[01])\.)/.test(u);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A provider is "local" (no egress) when it is a known on-device engine, or
|
|
71
|
+
* (for an unknown/custom provider) its baseUrl resolves to the device / the
|
|
72
|
+
* user's own LAN. A known cloud provider is never local even if it is called
|
|
73
|
+
* with a default/stale localhost baseUrl — the provider name wins.
|
|
74
|
+
*/
|
|
75
|
+
export function isLocalProvider(provider, baseUrl) {
|
|
76
|
+
const p = String(provider || "")
|
|
77
|
+
.toLowerCase()
|
|
78
|
+
.trim();
|
|
79
|
+
if (p && LOCAL_PROVIDERS.has(p)) return true;
|
|
80
|
+
if (p && CLOUD_PROVIDERS.has(p)) return false;
|
|
81
|
+
// Unknown/custom provider — decide by where its baseUrl points.
|
|
82
|
+
return isLocalBaseUrl(baseUrl);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Cloud = a turn whose conversation context leaves the device. An empty
|
|
87
|
+
* provider means no LLM ran (not cloud); an unknown non-empty provider is
|
|
88
|
+
* treated as cloud so an egress is never silently hidden.
|
|
89
|
+
*/
|
|
90
|
+
export function isCloudProvider(provider, baseUrl) {
|
|
91
|
+
if (!provider) return false;
|
|
92
|
+
return !isLocalProvider(provider, baseUrl);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Classify a tool call as a data-egress channel, or null when it stays on the
|
|
97
|
+
* device. Tool names may carry an MCP prefix (mcp__pdh__collect_app_data) or be
|
|
98
|
+
* bare (send_message); we match on the bare suffix.
|
|
99
|
+
*
|
|
100
|
+
* @returns {"message"|"export"|"cross_device"|"web"|"remote_api"|null}
|
|
101
|
+
*/
|
|
102
|
+
export function classifyEgressTool(toolName) {
|
|
103
|
+
const raw = String(toolName || "")
|
|
104
|
+
.toLowerCase()
|
|
105
|
+
.trim();
|
|
106
|
+
if (!raw) return null;
|
|
107
|
+
// Strip an MCP server prefix: mcp__<server>__<tool> → <tool>.
|
|
108
|
+
const bare = raw.includes("__") ? raw.slice(raw.lastIndexOf("__") + 2) : raw;
|
|
109
|
+
|
|
110
|
+
// Sending data OUT to another party.
|
|
111
|
+
if (bare === "send_message" || bare.startsWith("send_")) return "message";
|
|
112
|
+
// Exporting data off the device.
|
|
113
|
+
if (bare.includes("export")) return "export";
|
|
114
|
+
// Cross-device sync / backup — leaves THIS device for another.
|
|
115
|
+
if (
|
|
116
|
+
bare.includes("cross_device") ||
|
|
117
|
+
bare.includes("backup") ||
|
|
118
|
+
bare.startsWith("sync_to") ||
|
|
119
|
+
bare.includes("transfer")
|
|
120
|
+
) {
|
|
121
|
+
return "cross_device";
|
|
122
|
+
}
|
|
123
|
+
// Generic web egress.
|
|
124
|
+
if (bare === "web_search" || bare === "web_fetch" || bare === "fetch") {
|
|
125
|
+
return "web";
|
|
126
|
+
}
|
|
127
|
+
// The PDH cookie-API tools transmit the user's auth cookie + query to a
|
|
128
|
+
// remote 3rd-party API (to fetch the user's own data back). The cookie + the
|
|
129
|
+
// query leave the device, so this IS an egress channel — honest disclosure.
|
|
130
|
+
// The root / snapshot / salvage / system / files variants are purely on-device
|
|
131
|
+
// reads and therefore fall through to null.
|
|
132
|
+
if (bare === "collect_app_data" || bare === "query_app_data") {
|
|
133
|
+
return "remote_api";
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Build the `egress` stream-json event the Android ledger records.
|
|
140
|
+
* kind: "cloud_llm" | "tool"
|
|
141
|
+
* channel: provider name (cloud_llm) | egress channel (tool)
|
|
142
|
+
*/
|
|
143
|
+
export function buildEgressEvent(fields = {}) {
|
|
144
|
+
const ev = { type: "egress", kind: fields.kind, channel: fields.channel };
|
|
145
|
+
if (fields.provider) ev.provider = fields.provider;
|
|
146
|
+
if (fields.model) ev.model = fields.model;
|
|
147
|
+
if (fields.tool) ev.tool = fields.tool;
|
|
148
|
+
if (fields.sessionId) ev.session_id = fields.sessionId;
|
|
149
|
+
if (fields.turn != null) ev.turn = fields.turn;
|
|
150
|
+
if (fields.tokens != null) ev.tokens = fields.tokens;
|
|
151
|
+
return ev;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Compute the egress events for one completed turn (cloud-LLM call + any
|
|
156
|
+
* egress-classed tools). Pure over its inputs; the caller decides whether to
|
|
157
|
+
* emit (PDH-gated). Returns [] when nothing left the device — the honest
|
|
158
|
+
* "0 条出境" case (a fully local turn with only on-device tools).
|
|
159
|
+
*
|
|
160
|
+
* @param {object} p
|
|
161
|
+
* @param {string} p.provider effective provider used for this turn
|
|
162
|
+
* @param {string} [p.baseUrl] effective baseUrl (localhost/LAN → not cloud)
|
|
163
|
+
* @param {string} [p.model] effective model
|
|
164
|
+
* @param {Array<{tool:string}>} [p.toolCalls] tools executed this turn
|
|
165
|
+
* @param {object} [p.usage] { input_tokens, output_tokens } magnitude proxy
|
|
166
|
+
* @param {string} [p.sessionId]
|
|
167
|
+
* @param {number} [p.turn]
|
|
168
|
+
* @returns {Array<object>} egress events (possibly empty)
|
|
169
|
+
*/
|
|
170
|
+
export function turnEgressEvents({
|
|
171
|
+
provider,
|
|
172
|
+
baseUrl,
|
|
173
|
+
model,
|
|
174
|
+
toolCalls = [],
|
|
175
|
+
usage = null,
|
|
176
|
+
sessionId = null,
|
|
177
|
+
turn = null,
|
|
178
|
+
} = {}) {
|
|
179
|
+
const events = [];
|
|
180
|
+
if (isCloudProvider(provider, baseUrl)) {
|
|
181
|
+
events.push(
|
|
182
|
+
buildEgressEvent({
|
|
183
|
+
kind: "cloud_llm",
|
|
184
|
+
channel: provider,
|
|
185
|
+
provider,
|
|
186
|
+
model,
|
|
187
|
+
sessionId,
|
|
188
|
+
turn,
|
|
189
|
+
tokens: usage
|
|
190
|
+
? (usage.input_tokens || 0) + (usage.output_tokens || 0)
|
|
191
|
+
: null,
|
|
192
|
+
}),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
for (const call of Array.isArray(toolCalls) ? toolCalls : []) {
|
|
196
|
+
const channel = classifyEgressTool(call?.tool);
|
|
197
|
+
if (channel) {
|
|
198
|
+
events.push(
|
|
199
|
+
buildEgressEvent({
|
|
200
|
+
kind: "tool",
|
|
201
|
+
channel,
|
|
202
|
+
tool: call.tool,
|
|
203
|
+
sessionId,
|
|
204
|
+
turn,
|
|
205
|
+
}),
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return events;
|
|
210
|
+
}
|
|
@@ -136,23 +136,62 @@ export function makeAtCompleter(opts = {}) {
|
|
|
136
136
|
? [...new Set(opts.slashCommands)].sort()
|
|
137
137
|
: [];
|
|
138
138
|
|
|
139
|
+
// User/project custom slash commands (.claude/commands/*.md → `/git:commit`),
|
|
140
|
+
// surfaced in TAB completion the same as built-ins (Claude-Code parity — its
|
|
141
|
+
// slash autocomplete includes user-authored commands too). Pulled from an
|
|
142
|
+
// injected SYNC source so newly authored command files become completable
|
|
143
|
+
// without a restart and `/cd` follows whichever project's commands apply.
|
|
144
|
+
// Cached with the same short TTL as the IDE source so a burst of TABs never
|
|
145
|
+
// re-walks the filesystem.
|
|
146
|
+
const getDynamic =
|
|
147
|
+
typeof opts.getDynamicSlashCommands === "function"
|
|
148
|
+
? opts.getDynamicSlashCommands
|
|
149
|
+
: null;
|
|
150
|
+
let dynCache = [];
|
|
151
|
+
let dynFetchedAt = -Infinity;
|
|
152
|
+
const dynamicSlashCommands = () => {
|
|
153
|
+
if (!getDynamic) return [];
|
|
154
|
+
if (now() - dynFetchedAt < IDE_CACHE_TTL_MS) return dynCache;
|
|
155
|
+
try {
|
|
156
|
+
const list = getDynamic();
|
|
157
|
+
dynCache = Array.isArray(list)
|
|
158
|
+
? list.filter((c) => typeof c === "string" && c)
|
|
159
|
+
: [];
|
|
160
|
+
} catch {
|
|
161
|
+
dynCache = []; // a broken command source never breaks completion
|
|
162
|
+
}
|
|
163
|
+
dynFetchedAt = now();
|
|
164
|
+
return dynCache;
|
|
165
|
+
};
|
|
166
|
+
const mergedSlashCommands = () => {
|
|
167
|
+
const dyn = dynamicSlashCommands();
|
|
168
|
+
if (!dyn.length) return slashCommands; // common case: built-ins only
|
|
169
|
+
return [...new Set([...slashCommands, ...dyn])].sort();
|
|
170
|
+
};
|
|
171
|
+
|
|
139
172
|
const completer = (line) => {
|
|
140
173
|
// `/command` completion (Claude-Code parity): only while typing the
|
|
141
|
-
// command token itself — once a space follows, args are the user's.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
)
|
|
148
|
-
|
|
174
|
+
// command token itself — once a space follows, args are the user's. The
|
|
175
|
+
// token charset includes `:` / `.` / digits so namespaced custom commands
|
|
176
|
+
// (`/git:commit` from commands/git/commit.md) complete too.
|
|
177
|
+
const slash = /^\/([A-Za-z0-9:._-]*)$/.exec(line);
|
|
178
|
+
if (slash) {
|
|
179
|
+
const all = mergedSlashCommands();
|
|
180
|
+
if (all.length) {
|
|
181
|
+
const pref = `/${slash[1].toLowerCase()}`;
|
|
182
|
+
const hits = all.filter((c) => c.toLowerCase().startsWith(pref));
|
|
183
|
+
return [hits, line];
|
|
184
|
+
}
|
|
149
185
|
}
|
|
150
186
|
const at = extractAtPrefix(line);
|
|
151
187
|
if (!at) return [[], line];
|
|
152
188
|
refreshIde(); // async top-up for the NEXT tab; this one uses the cache
|
|
153
189
|
const norm = fwd(at.prefix).toLowerCase();
|
|
154
190
|
const fromIde = ideFiles.filter((f) => f.toLowerCase().startsWith(norm));
|
|
155
|
-
const fromFs = fileCandidates(at.prefix, {
|
|
191
|
+
const fromFs = fileCandidates(at.prefix, {
|
|
192
|
+
cwd: getCwd(),
|
|
193
|
+
deps: opts.deps,
|
|
194
|
+
});
|
|
156
195
|
const merged = [...new Set([...fromIde, ...fromFs])].slice(
|
|
157
196
|
0,
|
|
158
197
|
MAX_CANDIDATES,
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -894,6 +894,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
894
894
|
// `@` tab-completion (Claude-Code @-mention parity): filesystem paths +
|
|
895
895
|
// (when the IDE bridge is connected) the editor's open tabs ranked first.
|
|
896
896
|
const { makeAtCompleter } = await import("../lib/repl-completer.js");
|
|
897
|
+
const { discoverCommands } = await import("../lib/slash-commands.js");
|
|
897
898
|
const atCompleter = makeAtCompleter({
|
|
898
899
|
// cwd left unset on purpose: the completer resolves process.cwd() lazily
|
|
899
900
|
// so it follows `/cd` mid-session.
|
|
@@ -941,6 +942,17 @@ export async function startAgentRepl(options = {}) {
|
|
|
941
942
|
"/ultrathink",
|
|
942
943
|
"/vim",
|
|
943
944
|
],
|
|
945
|
+
// User/project custom commands (.claude/commands/*.md) join TAB completion
|
|
946
|
+
// alongside the built-ins above. Sync + best-effort; the completer
|
|
947
|
+
// TTL-caches the result so this filesystem walk runs at most once per few
|
|
948
|
+
// seconds, and process.cwd() makes it follow `/cd` mid-session.
|
|
949
|
+
getDynamicSlashCommands: () => {
|
|
950
|
+
try {
|
|
951
|
+
return discoverCommands(process.cwd()).map((cmd) => `/${cmd.name}`);
|
|
952
|
+
} catch {
|
|
953
|
+
return [];
|
|
954
|
+
}
|
|
955
|
+
},
|
|
944
956
|
getIdeOpenFiles: async () => {
|
|
945
957
|
const exec = _adhocMcp?.externalToolExecutors?.mcp__ide__getOpenEditors;
|
|
946
958
|
if (!exec || exec.kind !== "mcp" || !_adhocMcp?.mcpClient?.callTool) {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { execSync } from "node:child_process";
|
|
16
16
|
import { existsSync, readdirSync } from "node:fs";
|
|
17
|
+
import { createRequire } from "node:module";
|
|
17
18
|
import { createConnection } from "node:net";
|
|
18
19
|
import semver from "semver";
|
|
19
20
|
|
|
@@ -62,6 +63,41 @@ function safeExec(cmd) {
|
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Verify the personal-data-hub package (lazily loaded by every `cc hub …`
|
|
68
|
+
* command) is fully present on disk.
|
|
69
|
+
*
|
|
70
|
+
* A partial global install — most commonly an interrupted `npm i -g
|
|
71
|
+
* chainlesschain` whose extraction was blocked by a running `cc` process
|
|
72
|
+
* locking a native file (EBUSY) — leaves pdh files unwritten. The hub
|
|
73
|
+
* commands then fail at runtime with a raw ERR_MODULE_NOT_FOUND. Because pdh
|
|
74
|
+
* is lazy-loaded, `cc doctor` itself still starts and can surface this
|
|
75
|
+
* proactively with a one-line repair hint instead of leaving the user to
|
|
76
|
+
* decode a stack trace.
|
|
77
|
+
*
|
|
78
|
+
* Probes the two exported entry points (main + the wechat adapter); CJS
|
|
79
|
+
* require.resolve verifies the target file exists, so a missing file throws.
|
|
80
|
+
* Deps are injectable for unit tests.
|
|
81
|
+
*/
|
|
82
|
+
export function checkPdhPackageIntegrity(deps = {}) {
|
|
83
|
+
const resolve =
|
|
84
|
+
deps.resolve || ((spec) => createRequire(import.meta.url).resolve(spec));
|
|
85
|
+
const exists = deps.existsSync || existsSync;
|
|
86
|
+
const repair = "Repair: npm i -g chainlesschain@latest";
|
|
87
|
+
const probes = [
|
|
88
|
+
"@chainlesschain/personal-data-hub",
|
|
89
|
+
"@chainlesschain/personal-data-hub/adapters/wechat",
|
|
90
|
+
];
|
|
91
|
+
try {
|
|
92
|
+
const paths = probes.map((spec) => resolve(spec));
|
|
93
|
+
const missing = paths.filter((p) => !exists(p));
|
|
94
|
+
if (missing.length === 0) return { ok: true, detail: "" };
|
|
95
|
+
return { ok: false, detail: `Incomplete install — ${repair}` };
|
|
96
|
+
} catch {
|
|
97
|
+
return { ok: false, detail: `Missing/unresolvable — ${repair}` };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
65
101
|
/**
|
|
66
102
|
* Collect a machine-readable doctor report.
|
|
67
103
|
*
|
|
@@ -179,6 +215,18 @@ export async function collectDoctorReport() {
|
|
|
179
215
|
detail: setupCompleted ? "" : 'Run "chainlesschain setup"',
|
|
180
216
|
});
|
|
181
217
|
|
|
218
|
+
// Personal Data Hub package integrity (catches partial/EBUSY-corrupted
|
|
219
|
+
// global installs before the user hits a raw ERR_MODULE_NOT_FOUND from a
|
|
220
|
+
// `cc hub …` command). Optional: non-hub usage works without it.
|
|
221
|
+
const pdh = checkPdhPackageIntegrity();
|
|
222
|
+
checks.push({
|
|
223
|
+
id: "pdh-package",
|
|
224
|
+
name: "Personal Data Hub package",
|
|
225
|
+
ok: pdh.ok,
|
|
226
|
+
optional: true,
|
|
227
|
+
detail: pdh.detail,
|
|
228
|
+
});
|
|
229
|
+
|
|
182
230
|
// Port scan
|
|
183
231
|
const ports = [];
|
|
184
232
|
for (const [name, port] of Object.entries(DEFAULT_PORTS)) {
|
|
@@ -582,9 +582,13 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
582
582
|
// the very first turn — the read side of pdh-feedback-ledger.js. Gated to PDH
|
|
583
583
|
// context (the in-APK chat sets CHAINLESSCHAIN_PDH_PORT; `--pdh` forces,
|
|
584
584
|
// `--no-pdh` opts out) so IDE/coding sessions are never polluted. Best-effort.
|
|
585
|
+
// PDH context gate — reused by the §3.5.13 flywheel injection below and the
|
|
586
|
+
// §3.5.18 egress reporting after each turn (in-APK chat sets
|
|
587
|
+
// CHAINLESSCHAIN_PDH_PORT; `--pdh` forces, `--no-pdh` opts out).
|
|
588
|
+
let pdhContext = false;
|
|
585
589
|
try {
|
|
586
590
|
const { isInPdhTerminal } = await import("../lib/pdh-bridge.js");
|
|
587
|
-
|
|
591
|
+
pdhContext =
|
|
588
592
|
options.pdh === true ||
|
|
589
593
|
(options.pdh !== false && isInPdhTerminal(process.env));
|
|
590
594
|
if (pdhContext) {
|
|
@@ -1275,6 +1279,38 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1275
1279
|
}
|
|
1276
1280
|
currentAbort = null;
|
|
1277
1281
|
|
|
1282
|
+
// §3.5.18 出境台账: report what left the device this turn (the cloud-LLM
|
|
1283
|
+
// call + any egress-classed tool) so the Android transparency ledger —
|
|
1284
|
+
// which cannot see the cc subprocess's cloud call — records it. PDH-gated
|
|
1285
|
+
// and emit-only (cc never keeps its own ledger; it stays a single on-device
|
|
1286
|
+
// encrypted store). A local-only turn emits nothing — the honest "0 条出境".
|
|
1287
|
+
// Uses the EFFECTIVE per-turn LLM (a §3.5.10 privacy-tier / vision override
|
|
1288
|
+
// is exactly the egress-relevant decision).
|
|
1289
|
+
if (pdhContext) {
|
|
1290
|
+
try {
|
|
1291
|
+
const { turnEgressEvents } = await import("../lib/pdh-egress.js");
|
|
1292
|
+
const effProvider =
|
|
1293
|
+
turnVisionLlm?.provider || turnLlmOverride?.provider || provider;
|
|
1294
|
+
const effModel =
|
|
1295
|
+
turnVisionLlm?.model || turnLlmOverride?.model || model;
|
|
1296
|
+
const effBaseUrl =
|
|
1297
|
+
turnVisionLlm?.baseUrl || turnLlmOverride?.baseUrl || baseUrl;
|
|
1298
|
+
for (const ev of turnEgressEvents({
|
|
1299
|
+
provider: effProvider,
|
|
1300
|
+
baseUrl: effBaseUrl,
|
|
1301
|
+
model: effModel,
|
|
1302
|
+
toolCalls: outcome.toolCalls,
|
|
1303
|
+
usage: outcome.usage,
|
|
1304
|
+
sessionId,
|
|
1305
|
+
turn: turns,
|
|
1306
|
+
})) {
|
|
1307
|
+
emit(ev);
|
|
1308
|
+
}
|
|
1309
|
+
} catch {
|
|
1310
|
+
/* egress reporting is best-effort — never break the chat */
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1278
1314
|
// Grow the conversation so the next turn has context.
|
|
1279
1315
|
messages.push({ role: "assistant", content: outcome.finalText });
|
|
1280
1316
|
if (persist) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{E as N,r as k,I as m,J as F,U as d,c as i,K as l,V as u,S,F as R,Z as q,o as I,a as A,P as g,Q as x,R as C,_ as E}from"./vendor-BvqAck49.js";import{u as M,_ as H,d as _}from"./index-E9fKdmZS.js";import{a as D,b as Q,c as j}from"./parsers-UEvh_ShA.js";import{R as W}from"./icons-DP3uiYxy.js";const B=N("providers",()=>{const K=k(!1),o=k(null),v=k([]),e=k([]),w=k(null);async function U(){const s=M();K.value=!0;try{const{output:f}=await s.execute("llm providers",15e3);v.value=D(f);const p=v.value.find(h=>h.active);p&&(w.value=p.name);const{output:b}=await s.execute("llm models",15e3);e.value=Q(b)}catch(f){console.error("Failed to load providers:",f)}finally{K.value=!1}}async function y(s){await M().execute(`llm switch ${s}`,1e4),v.value.forEach(p=>p.active=p.name===s),w.value=s}async function a(s){const f=M();o.value=s;try{const{output:p,exitCode:b}=await f.execute("llm test",3e4),h=v.value.find(L=>L.name===s);return h&&(h.status=b===0?"ok":"error"),b===0}catch{const p=v.value.find(b=>b.name===s);return p&&(p.status="error"),!1}finally{o.value=null}}return{loading:K,testing:o,providers:v,localModels:e,activeProvider:w,loadProviders:U,switchProvider:y,testProvider:a}}),J={__name:"Providers",setup(K,{expose:o}){o();const v=B(),e=M(),w=k(!1),U=k(!1),y=k(!1),a=A({provider:void 0,model:"",apiKey:"",baseUrl:"",temperature:.7,maxTokens:4096});let s={};const f=["ollama","openai","anthropic","volcengine","deepseek","gemini","groq","mistral","custom","zhipu"],p={ollama:"Ollama(本地)",openai:"OpenAI",anthropic:"Anthropic",volcengine:"火山引擎(豆包)",deepseek:"DeepSeek",gemini:"Google Gemini",groq:"Groq",mistral:"Mistral",custom:"Custom(自定义)",zhipu:"智谱 AI"},b=f.map(n=>({value:n,label:p[n]||n}));async function h(n){try{await v.switchProvider(n),_.success(`已切换到 ${n}`)}catch(t){_.error(`切换失败: ${t.message}`)}}async function L(n){await v.testProvider(n)?_.success(`${n} 连接正常`):_.warning(`${n} 连接失败,请检查配置`)}async function z(){w.value=!0;try{const{output:n}=await e.execute("config list",15e3),t=j(n);t.provider&&(a.provider=t.provider),t.model&&(a.model=t.model),t.apiKey&&(a.apiKey=t.apiKey),t.baseUrl&&(a.baseUrl=t.baseUrl),t.temperature!==void 0&&(a.temperature=t.temperature),t.maxTokens!==void 0&&(a.maxTokens=t.maxTokens),s={provider:t.provider??"",model:t.model??"",apiKey:t.apiKey??"",baseUrl:t.baseUrl??"",temperature:t.temperature??a.temperature,maxTokens:t.maxTokens??a.maxTokens},_.success("配置已加载")}catch(n){_.error(`加载配置失败: ${n.message}`)}finally{w.value=!1}}async function O(){U.value=!0;const n=[],t=[];try{if(a.provider&&a.provider!==s.provider)try{await e.execute(`config set llm.provider ${a.provider}`,1e4),t.push("provider")}catch(c){n.push(`provider: ${c.message}`)}if(a.model&&a.model!==s.model)try{await e.execute(`config set llm.model ${a.model}`,1e4),t.push("model")}catch(c){n.push(`model: ${c.message}`)}if(a.apiKey&&a.apiKey!==s.apiKey)try{await e.execute(`config set llm.apiKey ${a.apiKey}`,1e4),t.push("apiKey")}catch(c){n.push(`apiKey: ${c.message}`)}if(a.baseUrl!==void 0&&a.baseUrl!==s.baseUrl)try{await e.execute(`config set llm.baseUrl ${a.baseUrl}`,1e4),t.push("baseUrl")}catch(c){n.push(`baseUrl: ${c.message}`)}if(a.temperature!==s.temperature)try{await e.execute(`config set llm.temperature ${a.temperature}`,1e4),t.push("temperature")}catch(c){n.push(`temperature: ${c.message}`)}if(a.maxTokens!==s.maxTokens)try{await e.execute(`config set llm.maxTokens ${a.maxTokens}`,1e4),t.push("maxTokens")}catch(c){n.push(`maxTokens: ${c.message}`)}n.length>0?_.warning(`部分配置保存失败: ${n.join("; ")}`):t.length>0?(_.success(`已保存 ${t.length} 项配置`),s={...a},(t.includes("apiKey")||t.includes("provider")||t.includes("baseUrl")||t.includes("model"))&&(y.value=!0),t.includes("provider")&&v.loadProviders()):_.info("没有检测到配置变更")}catch(c){_.error(`保存配置失败: ${c.message}`)}finally{U.value=!1}}function P(){a.provider=s.provider||void 0,a.model=s.model||"",a.apiKey=s.apiKey||"",a.baseUrl=s.baseUrl||"",a.temperature=s.temperature??.7,a.maxTokens=s.maxTokens??4096}I(()=>{v.loadProviders(),z()});const T={providersStore:v,ws:e,configLoading:w,configSaving:U,showRestartHint:y,configForm:a,get loadedConfig(){return s},set loadedConfig(n){s=n},knownProviders:f,providerLabels:p,providerOptions:b,switchProvider:h,test:L,loadConfig:z,saveConfig:O,resetForm:P,onMounted:I,reactive:A,ref:k,get ReloadOutlined(){return W},get message(){return _},get useProvidersStore(){return B},get useWsStore(){return M},get parseLlmConfigOutput(){return j}};return Object.defineProperty(T,"__isScriptSetup",{enumerable:!1,value:!0}),T}},Y={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Z={key:1,style:{"text-align":"center",padding:"60px"}},X={class:"providers-grid"},$={style:{display:"flex","align-items":"center",gap:"12px","margin-bottom":"12px"}},ee={style:{"font-size":"24px"}},oe={style:{flex:"1"}},ae={style:{color:"#e0e0e0","font-weight":"500"}},te={style:{color:"var(--text-secondary)","font-size":"11px","font-family":"monospace"}},re={style:{display:"flex",gap:"8px","justify-content":"flex-end"}},se={key:0,style:{"margin-top":"24px"}},ne={style:{color:"#ccc","font-family":"monospace","font-size":"13px"}},ie={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"16px"}},le={class:"config-grid"},de={style:{display:"flex","align-items":"center",gap:"12px"}},ce={style:{display:"flex",gap:"12px","justify-content":"flex-end","margin-top":"16px"}};function me(K,o,v,e,w,U){const y=m("a-button"),a=m("a-alert"),s=m("a-spin"),f=m("a-tag"),p=m("a-badge"),b=m("a-card"),h=m("a-list-item"),L=m("a-list"),z=m("a-divider"),O=m("a-select"),P=m("a-form-item"),T=m("a-input"),n=m("a-input-password"),t=m("a-slider"),c=m("a-input-number"),V=m("a-form");return g(),F("div",null,[d("div",Y,[o[10]||(o[10]=d("div",null,[d("h2",{class:"page-title"},"LLM 配置"),d("p",{class:"page-sub"},"管理 AI 服务提供商")],-1)),i(y,{type:"primary",ghost:"",loading:e.providersStore.loading,onClick:o[0]||(o[0]=r=>e.providersStore.loadProviders())},{icon:l(()=>[i(e.ReloadOutlined)]),default:l(()=>[o[9]||(o[9]=x(" 刷新 ",-1))]),_:1},8,["loading"])]),u(" Active Provider Banner "),e.providersStore.activeProvider?(g(),S(a,{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(()=>[d("span",null,[o[11]||(o[11]=x("当前激活:",-1)),d("strong",null,C(e.providersStore.activeProvider),1)])]),_:1})):u("v-if",!0),u(" Loading "),e.providersStore.loading?(g(),F("div",Z,[i(s,{size:"large"}),o[12]||(o[12]=d("div",{style:{color:"var(--text-muted)","margin-top":"12px"}},"加载 LLM 信息中...",-1))])):(g(),F(R,{key:2},[u(" Providers Grid "),d("div",null,[d("div",X,[(g(!0),F(R,null,q(e.providersStore.providers,r=>(g(),S(b,{key:r.name,class:E(["provider-card",{active:r.active}]),style:{background:"var(--bg-card)"},size:"small"},{default:l(()=>[d("div",$,[d("span",ee,C(r.icon),1),d("div",oe,[d("div",ae,C(r.label),1),d("div",te,C(r.name),1)]),d("div",null,[r.active?(g(),S(f,{key:0,color:"green"},{default:l(()=>[...o[13]||(o[13]=[x("活跃",-1)])]),_:1})):r.status==="ok"?(g(),S(p,{key:1,status:"success",text:""})):r.status==="error"?(g(),S(p,{key:2,status:"error",text:""})):u("v-if",!0)])]),d("div",re,[i(y,{size:"small",style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"},loading:e.providersStore.testing===r.name,onClick:G=>e.test(r.name)},{default:l(()=>[...o[14]||(o[14]=[x(" 测试 ",-1)])]),_:1},8,["loading","onClick"]),r.active?(g(),S(f,{key:1,color:"green",style:{margin:"0","line-height":"24px"}},{default:l(()=>[...o[16]||(o[16]=[x("当前",-1)])]),_:1})):(g(),S(y,{key:0,size:"small",type:"primary",ghost:"",onClick:G=>e.switchProvider(r.name)},{default:l(()=>[...o[15]||(o[15]=[x(" 切换 ",-1)])]),_:1},8,["onClick"]))])]),_:2},1032,["class"]))),128))]),u(" Local Models (Ollama) "),e.providersStore.localModels.length?(g(),F("div",se,[o[17]||(o[17]=d("h3",{style:{color:"#ccc","font-size":"15px","margin-bottom":"12px"}}," 本地模型(Ollama) ",-1)),i(L,{"data-source":e.providersStore.localModels,size:"small",style:{background:"var(--bg-card)","border-radius":"8px",border:"1px solid var(--border-color)"}},{renderItem:l(({item:r})=>[i(h,{style:{padding:"10px 16px","border-color":"#252525"}},{actions:l(()=>[i(f,{color:"cyan",style:{"font-size":"10px"}},{default:l(()=>[x(C(r.size||"local"),1)]),_:2},1024)]),default:l(()=>[d("span",ne,C(r.name),1)]),_:2},1024)]),_:1},8,["data-source"])])):u("v-if",!0),u(" LLM Parameter Settings "),i(z,{style:{"border-color":"var(--border-color)",margin:"32px 0 24px"}}),e.showRestartHint?(g(),S(a,{key:1,type:"warning","show-icon":"",closable:"",style:{"margin-bottom":"16px"},message:"配置已保存,但当前聊天会话仍在用旧 key",description:"桌面端的 LLM 会话只在新建会话时重读配置。请新建一个 Chat,或重启应用,新 key/Provider 才会生效。",onClose:o[1]||(o[1]=r=>e.showRestartHint=!1)})):u("v-if",!0),d("div",ie,[o[19]||(o[19]=d("h3",{class:"section-title"},"LLM 参数设置",-1)),i(y,{size:"small",loading:e.configLoading,onClick:e.loadConfig,style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{icon:l(()=>[i(e.ReloadOutlined)]),default:l(()=>[o[18]||(o[18]=x(" 加载配置 ",-1))]),_:1},8,["loading"])]),i(b,{class:"config-card",style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:l(()=>[i(V,{model:e.configForm,layout:"vertical",class:"config-form"},{default:l(()=>[d("div",le,[u(" Provider "),i(P,{label:"Provider(提供商)"},{default:l(()=>[i(O,{value:e.configForm.provider,"onUpdate:value":o[2]||(o[2]=r=>e.configForm.provider=r),placeholder:"选择 LLM 提供商",options:e.providerOptions,style:{width:"100%"},disabled:e.configSaving},null,8,["value","options","disabled"])]),_:1}),u(" Model "),i(P,{label:"Model(模型名称)"},{default:l(()=>[i(T,{value:e.configForm.model,"onUpdate:value":o[3]||(o[3]=r=>e.configForm.model=r),placeholder:"例如 doubao-seed-1-6-251015","allow-clear":"",disabled:e.configSaving},null,8,["value","disabled"])]),_:1}),u(" API Key "),i(P,{label:"API Key"},{default:l(()=>[i(n,{value:e.configForm.apiKey,"onUpdate:value":o[4]||(o[4]=r=>e.configForm.apiKey=r),placeholder:"输入 API Key",disabled:e.configSaving},null,8,["value","disabled"])]),_:1}),u(" Base URL "),i(P,{label:"Base URL"},{default:l(()=>[i(T,{value:e.configForm.baseUrl,"onUpdate:value":o[5]||(o[5]=r=>e.configForm.baseUrl=r),placeholder:"例如 https://ark.cn-beijing.volces.com/api/v3","allow-clear":"",disabled:e.configSaving},null,8,["value","disabled"])]),_:1}),u(" Temperature "),i(P,{label:"Temperature(温度)"},{default:l(()=>[d("div",de,[i(t,{value:e.configForm.temperature,"onUpdate:value":o[6]||(o[6]=r=>e.configForm.temperature=r),min:0,max:2,step:.1,style:{flex:"1"},disabled:e.configSaving},null,8,["value","disabled"]),i(c,{value:e.configForm.temperature,"onUpdate:value":o[7]||(o[7]=r=>e.configForm.temperature=r),min:0,max:2,step:.1,precision:1,style:{width:"80px"},disabled:e.configSaving},null,8,["value","disabled"])])]),_:1}),u(" Max Tokens "),i(P,{label:"Max Tokens(最大输出长度)"},{default:l(()=>[i(c,{value:e.configForm.maxTokens,"onUpdate:value":o[8]||(o[8]=r=>e.configForm.maxTokens=r),min:256,max:128e3,step:256,style:{width:"100%"},placeholder:"4096",disabled:e.configSaving},null,8,["value","disabled"])]),_:1})]),d("div",ce,[i(y,{onClick:e.resetForm,disabled:e.configSaving,style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)"}},{default:l(()=>[...o[20]||(o[20]=[x(" 重置 ",-1)])]),_:1},8,["disabled"]),i(y,{type:"primary",loading:e.configSaving,onClick:e.saveConfig},{default:l(()=>[...o[21]||(o[21]=[x(" 保存配置 ",-1)])]),_:1},8,["loading"])])]),_:1},8,["model"])]),_:1})])],2112))])}const ge=H(J,[["render",me],["__scopeId","data-v-64155d06"],["__file","/tmp/cc-web-panel-YQtVbb/repo/packages/web-panel/src/views/Providers.vue"]]);export{ge as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as u,J as g,U as m,R as c,c as r,K as t,V as f,S as k,r as v,o as se,a as ie,b as j,P as d,Q as _,a2 as ke,F as O,Z as L}from"./vendor-BvqAck49.js";import{_ as Se,b as ce,u as de,E as ue,d as F}from"./index-E9fKdmZS.js";import{s as ye}from"./community-parser-CO25nZFt.js";import{at as Ce,l as Te,a4 as Ne,a_ as Ae,a9 as Oe,a2 as ze,$ as we,k as Ee,R as Me}from"./icons-DP3uiYxy.js";function ae(n){const o=ye(n);if(!o)return null;try{return JSON.parse(o)}catch{}const s=o.match(/\{[\s\S]*\}|\[[\s\S]*\]/);if(!s)return null;try{return JSON.parse(s[0])}catch{return null}}const Ie=Object.freeze(["bm25","vector","hybrid"]);function Fe(n,o=0){return typeof n=="number"&&Number.isFinite(n)?n:o}function Re(n){if(Array.isArray(n))return n.filter(o=>typeof o=="string");if(typeof n!="string")return[];try{const o=JSON.parse(n);if(Array.isArray(o))return o.filter(s=>typeof s=="string")}catch{}return[]}function J(n){if(!n)return{noDb:!1,error:""};const o=ye(n),s=/Database not available/i.test(o);return{noDb:s,error:s?"Database not available":""}}function De(n,o=0){if(!n||typeof n!="object")return null;const s=n.id||"";return s?{key:s,id:s,score:Fe(n.score,0),title:String(n.title||""),category:String(n.category||"general"),createdAt:n.created_at??n.createdAt??"",snippet:String(n.snippet||""),_idx:o}:null}function fe(n){const o=ae(n);return Array.isArray(o)?o.map(De).filter(Boolean):[]}function he(n,o=0){if(!n||typeof n!="object")return null;const s=n.id||"";return s?{key:s,id:s,title:String(n.title||""),content:n.content??"",tags:Re(n.tags),category:String(n.category||"general"),createdAt:n.created_at??n.createdAt??"",updatedAt:n.updated_at??n.updatedAt??"",_idx:o}:null}function ge(n){const o=ae(n);return Array.isArray(o)?o.map(he).filter(Boolean):[]}function me(n){const o=ae(n);return!o||typeof o!="object"||Array.isArray(o)?null:he(o,0)}function _e(n){if(!Array.isArray(n)||n.length===0)return{total:0,categories:[],tags:[]};const o=new Map,s=new Map;for(const e of n){o.set(e.category,(o.get(e.category)||0)+1);for(const x of e.tags)s.set(x,(s.get(x)||0)+1)}return{total:n.length,categories:[...o.entries()].map(([e,x])=>({name:e,count:x})).sort((e,x)=>x.count-e.count),tags:[...s.entries()].map(([e,x])=>({name:e,count:x})).sort((e,x)=>x.count-e.count)}}function Le(n){if(n==null||n==="")return"—";const o=String(n),s=o.includes(" ")&&!o.includes("T")?o.replace(" ","T")+"Z":o,e=new Date(s);return isNaN(e.getTime())?o:e.toLocaleString("zh-CN",{hour12:!1})}const V="cc.web-panel.search.recent",re=8,Pe={__name:"Search",setup(n,{expose:o}){o();const{t:s}=ce(),e=de(),x=ue.PRESENTED_IMAGE_SIMPLE,q=v(!1),C=v(!1),P=v(!1),Q=v(!1),z=v([]),h=v([]),A=v({noDb:!1,error:""}),T=ie({query:"",mode:"hybrid",topK:10}),B=v(""),w=v(U()),K=v("results"),S=v(""),N=v(""),E=v(!1),M=v(null),G=j(()=>_e(z.value)),Y=j(()=>h.value.length?Math.max(...h.value.map(l=>l.score)):0),W=j(()=>[{title:s("search.noteColumns.title"),key:"title"},{title:s("search.noteColumns.category"),key:"category",width:"120px"},{title:s("search.noteColumns.tags"),key:"tags",width:"240px"},{title:s("search.noteColumns.createdAt"),key:"createdAt",width:"180px"},{title:s("search.noteColumns.action"),key:"action",width:"180px"}]),Z=j(()=>{let l=z.value;if(S.value&&(l=l.filter(i=>i.category===S.value)),N.value.trim()){const i=N.value.trim().toLowerCase();l=l.filter(y=>y.tags.some(b=>b.toLowerCase().includes(i)))}return l});function H(l){const i=`search.mode.${l}`,y=s(i);return y===i?l:y}function X(l){const i=["blue","green","purple","orange","cyan","magenta","gold","volcano"];let y=0;for(let b=0;b<(l||"").length;b++)y=y*31+l.charCodeAt(b)>>>0;return i[y%i.length]}function $(l){return l>=.7?"#52c41a":l>=.5?"#1677ff":l>=.3?"#faad14":"#ff4d4f"}function R(l){return String(l).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function I(l,i){if(!i||!l)return R(l);const y=i.split(/\s+/).filter(Boolean);let b=R(l);for(const be of y){const xe=new RegExp(`(${be.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})`,"gi");b=b.replace(xe,"<mark>$1</mark>")}return b}function ee(l,i){return i?I(l,i):R(l)}function U(){try{const l=localStorage.getItem(V);if(l){const i=JSON.parse(l);if(Array.isArray(i))return i.filter(y=>typeof y=="string").slice(0,re)}}catch{}return[]}function a(l){const i=l.trim();if(!i)return;const y=[i,...w.value.filter(b=>b!==i)];w.value=y.slice(0,re);try{localStorage.setItem(V,JSON.stringify(w.value))}catch{}}function p(){w.value=[];try{localStorage.removeItem(V)}catch{}}function D(l){T.query=l,te()}async function oe(){q.value=!0,A.value={noDb:!1,error:""};try{const{output:l}=await e.execute("note list -n 500 --json",12e3).catch(()=>({output:""})),i=J(l);if(i.noDb){A.value=i,z.value=[];return}z.value=ge(l)}catch(l){F.error(s("search.messages.loadIndexFailed",{err:l?.message||l}))}finally{q.value=!1}}async function te(){const l=T.query.trim();if(!l){F.warning(s("search.messages.queryRequired"));return}P.value=!0,A.value={noDb:!1,error:""};try{const i=[`search ${ne(l)}`,`--mode ${T.mode}`,`--top-k ${T.topK||10}`,"--json"],{output:y}=await e.execute(i.join(" "),15e3),b=J(y);if(b.noDb){A.value=b,h.value=[],Q.value=!0,B.value=l;return}h.value=fe(y),B.value=l,Q.value=!0,a(l),K.value="results"}catch(i){F.error(s("search.messages.searchFailed",{err:i?.message||i}))}finally{P.value=!1}}function ne(l){return`"${String(l).replace(/"/g,'\\"')}"`}function pe(l){T.query=l.title,T.mode="vector",te()}async function ve(l){E.value=!0,C.value=!0,M.value=null;try{const{output:i}=await e.execute(`note show ${l} --json`,8e3);if(J(i).noDb){F.error(s("search.messages.needInit"));return}M.value=me(i),M.value||F.error(s("search.messages.noteLoadFailed"))}catch(i){F.error(s("search.messages.loadFailed",{err:i?.message||i}))}finally{C.value=!1}}se(oe);const le={t:s,ws:e,EMPTY_IMG:x,RECENT_LS:V,RECENT_MAX:re,loadingIndex:q,loadingNote:C,searching:P,searched:Q,notes:z,results:h,errorState:A,form:T,currentQuery:B,recentQueries:w,activeTab:K,indexCategoryFilter:S,indexTagFilter:N,showNoteModal:E,currentNote:M,indexSummary:G,topScore:Y,noteColumns:W,filteredNotes:Z,modeLabel:H,categoryColor:X,scoreColor:$,escapeHtml:R,highlightSnippet:I,highlightContent:ee,loadRecent:U,pushRecent:a,clearRecent:p,rerunQuery:D,loadIndex:oe,runSearch:te,shellQuote:ne,searchSimilar:pe,viewNote:ve,ref:v,computed:j,onMounted:se,reactive:ie,get useI18n(){return ce},get ReloadOutlined(){return Me},get SearchOutlined(){return Ee},get ThunderboltOutlined(){return we},get BookOutlined(){return ze},get AppstoreOutlined(){return Oe},get TagsOutlined(){return Ae},get FileTextOutlined(){return Ne},get TrophyOutlined(){return Te},get EyeOutlined(){return Ce},get message(){return F},get Empty(){return ue},get useWsStore(){return de},get parseSearchResults(){return fe},get parseNotes(){return ge},get parseNote(){return me},get buildIndexSummary(){return _e},get detectSearchError(){return J},get formatSearchTime(){return Le},get SEARCH_MODES(){return Ie}};return Object.defineProperty(le,"__isScriptSetup",{enumerable:!1,value:!0}),le}},Qe={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Be={class:"page-title"},je={class:"page-sub"},qe={key:0,class:"recent-row"},Ke={class:"recent-label"},He={class:"score-block"},Ue={class:"result-title"},Je={style:{color:"var(--text-muted)","font-size":"11px","font-family":"monospace"}},Ve={style:{"margin-left":"8px",color:"var(--text-secondary)","font-size":"11px"}},Ge={key:0,class:"result-snippet"},Ye=["innerHTML"],We={class:"filter-bar"},Ze={key:0,class:"tag-row"},Xe={class:"tag-row-label"},$e={class:"tag-count"},et={style:{color:"var(--text-primary)","font-weight":"500"}},tt={style:{color:"var(--text-muted)","font-size":"11px","font-family":"monospace","margin-top":"2px"}},rt={key:0,style:{color:"var(--text-muted)","font-size":"11px"}},at={key:3,style:{color:"var(--text-secondary)","font-size":"11px"}},ot={style:{padding:"40px",color:"var(--text-muted)","text-align":"center"}},nt={key:0,style:{padding:"40px","text-align":"center"}},lt={key:1,style:{"padding-top":"8px"}},st={style:{"font-family":"monospace","font-size":"12px"}},it={key:0,style:{color:"var(--text-muted)"}},ct={style:{color:"var(--text-primary)","font-size":"13px",margin:"16px 0 8px"}},dt={key:0,class:"note-content"},ut=["innerHTML"];function ft(n,o,s,e,x,q){const C=u("a-button"),P=u("a-space"),Q=u("a-alert"),z=u("a-input"),h=u("a-col"),A=u("a-radio-button"),T=u("a-radio-group"),B=u("a-input-number"),w=u("a-row"),K=u("a-form"),S=u("a-tag"),N=u("a-card"),E=u("a-statistic"),M=u("a-empty"),G=u("a-progress"),Y=u("a-list-item-meta"),W=u("a-list-item"),Z=u("a-list"),H=u("a-tab-pane"),X=u("a-table"),$=u("a-tabs"),R=u("a-spin"),I=u("a-descriptions-item"),ee=u("a-descriptions"),U=u("a-modal");return d(),g("div",null,[m("div",Qe,[m("div",null,[m("h2",Be,c(e.t("search.title")),1),m("p",je,c(e.t("search.subtitle")),1)]),r(P,null,{default:t(()=>[r(C,{loading:e.loadingIndex,onClick:e.loadIndex},{icon:t(()=>[r(e.ReloadOutlined)]),default:t(()=>[_(" "+c(e.t("search.refreshIndex")),1)]),_:1},8,["loading"])]),_:1})]),f(" noDb banner "),e.errorState.noDb?(d(),k(Q,{key:0,type:"info","show-icon":"",message:e.t("search.noDb.message"),description:e.t("search.noDb.description"),style:{"margin-bottom":"16px"}},null,8,["message","description"])):f("v-if",!0),f(" Search bar "),r(N,{size:"small",style:{background:"var(--bg-card)","border-color":"var(--border-color)","margin-bottom":"16px"},"body-style":{padding:"14px 16px"}},{default:t(()=>[r(K,{layout:"vertical",model:e.form,onSubmit:ke(e.runSearch,["prevent"])},{default:t(()=>[r(w,{gutter:12},{default:t(()=>[r(h,{span:14},{default:t(()=>[r(z,{value:e.form.query,"onUpdate:value":o[0]||(o[0]=a=>e.form.query=a),size:"large",placeholder:e.t("search.form.queryPlaceholder"),"allow-clear":"",onPressEnter:e.runSearch},{prefix:t(()=>[r(e.SearchOutlined)]),_:1},8,["value","placeholder"])]),_:1}),r(h,{span:4},{default:t(()=>[r(T,{value:e.form.mode,"onUpdate:value":o[1]||(o[1]=a=>e.form.mode=a),size:"large","button-style":"solid"},{default:t(()=>[(d(!0),g(O,null,L(e.SEARCH_MODES,a=>(d(),k(A,{key:a,value:a},{default:t(()=>[_(c(e.modeLabel(a)),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"])]),_:1}),r(h,{span:3},{default:t(()=>[r(B,{value:e.form.topK,"onUpdate:value":o[2]||(o[2]=a=>e.form.topK=a),min:1,max:50,placeholder:e.t("search.form.topKPlaceholder"),size:"large",style:{width:"100%"}},null,8,["value","placeholder"])]),_:1}),r(h,{span:3},{default:t(()=>[r(C,{type:"primary",size:"large",loading:e.searching,block:"",onClick:e.runSearch},{icon:t(()=>[r(e.ThunderboltOutlined)]),default:t(()=>[_(" "+c(e.t("search.form.submit")),1)]),_:1},8,["loading"])]),_:1})]),_:1})]),_:1},8,["model"]),f(" Recent queries chips "),e.recentQueries.length?(d(),g("div",qe,[m("span",Ke,c(e.t("search.recent.label")),1),(d(!0),g(O,null,L(e.recentQueries,a=>(d(),k(S,{key:a,color:"blue",class:"recent-chip",onClick:p=>e.rerunQuery(a)},{default:t(()=>[_(c(a),1)]),_:2},1032,["onClick"]))),128)),r(C,{size:"small",type:"link",danger:"",onClick:e.clearRecent},{default:t(()=>[_(c(e.t("search.recent.clear")),1)]),_:1})])):f("v-if",!0)]),_:1}),f(" Stat cards "),r(w,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:t(()=>[r(h,{xs:12,sm:8,lg:5},{default:t(()=>[r(N,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[r(E,{title:e.t("search.stats.indexedNotes"),value:e.indexSummary.total,"value-style":{color:"#1677ff",fontSize:"20px"}},{prefix:t(()=>[r(e.BookOutlined)]),_:1},8,["title","value"])]),_:1})]),_:1}),r(h,{xs:12,sm:8,lg:5},{default:t(()=>[r(N,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[r(E,{title:e.t("search.stats.categories"),value:e.indexSummary.categories.length,"value-style":{color:"#722ed1",fontSize:"20px"}},{prefix:t(()=>[r(e.AppstoreOutlined)]),_:1},8,["title","value"])]),_:1})]),_:1}),r(h,{xs:12,sm:8,lg:5},{default:t(()=>[r(N,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[r(E,{title:e.t("search.stats.tags"),value:e.indexSummary.tags.length,"value-style":{color:"#13c2c2",fontSize:"20px"}},{prefix:t(()=>[r(e.TagsOutlined)]),_:1},8,["title","value"])]),_:1})]),_:1}),r(h,{xs:12,sm:8,lg:5},{default:t(()=>[r(N,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[r(E,{title:e.t("search.stats.results"),value:e.results.length,"value-style":{color:e.results.length>0?"#52c41a":"#888",fontSize:"20px"}},{prefix:t(()=>[r(e.FileTextOutlined)]),_:1},8,["title","value","value-style"])]),_:1})]),_:1}),r(h,{xs:24,sm:8,lg:4},{default:t(()=>[r(N,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[r(E,{title:e.t("search.stats.topScore"),value:e.topScore,precision:3,"value-style":{color:e.scoreColor(e.topScore),fontSize:"20px"}},{prefix:t(()=>[r(e.TrophyOutlined)]),_:1},8,["title","value","value-style"])]),_:1})]),_:1})]),_:1}),f(" Tabs "),r($,{activeKey:e.activeTab,"onUpdate:activeKey":o[5]||(o[5]=a=>e.activeTab=a),class:"search-tabs"},{default:t(()=>[f(" ── Results tab ───────────────────────────────────────── "),r(H,{key:"results",tab:e.t("search.tabs.results")},{default:t(()=>[e.searched?e.results.length?(d(),k(Z,{key:2,"data-source":e.results,"item-layout":"vertical",size:"large"},{renderItem:t(({item:a})=>[r(W,{class:"result-row"},{actions:t(()=>[r(C,{type:"link",size:"small",onClick:p=>e.viewNote(a.id)},{icon:t(()=>[r(e.EyeOutlined)]),default:t(()=>[_(" "+c(e.t("search.results.viewFull")),1)]),_:1},8,["onClick"])]),extra:t(()=>[m("div",He,[r(G,{type:"circle",percent:Math.round(Math.min(1,a.score)*100),"stroke-color":e.scoreColor(a.score),format:()=>a.score.toFixed(3),width:60},null,8,["percent","stroke-color","format"])])]),default:t(()=>[r(Y,null,{title:t(()=>[m("span",Ue,c(a.title||e.t("search.results.noTitle")),1),r(S,{color:e.categoryColor(a.category),style:{"margin-left":"8px"}},{default:t(()=>[_(c(a.category),1)]),_:2},1032,["color"])]),description:t(()=>[m("span",Je,c(a.id.slice(0,16)),1),m("span",Ve,c(e.formatSearchTime(a.createdAt)),1)]),_:2},1024),a.snippet?(d(),g("div",Ge,[m("span",{innerHTML:e.highlightSnippet(a.snippet,e.currentQuery)},null,8,Ye)])):f("v-if",!0)]),_:2},1024)]),_:1},8,["data-source"])):(d(),k(M,{key:1,description:e.t("search.results.noMatch",{query:e.currentQuery}),image:e.EMPTY_IMG,style:{padding:"40px 0"}},null,8,["description","image"])):(d(),k(M,{key:0,description:e.t("search.results.promptEmpty"),image:e.EMPTY_IMG,style:{padding:"40px 0"}},null,8,["description","image"]))]),_:1},8,["tab"]),f(" ── Index browser tab ────────────────────────────────── "),r(H,{key:"index",tab:e.t("search.tabs.index")},{default:t(()=>[m("div",We,[r(T,{value:e.indexCategoryFilter,"onUpdate:value":o[3]||(o[3]=a=>e.indexCategoryFilter=a),size:"small","button-style":"solid"},{default:t(()=>[r(A,{value:""},{default:t(()=>[_(c(e.t("search.index.allCategories")),1)]),_:1}),(d(!0),g(O,null,L(e.indexSummary.categories.slice(0,6),a=>(d(),k(A,{key:a.name,value:a.name},{default:t(()=>[_(c(a.name)+" ("+c(a.count)+") ",1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"]),r(z,{value:e.indexTagFilter,"onUpdate:value":o[4]||(o[4]=a=>e.indexTagFilter=a),placeholder:e.t("search.index.tagFilterPlaceholder"),"allow-clear":"",size:"small",style:{"max-width":"180px"}},null,8,["value","placeholder"])]),f(" Top tags chips "),e.indexSummary.tags.length?(d(),g("div",Ze,[m("span",Xe,c(e.t("search.index.topTagsLabel")),1),(d(!0),g(O,null,L(e.indexSummary.tags.slice(0,12),a=>(d(),k(S,{key:a.name,color:e.indexTagFilter===a.name?"blue":"default",class:"tag-chip",onClick:p=>e.indexTagFilter=e.indexTagFilter===a.name?"":a.name},{default:t(()=>[_(c(a.name)+" ",1),m("span",$e,c(a.count),1)]),_:2},1032,["color","onClick"]))),128))])):f("v-if",!0),r(X,{columns:e.noteColumns,"data-source":e.filteredNotes,pagination:{pageSize:20,showTotal:a=>e.t("search.totals.rows",{count:a})},size:"small",loading:e.loadingIndex,style:{background:"var(--bg-card)"}},{bodyCell:t(({column:a,record:p})=>[a.key==="title"?(d(),g(O,{key:0},[m("span",et,c(p.title||e.t("search.results.noTitle")),1),m("div",tt,c(p.id.slice(0,16)),1)],64)):f("v-if",!0),a.key==="category"?(d(),k(S,{key:1,color:e.categoryColor(p.category)},{default:t(()=>[_(c(p.category),1)]),_:2},1032,["color"])):f("v-if",!0),a.key==="tags"?(d(),g(O,{key:2},[(d(!0),g(O,null,L(p.tags.slice(0,4),D=>(d(),k(S,{key:D,color:"default",style:{"font-size":"11px"}},{default:t(()=>[_(c(D),1)]),_:2},1024))),128)),p.tags.length>4?(d(),g("span",rt,"+"+c(p.tags.length-4),1)):f("v-if",!0)],64)):f("v-if",!0),a.key==="createdAt"?(d(),g("span",at,c(e.formatSearchTime(p.createdAt)),1)):f("v-if",!0),a.key==="action"?(d(),g(O,{key:4},[r(C,{size:"small",type:"link",onClick:D=>e.viewNote(p.id)},{default:t(()=>[_(c(e.t("search.index.rowAction.view")),1)]),_:1},8,["onClick"]),r(C,{size:"small",type:"link",onClick:D=>e.searchSimilar(p)},{default:t(()=>[_(c(e.t("search.index.rowAction.similar")),1)]),_:1},8,["onClick"])],64)):f("v-if",!0)]),emptyText:t(()=>[m("div",ot,[r(e.BookOutlined,{style:{"font-size":"36px","margin-bottom":"10px",display:"block"}}),_(" "+c(e.indexCategoryFilter||e.indexTagFilter?e.t("search.empty.filtered"):e.t("search.empty.noNotes")),1)])]),_:1},8,["columns","data-source","pagination","loading"])]),_:1},8,["tab"])]),_:1},8,["activeKey"]),f(" ── Note detail modal ─────────────────────────────────── "),r(U,{open:e.showNoteModal,"onUpdate:open":o[6]||(o[6]=a=>e.showNoteModal=a),title:e.t("search.note.title",{title:e.currentNote?.title||""}),width:780,footer:null},{default:t(()=>[e.loadingNote?(d(),g("div",nt,[r(R)])):e.currentNote?(d(),g("div",lt,[r(ee,{column:2,size:"small",bordered:""},{default:t(()=>[r(I,{label:e.t("search.note.id"),span:2},{default:t(()=>[m("span",st,c(e.currentNote.id),1)]),_:1},8,["label"]),r(I,{label:e.t("search.note.category")},{default:t(()=>[r(S,{color:e.categoryColor(e.currentNote.category)},{default:t(()=>[_(c(e.currentNote.category),1)]),_:1},8,["color"])]),_:1},8,["label"]),r(I,{label:e.t("search.note.tags")},{default:t(()=>[(d(!0),g(O,null,L(e.currentNote.tags,a=>(d(),k(S,{key:a,color:"default"},{default:t(()=>[_(c(a),1)]),_:2},1024))),128)),e.currentNote.tags.length?f("v-if",!0):(d(),g("span",it,"—"))]),_:1},8,["label"]),r(I,{label:e.t("search.note.createdAt")},{default:t(()=>[_(c(e.formatSearchTime(e.currentNote.createdAt)),1)]),_:1},8,["label"]),r(I,{label:e.t("search.note.updatedAt")},{default:t(()=>[_(c(e.formatSearchTime(e.currentNote.updatedAt)),1)]),_:1},8,["label"])]),_:1}),m("h4",ct,c(e.t("search.note.content")),1),e.currentNote.content?(d(),g("div",dt,[m("span",{innerHTML:e.highlightContent(e.currentNote.content,e.currentQuery)},null,8,ut)])):(d(),k(M,{key:1,description:e.t("search.note.emptyContent"),image:e.EMPTY_IMG},null,8,["description","image"]))])):f("v-if",!0)]),_:1},8,["open","title"])])}const ht=Se(Pe,[["render",ft],["__scopeId","data-v-d2b94ce3"],["__file","/tmp/cc-web-panel-YQtVbb/repo/packages/web-panel/src/views/Search.vue"]]);export{ht as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as r}from"./index-E9fKdmZS.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-Dut8pwo9.js";import{U as t}from"./index-E9fKdmZS.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-BnImSTAx.js";import"./useFlexGapSupport-CPCXJDFA.js";import"./styleChecker-tp7AHEoi.js";import"./index-DzslfpyE.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-CZ8DawUj.js";import{U as t}from"./index-E9fKdmZS.js";import"./vendor-BvqAck49.js";import"./index-DzslfpyE.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
|