chainlesschain 0.161.5 → 0.161.7
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/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-DGVHYt7m.js → AIOps-C06IYJkC.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-B3a-9Af9.js → ActionButton-Cq4f1js5.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bx3Oxl0X.js → Analytics-DyJsowHu.js} +1 -1
- package/src/assets/web-panel/assets/{AppLayout-BzejRYN2.js → AppLayout-DSFSWtOZ.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-NY4P1SWh.js → Audit-C7y4wGzh.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DZq4lKGA.js → Backup-BxkJJwr5.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CdsLMh-s.js → BaseInput-BraWNP3N.js} +1 -1
- package/src/assets/web-panel/assets/Chat-BhZPLetb.js +7 -0
- package/src/assets/web-panel/assets/{Chat-D4oAhi11.css → Chat-IlrLB9ZV.css} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C5XnHFiF.js → Checkbox-DuDAToKQ.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BKxq1Elq.js → Codegen-DWHT3ZCT.js} +1 -1
- package/src/assets/web-panel/assets/{Col-9_JZdhJl.js → Col-rZ1FbPeP.js} +1 -1
- package/src/assets/web-panel/assets/{Community-RjNSGqVo.js → Community-BHefT_qI.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-COZAt3WB.js → Compact-D68vLPVh.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-hk2sypg0.js → Compliance-cxmKFzWJ.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-9CLNBbEQ.js → Cowork-Dzt1uT50.js} +1 -1
- package/src/assets/web-panel/assets/{Cron-74hvFk4_.js → Cron-oWxj9K9p.js} +1 -1
- package/src/assets/web-panel/assets/{Crosschain-M_9qbH-m.js → Crosschain-C9UdRkm2.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BOx1xBNu.js → DID-D5WEHKMO.js} +1 -1
- package/src/assets/web-panel/assets/{Dashboard-C3KfYy9t.js → Dashboard-dP1_OGh-.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Buk4zcYG.js → Dropdown-C55GjQPR.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-96LSDwN_.js → Federation-oJxrz7TD.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DY7VfLgy.js → FormItemContext-CeLP5Pvz.js} +1 -1
- package/src/assets/web-panel/assets/{Git-KCUcIFj0.js → Git-CWs6CrRt.js} +1 -1
- package/src/assets/web-panel/assets/{Governance--yT5V49L.js → Governance-wo9Gz6OK.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-D0NeQyx6.js → Inference-75Ob1OAF.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DYRq64do.js → KnowledgeGraph-DNw3Xz30.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DHSi_Oi1.js → Logs-Bo7_f07I.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-TT0gv-wI.js → Marketplace-Dm0yQkoQ.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DfCzYzeM.js → McpTools-oh6SZgBB.js} +1 -1
- package/src/assets/web-panel/assets/{Memory-35QBk-VQ.js → Memory-DANDCrzX.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Dvc-7WJs.js → Mtc-4D52E6FP.js} +1 -1
- package/src/assets/web-panel/assets/{MtcAudit-CzTgYL-a.js → MtcAudit-BmlorrLr.js} +1 -1
- package/src/assets/web-panel/assets/{NLProgramming-CrcJekBx.js → NLProgramming-DolGSSOm.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-0B3NXKhh.js → Notes-BTyTq1Qk.js} +1 -1
- package/src/assets/web-panel/assets/{NotificationSettings-KlJUb1mE.js → NotificationSettings-Db1AaWp_.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-COS-etp0.js → Organization-DC4RfB2j.js} +1 -1
- package/src/assets/web-panel/assets/{Overflow-Cy4-usEJ.js → Overflow-cYKtW74T.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-C0_fKvmV.js → P2P-CY5dBoF-.js} +1 -1
- package/src/assets/web-panel/assets/{Permissions-C59VtMDt.js → Permissions-B-U6t8Wf.js} +1 -1
- package/src/assets/web-panel/assets/{Pipeline-BjFugIMn.js → Pipeline-a2pkdq6t.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-tAalWiJA.js → Privacy-ClgLdkPP.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectSettings-CLRVvTkY.js → ProjectSettings-D4Fi9bEQ.js} +1 -1
- package/src/assets/web-panel/assets/{Projects-ByvwUl9Z.js → Projects-BiSWtWMm.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-CP6aUtPG.js → Providers-ydpAao66.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-5wazQ8Rv.js → QuickAsk-Bg955QRg.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Z-lSAvhS.js → Recommend-BqynHnTn.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-DaCrszi3.js → Reputation-B8xfdWQt.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BFHRFhrC.js → Row-D4zoYiqD.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-61djI0cm.js → RssFeed-BI0FPtP6.js} +1 -1
- package/src/assets/web-panel/assets/{Search-B4DqaBN0.js → Search-BG975ISr.js} +1 -1
- package/src/assets/web-panel/assets/{Security-8BvDlsI4.js → Security-BObRR-p6.js} +1 -1
- package/src/assets/web-panel/assets/{Services-BOgC-V6e.js → Services-B2TScn1O.js} +1 -1
- package/src/assets/web-panel/assets/{Skeleton-DxGa2EcF.js → Skeleton-PYzlv5Fw.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DsHzWQAl.js → Skills-DbsTF84K.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-3KdTHpSY.js → Sla-D8q9j9bo.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C8xEI_J4.js → SpeechSettings-CjjNbmVH.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BrTgn_a6.js → SyncSettings-UEp5lB2T.js} +1 -1
- package/src/assets/web-panel/assets/{Tasks-BsatF04-.js → Tasks-CoCW4gWI.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BXG2BXzE.js → Templates-hd7UB-8K.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-OjqSY3OD.js → Tenant-CqebAGfR.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-WrFIqGuF.js → Tokens-9b0DDm86.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-ql7VwBhY.js → Trigger-CG_ZXii2.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BnJxgiUu.js → Trust-CoCtornh.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DI1rcWZ-.js → UkeySign-mBEc6SBj.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C1jgL5fG.js → VideoEditing-41j-ZZYu.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CVMM1wf-.js → Wallet-DX4iBaEj.js} +1 -1
- package/src/assets/web-panel/assets/{WebAuthn-Bz-7j8cP.js → WebAuthn-9BlQYiNI.js} +1 -1
- package/src/assets/web-panel/assets/{WorkflowEditor-B_En7K3B.js → WorkflowEditor-BVm3icIg.js} +1 -1
- package/src/assets/web-panel/assets/chat-D98zBL7S.js +1 -0
- package/src/assets/web-panel/assets/{colors-C-_WCP_I.js → colors-ARL9W9UC.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DRlYnN0j.js → compact-item-MYI7UP_X.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CQjz89ZD.js → createContext-BddTmM7g.js} +1 -1
- package/src/assets/web-panel/assets/{hasIn-DkvrU3Ng.js → hasIn-2OsB0OBj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dp-9lS6Q.js → index-B5UMIkIp.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_UyFEni.js → index-B7XKJHg8.js} +1 -1
- package/src/assets/web-panel/assets/{index-nqPi_FUF.js → index-BA8yc-bG.js} +1 -1
- package/src/assets/web-panel/assets/{index-gyq6o1eH.js → index-BIpkHBFo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPtmPFwc.js → index-BKl1SKpb.js} +4 -4
- package/src/assets/web-panel/assets/{index-DEEKNhJo.js → index-BNXp47dX.js} +1 -1
- package/src/assets/web-panel/assets/{index-D8kTtVhG.js → index-BNjLDXWZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-spVYB7ka.js → index-BO0TQWkU.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4WoTHzD.js → index-BP5G8FRT.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bh1pl2no.js → index-BSKiudeY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWrmR8z4.js → index-BYKZplcs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5_IA35Q.js → index-BYbgYr7r.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxGG_QJu.js → index-Bc-fiOB-.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW6aTL_U.js → index-BhgLJAQi.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bm5beO8z.js → index-C5qBLUjM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFWu8Nod.js → index-CHfRLYw8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZ0FDal8.js → index-CISWdYQV.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQJBwuxS.js → index-CXMgUcC_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaKiN39Q.js → index-CndUS0Yo.js} +1 -1
- package/src/assets/web-panel/assets/{index-SGHpg8vZ.js → index-CtCi5cvq.js} +1 -1
- package/src/assets/web-panel/assets/{index-qVl4nFNX.js → index-CuoiTv71.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAWrRKBV.js → index-D2lcW3-z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWnUOEdQ.js → index-DK71wnJK.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAXp9Lwm.js → index-DVB0ott1.js} +1 -1
- package/src/assets/web-panel/assets/{index-eZTZv_mW.js → index-DnL-YqLO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTCCIKB3.js → index-DpAOSmby.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVvcsuh0.js → index-DqCyINtK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BrE6wIhJ.js → index-Dz5ro_F6.js} +1 -1
- package/src/assets/web-panel/assets/index-G5xmB5Af.js +1 -0
- package/src/assets/web-panel/assets/{index-CwYZLSvq.js → index-GxbpL_A7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CreE5ozl.js → index-N8eKGGPN.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcIcrbaL.js → index-N9X-UOF0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DDElQABk.js → index-TepTGolv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Banf4rVv.js → index-awm9n2jp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuutOf_b.js → index-hP2fDMJo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DhAdUGyf.js → index-kNDK9K4y.js} +1 -1
- package/src/assets/web-panel/assets/index-qbPE-_18.js +1 -0
- package/src/assets/web-panel/assets/{index-Dcotn-Yi.js → index-tSE1B4ri.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DzCq75v2.js → initDefaultProps-CJbHV9hH.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CwDCjQBX.js → motion-BTVrWA7N.js} +1 -1
- package/src/assets/web-panel/assets/{move-CiyNq_dM.js → move-CRIIhWv7.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CV_avDvk.js → omit-CDcQHhGi.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BVSL31rv.js → pickAttrs-Dplb8z8U.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-oxkKuQCJ.js → placementArrow-CP1cLg6P.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Dva2arKe.js → responsiveObserve-PFMAIMDu.js} +1 -1
- package/src/assets/web-panel/assets/{slide-FbHwK4f8.js → slide-_CVxhTa3.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Pg-fsC5F.js → statusUtils-6j8grlgm.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CuXdVqkl.js → styleChecker-BbC7i8Sl.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-z-vK8Wcv.js → useFlexGapSupport-Ctha7v2w.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Cr5jQ4qa.js → useFs-CeTUZIh2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-51kseDDa.js → vnode-kefkre4N.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DSlt2Q3p.js → zoom-CZjCXV_O.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/gateways/ws/chat-intent-protocol.js +13 -19
- package/src/gateways/ws/llm-chat-protocol.js +166 -0
- package/src/gateways/ws/llm-creds.js +93 -0
- package/src/gateways/ws/message-dispatcher.js +1 -0
- package/src/gateways/ws/ws-server.js +6 -0
- package/src/lib/chat-core.js +60 -34
- package/src/assets/web-panel/assets/Chat-BhwqdoXy.js +0 -7
- package/src/assets/web-panel/assets/chat-HZBXEHqE.js +0 -1
- package/src/assets/web-panel/assets/index-BrNvQLt8.js +0 -1
- package/src/assets/web-panel/assets/index-DtjB2WpK.js +0 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* llm.chat WS protocol — single-shot streaming chat for cc ui's QuickAsk page.
|
|
3
|
+
*
|
|
4
|
+
* The desktop web-shell has had this topic since `4eaf90137` (Phase 2). cc ui
|
|
5
|
+
* never registered it, so QuickAsk would hit ws.sendStream's 60s idle timer
|
|
6
|
+
* and surface "Stream idle timeout" forever. Filed as a regression report
|
|
7
|
+
* comparing v5.0.3.43 desktop (works) with v5.0.3.44 cc ui (hung) — root
|
|
8
|
+
* cause is the missing handler, not a code regression.
|
|
9
|
+
*
|
|
10
|
+
* Frame shape mirrors the desktop's llm-handlers.js so the SPA's
|
|
11
|
+
* `useLlmChat()` consumer is environment-agnostic:
|
|
12
|
+
*
|
|
13
|
+
* client → server: { id, type:"llm.chat", messages:[{role, content}],
|
|
14
|
+
* sessionId?, options?:{ provider?, model?, baseUrl?,
|
|
15
|
+
* apiKey?, temperature? } }
|
|
16
|
+
*
|
|
17
|
+
* server → client (streaming):
|
|
18
|
+
* { id, type:"llm.chat.chunk", chunk:{ delta, content } }
|
|
19
|
+
* ... per-token ...
|
|
20
|
+
* { id, type:"llm.chat.result", ok:true,
|
|
21
|
+
* result:{ message:{role:"assistant", content}, model, tokens? } }
|
|
22
|
+
*
|
|
23
|
+
* On error before / mid-stream:
|
|
24
|
+
* { id, type:"llm.chat.result", ok:false, error:"<msg>" }
|
|
25
|
+
*
|
|
26
|
+
* Provider resolution (first non-null wins):
|
|
27
|
+
* 1. message.options — explicit provider/model/apiKey from the client
|
|
28
|
+
* 2. server.sessionManager.getSession(sessionId) — set via `cc auth llm`
|
|
29
|
+
* 3. process.env[BUILT_IN_PROVIDERS[provider].apiKeyEnv]
|
|
30
|
+
*
|
|
31
|
+
* Without any source of credentials we send a clean ok:false frame instantly
|
|
32
|
+
* — the user sees an actionable error rather than a 60s hang.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import {
|
|
36
|
+
streamOllama,
|
|
37
|
+
streamOpenAI,
|
|
38
|
+
streamAnthropic,
|
|
39
|
+
} from "../../lib/chat-core.js";
|
|
40
|
+
import { BUILT_IN_PROVIDERS } from "../../lib/llm-providers.js";
|
|
41
|
+
import { resolveLlmCreds } from "./llm-creds.js";
|
|
42
|
+
|
|
43
|
+
function validateMessages(messages) {
|
|
44
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
45
|
+
return "messages_required";
|
|
46
|
+
for (const m of messages) {
|
|
47
|
+
if (
|
|
48
|
+
!m ||
|
|
49
|
+
typeof m !== "object" ||
|
|
50
|
+
typeof m.role !== "string" ||
|
|
51
|
+
typeof m.content !== "string"
|
|
52
|
+
) {
|
|
53
|
+
return "invalid_message_shape";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Streaming handler for `llm.chat`. The dispatcher invokes it; we own the
|
|
61
|
+
* full frame protocol (chunks + terminal result) so the consumer-side
|
|
62
|
+
* useLlmChat() works unchanged whether the WS gateway is desktop's
|
|
63
|
+
* web-shell or cc ui.
|
|
64
|
+
*/
|
|
65
|
+
export async function handleLlmChat(server, id, ws, message) {
|
|
66
|
+
const topic = "llm.chat";
|
|
67
|
+
const send = (frame) => server._send(ws, { id, ...frame });
|
|
68
|
+
|
|
69
|
+
const validationError = validateMessages(message?.messages);
|
|
70
|
+
if (validationError) {
|
|
71
|
+
send({ type: `${topic}.result`, ok: false, error: validationError });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const creds = resolveLlmCreds(server, message);
|
|
76
|
+
if (!creds || !creds.provider) {
|
|
77
|
+
send({
|
|
78
|
+
type: `${topic}.result`,
|
|
79
|
+
ok: false,
|
|
80
|
+
error:
|
|
81
|
+
"no_llm_provider_configured: pass options.provider + apiKey, sessionId with creds, or set <PROVIDER>_API_KEY env",
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (creds.provider !== "ollama" && !creds.apiKey) {
|
|
87
|
+
const envHint = BUILT_IN_PROVIDERS[creds.provider]?.apiKeyEnv;
|
|
88
|
+
send({
|
|
89
|
+
type: `${topic}.result`,
|
|
90
|
+
ok: false,
|
|
91
|
+
error: `missing_api_key for ${creds.provider}${envHint ? ` (set ${envHint})` : ""}`,
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let accumulator = "";
|
|
97
|
+
const onToken = (token) => {
|
|
98
|
+
if (typeof token !== "string" || token.length === 0) return;
|
|
99
|
+
accumulator += token;
|
|
100
|
+
send({
|
|
101
|
+
type: `${topic}.chunk`,
|
|
102
|
+
chunk: { delta: token, content: accumulator },
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
let usage = null;
|
|
107
|
+
const onUsage = (u) => {
|
|
108
|
+
usage = u;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const baseUrl = creds.baseUrl || "http://localhost:11434";
|
|
113
|
+
if (creds.provider === "ollama") {
|
|
114
|
+
await streamOllama(
|
|
115
|
+
message.messages,
|
|
116
|
+
creds.model,
|
|
117
|
+
baseUrl,
|
|
118
|
+
onToken,
|
|
119
|
+
onUsage,
|
|
120
|
+
);
|
|
121
|
+
} else if (creds.provider === "anthropic") {
|
|
122
|
+
const def = BUILT_IN_PROVIDERS.anthropic;
|
|
123
|
+
const url = baseUrl !== "http://localhost:11434" ? baseUrl : def.baseUrl;
|
|
124
|
+
await streamAnthropic(
|
|
125
|
+
message.messages,
|
|
126
|
+
creds.model,
|
|
127
|
+
url,
|
|
128
|
+
creds.apiKey,
|
|
129
|
+
onToken,
|
|
130
|
+
onUsage,
|
|
131
|
+
);
|
|
132
|
+
} else {
|
|
133
|
+
// OpenAI-compatible — covers openai / volcengine / deepseek / dashscope /
|
|
134
|
+
// kimi / minimax / mistral / custom. baseUrl from creds; default-from
|
|
135
|
+
// BUILT_IN_PROVIDERS already applied above.
|
|
136
|
+
const def = BUILT_IN_PROVIDERS[creds.provider];
|
|
137
|
+
const url = baseUrl !== "http://localhost:11434" ? baseUrl : def?.baseUrl;
|
|
138
|
+
await streamOpenAI(
|
|
139
|
+
message.messages,
|
|
140
|
+
creds.model,
|
|
141
|
+
url,
|
|
142
|
+
creds.apiKey,
|
|
143
|
+
onToken,
|
|
144
|
+
onUsage,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
send({
|
|
149
|
+
type: `${topic}.result`,
|
|
150
|
+
ok: true,
|
|
151
|
+
result: {
|
|
152
|
+
message: { role: "assistant", content: accumulator },
|
|
153
|
+
model: creds.model,
|
|
154
|
+
provider: creds.provider,
|
|
155
|
+
tokens: usage?.outputTokens ?? null,
|
|
156
|
+
promptTokens: usage?.inputTokens ?? null,
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
} catch (err) {
|
|
160
|
+
send({
|
|
161
|
+
type: `${topic}.result`,
|
|
162
|
+
ok: false,
|
|
163
|
+
error: err?.message || String(err),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared LLM credential resolver for WS handlers.
|
|
3
|
+
*
|
|
4
|
+
* Used by both `llm.chat` (single-shot streaming) and `chat.intent.*`
|
|
5
|
+
* (intent-understanding flow). Encapsulates the precedence rules so adding
|
|
6
|
+
* a third consumer doesn't fork them again.
|
|
7
|
+
*
|
|
8
|
+
* Resolution order (first non-null wins):
|
|
9
|
+
* 1. Explicit `message.options.{provider,model,baseUrl,apiKey}` from client.
|
|
10
|
+
* 2. WS session creds via `server.sessionManager.getSession(sessionId)`.
|
|
11
|
+
* 3. Process env — first BUILT_IN_PROVIDERS entry whose apiKeyEnv is set.
|
|
12
|
+
*
|
|
13
|
+
* Fall-throughs:
|
|
14
|
+
* - Provider with `free: true` (ollama) doesn't need apiKey; a session
|
|
15
|
+
* entry with provider=ollama and no apiKey is valid.
|
|
16
|
+
* - For non-ollama providers, missing apiKey is a fatal — the caller
|
|
17
|
+
* should send a clean error frame instead of hanging on a 401.
|
|
18
|
+
* - When no source has any creds, returns null. Caller decides whether
|
|
19
|
+
* to fail-fast (llm.chat) or yield "LLM not configured" (chat-intent).
|
|
20
|
+
*
|
|
21
|
+
* @returns {{provider, model, baseUrl, apiKey} | null}
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { BUILT_IN_PROVIDERS } from "../../lib/llm-providers.js";
|
|
25
|
+
|
|
26
|
+
const ENV_PREFERRED_ORDER = [
|
|
27
|
+
"volcengine",
|
|
28
|
+
"openai",
|
|
29
|
+
"anthropic",
|
|
30
|
+
"deepseek",
|
|
31
|
+
"dashscope",
|
|
32
|
+
"gemini",
|
|
33
|
+
"kimi",
|
|
34
|
+
"minimax",
|
|
35
|
+
"mistral",
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
export function resolveLlmCreds(server, message) {
|
|
39
|
+
const opts = message?.options || {};
|
|
40
|
+
const optProvider = opts.provider;
|
|
41
|
+
const optModel = opts.model;
|
|
42
|
+
const optBaseUrl = opts.baseUrl;
|
|
43
|
+
const optApiKey = opts.apiKey;
|
|
44
|
+
|
|
45
|
+
if (optProvider) {
|
|
46
|
+
const def = BUILT_IN_PROVIDERS[optProvider];
|
|
47
|
+
return {
|
|
48
|
+
provider: optProvider,
|
|
49
|
+
model: optModel || def?.models?.[0] || null,
|
|
50
|
+
baseUrl: optBaseUrl || def?.baseUrl || null,
|
|
51
|
+
apiKey: optApiKey || (def?.apiKeyEnv ? process.env[def.apiKeyEnv] : null),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const sessionId = message?.sessionId;
|
|
56
|
+
if (sessionId && server?.sessionManager?.getSession) {
|
|
57
|
+
let session;
|
|
58
|
+
try {
|
|
59
|
+
session = server.sessionManager.getSession(sessionId);
|
|
60
|
+
} catch {
|
|
61
|
+
session = null;
|
|
62
|
+
}
|
|
63
|
+
if (session?.provider) {
|
|
64
|
+
const def = BUILT_IN_PROVIDERS[session.provider];
|
|
65
|
+
// Don't default baseUrl to ollama — that breaks every cloud provider
|
|
66
|
+
// when the session was created without an explicit baseUrl. Fall back
|
|
67
|
+
// to the provider's own default endpoint instead.
|
|
68
|
+
const fallbackBase =
|
|
69
|
+
def?.baseUrl ||
|
|
70
|
+
(session.provider === "ollama" ? "http://localhost:11434" : null);
|
|
71
|
+
return {
|
|
72
|
+
provider: session.provider,
|
|
73
|
+
model: optModel || session.model,
|
|
74
|
+
baseUrl: session.baseUrl || fallbackBase,
|
|
75
|
+
apiKey: session.apiKey,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
for (const name of ENV_PREFERRED_ORDER) {
|
|
81
|
+
const def = BUILT_IN_PROVIDERS[name];
|
|
82
|
+
if (def?.apiKeyEnv && process.env[def.apiKeyEnv]) {
|
|
83
|
+
return {
|
|
84
|
+
provider: name,
|
|
85
|
+
model: optModel || def.models?.[0] || null,
|
|
86
|
+
baseUrl: def.baseUrl,
|
|
87
|
+
apiKey: process.env[def.apiKeyEnv],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
@@ -96,6 +96,7 @@ export function createWsMessageDispatcher(server) {
|
|
|
96
96
|
server._handleChatIntentUnderstandStream(id, ws, message),
|
|
97
97
|
"chat.intent.classify-followup": () =>
|
|
98
98
|
server._handleChatIntentClassifyFollowup(id, ws, message),
|
|
99
|
+
"llm.chat": () => server._handleLlmChat(id, ws, message),
|
|
99
100
|
};
|
|
100
101
|
|
|
101
102
|
// Phase I — Hosted Session API streaming routes (stream.run).
|
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
handleChatIntentUnderstandStream,
|
|
80
80
|
handleChatIntentClassifyFollowup,
|
|
81
81
|
} from "./chat-intent-protocol.js";
|
|
82
|
+
import { handleLlmChat } from "./llm-chat-protocol.js";
|
|
82
83
|
|
|
83
84
|
const __filename = fileURLToPath(import.meta.url);
|
|
84
85
|
const __dirname = dirname(__filename);
|
|
@@ -519,6 +520,11 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
519
520
|
return handleChatIntentClassifyFollowup(this, id, ws, message);
|
|
520
521
|
}
|
|
521
522
|
|
|
523
|
+
/** @private — single-shot streaming chat for QuickAsk (`llm.chat` topic) */
|
|
524
|
+
async _handleLlmChat(id, ws, message) {
|
|
525
|
+
return handleLlmChat(this, id, ws, message);
|
|
526
|
+
}
|
|
527
|
+
|
|
522
528
|
/** @private */
|
|
523
529
|
_handleAuth(clientId, ws, message) {
|
|
524
530
|
const { id, token } = message;
|
package/src/lib/chat-core.js
CHANGED
|
@@ -242,26 +242,39 @@ export async function streamAnthropic(
|
|
|
242
242
|
export async function* chatStream(messages, options) {
|
|
243
243
|
const { provider, model, baseUrl, apiKey, sessionId } = options;
|
|
244
244
|
|
|
245
|
-
|
|
245
|
+
// Token queue + waiter promise. onToken (called synchronously by each
|
|
246
|
+
// streamX impl per delta) pushes onto the queue and wakes the generator
|
|
247
|
+
// loop, which yields immediately. Pre-v5.0.3.46 this was a buffering
|
|
248
|
+
// tokens[] array drained only after `await streamX(...)` resolved — so
|
|
249
|
+
// the "stream" surfaced no progress until the LLM call finished, which
|
|
250
|
+
// showed up as the chat.intent placeholder card spinning at "意图: 未识别"
|
|
251
|
+
// for the full LLM duration.
|
|
252
|
+
const queue = [];
|
|
253
|
+
let waiter = null;
|
|
254
|
+
let done = false;
|
|
255
|
+
let capturedUsage = null;
|
|
256
|
+
|
|
257
|
+
const wake = () => {
|
|
258
|
+
if (!waiter) return;
|
|
259
|
+
const w = waiter;
|
|
260
|
+
waiter = null;
|
|
261
|
+
w();
|
|
262
|
+
};
|
|
246
263
|
const onToken = (token) => {
|
|
247
|
-
|
|
264
|
+
queue.push(token);
|
|
265
|
+
wake();
|
|
248
266
|
};
|
|
249
|
-
|
|
250
|
-
let capturedUsage = null;
|
|
251
267
|
const onUsage = (u) => {
|
|
252
268
|
capturedUsage = u;
|
|
253
269
|
};
|
|
254
270
|
|
|
255
|
-
|
|
256
|
-
|
|
271
|
+
// Validate creds + assemble URL synchronously so missing-key errors
|
|
272
|
+
// surface immediately to the consumer instead of being deferred until
|
|
273
|
+
// the first queue drain tick.
|
|
274
|
+
let providerCall;
|
|
257
275
|
if (provider === "ollama") {
|
|
258
|
-
|
|
259
|
-
messages,
|
|
260
|
-
model,
|
|
261
|
-
baseUrl,
|
|
262
|
-
onToken,
|
|
263
|
-
onUsage,
|
|
264
|
-
);
|
|
276
|
+
providerCall = () =>
|
|
277
|
+
streamOllama(messages, model, baseUrl, onToken, onUsage);
|
|
265
278
|
} else if (provider === "anthropic") {
|
|
266
279
|
const providerDef = BUILT_IN_PROVIDERS.anthropic;
|
|
267
280
|
const url =
|
|
@@ -276,14 +289,8 @@ export async function* chatStream(messages, options) {
|
|
|
276
289
|
`API key required for anthropic (set ${providerDef?.apiKeyEnv || "ANTHROPIC_API_KEY"})`,
|
|
277
290
|
);
|
|
278
291
|
}
|
|
279
|
-
|
|
280
|
-
messages,
|
|
281
|
-
model,
|
|
282
|
-
url,
|
|
283
|
-
key,
|
|
284
|
-
onToken,
|
|
285
|
-
onUsage,
|
|
286
|
-
);
|
|
292
|
+
providerCall = () =>
|
|
293
|
+
streamAnthropic(messages, model, url, key, onToken, onUsage);
|
|
287
294
|
} else {
|
|
288
295
|
const providerDef = BUILT_IN_PROVIDERS[provider];
|
|
289
296
|
const url =
|
|
@@ -298,16 +305,40 @@ export async function* chatStream(messages, options) {
|
|
|
298
305
|
`API key required for ${provider} (set ${providerDef?.apiKeyEnv || "API key"})`,
|
|
299
306
|
);
|
|
300
307
|
}
|
|
301
|
-
|
|
302
|
-
messages,
|
|
303
|
-
model,
|
|
304
|
-
url,
|
|
305
|
-
key,
|
|
306
|
-
onToken,
|
|
307
|
-
onUsage,
|
|
308
|
-
);
|
|
308
|
+
providerCall = () =>
|
|
309
|
+
streamOpenAI(messages, model, url, key, onToken, onUsage);
|
|
309
310
|
}
|
|
310
311
|
|
|
312
|
+
// Run the provider stream concurrently with the queue-drain loop. finally
|
|
313
|
+
// flips `done` and wakes the waiter so a stream that ends without emitting
|
|
314
|
+
// any token still terminates the generator cleanly.
|
|
315
|
+
const streamPromise = (async () => {
|
|
316
|
+
try {
|
|
317
|
+
return await providerCall();
|
|
318
|
+
} finally {
|
|
319
|
+
done = true;
|
|
320
|
+
wake();
|
|
321
|
+
}
|
|
322
|
+
})();
|
|
323
|
+
// Swallow-only handler so an early rejection isn't logged as unhandled
|
|
324
|
+
// before the consumer reaches `await streamPromise` below. The eventual
|
|
325
|
+
// await still rethrows.
|
|
326
|
+
streamPromise.catch(() => {});
|
|
327
|
+
|
|
328
|
+
while (true) {
|
|
329
|
+
if (queue.length > 0) {
|
|
330
|
+
yield { type: "response-token", token: queue.shift() };
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (done) break;
|
|
334
|
+
await new Promise((resolve) => {
|
|
335
|
+
waiter = resolve;
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Rethrows if providerCall rejected.
|
|
340
|
+
const fullResponse = await streamPromise;
|
|
341
|
+
|
|
311
342
|
// Phase J — auto-record token usage to JSONL session store so
|
|
312
343
|
// `cc session usage` and the `usage.*` WS routes see real data.
|
|
313
344
|
if (sessionId && capturedUsage) {
|
|
@@ -325,11 +356,6 @@ export async function* chatStream(messages, options) {
|
|
|
325
356
|
}
|
|
326
357
|
}
|
|
327
358
|
|
|
328
|
-
// Yield all collected tokens
|
|
329
|
-
for (const token of tokens) {
|
|
330
|
-
yield { type: "response-token", token };
|
|
331
|
-
}
|
|
332
|
-
|
|
333
359
|
yield { type: "response-complete", content: fullResponse };
|
|
334
360
|
}
|
|
335
361
|
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import{L as l,M as m,R as f,Q as z,u as _,P as u,S as O,Z as Y,f as k,w as Z,o as ge,n as W,x as Me,$ as ae,F as G,Y as J,U as de,r as L,K as D,c as y,N as w,O as A,a0 as Oe,a1 as ze,H as Ee,I as Ae,a as Te}from"./vendor-Ci2pTZ_t.js";import{_ as ee,b as Fe}from"./index-BPtmPFwc.js";import{u as Re,M as Pe}from"./chat-HZBXEHqE.js";import{a as qe,L as ye,w as je,ad as De,ae as Le,f as Ne,c as We,p as Be,af as he,ag as Ve,b as He,F as fe,G as me,M as Ue,aa as pe,k as Qe,ah as Ke,ai as Ge}from"./icons-B2G69bhT.js";import{r as Je}from"./markdown-vYH_ziAO.js";import"./markdown-xjUYbPSW.js";const Xe=["data-testid"],Ye={class:"cb-action__icon"},Ze={class:"cb-action__label"},et={key:0,class:"cb-action__detail"},tt={key:1,class:"cb-action__caret"},st={__name:"ToolInvocationCard",props:{item:{type:Object,required:!0},expandable:{type:Boolean,default:!1},expanded:{type:Boolean,default:!1}},emits:["toggle"],setup(c,{emit:g}){const e=c,t=g;function s(){e.expandable&&t("toggle")}return(n,i)=>(l(),m("div",{class:Y(["cb-action",[`cb-action--${c.item.status}`,{"cb-action--expandable":c.expandable,"cb-action--open":c.expanded}]]),"data-testid":`tool-card-${c.item.id}`,onClick:s},[f("span",Ye,[c.item.status==="done"?(l(),z(_(qe),{key:0})):c.item.status==="running"?(l(),z(_(ye),{key:1})):(l(),z(_(je),{key:2}))]),f("span",Ze,u(c.item.label),1),c.item.detail?(l(),m("span",et,u(c.item.detail),1)):O("",!0),c.expandable?(l(),m("span",tt,[c.expanded?(l(),z(_(De),{key:0})):(l(),z(_(Le),{key:1}))])):O("",!0)],10,Xe))}},nt=ee(st,[["__scopeId","data-v-cf5a0925"]]),it=["innerHTML"],ot={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(c){const g=c,e=k(()=>Je(g.content||""));return(t,s)=>(l(),m("div",{class:"markdown-content",innerHTML:e.value},null,8,it))}},at=ee(ot,[["__scopeId","data-v-693ca57e"]]);function K(c,g,e){let t=e.initialDeps??[],s,n=!0;function i(){var a,r,I;let S;e.key&&((a=e.debug)!=null&&a.call(e))&&(S=Date.now());const b=c();if(!(b.length!==t.length||b.some((v,x)=>t[x]!==v)))return s;t=b;let d;if(e.key&&((r=e.debug)!=null&&r.call(e))&&(d=Date.now()),s=g(...b),e.key&&((I=e.debug)!=null&&I.call(e))){const v=Math.round((Date.now()-S)*100)/100,x=Math.round((Date.now()-d)*100)/100,M=x/16,T=(E,P)=>{for(E=String(E);E.length<P;)E=" "+E;return E};console.info(`%c⏱ ${T(x,5)} /${T(v,5)} ms`,`
|
|
2
|
-
font-size: .6rem;
|
|
3
|
-
font-weight: bold;
|
|
4
|
-
color: hsl(${Math.max(0,Math.min(120-120*M,120))}deg 100% 31%);`,e?.key)}return e?.onChange&&!(n&&e.skipInitialOnChange)&&e.onChange(s),n=!1,s}return i.updateDeps=a=>{t=a},i}function ve(c,g){if(c===void 0)throw new Error("Unexpected undefined");return c}const lt=(c,g)=>Math.abs(c-g)<1.01,rt=c=>c,ct=c=>{const g=Math.max(c.startIndex-c.overscan,0),e=Math.min(c.endIndex+c.overscan,c.count-1),t=[];for(let s=g;s<=e;s++)t.push(s);return t},ut=(c,g,e)=>{if(g?.borderBoxSize){const t=g.borderBoxSize[0];if(t)return Math.round(t[e.options.horizontal?"inlineSize":"blockSize"])}return c[e.options.horizontal?"offsetWidth":"offsetHeight"]};class dt{constructor(g){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.scrollState=null,this.measurementsCache=[],this.itemSizeCache=new Map,this.laneAssignments=new Map,this.pendingMeasuredCacheIndexes=[],this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this.elementsCache=new Map,this.now=()=>{var e,t,s;return((s=(t=(e=this.targetWindow)==null?void 0:e.performance)==null?void 0:t.now)==null?void 0:s.call(t))??Date.now()},this.observer=(()=>{let e=null;const t=()=>e||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:e=new this.targetWindow.ResizeObserver(s=>{s.forEach(n=>{const i=()=>{const a=n.target,r=this.indexFromElement(a);if(!a.isConnected){this.observer.unobserve(a);return}this.shouldMeasureDuringScroll(r)&&this.resizeItem(r,this.options.measureElement(a,n,this))};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(i):i()})}));return{disconnect:()=>{var s;(s=t())==null||s.disconnect(),e=null},observe:s=>{var n;return(n=t())==null?void 0:n.observe(s,{box:"border-box"})},unobserve:s=>{var n;return(n=t())==null?void 0:n.unobserve(s)}}})(),this.range=null,this.setOptions=e=>{Object.entries(e).forEach(([t,s])=>{typeof s>"u"&&delete e[t]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:rt,rangeExtractor:ct,onChange:()=>{},measureElement:ut,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,laneAssignmentMode:"estimate",...e}},this.notify=e=>{var t,s;(s=(t=this.options).onChange)==null||s.call(t,this,e)},this.maybeNotify=K(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),e=>{this.notify(e)},{key:!1,debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(e=>e()),this.unsubs=[],this.observer.disconnect(),this.rafId!=null&&this.targetWindow&&(this.targetWindow.cancelAnimationFrame(this.rafId),this.rafId=null),this.scrollState=null,this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var e;const t=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==t){if(this.cleanup(),!t){this.maybeNotify();return}this.scrollElement=t,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((e=this.scrollElement)==null?void 0:e.window)??null,this.elementsCache.forEach(s=>{this.observer.observe(s)}),this.unsubs.push(this.options.observeElementRect(this,s=>{this.scrollRect=s,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(s,n)=>{this.scrollAdjustments=0,this.scrollDirection=n?this.getScrollOffset()<s?"forward":"backward":null,this.scrollOffset=s,this.isScrolling=n,this.scrollState&&this.scheduleScrollReconcile(),this.maybeNotify()})),this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}},this.rafId=null,this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(e,t)=>{const s=new Map,n=new Map;for(let i=t-1;i>=0;i--){const a=e[i];if(s.has(a.lane))continue;const r=n.get(a.lane);if(r==null||a.end>r.end?n.set(a.lane,a):a.end<r.end&&s.set(a.lane,!0),s.size===this.options.lanes)break}return n.size===this.options.lanes?Array.from(n.values()).sort((i,a)=>i.end===a.end?i.index-a.index:i.end-a.end)[0]:void 0},this.getMeasurementOptions=K(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes,this.options.laneAssignmentMode],(e,t,s,n,i,a,r)=>(this.prevLanes!==void 0&&this.prevLanes!==a&&(this.lanesChangedFlag=!0),this.prevLanes=a,this.pendingMeasuredCacheIndexes=[],{count:e,paddingStart:t,scrollMargin:s,getItemKey:n,enabled:i,lanes:a,laneAssignmentMode:r}),{key:!1}),this.getMeasurements=K(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:e,paddingStart:t,scrollMargin:s,getItemKey:n,enabled:i,lanes:a,laneAssignmentMode:r},I)=>{if(!i)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>e)for(const d of this.laneAssignments.keys())d>=e&&this.laneAssignments.delete(d);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMeasuredCacheIndexes=[]),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(d=>{this.itemSizeCache.set(d.key,d.size)}));const S=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===e&&(this.lanesSettling=!1);const b=this.measurementsCache.slice(0,S),R=new Array(a).fill(void 0);for(let d=0;d<S;d++){const v=b[d];v&&(R[v.lane]=d)}for(let d=S;d<e;d++){const v=n(d),x=this.laneAssignments.get(d);let M,T;const E=r==="estimate"||I.has(v);if(x!==void 0&&this.options.lanes>1){M=x;const C=R[M],B=C!==void 0?b[C]:void 0;T=B?B.end+this.options.gap:t+s}else{const C=this.options.lanes===1?b[d-1]:this.getFurthestMeasurement(b,d);T=C?C.end+this.options.gap:t+s,M=C?C.lane:d%this.options.lanes,this.options.lanes>1&&E&&this.laneAssignments.set(d,M)}const P=I.get(v),H=typeof P=="number"?P:this.options.estimateSize(d),q=T+H;b[d]={index:d,start:T,size:H,end:q,key:v,lane:M},R[M]=d}return this.measurementsCache=b,b},{key:!1,debug:()=>this.options.debug}),this.calculateRange=K(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(e,t,s,n)=>this.range=e.length>0&&t>0?ht({measurements:e,outerSize:t,scrollOffset:s,lanes:n}):null,{key:!1,debug:()=>this.options.debug}),this.getVirtualIndexes=K(()=>{let e=null,t=null;const s=this.calculateRange();return s&&(e=s.startIndex,t=s.endIndex),this.maybeNotify.updateDeps([this.isScrolling,e,t]),[this.options.rangeExtractor,this.options.overscan,this.options.count,e,t]},(e,t,s,n,i)=>n===null||i===null?[]:e({startIndex:n,endIndex:i,overscan:t,count:s}),{key:!1,debug:()=>this.options.debug}),this.indexFromElement=e=>{const t=this.options.indexAttribute,s=e.getAttribute(t);return s?parseInt(s,10):(console.warn(`Missing attribute name '${t}={index}' on measured element.`),-1)},this.shouldMeasureDuringScroll=e=>{var t;if(!this.scrollState||this.scrollState.behavior!=="smooth")return!0;const s=this.scrollState.index??((t=this.getVirtualItemForOffset(this.scrollState.lastTargetOffset))==null?void 0:t.index);if(s!==void 0&&this.range){const n=Math.max(this.options.overscan,Math.ceil((this.range.endIndex-this.range.startIndex)/2)),i=Math.max(0,s-n),a=Math.min(this.options.count-1,s+n);return e>=i&&e<=a}return!0},this.measureElement=e=>{if(!e){this.elementsCache.forEach((i,a)=>{i.isConnected||(this.observer.unobserve(i),this.elementsCache.delete(a))});return}const t=this.indexFromElement(e),s=this.options.getItemKey(t),n=this.elementsCache.get(s);n!==e&&(n&&this.observer.unobserve(n),this.observer.observe(e),this.elementsCache.set(s,e)),(!this.isScrolling||this.scrollState)&&this.shouldMeasureDuringScroll(t)&&this.resizeItem(t,this.options.measureElement(e,void 0,this))},this.resizeItem=(e,t)=>{var s;const n=this.measurementsCache[e];if(!n)return;const i=this.itemSizeCache.get(n.key)??n.size,a=t-i;a!==0&&(((s=this.scrollState)==null?void 0:s.behavior)!=="smooth"&&(this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(n,a,this):n.start<this.getScrollOffset()+this.scrollAdjustments)&&this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=a,behavior:void 0}),this.pendingMeasuredCacheIndexes.push(n.index),this.itemSizeCache=new Map(this.itemSizeCache.set(n.key,t)),this.notify(!1))},this.getVirtualItems=K(()=>[this.getVirtualIndexes(),this.getMeasurements()],(e,t)=>{const s=[];for(let n=0,i=e.length;n<i;n++){const a=e[n],r=t[a];s.push(r)}return s},{key:!1,debug:()=>this.options.debug}),this.getVirtualItemForOffset=e=>{const t=this.getMeasurements();if(t.length!==0)return ve(t[_e(0,t.length-1,s=>ve(t[s]).start,e)])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const e=this.scrollElement.document.documentElement;return this.options.horizontal?e.scrollWidth-this.scrollElement.innerWidth:e.scrollHeight-this.scrollElement.innerHeight}},this.getOffsetForAlignment=(e,t,s=0)=>{if(!this.scrollElement)return 0;const n=this.getSize(),i=this.getScrollOffset();t==="auto"&&(t=e>=i+n?"end":"start"),t==="center"?e+=(s-n)/2:t==="end"&&(e-=n);const a=this.getMaxScrollOffset();return Math.max(Math.min(a,e),0)},this.getOffsetForIndex=(e,t="auto")=>{e=Math.max(0,Math.min(e,this.options.count-1));const s=this.getSize(),n=this.getScrollOffset(),i=this.measurementsCache[e];if(!i)return;if(t==="auto")if(i.end>=n+s-this.options.scrollPaddingEnd)t="end";else if(i.start<=n+this.options.scrollPaddingStart)t="start";else return[n,t];if(t==="end"&&e===this.options.count-1)return[this.getMaxScrollOffset(),t];const a=t==="end"?i.end+this.options.scrollPaddingEnd:i.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(a,t,i.size),t]},this.scrollToOffset=(e,{align:t="start",behavior:s="auto"}={})=>{const n=this.getOffsetForAlignment(e,t),i=this.now();this.scrollState={index:null,align:t,behavior:s,startedAt:i,lastTargetOffset:n,stableFrames:0},this._scrollToOffset(n,{adjustments:void 0,behavior:s}),this.scheduleScrollReconcile()},this.scrollToIndex=(e,{align:t="auto",behavior:s="auto"}={})=>{e=Math.max(0,Math.min(e,this.options.count-1));const n=this.getOffsetForIndex(e,t);if(!n)return;const[i,a]=n,r=this.now();this.scrollState={index:e,align:a,behavior:s,startedAt:r,lastTargetOffset:i,stableFrames:0},this._scrollToOffset(i,{adjustments:void 0,behavior:s}),this.scheduleScrollReconcile()},this.scrollBy=(e,{behavior:t="auto"}={})=>{const s=this.getScrollOffset()+e,n=this.now();this.scrollState={index:null,align:"start",behavior:t,startedAt:n,lastTargetOffset:s,stableFrames:0},this._scrollToOffset(s,{adjustments:void 0,behavior:t}),this.scheduleScrollReconcile()},this.getTotalSize=()=>{var e;const t=this.getMeasurements();let s;if(t.length===0)s=this.options.paddingStart;else if(this.options.lanes===1)s=((e=t[t.length-1])==null?void 0:e.end)??0;else{const n=Array(this.options.lanes).fill(null);let i=t.length-1;for(;i>=0&&n.some(a=>a===null);){const a=t[i];n[a.lane]===null&&(n[a.lane]=a.end),i--}s=Math.max(...n.filter(a=>a!==null))}return Math.max(s-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(e,{adjustments:t,behavior:s})=>{this.options.scrollToFn(e,{behavior:s,adjustments:t},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(g)}scheduleScrollReconcile(){if(!this.targetWindow){this.scrollState=null;return}this.rafId==null&&(this.rafId=this.targetWindow.requestAnimationFrame(()=>{this.rafId=null,this.reconcileScroll()}))}reconcileScroll(){if(!this.scrollState||!this.scrollElement)return;if(this.now()-this.scrollState.startedAt>5e3){this.scrollState=null;return}const t=this.scrollState.index!=null?this.getOffsetForIndex(this.scrollState.index,this.scrollState.align):void 0,s=t?t[0]:this.scrollState.lastTargetOffset,n=1,i=s!==this.scrollState.lastTargetOffset;if(!i&<(s,this.getScrollOffset())){if(this.scrollState.stableFrames++,this.scrollState.stableFrames>=n){this.scrollState=null;return}}else this.scrollState.stableFrames=0,i&&(this.scrollState.lastTargetOffset=s,this.scrollState.behavior="auto",this._scrollToOffset(s,{adjustments:void 0,behavior:"auto"}));this.scheduleScrollReconcile()}}const _e=(c,g,e,t)=>{for(;c<=g;){const s=(c+g)/2|0,n=e(s);if(n<t)c=s+1;else if(n>t)g=s-1;else return s}return c>0?c-1:0};function ht({measurements:c,outerSize:g,scrollOffset:e,lanes:t}){const s=c.length-1,n=r=>c[r].start;if(c.length<=t)return{startIndex:0,endIndex:s};let i=_e(0,s,n,e),a=i;if(t===1)for(;a<s&&c[a].end<e+g;)a++;else if(t>1){const r=Array(t).fill(0);for(;a<s&&r.some(S=>S<e+g);){const S=c[a];r[S.lane]=S.end,a++}const I=Array(t).fill(e+g);for(;i>=0&&I.some(S=>S>=e);){const S=c[i];I[S.lane]=S.start,i--}i=Math.max(0,i-i%t),a=Math.min(s,a+(t-1-a%t))}return{startIndex:i,endIndex:a}}const ft={key:1,class:"fallback-list"},mt={__name:"VirtualMessageList",props:{messages:{type:Array,required:!0,default:()=>[]},estimateSize:{type:Number,default:120}},emits:["scroll-to-bottom","load-more"],setup(c,{expose:g,emit:e}){const t=c,s=e,n=L(null),i=L(null),a=L(0),r=k(()=>i.value?(a.value,i.value.getVirtualItems()):[]),I=()=>{if(n.value)try{i.value=new dt({count:t.messages.length,getScrollElement:()=>n.value,estimateSize:()=>t.estimateSize,overscan:5,scrollMargin:0,onChange:()=>{a.value++}}),W(()=>{i.value&&n.value&&(i.value.measure(),a.value++,n.value.scrollTop=1,setTimeout(()=>{n.value&&(n.value.scrollTop=0)},50))})}catch(d){console.error("[VirtualMessageList] init failed:",d)}},S=()=>{if(!n.value)return;i.value&&i.value.measure();const{scrollTop:d,scrollHeight:v,clientHeight:x}=n.value;d<100&&s("load-more"),d+x>=v-50&&s("scroll-to-bottom")},b=()=>{n.value&&requestAnimationFrame(()=>{n.value&&(n.value.scrollTop=n.value.scrollHeight)})},R=d=>{const v=t.messages.findIndex(x=>x.id===d);v!==-1&&i.value&&i.value.scrollToIndex(v,{align:"center"})};return Z(()=>t.messages.length,(d,v)=>{i.value?(i.value.setOptions({count:d,estimateSize:()=>t.estimateSize}),a.value++,d>v&&W(()=>b())):W(()=>{I(),i.value&&a.value++})}),Z(()=>t.messages,d=>{!i.value&&d.length>0?W(()=>I()):i.value&&(i.value.setOptions({count:d.length,estimateSize:()=>t.estimateSize,getScrollElement:()=>n.value,overscan:5,scrollMargin:0,onChange:()=>{a.value++}}),a.value++,W(()=>{i.value&&i.value.measure()}))},{deep:!0}),g({scrollToBottom:b,scrollToMessage:R}),ge(()=>{W(()=>{I(),t.messages.length>0&&b()})}),Me(()=>{i.value&&(i.value=null)}),(d,v)=>(l(),m("div",{ref_key:"scrollContainer",ref:n,class:"virtual-message-list",onScroll:S},[i.value&&r.value.length>0?(l(),m("div",{key:0,style:ae({height:`${i.value.getTotalSize()}px`,width:"100%",position:"relative"})},[(l(!0),m(G,null,J(r.value,x=>(l(),m("div",{key:x.key,style:ae({position:"absolute",top:0,left:0,width:"100%",transform:`translateY(${x.start}px)`})},[de(d.$slots,"default",{message:c.messages[x.index],index:x.index},void 0)],4))),128))],4)):(l(),m("div",ft,[(l(!0),m(G,null,J(c.messages,(x,M)=>(l(),m("div",{key:x.id||M},[de(d.$slots,"default",{message:x,index:M},void 0)]))),128))]))],544))}},pt=ee(mt,[["__scopeId","data-v-3c34170a"]]),vt={class:"intent-confirmation-message"},gt={class:"confirmation-header"},yt={class:"header-icon"},_t={class:"header-text"},bt={key:0},St={key:1},xt={key:2},kt={class:"understanding-content"},Ct={key:0,class:"original-input"},wt={class:"label"},$t={class:"value original-text"},It={key:1,class:"corrected-input"},Mt={class:"label"},Ot={class:"value corrected-text"},zt={class:"intent-section"},Et={class:"label"},At={class:"value"},Tt={key:2,class:"key-points-section"},Ft={class:"label"},Rt={class:"key-points-list"},Pt={key:3,class:"correction-section"},qt={class:"label"},jt={class:"value correction-text"},Dt={key:0,class:"streaming-indicator"},Lt={key:0,class:"streaming-tokens"},Nt={key:1,class:"action-buttons"},Wt={key:2,class:"correction-input-section"},Bt={class:"correction-actions"},Vt={__name:"IntentConfirmationMessage",props:{message:{type:Object,required:!0}},emits:["confirm","correct"],setup(c,{emit:g}){const e=c,t=g,s=L(!1),n=L(""),i=k(()=>e.message.metadata?.originalInput||""),a=k(()=>e.message.metadata?.understanding||{}),r=k(()=>a.value.correctedInput||i.value),I=k(()=>a.value.intent||"未识别"),S=k(()=>a.value.keyPoints||[]),b=k(()=>r.value!==i.value&&i.value.trim()!==""),R=k(()=>e.message.metadata?.status||"pending"),d=k(()=>R.value==="confirmed"),v=k(()=>R.value==="corrected"),x=k(()=>!!e.message.metadata?.streaming),M=k(()=>e.message.metadata?.streamingTokens||0),T=k(()=>e.message.metadata?.correction||null);function E(){t("confirm",{messageId:e.message.id,originalInput:i.value,understanding:a.value})}function P(){s.value=!0,n.value=r.value}function H(){n.value.trim()&&(t("correct",{messageId:e.message.id,originalInput:i.value,correction:n.value}),s.value=!1)}function q(){s.value=!1,n.value=""}return(C,B)=>{const U=D("a-button"),Q=D("a-textarea");return l(),m("div",vt,[f("div",gt,[f("div",yt,[d.value?(l(),z(_(Ne),{key:0,style:{color:"#52c41a"}})):v.value?(l(),z(_(We),{key:1,style:{color:"#faad14"}})):(l(),z(_(Be),{key:2,style:{color:"#1890ff"}}))]),f("div",_t,[d.value?(l(),m("span",bt,u(C.$t("chat.intent.confirmed")),1)):v.value?(l(),m("span",St,u(C.$t("chat.intent.corrected")),1)):(l(),m("span",xt,u(c.message.content),1))])]),f("div",kt,[b.value?(l(),m("div",Ct,[f("div",wt,u(C.$t("chat.intent.label.original")),1),f("div",$t,u(i.value),1)])):O("",!0),b.value?(l(),m("div",It,[f("div",Mt,u(C.$t("chat.intent.label.understood")),1),f("div",Ot,u(r.value),1)])):O("",!0),f("div",zt,[f("div",Et,"🎯 "+u(C.$t("chat.intent.label.intent")),1),f("div",At,u(I.value),1)]),S.value&&S.value.length>0?(l(),m("div",Tt,[f("div",Ft,"📝 "+u(C.$t("chat.intent.label.keyPoints")),1),f("ul",Rt,[(l(!0),m(G,null,J(S.value,(N,ne)=>(l(),m("li",{key:ne},u(N),1))),128))])])):O("",!0),T.value?(l(),m("div",Pt,[f("div",qt,"📝 "+u(C.$t("chat.intent.label.correction")),1),f("div",jt,u(T.value),1)])):O("",!0)]),x.value?(l(),m("div",Dt,[y(_(ye),{spin:""}),f("span",null,u(C.$t("chat.intent.status.understanding")),1),M.value>0?(l(),m("span",Lt,"· "+u(M.value)+" tokens",1)):O("",!0)])):!d.value&&!v.value?(l(),m("div",Nt,[y(U,{type:"primary",onClick:E},{default:w(()=>[y(_(he)),A(" "+u(C.$t("chat.intent.action.confirm")),1)]),_:1}),y(U,{onClick:P},{default:w(()=>[y(_(Ve)),A(" "+u(C.$t("chat.intent.action.correct")),1)]),_:1})])):O("",!0),s.value?(l(),m("div",Wt,[y(Q,{value:n.value,"onUpdate:value":B[0]||(B[0]=N=>n.value=N),placeholder:C.$t("chat.intent.action.correctPlaceholder"),"auto-size":{minRows:2,maxRows:6}},null,8,["value","placeholder"]),f("div",Bt,[y(U,{type:"primary",size:"small",onClick:H},{default:w(()=>[y(_(he)),A(" "+u(C.$t("chat.intent.action.submitCorrection")),1)]),_:1}),y(U,{size:"small",onClick:q},{default:w(()=>[y(_(He)),A(" "+u(C.$t("chat.intent.action.cancelCorrection")),1)]),_:1})])])):O("",!0)])}}},Ht=ee(Vt,[["__scopeId","data-v-ded139e5"]]),Ut={style:{display:"flex",height:"calc(100vh - 56px - 48px)",gap:"16px"}},Qt={style:{width:"240px","flex-shrink":"0",background:"var(--bg-card)","border-radius":"8px",border:"1px solid var(--border-color)",display:"flex","flex-direction":"column",overflow:"hidden"}},Kt={key:0,style:{padding:"6px 12px 4px","font-size":"11px",color:"#1677ff",background:"rgba(22,119,255,.07)","border-bottom":"1px solid rgba(22,119,255,.15)",display:"flex","align-items":"center",gap:"4px"}},Gt=["title"],Jt={key:1,style:{padding:"6px 12px 4px","font-size":"11px",color:"#722ed1",background:"rgba(114,46,209,.07)","border-bottom":"1px solid rgba(114,46,209,.15)",display:"flex","align-items":"center",gap:"4px"}},Xt={style:{padding:"10px 12px","border-bottom":"1px solid var(--border-color)",display:"flex",gap:"8px"}},Yt={style:{flex:"1","overflow-y":"auto",padding:"8px"}},Zt=["onClick"],es={class:"session-icon"},ts={class:"session-info"},ss={class:"session-title"},ns={class:"session-meta"},is={key:0,style:{"text-align":"center",color:"var(--text-muted)",padding:"24px 0","font-size":"13px"}},os={style:{flex:"1",background:"var(--bg-card)","border-radius":"8px",border:"1px solid var(--border-color)",display:"flex","flex-direction":"column",overflow:"hidden"}},as={key:0,style:{flex:"1",display:"flex","flex-direction":"column","align-items":"center","justify-content":"center",color:"var(--text-muted)"}},ls={style:{"font-size":"16px","margin-bottom":"8px",color:"#777"}},rs={style:{"font-size":"13px",color:"var(--text-muted)"}},cs={style:{"margin-top":"24px",display:"flex",gap:"12px"}},us={key:1,class:"chat-header"},ds={key:2,class:"chat-area-body"},hs={key:0,class:"chat-empty-prompts"},fs={class:"empty-title"},ms={class:"empty-hint"},ps={class:"quick-prompts"},vs={key:1,class:"system-banner"},gs={key:2,class:"tool-msg"},ys={key:0,class:"tool-detail"},_s={class:"tool-detail__pre tool-detail__pre--input"},bs={key:0,class:"tool-detail__result"},Ss={class:"tool-detail__pre tool-detail__pre--result"},xs={class:"msg-body"},ks={class:"msg-meta-row"},Cs={class:"msg-role"},ws={class:"msg-time"},$s={key:0,class:"msg-tokens"},Is={key:0,class:"bubble user"},Ms={key:2,class:"question-card"},Os={class:"question-text"},zs={key:0,style:{display:"flex","flex-wrap":"wrap",gap:"8px","margin-top":"10px"}},Es={key:3,style:{padding:"16px","border-top":"1px solid var(--border-color)"}},As={style:{display:"flex",gap:"8px","align-items":"flex-end"}},Ts={style:{"margin-bottom":"8px","font-size":"12px",color:"var(--text-muted)"}},Fs={style:{"margin-top":"8px"}},Rs={__name:"Chat",setup(c){const{t:g,tm:e,rt:t}=Fe(),s=Ee()||null,n=Ae()||null,i=window.__CC_CONFIG__||{},a=k(()=>i.mode==="project"),r=Re(),I=new Set,S=L(null),b=L(""),R=k(()=>r.contextMode);function d(o){r.setContextMode(o)}const v=k(()=>r.currentSessionId),x=k(()=>v.value?r.getMessages(v.value):[]),M=k(()=>{const o=r.streaming[v.value];return o?.active?o.content:null}),T=k(()=>{const o=x.value;return M.value?[...o,{role:"assistant",content:M.value,_streaming:!0,timestamp:Date.now()}]:o}),E=k(()=>r.pendingQuestion[v.value]),P=k(()=>r.getIsLoading(v.value));function H(o){if(!o)return"";const p=new Date(o);return`${String(p.getHours()).padStart(2,"0")}:${String(p.getMinutes()).padStart(2,"0")}`}const q=Te(new Set);function C(o){q.has(o)?q.delete(o):q.add(o)}function B(o,p){return{id:`tool-${p}`,label:o.tool||g("chat.tool.unknownTool"),detail:U(o),status:o.status==="done"?"done":"running"}}function U(o){if(o.status==="running"){const F=o.input&&typeof o.input=="object"?Object.keys(o.input):[];return F.length?g("chat.tool.argsPreview",{n:F.length,key:F[0]}):g("chat.tool.running")}if(o.result==null)return g("chat.tool.done");const $=(typeof o.result=="string"?o.result:JSON.stringify(o.result)).split(`
|
|
5
|
-
`)[0]||"";return $.length>48?`${$.slice(0,48)}…`:$||g("chat.tool.done")}async function Q(o){await r.createSession(o)}async function N(){if(!b.value.trim()||P.value||!v.value)return;const o=b.value;b.value="",await r.submitUserInput(v.value,o)}function ne(o){r.confirmIntent(v.value,o.messageId)}function be(o){r.correctIntent(v.value,o.messageId,o.correction)}const le=k(()=>{const o=r.customQuickPrompts;if(Array.isArray(o)&&o.length>0)return o;const p=e("chat.quickPrompts");return p?Object.values(p).map($=>t($)):[]}),X=L(!1),te=L("");function Se(){te.value=le.value.join(`
|
|
6
|
-
`),X.value=!0}function xe(){const o=te.value.split(`
|
|
7
|
-
`).map(p=>p.trim()).filter(p=>p.length>0);r.setCustomQuickPrompts(o.length>0?o:null),X.value=!1}function ke(){r.setCustomQuickPrompts(null),X.value=!1}const Ce=k(()=>g(`chat.empty.hint.${R.value}`));async function we(o){v.value||await r.createSession("chat"),b.value=o,await N()}function re(o){r.answerQuestion(v.value,o)}Z([x,M],()=>{W(()=>{S.value?.scrollToBottom()})},{deep:!0});async function ce({prompt:o,autoSend:p,session:$,token:F}){if(!o||I.has(F))return;I.add(F);let j=$||v.value;j?j!==v.value&&await r.switchSession(j):j=await r.createSession("chat"),b.value=o,p!==!1&&(await W(),await N())}function $e(){const o=s?.query||{};if(!o.prompt)return null;const p=Array.isArray(o.prompt)?o.prompt[0]:String(o.prompt);if(!p.trim())return null;const F=(Array.isArray(o.autoSend)?o.autoSend[0]:o.autoSend)!=="false",j=Array.isArray(o.session)?o.session[0]:o.session,se=j?String(j):null,oe=`query::${p}::${se||""}::${F}`;return{prompt:p,autoSend:F,session:se,token:oe}}async function ie(){const o=$e();if(o){await ce(o),n&&s&&n.replace({path:s.path,query:{}}).catch(()=>{});return}const p=r.pendingAutoSend;if(p?.prompt){const $=p.token||`staged::${p.prompt}::${Date.now()}`;await ce({...p,token:$}),r.clearAutoSend?.()}}return s&&Z(()=>[s.query.prompt,s.query.autoSend,s.query.session],()=>{ie()},{immediate:!1}),Z(()=>r.pendingAutoSend,()=>{ie()},{deep:!0}),ge(async()=>{await r.loadSessions(),await ie()}),(o,p)=>{const $=D("a-button"),F=D("a-radio-button"),j=D("a-radio-group"),se=D("a-avatar"),oe=D("a-input-search"),ue=D("a-textarea"),Ie=D("a-modal");return l(),m("div",Ut,[f("div",Qt,[a.value?(l(),m("div",Kt,[y(_(fe)),f("span",{style:{overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap"},title:_(i).projectRoot},u(_(i).projectName||o.$t("chat.scope.fallbackProjectName")),9,Gt)])):(l(),m("div",Jt,[y(_(me)),f("span",null,u(o.$t("chat.scope.globalSessions")),1)])),f("div",Xt,[y($,{type:"primary",size:"small",style:{flex:"1"},onClick:p[0]||(p[0]=h=>Q("chat"))},{icon:w(()=>[y(_(Ue))]),default:w(()=>[A(" "+u(o.$t("chat.newChat")),1)]),_:1}),y($,{size:"small",style:{flex:"1"},onClick:p[1]||(p[1]=h=>Q("agent"))},{icon:w(()=>[y(_(pe))]),default:w(()=>[A(" "+u(o.$t("chat.newAgent")),1)]),_:1})]),f("div",Yt,[(l(!0),m(G,null,J(_(r).sessions,h=>(l(),m("div",{key:h.id,class:Y(["session-item",{active:h.id===_(r).currentSessionId}]),onClick:V=>_(r).switchSession(h.id)},[f("span",es,u(h.type==="agent"?"🤖":"💬"),1),f("div",ts,[f("div",ss,u(h.title||o.$t("chat.session.untitled")),1),f("div",ns,u(o.$t("chat.session.messageCountSuffix",{n:h.messageCount||0})),1)])],10,Zt))),128)),_(r).sessions.length?O("",!0):(l(),m("div",is,u(o.$t("chat.sidebarEmpty")),1))])]),f("div",os,[v.value?O("",!0):(l(),m("div",as,[p[7]||(p[7]=f("div",{style:{"font-size":"48px","margin-bottom":"16px"}},"💬",-1)),f("div",ls,u(o.$t("chat.empty.title")),1),f("div",rs,u(o.$t("chat.empty.subtitle")),1),f("div",cs,[y($,{type:"primary",onClick:p[2]||(p[2]=h=>Q("chat"))},{default:w(()=>[A(u(o.$t("chat.empty.newChat")),1)]),_:1}),y($,{style:{},onClick:p[3]||(p[3]=h=>Q("agent"))},{default:w(()=>[A(u(o.$t("chat.empty.newAgent")),1)]),_:1})])])),v.value?(l(),m("div",us,[y(j,{value:R.value,size:"small","button-style":"solid","onUpdate:value":d},{default:w(()=>[y(F,{value:"project",disabled:!a.value},{default:w(()=>[y(_(fe)),A(" "+u(o.$t("chat.contextMode.project")),1)]),_:1},8,["disabled"]),y(F,{value:"file",disabled:""},{default:w(()=>[y(_(Qe)),A(" "+u(o.$t("chat.contextMode.file")),1)]),_:1}),y(F,{value:"global"},{default:w(()=>[y(_(me)),A(" "+u(o.$t("chat.contextMode.global")),1)]),_:1})]),_:1},8,["value"])])):O("",!0),v.value?(l(),m("div",ds,[T.value.length===0?(l(),m("div",hs,[p[8]||(p[8]=f("div",{class:"empty-icon"},"💬",-1)),f("div",fs,u(o.$t("chat.empty.startTitle")),1),f("div",ms,u(Ce.value),1),f("div",ps,[(l(!0),m(G,null,J(le.value,h=>(l(),z($,{key:h,size:"small",class:"quick-prompt-btn",onClick:V=>we(h)},{default:w(()=>[A(u(h),1)]),_:2},1032,["onClick"]))),128)),y($,{size:"small",type:"dashed",class:"quick-prompt-btn quick-prompt-edit",onClick:Se},{default:w(()=>[A(u(o.$t("chat.quickPromptsEditor.openButton")),1)]),_:1})])])):(l(),z(pt,{key:1,ref_key:"virtualListRef",ref:S,messages:T.value,"estimate-size":120,class:"chat-virtual-list"},{default:w(({message:h,index:V})=>[f("div",{class:Y(["message-row",h.role])},[h.type===_(Pe).INTENT_CONFIRMATION?(l(),z(Ht,{key:0,message:h,onConfirm:ne,onCorrect:be},null,8,["message"])):h.role==="system"?(l(),m("div",vs,u(h.content),1)):h.role==="tool"?(l(),m("div",gs,[y(nt,{item:B(h,V),expandable:"",expanded:q.has(V),onToggle:Ps=>C(V)},null,8,["item","expanded","onToggle"]),q.has(V)?(l(),m("div",ys,[f("pre",_s,u(JSON.stringify(h.input,null,2)),1),h.result?(l(),m("div",bs,[f("pre",Ss,u(typeof h.result=="string"?h.result:JSON.stringify(h.result,null,2)),1)])):O("",!0)])):O("",!0)])):(l(),m("div",{key:3,class:Y(["msg-with-avatar",h.role])},[y(se,{size:32,style:ae({backgroundColor:h.role==="user"?"#1890ff":"#52c41a",flexShrink:0})},{icon:w(()=>[h.role==="user"?(l(),z(_(Ke),{key:0})):(l(),z(_(pe),{key:1}))]),_:2},1032,["style"]),f("div",xs,[f("div",ks,[f("span",Cs,u(h.role==="user"?o.$t("chat.role.me"):"AI"),1),f("span",ws,u(H(h.timestamp)),1),h.tokens?(l(),m("span",$s,"· "+u(h.tokens)+" tokens",1)):O("",!0)]),h.role==="user"?(l(),m("div",Is,u(h.content),1)):(l(),z(at,{key:1,class:Y(["bubble assistant",{streaming:h._streaming}]),content:h.content},null,8,["class","content"]))])],2))],2)]),_:1},8,["messages"])),E.value?(l(),m("div",Ms,[f("div",Os,u(E.value.question),1),E.value.choices?.length?(l(),m("div",zs,[(l(!0),m(G,null,J(E.value.choices,h=>(l(),z($,{key:h,size:"small",onClick:V=>re(h)},{default:w(()=>[A(u(h),1)]),_:2},1032,["onClick"]))),128))])):(l(),z(oe,{key:1,placeholder:o.$t("chat.input.answerPlaceholder"),"enter-button":o.$t("chat.input.send"),style:{"margin-top":"10px"},onSearch:re},null,8,["placeholder","enter-button"]))])):O("",!0)])):O("",!0),v.value?(l(),m("div",Es,[f("div",As,[y(ue,{value:b.value,"onUpdate:value":p[4]||(p[4]=h=>b.value=h),placeholder:P.value?o.$t("chat.input.loading"):o.$t("chat.input.placeholder"),"auto-size":{minRows:1,maxRows:6},disabled:P.value,style:{background:"var(--bg-card-hover)","border-color":"var(--border-color)",color:"var(--text-primary)",resize:"none",flex:"1"},onKeydown:Oe(ze(N,["exact","prevent"]),["enter"])},null,8,["value","placeholder","disabled","onKeydown"]),y($,{type:"primary",loading:P.value,onClick:N,style:{height:"40px"}},{icon:w(()=>[y(_(Ge))]),_:1},8,["loading"])])])):O("",!0)]),y(Ie,{open:X.value,"onUpdate:open":p[6]||(p[6]=h=>X.value=h),title:o.$t("chat.quickPromptsEditor.title"),"ok-text":o.$t("chat.quickPromptsEditor.save"),"cancel-text":o.$t("chat.quickPromptsEditor.cancel"),onOk:xe},{default:w(()=>[f("div",Ts,u(o.$t("chat.quickPromptsEditor.hint")),1),y(ue,{value:te.value,"onUpdate:value":p[5]||(p[5]=h=>te.value=h),rows:8,placeholder:o.$t("chat.quickPromptsEditor.placeholder")},null,8,["value","placeholder"]),f("div",Fs,[y($,{size:"small",onClick:ke},{default:w(()=>[A(u(o.$t("chat.quickPromptsEditor.reset")),1)]),_:1})])]),_:1},8,["open","title","ok-text","cancel-text"])])}}},Bs=ee(Rs,[["__scopeId","data-v-937db6c5"]]);export{Bs as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{E as dt,r as h,a as A,f as pt}from"./vendor-Ci2pTZ_t.js";import{u as g}from"./index-BPtmPFwc.js";let L=0;function Y(s){return L+=1,`msg_${Date.now()}_${L}_${s}`}const v=Object.freeze({USER:"user",ASSISTANT:"assistant",SYSTEM:"system",INTENT_RECOGNITION:"intent-recognition",INTENT_CONFIRMATION:"intent-confirmation",TASK_ANALYSIS:"task-analysis",INTERVIEW:"interview",TASK_PLAN:"task-plan",PROGRESS:"progress",ERROR:"error"}),Q=Object.freeze({USER:"user",ASSISTANT:"assistant",SYSTEM:"system"});function mt(s,i){return{id:Y("intent_confirmation"),role:Q.ASSISTANT,type:v.INTENT_CONFIRMATION,content:"我理解您的需求如下,请确认:",timestamp:Date.now(),metadata:{originalInput:s,understanding:i||{},status:"pending",correction:null}}}function gt(s,i,u={}){const{reason:c,extractedInfo:p}=u,m={CONTINUE_EXECUTION:"✅ 收到,继续执行任务...",MODIFY_REQUIREMENT:`⚠️ 检测到需求变更:${p||i}`,CLARIFICATION:`📝 已记录补充信息:${p||i}`,CANCEL_TASK:"❌ 任务已取消"};return{id:Y("intent_system"),role:Q.SYSTEM,type:v.SYSTEM,content:m[s]||"⚠️ 未识别意图",timestamp:Date.now(),metadata:{intent:s,reason:c,userInput:i,extractedInfo:p}}}const I="新对话",b="新 Agent",K="cc.web-panel.chat.contextMode",G=["project","file","global"],B="cc.web-panel.chat.intentDecisions",$=200;function St(){try{const s=typeof localStorage<"u"?localStorage.getItem(K):null;return G.includes(s)?s:null}catch{return null}}function J(){try{if(typeof localStorage>"u")return{};const s=localStorage.getItem(B);if(!s)return{};const i=JSON.parse(s);return i&&typeof i=="object"?i:{}}catch{return{}}}function yt(s){try{if(typeof localStorage>"u")return;const i=Object.entries(s);if(i.length>$){i.sort((c,p)=>(c[1]?.ts||0)-(p[1]?.ts||0));const u=i.slice(-$);s=Object.fromEntries(u)}localStorage.setItem(B,JSON.stringify(s))}catch{}}function F(s,i,u){if(!s||!i)return;const c=J();c[`${s}::${i}`]={...u,ts:Date.now()},yt(c)}function Tt(s,i){return!s||!i?null:J()[`${s}::${i}`]||null}const ht={"assistant.delta":"response-token","assistant.final":"response-complete","assistant.message":"response-complete","tool.call.started":"tool-executing","tool.call.completed":"tool-result","tool.call.failed":"tool-result","slot.filling":"question","approval.requested":"question",error:"error"},vt=dt("chat",()=>{const s=h([]),i=h(null),u=A({}),c=A({}),p=A({}),m=A({}),P=(typeof window<"u"&&window.__CC_CONFIG__||{}).mode==="project",X=P?"project":"global",C=St(),O=h(C==="file"||C==="project"&&!P?"global":C||X);function z(t){if(G.includes(t)){O.value=t;try{typeof localStorage<"u"&&localStorage.setItem(K,t)}catch{}}}const w="cc.web-panel.chat.customQuickPrompts";function V(){try{if(typeof localStorage>"u")return null;const t=localStorage.getItem(w);if(!t)return null;const e=JSON.parse(t);if(!Array.isArray(e))return null;const n=e.map(o=>typeof o=="string"?o.trim():"").filter(o=>o.length>0&&o.length<=120).slice(0,12);return n.length>0?n:null}catch{return null}}const M=h(V());function W(t){if(t==null){M.value=null;try{typeof localStorage<"u"&&localStorage.removeItem(w)}catch{}return}if(!Array.isArray(t))return;const e=t.map(n=>typeof n=="string"?n.trim():"").filter(n=>n.length>0&&n.length<=120).slice(0,12);M.value=e.length>0?e:null;try{typeof localStorage<"u"&&(e.length>0?localStorage.setItem(w,JSON.stringify(e)):localStorage.removeItem(w))}catch{}}const D=h(null);let j=0;function H({prompt:t,autoSend:e=!0,session:n=null}={}){!t||!String(t).trim()||(j+=1,D.value={prompt:String(t),autoSend:e!==!1,session:n||null,token:`staged::${j}::${Date.now()}`})}function Z(){D.value=null}let U=null;const q=new Set;function S(t){return u[t]||(u[t]=[]),u[t]}function x(t){return!!(t&&m[t])}function y(t,e){t&&(m[t]=!!e)}function R(t){if(!t?.id)return;const e=s.value.find(n=>n.id===t.id);if(e){Object.assign(e,t);return}s.value.unshift(t)}function k(t,e=g()){u[t]||(u[t]=[]),c[t]||(c[t]={content:"",active:!1}),m[t]==null&&(m[t]=!1),!q.has(t)&&(q.add(t),e.onSession(t,n=>nt(t,n)))}function _(t=g()){U||(U=t.onRuntimeEvent(e=>{const n=e.payload||{},o=n.record||{};if(e.type==="session:start"){const a=n.sessionType||o.type||"chat";y(n.sessionId,!1),R({id:n.sessionId,type:a,provider:o.provider||null,model:o.model||null,projectRoot:o.projectRoot||null,status:o.status||"created",title:a==="chat"?I:b,createdAt:Date.now(),messageCount:o.messageCount??0})}else if(e.type==="session:resume"){const a=n.sessionId;if(!a)return;Array.isArray(n.history)&&(u[a]=n.history.map(r=>({role:r.role,content:r.content,timestamp:r.timestamp||Date.now()}))),c[a]||(c[a]={content:"",active:!1}),m[a]==null&&(m[a]=!1),R({id:a,type:o.type||null,provider:o.provider||null,model:o.model||null,projectRoot:o.projectRoot||null,status:o.status||"resumed",messageCount:o.messageCount??(Array.isArray(n.history)?n.history.length:0)})}else if(e.type==="session:end"){const a=n.sessionId;s.value=s.value.filter(r=>r.id!==a),delete m[a],i.value===a&&(i.value=s.value[0]?.id||null)}}))}async function tt(){const t=g();_(t),s.value=await t.listSessions(),s.value.forEach(e=>{k(e.id,t)})}async function et(t="chat",e={}){const n=g();_(n);const o=await n.createSession(t,null,e);return R({id:o,type:t,title:t==="chat"?I:b,createdAt:Date.now(),messageCount:0}),y(o,!1),k(o,n),i.value=o,o}function nt(t,e){const n=S(t),o=ht[e.type]||e.type,a=e.payload||{};if(o==="response-token"){c[t]||(c[t]={content:"",active:!0});const r=e.token||a.token||a.delta||a.content||"";c[t].content+=r,c[t].active=!0,y(t,!0)}else if(o==="response-complete"){const r=e.content||a.content||c[t]?.content||"";n.push({role:"assistant",content:r,timestamp:Date.now()}),c[t]&&(c[t].content="",c[t].active=!1);const f=s.value.find(l=>l.id===t);if(f&&(f.title===I||f.title===b)){const l=n.find(E=>E.role==="user");l&&(f.title=l.content.slice(0,30))}f&&(f.messageCount=n.filter(l=>l.role!=="tool").length),y(t,!1)}else if(o==="tool-executing")n.push({role:"tool",tool:e.tool||a.tool||a.toolName||"unknown",input:e.input||a.input||a.args||null,status:"running",timestamp:Date.now()}),y(t,!0);else if(o==="tool-result"){const r=e.tool||a.tool||a.toolName||"unknown",f=[...n].reverse().find(l=>l.role==="tool"&&l.tool===r);f&&(f.result=e.result||a.result||a.output||null,f.status="done")}else if(o==="question")p[t]={requestId:e.requestId||a.requestId||e.id,question:e.question||a.question||a.message||"",choices:e.choices||a.choices||a.options||[]},y(t,!1);else if(o==="error"){const r=e.message||a.message||"Unknown error";n.push({role:"assistant",content:`Error: ${r}`,timestamp:Date.now()}),y(t,!1),c[t]&&(c[t].active=!1)}}async function T(t,e){const n=g();_(n),S(t).push({role:"user",content:e,timestamp:Date.now()}),c[t]||(c[t]={content:"",active:!1}),c[t].active=!0,y(t,!0),n.sendSessionMessage(t,e)}async function ot(t,e){if(!t||!e?.trim())return;const n=O.value;if(n==="global"){await T(t,e);return}const o=g(),a=S(t).filter(d=>d.role==="user"||d.role==="assistant").slice(-5).map(d=>({role:d.role,content:String(d.content||"").slice(0,500)})),r=mt(e,{});r.metadata&&(r.metadata.streaming=!0,r.metadata.streamingTokens=0),r.content="理解中…";const f=S(t);f.push(r);let l=null;const E=new AbortController,ft=setTimeout(()=>E.abort(new Error("Intent understand wall-clock timeout")),9e4);try{const d=await o.sendStream({type:"chat.intent.understand-stream",sessionId:t,userInput:e,contextMode:n,history:a},{onChunk:()=>{r.metadata&&(r.metadata.streamingTokens=(r.metadata.streamingTokens||0)+1)},idleMs:6e4,signal:E.signal});d?.success&&(l=d)}catch{}finally{clearTimeout(ft)}if(!(l&&(l.correctedInput&&l.correctedInput!==e||Array.isArray(l.keyPoints)&&l.keyPoints.length>0))){const d=f.indexOf(r);d>=0&&f.splice(d,1),await T(t,e);return}r.content="我理解您的需求如下,请确认:",r.metadata&&(r.metadata.streaming=!1,r.metadata.understanding={correctedInput:l.correctedInput,intent:l.intent,keyPoints:l.keyPoints});const N=Tt(t,r.id);N?.status&&r.metadata&&(r.metadata.status=N.status,N.correction&&(r.metadata.correction=N.correction))}async function at(t,e){const o=S(t).find(r=>r.id===e);if(!o||o.type!==v.INTENT_CONFIRMATION)return;o.metadata&&(o.metadata.status="confirmed"),F(t,e,{status:"confirmed",correction:null});const a=o.metadata?.originalInput||"";a.trim()&&await T(t,a)}async function rt(t,e,n){const a=S(t).find(f=>f.id===e);if(!a||a.type!==v.INTENT_CONFIRMATION)return;a.metadata&&(a.metadata.status="corrected",a.metadata.correction=n),F(t,e,{status:"corrected",correction:n});const r=(n||"").trim();r&&await T(t,r)}async function st(t,e,n={}){const o=g();try{return await o.sendRaw({type:"chat.intent.classify-followup",sessionId:t,input:e,context:n},2e4)}catch{return null}}function it(t,e,n,o={}){S(t).push(gt(e,n,o))}function ct(t,e){const n=g(),o=p[t];o&&(n.answerQuestion(t,o.requestId,e),delete p[t])}async function lt(t){const e=g();if(_(e),i.value=t,k(t,e),!u[t]||u[t].length===0)try{await e.resumeSession(t)}catch{}}const ut=pt(()=>x(i.value));return{sessions:s,currentSessionId:i,messages:u,streaming:c,pendingQuestion:p,loadingBySession:m,isLoading:ut,contextMode:O,setContextMode:z,customQuickPrompts:M,setCustomQuickPrompts:W,pendingAutoSend:D,scheduleAutoSend:H,clearAutoSend:Z,getIsLoading:x,loadSessions:tt,createSession:et,sendMessage:T,submitUserInput:ot,confirmIntent:at,correctIntent:rt,classifyFollowupIntent:st,pushFollowupIntentBanner:it,answerQuestion:ct,switchSession:lt,getMessages:S}});export{v as M,vt as u};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-9_JZdhJl.js";import{R as t}from"./index-BPtmPFwc.js";import"./index-DVvcsuh0.js";import"./vendor-Ci2pTZ_t.js";import"./icons-B2G69bhT.js";const s=t(o);export{s as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-BFHRFhrC.js";import{R as t}from"./index-BPtmPFwc.js";import"./responsiveObserve-Dva2arKe.js";import"./vendor-Ci2pTZ_t.js";import"./useFlexGapSupport-z-vK8Wcv.js";import"./styleChecker-CuXdVqkl.js";import"./index-DVvcsuh0.js";import"./icons-B2G69bhT.js";const l=t(o);export{l as default};
|