From a6ba72053f73cf7b70e9f9cc4654da9d36402b7c Mon Sep 17 00:00:00 2001 From: pyx Date: Thu, 2 Jul 2026 09:36:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20SDK=20RAG=20=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=BC=80=E5=90=AF=E9=80=BB=E8=BE=91=E5=B9=B6=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B5=8B=E8=AF=95=E9=A1=B5=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/dist/chatbot-sdk.js | 8 ++++---- client/dist/chatbot-sdk.min.js | 2 +- client/src/chat.ts | 8 ++++---- client/src/config.ts | 2 +- client/src/types.ts | 4 ++-- src/main/resources/static/sdk/chatbot-sdk.js | 8 ++++---- src/main/resources/static/sdk/chatbot-sdk.min.js | 2 +- src/main/resources/static/sdk/test.html | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/client/dist/chatbot-sdk.js b/client/dist/chatbot-sdk.js index 55a2995..a699d3d 100644 --- a/client/dist/chatbot-sdk.js +++ b/client/dist/chatbot-sdk.js @@ -3472,7 +3472,7 @@ var ChatbotSDK = (function () { hideLoadingFn$1 = dom.hideLoading; // 初始化知识库分类 currentCategoryId = cfg.categoryId; - useRag = !!cfg.enableRag || !!cfg.categoryId || !!cfg.showCategorySwitch; + useRag = cfg.enableRag; // 绑定发送事件 bindSendEvents(); // 绑定滚动监听(智能滚动 + 新消息提示) @@ -3784,8 +3784,8 @@ var ChatbotSDK = (function () { await initChatId(); } const aiTimestamp = now(); - // RAG 启用条件:显式开启 enableRag,或已选择知识库分类 - const shouldUseRag = useRag && (config$1.enableRag || currentCategoryId !== undefined || config$1.categoryId !== undefined); + // RAG 启用条件:由 enableRag 控制 + const shouldUseRag = useRag; // 显示 loading if (showLoadingFn$1) showLoadingFn$1(); @@ -4060,7 +4060,7 @@ var ChatbotSDK = (function () { /** 设置当前知识库分类 */ function setCategory(categoryId) { currentCategoryId = categoryId; - useRag = categoryId !== undefined; + useRag = config$1?.enableRag ?? true; logger.lifecycleCategoryChange(categoryId !== null && categoryId !== void 0 ? categoryId : '全部'); } // ==================== 会话管理面板 ==================== diff --git a/client/dist/chatbot-sdk.min.js b/client/dist/chatbot-sdk.min.js index c6ffa68..b1af946 100644 --- a/client/dist/chatbot-sdk.min.js +++ b/client/dist/chatbot-sdk.min.js @@ -1,2 +1,2 @@ -var ChatbotSDK=function(){"use strict";const e="[ChatbotSDK]";let n=!0,t=null;function r(e){t=e||null}const s={},o={info(t,r){n&&console.log(e,t,void 0!==r?r:"")},warn(t,r){n&&console.warn(e,t,void 0!==r?r:"")},error(n,r){if(console.error(e,n,void 0!==r?r:""),t)try{const e=r instanceof Error&&r.type||"error";t({message:n,code:String(e),detail:r})}catch(e){}},time(e){s[e]=Date.now()},timeEnd(t,r){const o=s[t];if(void 0!==o){const a=Date.now()-o;if(delete s[t],n){const n=r?`${r} ${a}ms`:`${t} ${a}ms`;console.log(e,n)}return a}return 0},lifecycleInit(e,n){this.info(`初始化完成 integrateId=${e} requestDomain=${n}`)},lifecycleDestroy(e){this.info(`销毁实例 integrateId=${e}`)},lifecycleSend(e,n){this.info(`发送消息 integrateId=${e} length=${n}`),this.time(`send_${e}`)},lifecycleReply(e,n){const t=this.timeEnd(`send_${e}`,"AI 回复");this.info(`AI 回复 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleError(e,n,t){this.timeEnd(`send_${e}`),this.error(`请求失败 integrateId=${e} status=${n} message=${t}`)},lifecycleClear(e){this.info(`清空会话 integrateId=${e}`)},lifecycleStreamDone(e,n){const t=this.timeEnd(`send_${e}`,"流式回复");this.info(`流式回复完成 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleCategoryChange(e){this.info(`切换知识库分类 categoryId=${e}`)}},a='\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n';function i(e,n,t){return`\n \n \x3c!-- 高光渐变:模拟玻璃反射 --\x3e\n \n \n \n \n \x3c!-- 机器人身体渐变 --\x3e\n \n \n \n \n \n \x3c!-- 机器人主体(圆角矩形 + 对话气泡尾巴) --\x3e\n \n \n \x3c!-- 高光反射层(左上角弧形高光) --\x3e\n \n \x3c!-- 天线 + 能量球 --\x3e\n \n \n \x3c!-- 眼睛(会眨) --\x3e\n \n \n \x3c!-- 眼睛高光点 --\x3e\n \n \n \x3c!-- 微笑 --\x3e\n \n \x3c!-- 跳动气泡装饰(3 个小圆点) --\x3e\n \n \n \n`}const c=i("rgba(139,92,246,0.6)","rgba(139,92,246,0.45)","rgba(240,171,252,0.85)"),l=i("rgba(16,185,129,0.6)","rgba(16,185,129,0.45)","rgba(110,231,183,0.85)"),d=i("rgba(244,63,94,0.55)","rgba(244,63,94,0.4)","rgba(253,186,116,0.85)"),p=i("rgba(56,189,248,0.6)","rgba(56,189,248,0.45)","rgba(167,139,250,0.85)"),u={"dream-purple":"#A78BFA","mint-tech":"#34D399","coral-peach":"#FB7185","sky-blue":"#7DD3FC"};const g={"zh-CN":{title:"AI 智能助手",minimize:"最小化",close:"关闭",status_online:"在线",welcome_title:"你好,我是 AI 智能助手",welcome_desc:"有什么可以帮你的吗?在下方输入框开始提问吧~",placeholder:"输入您的问题...",send:"发送",stop:"停止生成",new_message:"新消息",copy:"复制",copied:"已复制",retry:"重新生成",retrying:"重新生成中...",loading:"正在思考...",stream_interrupted:"回复被中断",stream_unstable:"网络不稳定,内容可能不完整",category_placeholder:"选择知识库分类",category_all:"全部分类",category_load_error:"加载分类失败",source_title:"参考来源",source_count:"{n} 条参考来源",source_loading:"加载来源中...",clear:"清空对话",clear_confirm:"确定清空所有对话记录?",history_title:"历史会话",history_empty:"暂无历史会话",history_load_error:"加载会话列表失败",history_delete_confirm:"确定删除该会话?",history_export:"导出",history_delete:"删除",history_search:"搜索会话...",history_group_today:"今天",history_group_yesterday:"昨天",history_group_week:"本周",history_group_earlier:"更早",feedback_up:"有帮助",feedback_down:"没帮助",teaser_text:"有什么可以帮你的吗?",new_msg_announce:"收到新消息",error_network:"网络连接失败,请检查网络",error_timeout:"请求超时,请稍后重试",error_server:"服务器异常,请稍后重试",error_cors:"跨域请求被拦截,请联系管理员将当前域名加入 API 白名单",error_auth:"鉴权失败,请联系管理员",error_forbidden:"无访问权限,请联系管理员配置",error_not_found:"请求的资源不存在",error_rate_limit:"请求过于频繁,请稍后重试",error_unavailable:"服务暂不可用,请稍后重试",error_unknown:"请求发生未知错误",error_send:"发送失败,请稍后重试",error_stream_unsupported:"浏览器不支持流式读取"},en:{title:"AI Assistant",minimize:"Minimize",close:"Close",status_online:"Online",welcome_title:"Hi, I am your AI assistant",welcome_desc:"How can I help you? Type your question below to get started.",placeholder:"Type your question...",send:"Send",stop:"Stop generating",new_message:"New message",copy:"Copy",copied:"Copied",retry:"Regenerate",retrying:"Regenerating...",loading:"Thinking...",stream_interrupted:"Response interrupted",stream_unstable:"Network unstable, content may be incomplete",category_placeholder:"Select category",category_all:"All categories",category_load_error:"Failed to load categories",source_title:"Sources",source_count:"{n} source(s)",source_loading:"Loading sources...",clear:"Clear chat",clear_confirm:"Clear all conversation history?",history_title:"History",history_empty:"No conversations yet",history_load_error:"Failed to load conversations",history_delete_confirm:"Delete this conversation?",history_export:"Export",history_delete:"Delete",history_search:"Search conversations...",history_group_today:"Today",history_group_yesterday:"Yesterday",history_group_week:"This Week",history_group_earlier:"Earlier",feedback_up:"Helpful",feedback_down:"Not helpful",teaser_text:"How can I help you?",new_msg_announce:"New message received",error_network:"Network connection failed",error_timeout:"Request timed out, please try again",error_server:"Server error, please try again later",error_cors:"CORS request blocked. Please contact admin to whitelist your domain",error_auth:"Authentication failed, please contact admin",error_forbidden:"Access denied, please contact admin",error_not_found:"Resource not found",error_rate_limit:"Too many requests, please try again later",error_unavailable:"Service temporarily unavailable",error_unknown:"Unknown request error",error_send:"Failed to send, please try again",error_stream_unsupported:"Browser does not support streaming"}};let k="zh-CN";function m(e,n){let t=(g[k]||g["zh-CN"])[e]||g["zh-CN"][e]||e;if(n)for(const[e,r]of Object.entries(n))t=t.replace(`{${e}}`,String(r));return t}let h=null;function b(e){h&&(h.chatId=e)}function f(){return(null==h?void 0:h.chatId)||""}function y(e){if(!h)throw new Error("API 配置未初始化");return`${h.requestDomain.replace(/\/+$/,"")}${e.startsWith("/")?e:`/${e}`}`}function x(e,n,t){null!=t&&("string"==typeof t&&""===t.trim()||e.set(n,String(t)))}async function v(e,n={},t=3e4,r){const s=new AbortController,o=setTimeout(()=>s.abort(),t);r&&(r.aborted?s.abort():r.addEventListener("abort",()=>s.abort(),{once:!0}));try{return await fetch(e,Object.assign(Object.assign({},n),{signal:s.signal,mode:"cors",credentials:"include"}))}catch(e){if(null==r?void 0:r.aborted)throw new w("aborted","aborted");if(e instanceof DOMException&&"AbortError"===e.name)throw new w(m("error_timeout"),"timeout");if(e instanceof TypeError&&e.message.includes("Failed to fetch"))throw new w(m("error_cors"),"cors");throw new w(m("error_network"),"network")}finally{clearTimeout(o)}}class w extends Error{constructor(e,n){super(e),this.name="CskError",this.type=n}}function _(e){switch(e){case 401:return m("error_auth");case 403:return m("error_forbidden");case 404:return m("error_not_found");case 429:return m("error_rate_limit");case 500:return m("error_server");case 502:case 503:return m("error_unavailable");default:return`${m("error_unknown")}(${e})`}}async function E(e){const n=function(e){const n=new URLSearchParams;return n.set("message",e),n.set("chatId",h.chatId),x(n,"roleId",h.integrateId),x(n,"accountId",h.userId),y(`/ai/assistant_app/chat/sync?${n.toString()}`)}(e);o.lifecycleSend(h.integrateId,e.length);try{const e=await v(n);if(!e.ok){const n=_(e.status);throw o.lifecycleError(h.integrateId,String(e.status),n),new w(n,`http_${e.status}`)}const t=await e.text();return o.lifecycleReply(h.integrateId,t.length),t}catch(e){if(e instanceof w)throw e;throw o.lifecycleError(h.integrateId,"unknown",String(e)),new w(m("error_unknown"),"unknown")}}async function C(e,n,t,r,s,a,i){var c;const l=a?function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/rag/sse?${t.toString()}`)}(e,s):function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/sse?${t.toString()}`)}(e,s);let d="";o.lifecycleSend(h.integrateId,e.length);try{const e=await v(l,{},6e4,i);if(!e.ok){const n=_(e.status);return o.lifecycleError(h.integrateId,String(e.status),n),void r(new w(n,`http_${e.status}`))}const s=null===(c=e.body)||void 0===c?void 0:c.getReader();if(!s)return void r(new w(m("error_stream_unsupported"),"stream_unsupported"));const a=new TextDecoder("utf-8",{stream:!0});let p="";try{for(;;){const{done:e,value:t}=await s.read();if(e)break;p+=a.decode(t,{stream:!0});const r=p.split("\n");p=r.pop()||"";for(const e of r){const t=e.trim();if(t&&!t.startsWith(":"))if(t.startsWith("data:")){const e=t.substring(5).trim();e&&(d+=e,n(e))}else{if("[DONE]"===t)break;t.startsWith("event:")||t.startsWith("id:")||t.startsWith("retry:")||(d+=t,n(t))}}}if(p.trim()){const e=p.trim();if(e.startsWith("data:")){const t=e.substring(5).trim();t&&(d+=t,n(t))}else"[DONE]"!==e&&(d+=e,n(e))}}catch(e){if(null==i?void 0:i.aborted)o.info(`流式被用户中断,保留已生成内容 length=${d.length}`);else{if(!(d.length>0))throw e;n("\n\n"+m("stream_unstable"))}}finally{s.releaseLock()}o.lifecycleStreamDone(h.integrateId,d.length),t()}catch(e){if((null==i?void 0:i.aborted)||e instanceof w&&"aborted"===e.type)return void t();e instanceof w?r(e):(o.lifecycleError(h.integrateId,"unknown",String(e)),r(new w(m("error_network"),"network")))}}async function I(e,n){const t=function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/rag/sources?${t.toString()}`)}(e,n);try{const e=await v(t);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return n.success&&Array.isArray(n.data)?(o.info(`获取引用来源 count=${n.data.length}`),n.data):[]}catch(e){return o.error("获取引用来源失败",e),[]}}async function $(e=1,n=20,t,r){let s=`/conversation/list?page=${e}&size=${n}`;t&&(s+=`&accountId=${encodeURIComponent(t)}`),r&&(s+=`&roleId=${encodeURIComponent(r)}`);const a=y(s);try{const e=await v(a);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return{list:n.success&&Array.isArray(n.data)?n.data:[],total:n.total||0,pages:n.pages||0}}catch(e){return o.error("加载会话列表失败",e),{list:[],total:0,pages:0}}}async function A(e){const n=y(`/conversation/${e}/messages`);try{const e=await v(n);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const t=await e.json();return{messages:t.success&&Array.isArray(t.data)?t.data:[],total:t.total||0}}catch(e){return o.error("加载会话消息失败",e),{messages:[],total:0}}}async function L(e){const n=y(`/conversation/${e}`);try{const t=await v(n,{method:"DELETE"});if(!t.ok)throw new w(_(t.status),`http_${t.status}`);const r=await t.json();return o.info(`删除会话 id=${e} success=${r.success}`),r.success||!1}catch(e){return o.error("删除会话失败",e),!1}}function S(e){return y(`/conversation/${e}/export`)}async function F(){if(!h)return"";const e=function(e,n){try{return localStorage.getItem(N(e,n))||""}catch(e){return""}}(h.integrateId,h.userId);if(e)return h.chatId=e,o.info(`从缓存恢复 chatId=${e}`),e;try{const e=await $(1,5,h.userId,h.integrateId);if(e.list.length>0){const n=e.list[0],t=n.conversationId||n.chatId||"";if(t)return h.chatId=t,M(h.integrateId,h.userId,t),o.info(`从后端恢复会话 chatId=${t} messageCount=${n.messageCount}`),t}}catch(e){o.warn("查询后端会话列表失败,将生成新 chatId",e)}const n=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();return h.chatId=n,M(h.integrateId,h.userId,n),o.info(`生成新 chatId=${n}`),n}function N(e,n){return`csk_chatId_${e}${n?"_"+n:""}`}function M(e,n,t){try{t?localStorage.setItem(N(e,n),t):localStorage.removeItem(N(e,n))}catch(e){}}let T=null;function D(e){const n=B(e.primaryColor,-15),t=B(e.primaryColor,18),r=function(e){const n=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);return n?`${parseInt(n[1],16)}, ${parseInt(n[2],16)}, ${parseInt(n[3],16)}`:"79, 70, 229"}(e.primaryColor),s=e.launcherTheme?{"dream-purple":{grad1:"#A78BFA",grad2:"#F0ABFC",glow:"167, 139, 250"},"mint-tech":{grad1:"#6EE7B7",grad2:"#34D399",glow:"52, 211, 153"},"coral-peach":{grad1:"#FB7185",grad2:"#FDBA74",glow:"251, 113, 133"},"sky-blue":{grad1:"#7DD3FC",grad2:"#A78BFA",glow:"125, 211, 252"}}[e.launcherTheme]:null;return`\n --csk-primary: ${e.primaryColor};\n --csk-primary-hover: ${n};\n --csk-primary-light: ${t};\n --csk-primary-rgb: ${r};\n --csk-bg-user: linear-gradient(135deg, ${e.primaryColor}, ${n});\n --csk-bg-ai: #ffffff;\n --csk-text-user: #ffffff;\n --csk-text-ai: #1F2937;\n --csk-window-width: ${e.width}px;\n --csk-window-height: ${e.height}px;\n --csk-radius: 16px;\n --csk-shadow-window: 0 12px 48px rgba(15, 23, 42, 0.18), 0 2px 8px rgba(15, 23, 42, 0.06);\n --csk-shadow-bubble: 0 1px 2px rgba(15, 23, 42, 0.06);\n --csk-border: #ECEEF2;\n --csk-bg-app: #F6F7F9;\n ${s?`\n --csk-launcher-grad-1: ${s.grad1};\n --csk-launcher-grad-2: ${s.grad2};\n --csk-launcher-glow: ${s.glow};\n `:""}\n `}function B(e,n){const t=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!t)return e;const r=e=>Math.max(0,Math.min(255,e)),s=r(parseInt(t[1],16)+n),o=r(parseInt(t[2],16)+n),a=r(parseInt(t[3],16)+n);return`#${s.toString(16).padStart(2,"0")}${o.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}`}function q(e){document.querySelector("style[data-csk-sdk]")||(T=document.createElement("style"),T.setAttribute("data-csk-sdk",""),T.textContent=function(e){return`\n/* ChatbotSDK 样式 - csk- 命名空间 */\n.csk-root {\n ${D(e)}\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;\n font-size: 14px;\n line-height: 1.55;\n color: #1F2937;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n.csk-root *, .csk-root *::before, .csk-root *::after { box-sizing: border-box; }\n\n/* ========== 悬浮按钮 ========== */\n.csk-launcher {\n position: fixed;\n bottom: 24px;\n z-index: 9998;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n user-select: none;\n overflow: visible;\n /* 半透明白色光环边框,在白色页面上清晰分离按钮与背景 */\n border: 2.5px solid rgba(255, 255, 255, 0.55);\n /* 三层投影:接地阴影 + 彩色光晕,把按钮从白底「托」出来 */\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.25s ease,\n border-color 0.25s ease;\n animation: csk-launcher-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;\n}\n.csk-launcher--right { right: 24px; }\n.csk-launcher--left { left: 24px; }\n\n/* 高光扫过动效 */\n.csk-launcher::before {\n content: '';\n position: absolute;\n top: -50%;\n left: -50%;\n width: 40%;\n height: 200%;\n border-radius: 50%;\n background: linear-gradient(\n 105deg,\n transparent 30%,\n rgba(255, 255, 255, 0.28) 48%,\n rgba(255, 255, 255, 0.1) 52%,\n transparent 70%\n );\n transform: rotate(25deg);\n animation: csk-shimmer 4s ease-in-out infinite;\n pointer-events: none;\n}\n/* 呼吸色晕 — 配合接地阴影,强化白底上的立体存在感 */\n.csk-launcher::after {\n content: '';\n position: absolute;\n inset: -18px;\n border-radius: 50%;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.18) 0%, rgba(var(--csk-primary-rgb), 0.05) 45%, transparent 68%);\n animation: csk-breathe 3.5s ease-in-out infinite;\n pointer-events: none;\n}\n.csk-launcher:hover {\n transform: translateY(-3px) scale(1.08);\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.10),\n 0 8px 24px rgba(0, 0, 0, 0.14),\n 0 10px 36px rgba(var(--csk-primary-rgb), 0.32),\n 0 0 56px rgba(var(--csk-primary-rgb), 0.14);\n}\n.csk-launcher:hover::before { animation-play-state: paused; }\n.csk-launcher:hover::after {\n animation: none;\n inset: -22px;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.22) 0%, rgba(var(--csk-primary-rgb), 0.06) 45%, transparent 68%);\n}\n.csk-launcher:active { transform: scale(0.93); }\n.csk-launcher svg {\n width: 30px;\n height: 30px;\n position: relative;\n z-index: 1;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.15));\n}\n\n@keyframes csk-launcher-in {\n 0% { opacity: 0; transform: scale(0.5) translateY(16px); }\n 60% { transform: scale(1.06) translateY(-2px); }\n 100% { opacity: 1; transform: scale(1) translateY(0); }\n}\n@keyframes csk-shimmer {\n 0%, 100% { left: -60%; opacity: 0; }\n 20% { opacity: 1; }\n 60% { opacity: 1; }\n 80% { left: 120%; opacity: 0; }\n}\n@keyframes csk-breathe {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.15); opacity: 0.35; }\n}\n\n/* SVG 图标内部动效:眨眼 */\n.csk-launcher .csk-ico-eye {\n animation: csk-eye-blink 4s ease-in-out infinite;\n}\n@keyframes csk-eye-blink {\n 0%, 42%, 48%, 100% { opacity: 1; }\n 45% { opacity: 0.1; }\n}\n/* SVG 图标内部动效:天线能量闪烁 */\n.csk-launcher .csk-ico-antenna {\n animation: csk-antenna-glow 2s ease-in-out infinite;\n}\n@keyframes csk-antenna-glow {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n/* ========== 磨砂玻璃质感悬浮按钮 ========== */\n.csk-launcher--glass {\n background: linear-gradient(\n 135deg,\n var(--csk-launcher-grad-1, var(--csk-primary)) 0%,\n var(--csk-launcher-grad-2, var(--csk-primary-light)) 100%\n ) !important;\n backdrop-filter: blur(12px) saturate(180%);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n border: 1.5px solid rgba(255, 255, 255, 0.55) !important;\n /* 多层阴影:接地 + 彩色光晕 + 内阴影立体感 */\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.04),\n 0 6px 20px rgba(0, 0, 0, 0.08),\n 0 8px 32px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.30),\n inset 0 1px 1px rgba(255, 255, 255, 0.35),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n.csk-launcher--glass:hover {\n border-color: rgba(255, 255, 255, 0.75) !important;\n box-shadow:\n 0 4px 8px rgba(0, 0, 0, 0.06),\n 0 10px 28px rgba(0, 0, 0, 0.10),\n 0 12px 40px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.38),\n inset 0 1px 2px rgba(255, 255, 255, 0.45),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n\n/* 玻璃按钮的呼吸色晕 — 更鲜艳、更醒目 */\n.csk-launcher--glass::after {\n background: radial-gradient(\n circle,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.28) 0%,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.10) 40%,\n transparent 65%\n ) !important;\n animation: csk-breathe-glow 3.5s ease-in-out infinite;\n}\n@keyframes csk-breathe-glow {\n 0%, 100% { transform: scale(1); opacity: 0.8; }\n 50% { transform: scale(1.22); opacity: 0.25; }\n}\n\n/* 玻璃按钮的高光扫过 — 更柔和的玻璃质感 */\n.csk-launcher--glass::before {\n background: linear-gradient(\n 115deg,\n transparent 25%,\n rgba(255, 255, 255, 0.35) 45%,\n rgba(255, 255, 255, 0.15) 55%,\n transparent 75%\n ) !important;\n width: 50%;\n animation: csk-shimmer-glass 5s ease-in-out infinite;\n}\n@keyframes csk-shimmer-glass {\n 0%, 100% { left: -70%; opacity: 0; }\n 15% { opacity: 1; }\n 55% { opacity: 1; }\n 70% { left: 130%; opacity: 0; }\n}\n\n/* SVG 内部动效:跳动气泡(3 个小圆点交错弹跳) */\n.csk-launcher .csk-ico-bubble {\n animation: csk-bubble-jump 1.4s ease-in-out infinite;\n}\n.csk-launcher .csk-ico-bubble--1 { animation-delay: 0s; }\n.csk-launcher .csk-ico-bubble--2 { animation-delay: 0.18s; }\n.csk-launcher .csk-ico-bubble--3 { animation-delay: 0.36s; }\n@keyframes csk-bubble-jump {\n 0%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-3.5px); }\n 60% { transform: translateY(-1px); }\n}\n\n/* ========== 聊天弹窗 ========== */\n.csk-window {\n position: fixed;\n bottom: 24px;\n z-index: 9999;\n width: var(--csk-window-width);\n height: var(--csk-window-height);\n max-height: calc(100vh - 48px);\n background: #fff;\n border-radius: var(--csk-radius);\n box-shadow: var(--csk-shadow-window);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transform-origin: bottom right;\n transition: opacity 0.24s ease, transform 0.24s cubic-bezier(0.34, 1.2, 0.64, 1), visibility 0.24s;\n opacity: 1;\n transform: translateY(0) scale(1);\n visibility: visible;\n pointer-events: auto;\n}\n.csk-window--right { right: 24px; transform-origin: bottom right; }\n.csk-window--left { left: 24px; transform-origin: bottom left; }\n.csk-window--hidden {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n visibility: hidden;\n pointer-events: none;\n}\n\n/* ========== 头部 ========== */\n.csk-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n min-height: 60px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: move;\n user-select: none;\n position: relative;\n flex-shrink: 0;\n}\n.csk-header::after {\n content: '';\n position: absolute;\n left: 0; right: 0; bottom: 0;\n height: 24px;\n background: linear-gradient(to bottom, rgba(0,0,0,0.04), transparent);\n pointer-events: none;\n}\n.csk-header__left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n.csk-header__avatar {\n width: 38px;\n height: 38px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);\n}\n.csk-header__avatar svg { width: 22px; height: 22px; }\n.csk-header__info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.csk-header__title {\n font-size: 15px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n letter-spacing: 0.2px;\n}\n.csk-header__status {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 11.5px;\n opacity: 0.9;\n margin-top: 2px;\n}\n.csk-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #6EE7B7;\n box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7);\n animation: csk-status-pulse 2s infinite;\n}\n@keyframes csk-status-pulse {\n 0% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7); }\n 70% { box-shadow: 0 0 0 6px rgba(110, 231, 183, 0); }\n 100% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0); }\n}\n.csk-header__actions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n.csk-header__btn,\n.csk-history-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #fff;\n cursor: pointer;\n border-radius: 8px;\n transition: background 0.15s, transform 0.15s;\n}\n.csk-header__btn:hover,\n.csk-history-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n.csk-header__btn:active,\n.csk-history-btn:active { transform: scale(0.92); }\n\n/* ========== 消息区 ========== */\n.csk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 20px 16px 12px;\n background: var(--csk-bg-app);\n scroll-behavior: smooth;\n}\n.csk-messages::-webkit-scrollbar { width: 6px; }\n.csk-messages::-webkit-scrollbar-track { background: transparent; }\n.csk-messages::-webkit-scrollbar-thumb {\n background: #D8DCE3;\n border-radius: 3px;\n}\n.csk-messages::-webkit-scrollbar-thumb:hover { background: #C2C7D0; }\n\n/* 欢迎空状态 */\n.csk-welcome {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 48px 24px 32px;\n color: #6B7280;\n animation: csk-fade-in 0.3s ease;\n}\n.csk-welcome__avatar {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 14px;\n box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-welcome__avatar svg { width: 30px; height: 30px; }\n.csk-welcome__title {\n font-size: 15px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.csk-welcome__desc {\n font-size: 13px;\n color: #9CA3AF;\n line-height: 1.6;\n}\n\n/* 消息气泡 */\n.csk-msg {\n display: flex;\n margin-bottom: 18px;\n max-width: 100%;\n word-break: break-word;\n animation: csk-msg-in 0.28s cubic-bezier(0.22, 1, 0.36, 1);\n}\n.csk-msg--user {\n flex-direction: row-reverse;\n align-items: flex-end;\n}\n.csk-msg--ai {\n flex-direction: row;\n align-items: flex-start;\n}\n.csk-msg__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg__avatar svg { width: 18px; height: 18px; }\n.csk-msg__avatar--ai {\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n}\n.csk-msg__avatar--user {\n background: var(--csk-bg-user);\n color: #fff;\n}\n.csk-msg__content {\n display: flex;\n flex-direction: column;\n min-width: 0;\n max-width: calc(100% - 46px);\n}\n.csk-msg--user .csk-msg__content { align-items: flex-end; }\n.csk-msg--ai .csk-msg__content { align-items: flex-start; }\n.csk-msg__bubble {\n padding: 10px 14px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.6;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg--user .csk-msg__bubble {\n background: var(--csk-bg-user);\n color: var(--csk-text-user);\n border-radius: 16px 16px 4px 16px;\n}\n.csk-msg--ai .csk-msg__bubble {\n background: var(--csk-bg-ai);\n color: var(--csk-text-ai);\n border-radius: 16px 16px 16px 4px;\n border: 1px solid var(--csk-border);\n}\n.csk-msg__time {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 5px;\n padding: 0 4px;\n}\n\n@keyframes csk-msg-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes csk-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ========== Loading 动画 ========== */\n.csk-loading {\n display: flex;\n align-items: center;\n margin-bottom: 18px;\n animation: csk-msg-in 0.28s ease;\n}\n.csk-loading__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-loading__avatar svg { width: 18px; height: 18px; }\n.csk-loading__bubble {\n background: #fff;\n border: 1px solid var(--csk-border);\n border-radius: 16px 16px 16px 4px;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.csk-loading__dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #B4B9C2;\n animation: csk-bounce 1.4s ease-in-out infinite both;\n}\n.csk-loading__dot:nth-child(1) { animation-delay: 0s; }\n.csk-loading__dot:nth-child(2) { animation-delay: 0.16s; }\n.csk-loading__dot:nth-child(3) { animation-delay: 0.32s; }\n\n@keyframes csk-bounce {\n 0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }\n 40% { transform: scale(1); opacity: 1; }\n}\n\n/* ========== 输入区 ========== */\n.csk-input-area {\n padding: 10px 12px 14px;\n background: #fff;\n border-top: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-input-wrap {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n background: var(--csk-bg-app);\n border: 1px solid var(--csk-border);\n border-radius: 14px;\n padding: 6px 6px 6px 14px;\n transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;\n}\n.csk-input-wrap--focus {\n border-color: var(--csk-primary);\n background: #fff;\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n.csk-input {\n flex: 1;\n border: none;\n background: transparent;\n padding: 8px 0;\n font-size: 14px;\n outline: none;\n font-family: inherit;\n resize: none;\n min-height: 22px;\n max-height: 120px;\n line-height: 1.5;\n color: #1F2937;\n}\n.csk-input::placeholder { color: #9CA3AF; }\n.csk-root .csk-input:focus-visible { outline: none; }\n.csk-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n min-width: 36px;\n border: none;\n border-radius: 10px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: pointer;\n transition: transform 0.18s, box-shadow 0.18s, opacity 0.18s;\n box-shadow: 0 3px 10px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-send-btn:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 5px 14px rgba(var(--csk-primary-rgb), 0.4);\n}\n.csk-send-btn:active:not(:disabled) { transform: scale(0.92); }\n.csk-send-btn:disabled {\n background: #D1D5DB;\n box-shadow: none;\n cursor: not-allowed;\n opacity: 0.7;\n}\n.csk-send-btn svg { width: 18px; height: 18px; }\n\n/* ========== 清空按钮 ========== */\n.csk-clear-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 999px;\n background: #fff;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n margin: 0 auto 8px;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-clear-btn:hover {\n background: #FEF2F2;\n border-color: #FCA5A5;\n color: #DC2626;\n}\n\n/* ========== P1: 知识库分类下拉 ========== */\n.csk-category-bar {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n border-top: 1px solid var(--csk-border);\n background: #FBFBFC;\n gap: 8px;\n flex-shrink: 0;\n}\n.csk-category-bar__label {\n font-size: 13px;\n white-space: nowrap;\n}\n.csk-category-select {\n flex: 1;\n padding: 6px 28px 6px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n color: #374151;\n background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 9px center;\n appearance: none;\n -webkit-appearance: none;\n outline: none;\n cursor: pointer;\n font-family: inherit;\n transition: border-color 0.2s, box-shadow 0.2s;\n max-width: 220px;\n}\n.csk-category-select:focus {\n border-color: var(--csk-primary);\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n\n/* ========== P1: RAG 引用来源卡片 ========== */\n.csk-sources {\n margin-top: 8px;\n border: 1px solid var(--csk-border);\n border-radius: 12px;\n overflow: hidden;\n font-size: 12px;\n max-width: 100%;\n background: #FAFBFC;\n}\n.csk-sources__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: #F3F4F7;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s;\n}\n.csk-sources__header:hover { background: #ECEEF2; }\n.csk-sources__title {\n display: flex;\n align-items: center;\n gap: 5px;\n font-weight: 500;\n color: #374151;\n}\n.csk-sources__arrow {\n transition: transform 0.2s;\n color: #9CA3AF;\n font-size: 10px;\n}\n.csk-sources--collapsed .csk-sources__arrow { transform: rotate(-90deg); }\n.csk-sources__body {\n border-top: 1px solid var(--csk-border);\n padding: 0;\n}\n.csk-sources--collapsed .csk-sources__body { display: none; }\n.csk-source-item {\n padding: 9px 12px;\n border-bottom: 1px solid #F0F1F4;\n transition: background 0.15s;\n}\n.csk-source-item:last-child { border-bottom: none; }\n.csk-source-item:hover { background: #fff; }\n.csk-source-item__name {\n font-weight: 500;\n color: #1F2937;\n margin-bottom: 3px;\n}\n.csk-source-item__snippet {\n color: #6B7280;\n line-height: 1.5;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n.csk-source-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 4px;\n}\n\n/* ========== P1: Markdown 渲染样式 ========== */\n.csk-msg--ai .csk-msg__bubble .csk-md-p { margin: 0 0 8px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-p:last-child { margin-bottom: 0; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h1,\n.csk-msg--ai .csk-msg__bubble .csk-md-h2,\n.csk-msg--ai .csk-msg__bubble .csk-md-h3,\n.csk-msg--ai .csk-msg__bubble .csk-md-h4,\n.csk-msg--ai .csk-msg__bubble .csk-md-h5,\n.csk-msg--ai .csk-msg__bubble .csk-md-h6 {\n margin: 14px 0 6px;\n font-weight: 600;\n line-height: 1.3;\n color: #111827;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-h1 { font-size: 20px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h2 { font-size: 17px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h3 { font-size: 15px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h4 { font-size: 14px; }\n\n.csk-md-code-block {\n background: #1E293B;\n color: #E2E8F0;\n padding: 12px 14px;\n border-radius: 10px;\n overflow-x: auto;\n margin: 8px 0;\n font-size: 13px;\n line-height: 1.55;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-md-code-block code {\n background: none;\n padding: 0;\n border-radius: 0;\n font-size: inherit;\n color: inherit;\n}\n.csk-md-inline-code {\n background: rgba(var(--csk-primary-rgb), 0.1);\n color: var(--csk-primary);\n padding: 1px 6px;\n border-radius: 5px;\n font-size: 13px;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol {\n padding-left: 22px;\n margin: 6px 0;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul li,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol li { margin-bottom: 4px; }\n.csk-md-blockquote {\n border-left: 3px solid var(--csk-primary);\n padding: 2px 12px;\n margin: 8px 0;\n color: #6B7280;\n background: rgba(var(--csk-primary-rgb), 0.05);\n border-radius: 0 6px 6px 0;\n}\n.csk-md-link {\n color: var(--csk-primary);\n text-decoration: none;\n border-bottom: 1px solid rgba(var(--csk-primary-rgb), 0.3);\n transition: border-color 0.15s;\n}\n.csk-md-link:hover { border-bottom-color: var(--csk-primary); }\n.csk-md-hr {\n border: none;\n border-top: 1px solid var(--csk-border);\n margin: 12px 0;\n}\n\n/* ========== P2: 会话管理面板 ========== */\n.csk-history-panel {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: #fff;\n z-index: 10;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: csk-slide-in 0.24s ease;\n}\n.csk-history-panel--hidden { display: none; }\n@keyframes csk-slide-in {\n from { transform: translateX(100%); opacity: 0.4; }\n to { transform: translateX(0); opacity: 1; }\n}\n.csk-history-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--csk-border);\n background: var(--csk-bg-app);\n flex-shrink: 0;\n}\n.csk-history-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n}\n.csk-history-panel__back {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n background: #fff;\n color: #374151;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-history-panel__back:hover { background: #F3F4F6; }\n.csk-history-panel__list {\n flex: 1;\n overflow-y: auto;\n padding: 10px;\n}\n.csk-history-panel__list::-webkit-scrollbar { width: 5px; }\n.csk-history-panel__list::-webkit-scrollbar-thumb { background: #E5E7EB; border-radius: 2px; }\n.csk-history-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 11px 12px;\n border-radius: 10px;\n cursor: pointer;\n transition: background 0.15s;\n margin-bottom: 5px;\n border: 1px solid transparent;\n}\n.csk-history-item:hover { background: #F3F4F6; }\n.csk-history-item--active {\n background: rgba(var(--csk-primary-rgb), 0.08);\n border-color: rgba(var(--csk-primary-rgb), 0.2);\n}\n.csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.12); }\n.csk-history-item__info { flex: 1; min-width: 0; }\n.csk-history-item__id {\n font-size: 13px;\n font-weight: 500;\n color: #1F2937;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.csk-history-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 3px;\n}\n.csk-history-item__actions {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.csk-history-item:hover .csk-history-item__actions { opacity: 1; }\n.csk-history-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 7px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.15s;\n}\n.csk-history-action--export { background: #EFF6FF; color: #2563EB; }\n.csk-history-action--export:hover { background: #DBEAFE; }\n.csk-history-action--delete { background: #FEF2F2; color: #DC2626; }\n.csk-history-action--delete:hover { background: #FEE2E2; }\n.csk-history-panel__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 20px;\n color: #9CA3AF;\n font-size: 13px;\n text-align: center;\n}\n.csk-history-panel__empty-icon {\n font-size: 34px;\n margin-bottom: 10px;\n opacity: 0.5;\n}\n.csk-history-panel__loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n color: #9CA3AF;\n font-size: 13px;\n}\n.csk-history-panel__loadmore {\n display: block;\n width: 100%;\n padding: 10px;\n border: none;\n background: #F9FAFB;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n text-align: center;\n transition: background 0.15s;\n}\n.csk-history-panel__loadmore:hover { background: #F3F4F6; }\n\n/* ========== 快捷问题芯片 ========== */\n.csk-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n margin-top: 18px;\n max-width: 320px;\n}\n.csk-quick-reply {\n border: 1px solid var(--csk-border);\n background: #fff;\n color: #374151;\n font-size: 12.5px;\n padding: 7px 13px;\n border-radius: 999px;\n cursor: pointer;\n font-family: inherit;\n line-height: 1.3;\n transition: all 0.18s ease;\n max-width: 100%;\n}\n.csk-quick-reply:hover {\n border-color: var(--csk-primary);\n color: var(--csk-primary);\n background: rgba(var(--csk-primary-rgb), 0.06);\n transform: translateY(-1px);\n}\n.csk-quick-reply:active { transform: scale(0.96); }\n\n/* ========== AI 消息操作条 ========== */\n.csk-msg__actions {\n display: flex;\n gap: 2px;\n margin-top: 5px;\n padding: 0 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n.csk-msg--ai:hover .csk-msg__actions { opacity: 1; }\n.csk-msg--streaming .csk-msg__actions { display: none; }\n.csk-action-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.csk-action-btn:hover {\n background: #F3F4F6;\n color: #374151;\n}\n.csk-action-btn--done { color: #10B981; }\n.csk-action-btn:active { transform: scale(0.9); }\n\n/* ========== 流式打字光标 ========== */\n.csk-caret {\n display: inline-block;\n width: 7px;\n height: 15px;\n margin-left: 2px;\n vertical-align: text-bottom;\n background: var(--csk-primary);\n border-radius: 1px;\n animation: csk-caret-blink 1s step-end infinite;\n}\n@keyframes csk-caret-blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n/* ========== 代码块复制按钮 ========== */\n.csk-md-code-block { position: relative; }\n.csk-md-code-copy {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(255, 255, 255, 0.12);\n color: #CBD5E1;\n border-radius: 6px;\n cursor: pointer;\n opacity: 0;\n transition: all 0.15s ease;\n}\n.csk-md-code-block:hover .csk-md-code-copy { opacity: 1; }\n.csk-md-code-copy:hover { background: rgba(255, 255, 255, 0.22); color: #fff; }\n.csk-md-code-copy:active { transform: scale(0.9); }\n\n/* ========== 新消息提示按钮 ========== */\n.csk-newmsg {\n position: absolute;\n bottom: 82px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 5;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 7px 14px;\n border: none;\n background: var(--csk-primary);\n color: #fff;\n font-size: 12px;\n font-family: inherit;\n border-radius: 999px;\n cursor: pointer;\n box-shadow: 0 4px 14px rgba(var(--csk-primary-rgb), 0.38);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: csk-msg-in 0.25s ease;\n white-space: nowrap;\n}\n.csk-newmsg:hover { transform: translateX(-50%) translateY(-1px); box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.48); }\n.csk-newmsg:active { transform: translateX(-50%) scale(0.95); }\n.csk-newmsg--hidden { display: none; }\n\n/* ========== 发送按钮停止态 ========== */\n.csk-send-btn--stop {\n background: #EF4444 !important;\n box-shadow: 0 3px 10px rgba(239, 68, 68, 0.35) !important;\n}\n.csk-send-btn--stop:hover:not(:disabled) {\n box-shadow: 0 5px 14px rgba(239, 68, 68, 0.45) !important;\n}\n\n/* ========== 暗色模式 ========== */\n.csk-root.csk-dark {\n --csk-bg-ai: #1E1E2E;\n --csk-text-ai: #E2E8F0;\n --csk-border: #3B3B52;\n --csk-bg-app: #141421;\n color: #E2E8F0;\n}\n.csk-dark .csk-window {\n background: #1A1A2E;\n box-shadow: 0 12px 48px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.2);\n}\n.csk-dark .csk-header::after { background: linear-gradient(to bottom, rgba(0,0,0,0.12), transparent); }\n.csk-dark .csk-msg__avatar--ai {\n background: var(--csk-bg-ai);\n color: var(--csk-primary);\n border-color: var(--csk-border);\n}\n.csk-dark .csk-input-area { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-input-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-input-wrap--focus { background: #1A1A2E; border-color: var(--csk-primary); }\n.csk-dark .csk-input { color: #E2E8F0; }\n.csk-dark .csk-loading__avatar { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__bubble { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__dot { background: #6B7280; }\n.csk-dark .csk-category-bar { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-category-select { background-color: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-sources { background: #1E1E2E; border-color: var(--csk-border); }\n.csk-dark .csk-sources__header { background: #25253A; }\n.csk-dark .csk-sources__header:hover { background: #2D2D48; }\n.csk-dark .csk-source-item:hover { background: var(--csk-bg-ai); }\n.csk-dark .csk-source-item__name { color: #E2E8F0; }\n.csk-dark .csk-source-item__meta { color: #6B7280; }\n.csk-dark .csk-history-panel { background: #1A1A2E; }\n.csk-dark .csk-history-panel__header { background: var(--csk-bg-app); border-bottom-color: var(--csk-border); }\n.csk-dark .csk-history-panel__back { background: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-history-panel__back:hover { background: #2D2D48; }\n.csk-dark .csk-history-item:hover { background: #25253A; }\n.csk-dark .csk-history-item__id { color: #E2E8F0; }\n.csk-dark .csk-history-item__meta { color: #6B7280; }\n.csk-dark .csk-history-item--active { background: rgba(var(--csk-primary-rgb), 0.15); }\n.csk-dark .csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.22); }\n.csk-dark .csk-action-btn:hover { background: #2D2D48; color: #E2E8F0; }\n.csk-dark .csk-clear-btn { background: var(--csk-bg-app); border-color: var(--csk-border); color: #9CA3AF; }\n.csk-dark .csk-clear-btn:hover { background: #3B1A1A; border-color: #7F1D1D; color: #FCA5A5; }\n.csk-dark .csk-md-code-block { background: #0F0F1A; }\n.csk-dark .csk-md-blockquote { background: rgba(var(--csk-primary-rgb), 0.08); }\n.csk-dark .csk-md-link { color: var(--csk-primary-light); }\n.csk-dark .csk-msg--ai .csk-msg__bubble { background: var(--csk-bg-ai); color: var(--csk-text-ai); border-color: var(--csk-border); }\n.csk-dark .csk-welcome__title { color: #E2E8F0; }\n.csk-dark .csk-welcome__desc { color: #6B7280; }\n.csk-dark .csk-quick-reply { background: var(--csk-bg-app); border-color: var(--csk-border); color: #CBD5E1; }\n.csk-dark .csk-quick-reply:hover { background: rgba(var(--csk-primary-rgb), 0.12); border-color: var(--csk-primary); color: var(--csk-primary-light); }\n.csk-dark .csk-teaser { background: #2D2D48; color: #E2E8F0; box-shadow: 0 4px 20px rgba(0,0,0,0.35); }\n.csk-dark .csk-teaser::after { border-top-color: #2D2D48; }\n.csk-dark .csk-teaser__close { color: #6B7280; }\n.csk-dark .csk-teaser__close:hover { color: #9CA3AF; }\n.csk-dark .csk-feedback-btn { background: rgba(var(--csk-primary-rgb), 0.1); color: #9CA3AF; }\n.csk-dark .csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.2); color: var(--csk-primary-light); }\n.csk-dark .csk-feedback-btn--active { background: rgba(var(--csk-primary-rgb), 0.28); color: var(--csk-primary-light); }\n.csk-dark .csk-history-panel__search-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-history-panel__search-wrap:focus-within { border-color: var(--csk-primary); }\n.csk-dark .csk-history-panel__search { color: #E2E8F0; }\n.csk-dark .csk-launcher__badge { box-shadow: 0 0 0 2px #1A1A2E; }\n.csk-dark .csk-welcome__avatar { box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.25); }\n.csk-dark .csk-header__avatar { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.1); }\n\n/* ========== Launcher 未读徽章 ========== */\n.csk-launcher__badge {\n position: absolute;\n top: -2px;\n right: -2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #EF4444;\n border: 2px solid #fff;\n box-shadow: 0 0 0 2px #fff;\n animation: csk-badge-in 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);\n pointer-events: none;\n}\n.csk-launcher__badge--hidden { display: none; }\n@keyframes csk-badge-in {\n from { transform: scale(0); }\n to { transform: scale(1); }\n}\n\n/* ========== Launcher 提示气泡 ========== */\n.csk-teaser {\n position: fixed;\n bottom: 90px;\n z-index: 9997;\n max-width: 240px;\n padding: 10px 14px;\n background: #fff;\n color: #1F2937;\n font-size: 13px;\n line-height: 1.5;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(15, 23, 42, 0.15);\n animation: csk-teaser-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);\n cursor: pointer;\n user-select: none;\n}\n.csk-teaser--right { right: 24px; }\n.csk-teaser--left { left: 24px; }\n.csk-teaser::after {\n content: '';\n position: absolute;\n bottom: -6px;\n right: 28px;\n width: 12px;\n height: 12px;\n background: inherit;\n border-radius: 2px;\n transform: rotate(45deg);\n box-shadow: 2px 2px 4px rgba(15, 23, 42, 0.08);\n}\n.csk-teaser--left::after { right: auto; left: 28px; }\n.csk-teaser__close {\n position: absolute;\n top: 4px;\n right: 6px;\n background: none;\n border: none;\n font-size: 16px;\n color: #9CA3AF;\n cursor: pointer;\n padding: 2px 4px;\n line-height: 1;\n border-radius: 4px;\n}\n.csk-teaser__close:hover { color: #374151; }\n.csk-teaser--hidden { display: none; }\n@keyframes csk-teaser-in {\n from { opacity: 0; transform: translateY(8px) scale(0.95); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n/* ========== 消息反馈按钮(👍 / 👎) ========== */\n.csk-feedback-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(var(--csk-primary-rgb), 0.08);\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n padding: 0;\n}\n.csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.18); color: var(--csk-primary); }\n.csk-feedback-btn--active {\n background: rgba(var(--csk-primary-rgb), 0.28);\n color: var(--csk-primary);\n}\n.csk-feedback-btn--active.down { background: #FEF2F2; color: #EF4444; }\n.csk-feedback-btn:active { transform: scale(0.9); }\n.csk-msg--streaming .csk-feedback-btn { display: none; }\n\n/* ========== 历史会话搜索框 ========== */\n.csk-history-panel__search-wrap {\n padding: 8px 10px;\n border-bottom: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-history-panel__search-wrap:focus-within {\n border-bottom-color: var(--csk-primary);\n}\n.csk-history-panel__search {\n width: 100%;\n padding: 7px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n font-family: inherit;\n color: #1F2937;\n background: var(--csk-bg-app);\n outline: none;\n transition: border-color 0.2s;\n}\n.csk-history-panel__search:focus { border-color: var(--csk-primary); }\n.csk-history-panel__search::placeholder { color: #9CA3AF; }\n\n/* ========== a11y 焦点指示 ========== */\n.csk-root :focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n}\n.csk-root button:focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n border-radius: inherit;\n}\n/* 弹窗打开时隐藏 launcher 上的焦点环 */\n.csk-launcher:focus-visible {\n outline: none;\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12),\n 0 0 0 4px rgba(var(--csk-primary-rgb), 0.3);\n}\n\n/* ========== a11y aria-live 播报区(视觉隐藏) ========== */\n.csk-sr-only {\n position: absolute !important;\n width: 1px !important;\n height: 1px !important;\n padding: 0 !important;\n margin: -1px !important;\n overflow: hidden !important;\n clip: rect(0,0,0,0) !important;\n white-space: nowrap !important;\n border: 0 !important;\n}\n\n/* ========== 会话分组标题 ========== */\n.csk-history-group {\n margin-bottom: 4px;\n}\n.csk-history-group__label {\n font-size: 11px;\n font-weight: 600;\n color: #9CA3AF;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: 8px 12px 4px;\n user-select: none;\n}\n.csk-dark .csk-history-group__label { color: #6B7280; }\n\n/* ========== 移动端适配 ========== */\n@media (max-width: 480px) {\n .csk-window {\n width: 100vw !important;\n height: 100vh !important;\n max-height: 100vh;\n bottom: 0 !important;\n right: 0 !important;\n left: 0 !important;\n border-radius: 0;\n }\n .csk-window--hidden { transform: translateY(100%); }\n .csk-launcher { bottom: 20px; }\n .csk-launcher--right { right: 20px; }\n .csk-launcher--left { left: 20px; }\n}\n`}(e),document.head.appendChild(T))}function z(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const n=16*Math.random()|0;return("x"===e?n:3&n|8).toString(16)})}function H(e){const n={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,e=>n[e]||e)}function j(){return Date.now()}const R='';function P(e,n){const t=document.createElement("div");t.id="csk-launcher";const r=e.launcherTheme?" csk-launcher--glass":"";t.className=`csk-launcher csk-launcher--${"left-bottom"===e.position?"left":"right"}${r}`,t.setAttribute("title",e.title),t.setAttribute("aria-label",e.title),t.setAttribute("role","button"),t.setAttribute("tabindex","0"),t.innerHTML=e.launcherIcon;const s=document.createElement("div");s.className="csk-launcher__badge csk-launcher__badge--hidden",t.appendChild(s);const o=function(e,n){let t=null;return function(...r){null!==t&&clearTimeout(t),t=setTimeout(()=>{e.apply(this,r),t=null},n)}}(n,300);return t.addEventListener("click",o),t.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),o())}),t}function U(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--user";const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--user",s.innerHTML='';const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.textContent=n;const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(t),o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),r}function O(e,n,t,r,s){const o=document.createElement("div");o.className="csk-msg csk-msg--ai",s&&(o.dataset.cskMsgId=s);const a=document.createElement("div");a.className="csk-msg__avatar csk-msg__avatar--ai",a.innerHTML=R;const i=document.createElement("div");i.className="csk-msg__content";const c=document.createElement("div");c.className="csk-msg__bubble",r?c.innerHTML=r(n):c.textContent=n;const l=document.createElement("div");return l.className="csk-msg__time",l.textContent=ne(t),i.appendChild(c),i.appendChild(G(c,o)),i.appendChild(l),o.appendChild(a),o.appendChild(i),e.appendChild(o),X(c),o}const Y='',W='';function G(e,n){const t=document.createElement("div");t.className="csk-msg__actions";const r=document.createElement("button");r.type="button",r.className="csk-action-btn",r.setAttribute("title",m("copy")),r.setAttribute("aria-label",m("copy")),r.innerHTML=Y,r.addEventListener("click",async n=>{n.stopPropagation();const t=e.textContent||"";await K(t,r)});const s=document.createElement("button");s.type="button",s.className="csk-action-btn",s.setAttribute("title",m("retry")),s.setAttribute("aria-label",m("retry")),s.innerHTML=W,s.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:retry",{detail:{msgId:n.dataset.cskMsgId||""}}))});const o=document.createElement("button");o.type="button",o.className="csk-feedback-btn",o.setAttribute("title",m("feedback_up")),o.setAttribute("aria-label",m("feedback_up")),o.innerHTML='',o.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"up"}}))});const a=document.createElement("button");return a.type="button",a.className="csk-feedback-btn",a.setAttribute("title",m("feedback_down")),a.setAttribute("aria-label",m("feedback_down")),a.innerHTML='',a.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"down"}}))}),t.appendChild(r),t.appendChild(s),t.appendChild(o),t.appendChild(a),t}function V(e,n){const t=e.querySelectorAll(".csk-feedback-btn");t.length<2||(t.forEach(e=>e.classList.remove("csk-feedback-btn--active","down")),"up"===n&&t[0]&&t[0].classList.add("csk-feedback-btn--active"),"down"===n&&t[1]&&t[1].classList.add("csk-feedback-btn--active","down"))}async function K(e,n){const t=n.innerHTML;try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(e);else{const n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}n.innerHTML='',n.classList.add("csk-action-btn--done"),setTimeout(()=>{n.innerHTML=t,n.classList.remove("csk-action-btn--done")},1500)}catch(e){}}function X(e){e.querySelectorAll(".csk-md-code-block").forEach(e=>{if(e.querySelector(".csk-md-code-copy"))return;const n=e.querySelector("code"),t=document.createElement("button");t.type="button",t.className="csk-md-code-copy",t.setAttribute("title",m("copy")),t.setAttribute("aria-label",m("copy")),t.innerHTML=Y,t.addEventListener("click",async e=>{e.stopPropagation(),await K((null==n?void 0:n.textContent)||"",t)}),e.appendChild(t)})}function J(e,n){e.classList.remove("csk-msg--streaming");const t=n.querySelector(".csk-caret");t&&t.remove(),X(n)}function Q(e,n){const t=e.querySelector(".csk-sources");if(t&&t.remove(),!n||0===n.length)return;const r=document.createElement("div");r.className="csk-sources csk-sources--collapsed";const s=document.createElement("div");s.className="csk-sources__header";const o=document.createElement("span");o.className="csk-sources__title",o.textContent=`📚 ${m("source_count",{n:n.length})}`;const a=document.createElement("span");a.className="csk-sources__arrow",a.textContent="▼",s.appendChild(o),s.appendChild(a),s.addEventListener("click",()=>{r.classList.toggle("csk-sources--collapsed")});const i=document.createElement("div");i.className="csk-sources__body";for(const e of n){const n=document.createElement("div");n.className="csk-source-item";const t=document.createElement("div");if(t.className="csk-source-item__name",t.textContent=e.title||e.sourceName||"未知文档",e.snippet){const t=document.createElement("div");t.className="csk-source-item__snippet",t.textContent=e.snippet,n.appendChild(t)}const r=document.createElement("div");r.className="csk-source-item__meta";const s=[];e.sourceName&&s.push(e.sourceName),void 0!==e.chunkIndex&&s.push(`分块 #${e.chunkIndex}`),void 0!==e.score&&s.push(`相关度 ${(100*e.score).toFixed(0)}%`),r.textContent=s.join(" · "),n.appendChild(t),n.appendChild(r),i.appendChild(n)}r.appendChild(s),r.appendChild(i);const c=e.querySelector(".csk-msg__time");c&&c.parentNode?c.parentNode.insertBefore(r,c):e.appendChild(r)}function Z(e,n,t,r,s,o,a){if(e.innerHTML="",0===n.length){const n=document.createElement("div");return n.className="csk-history-panel__empty",n.innerHTML=`\n
💬
\n
${m("history_empty")}
\n `,void e.appendChild(n)}const i=function(e){const n=new Date,t=new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime(),r=t-864e5,s=t-864e5*(n.getDay()||7)+864e5,o={today:[],yesterday:[],week:[],earlier:[]};for(const n of e){const e=n.lastMessageTime||n.createdAt,a=e?new Date(e).getTime():0;a>=t?o.today.push(n):a>=r?o.yesterday.push(n):a>=s?o.week.push(n):o.earlier.push(n)}const a=[];return o.today.length&&a.push({label:m("history_group_today"),items:o.today}),o.yesterday.length&&a.push({label:m("history_group_yesterday"),items:o.yesterday}),o.week.length&&a.push({label:m("history_group_week"),items:o.week}),o.earlier.length&&a.push({label:m("history_group_earlier"),items:o.earlier}),a}(n);for(const n of i){if(i.length>1){const t=document.createElement("div");t.className="csk-history-group";const r=document.createElement("div");r.className="csk-history-group__label",r.textContent=n.label,t.appendChild(r),e.appendChild(t)}for(const a of n.items){const n=document.createElement("div");n.className="csk-history-item";const i=a.chatId||a.id;o&&i===o&&n.classList.add("csk-history-item--active");const c=document.createElement("div");c.className="csk-history-item__info";const l=document.createElement("div");l.className="csk-history-item__id",a.lastMessagePreview?l.textContent=a.lastMessagePreview.length>60?a.lastMessagePreview.substring(0,60)+"...":a.lastMessagePreview:l.textContent=i;const d=document.createElement("div");d.className="csk-history-item__meta";const p=[];void 0!==a.messageCount&&p.push(`${a.messageCount} 条消息`),a.lastMessageTime?p.push(a.lastMessageTime):a.createdAt&&p.push(a.createdAt),d.textContent=p.join(" · "),c.appendChild(l),c.appendChild(d);const u=document.createElement("div");u.className="csk-history-item__actions";const g=document.createElement("button");g.className="csk-history-action csk-history-action--export",g.setAttribute("title",m("history_export")),g.innerHTML='',g.addEventListener("click",e=>{e.stopPropagation(),r(a.id)});const k=document.createElement("button");k.className="csk-history-action csk-history-action--delete",k.setAttribute("title",m("history_delete")),k.innerHTML='',k.addEventListener("click",e=>{e.stopPropagation(),s(a.id)}),u.appendChild(g),u.appendChild(k),n.appendChild(c),n.appendChild(u),n.addEventListener("click",()=>{t(i)}),e.appendChild(n)}}}function ee(e){e.scrollTop=e.scrollHeight}function ne(e){const n=new Date(e);return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}function te(e){return`csk_history_${e}`}function re(e,n){try{let t=n;t.length>200&&(t=t.slice(50),o.warn(`消息数量达到上限,已裁剪最早 50 条,当前 ${t.length} 条`));const r={messages:t,updatedAt:Date.now()};localStorage.setItem(te(e),JSON.stringify(r))}catch(e){e instanceof Error&&"QuotaExceededError"===e.name?o.error("localStorage 空间不足,会话历史保存失败。建议清空历史记录。"):o.error("保存会话历史失败",e)}}function se(e){try{localStorage.removeItem(te(e))}catch(e){o.warn("清空会话历史失败",e)}}const oe="\0CODEBLOCK_",ae="\0INLINECODE_";function ie(e){if(!e||"string"!=typeof e)return"";const n=[];let t=e;t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(e,t,r)=>{const s=n.length,o=H(r.trimEnd()),a=t?` class="language-${H(t)}"`:"";return n.push(`
${o}
`),`${oe}${s}\0`});const r=[];t=t.replace(/`([^`\n]+)`/g,(e,n)=>{const t=r.length;return r.push(`${H(n)}`),`${ae}${t}\0`}),t=H(t),t=ce(t,oe,n),t=ce(t,ae,r);const s=t.split("\n"),o=[];let a=!1,i="",c=!1,l=[];for(let e=0;e')){p(),u(),g(),o.push(n);continue}const t=n.match(/^(#{1,6})\s+(.+)/);if(t){p(),u(),g();const e=t[1].length;o.push(`${t[2]}`);continue}const r=n.match(/^>\s?(.*)/);if(r){p(),u(),c||(c=!0,o.push('
')),o.push(`

${d(r[1])}

`);continue}c&&g();const k=n.match(/^[\-\*]\s+(.+)/);if(k){p(),g(),a&&"ul"===i||(u(),a=!0,i="ul",o.push('
    ')),o.push(`
  • ${d(k[1])}
  • `);continue}const m=n.match(/^\d+\.\s+(.+)/);m?(p(),g(),a&&"ol"===i||(u(),a=!0,i="ol",o.push('
      ')),o.push(`
    1. ${d(m[1])}
    2. `)):""!==n.trim()?/^(\*{3,}|-{3,}|_{3,})$/.test(n.trim())?(p(),u(),g(),o.push('
      ')):(u(),g(),l.push(d(n))):(p(),u())}return p(),u(),g(),o.join("\n");function d(e){return e=(e=(e=(e=(e=(e=e.replace(/\*\*(.+?)\*\*/g,"$1")).replace(/__(.+?)__/g,"$1")).replace(/\*(.+?)\*/g,"$1")).replace(/(?$1")).replace(/~~(.+?)~~/g,"$1")).replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,n,t)=>`${n}`)}function p(){l.length>0&&(o.push(`

      ${l.join("
      ")}

      `),l=[])}function u(){a&&(o.push("ul"===i?"
":""),a=!1,i="")}function g(){c&&(o.push("
"),c=!1)}}function ce(e,n,t){return e.replace(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"(\\d+)\0","g"),(e,n)=>t[parseInt(n)]||"")}let le,de=null,pe=[],ue=null,ge=null,ke=null,me=null,he=null,be=null,fe=null,ye=null,xe=null,ve=null,we=null,_e=null,Ee=null,Ce=!1,Ie=null,$e=!0,Ae=[],Le="",Se=!1;function Fe(e,n){de=e,ue=n.messagesContainer,ge=n.inputEl,ke=n.inputEl.parentElement,me=n.sendBtn,he=n.clearBtn,be=n.categorySelect,fe=n.historyPanel,ye=n.welcomeEl,xe=n.newMsgBtn,ve=n.searchInput,we=n.ariaLiveEl,_e=n.showLoading,Ee=n.hideLoading,le=e.categoryId,Se=!!e.enableRag||!!e.categoryId||!!e.showCategorySwitch,function(){if(!ge||!me)return;me.addEventListener("click",()=>{Ce&&Ie?Ie.abort():je()}),ge.addEventListener("keydown",e=>{"Enter"!==e.key||e.shiftKey||e.isComposing||(e.preventDefault(),je())}),ge.addEventListener("input",()=>{He(),function(){if(!ge)return;ge.style.height="auto",ge.style.height=`${Math.min(ge.scrollHeight,120)}px`}()}),ge.addEventListener("focus",()=>{ke&&ke.classList.add("csk-input-wrap--focus")}),ge.addEventListener("blur",()=>{ke&&ke.classList.remove("csk-input-wrap--focus")}),he&&he.addEventListener("click",()=>function(){if(!de)return;if(!confirm(m("clear_confirm")))return;if(pe=[],ue){ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove())}he&&(he.style.display="none");ze(),se(de.integrateId);const e=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();b(e),M(de.integrateId,de.userId,e),o.lifecycleClear(de.integrateId),o.info(`新 chatId=${e}`)}())}(),function(){if(!ue)return;ue.addEventListener("scroll",()=>{if(!ue)return;const{scrollTop:e,scrollHeight:n,clientHeight:t}=ue;$e=n-e-t<80,$e&&Me()}),xe&&xe.addEventListener("click",()=>{ue&&ee(ue),$e=!0,Me()})}(),function(){if(!ve)return;ve.addEventListener("input",()=>{Le=ve.value.trim().toLowerCase(),Be()})}(),e.showCategorySwitch&&be&&async function(){if(!be)return;try{const e=await async function(){const e=y("/category/tree");try{const n=await v(e);if(!n.ok)throw new w(_(n.status),`http_${n.status}`);const t=await n.json();return t.success&&Array.isArray(t.data)?(o.info(`加载分类树成功 count=${t.data.length}`),t.data):[]}catch(e){return e instanceof w?o.error(`加载分类树失败: ${e.message}`):o.error("加载分类树失败",e),[]}}();if(0===e.length)return;be.innerHTML=``;const n=(e,t=0)=>{for(const r of e){const e=document.createElement("option");e.value=String(r.id),e.textContent=`${" ".repeat(t)}${r.name}`,void 0!==le&&String(r.id)===String(le)&&(e.selected=!0),be.appendChild(e),r.children&&r.children.length>0&&n(r.children,t+1)}};n(e),o.info(`知识库分类加载成功 count=${e.length}`)}catch(e){o.error(m("category_load_error"),e)}}()}async function Ne(){if(de&&ue&&(await F(),await async function(){if(!de||!ue)return;const e=f();if(!e)return;try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map((e,n)=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`从后端加载 ${pe.length} 条历史消息`),re(de.integrateId,pe))}catch(e){o.warn("从后端加载历史消息失败",e)}}(),0===pe.length)){const e=function(e){try{const n=localStorage.getItem(te(e));if(!n)return[];const t=JSON.parse(n);return t&&Array.isArray(t.messages)?(o.info(`加载历史消息 integrateId=${e} count=${t.messages.length}`),t.messages):[]}catch(e){return o.warn("加载会话历史失败",e),[]}}(de.integrateId);e.length>0&&(pe=e,Pe(),o.info(`从本地缓存恢复 ${e.length} 条消息`))}}function Me(){xe&&xe.classList.add("csk-newmsg--hidden")}function Te(){ue&&($e?ee(ue):xe&&xe.classList.remove("csk-newmsg--hidden"))}function De(e){me&&("stop"===e?(me.classList.add("csk-send-btn--stop"),me.removeAttribute("disabled"),me.setAttribute("title",m("stop")),me.setAttribute("aria-label",m("stop")),me.innerHTML=''):(me.classList.remove("csk-send-btn--stop"),me.setAttribute("title",m("send")),me.setAttribute("aria-label",m("send")),me.innerHTML='',He()))}function Be(){const e=null==fe?void 0:fe.querySelector("#csk-history-list");if(!e||!de)return;Z(e,Le?Ae.filter(e=>(e.lastMessagePreview||e.chatId||e.id||"").toLowerCase().includes(Le)):Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{if(!confirm(m("history_delete_confirm")))return;await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}function qe(e,n){if(!ue)return;const t=pe.find(n=>n.id===e&&"ai"===n.role);if(!t)return;const r=t.feedback===n?void 0:n;t.feedback=r;const s=ue.querySelector(`[data-csk-msg-id="${e}"]`);if(s&&V(s,r),de&&re(de.integrateId,pe),r){const n="up"===r?"THUMBS_UP":"THUMBS_DOWN";(async function(e,n){if(!h)return!1;const t=y("/feedback");try{const r=await v(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messageId:String(e),conversationId:h.chatId,feedbackType:n})});return r.ok?(await r.json()).success||!1:(o.error(`反馈提交失败 status=${r.status}`),!1)}catch(e){return o.error("反馈提交异常",e),!1}})(String(e),n).then(n=>{n?o.info(`消息反馈已提交 msgId=${e} value=${r}`):o.warn(`消息反馈提交失败 msgId=${e}(本地状态已更新)`)})}else o.info(`消息反馈已取消 msgId=${e}`)}function ze(){if(!ye)return;const e=pe.length>0||ue&&ue.querySelector(".csk-msg");ye.style.display=e?"none":""}function He(){if(!me||!ge)return;ge.value.trim().length>0&&!Ce?me.removeAttribute("disabled"):me.setAttribute("disabled","true")}async function je(){if(!ge||!de||Ce)return;const e=ge.value.trim();if(""===e)return;ge.value="",He(),ge.style.height="auto";const n=j(),t={id:z(),role:"user",content:e,timestamp:n};ue&&U(ue,e,n),pe.push(t),ze(),he&&pe.length>0&&(he.style.display="inline-flex"),ue&&Te(),await Re(e)}async function Re(e){if(!de||!ue)return;Ce=!0,De("stop"),de.chatId||await F();const n=j(),t=Se&&(de.enableRag||void 0!==le||void 0!==de.categoryId);_e&&_e(),ue&&Te();const r=z();let s="";try{de.streaming?s=await async function(e,n,t,r){Ie=new AbortController;const s=Ie.signal;return new Promise((o,a)=>{let i=null,c=null,l="",d=!1;C(e,e=>{if(l+=e,!d&&ue){Ee&&Ee();const{wrapper:e,bubble:t}=function(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--ai csk-msg--streaming",t&&(r.dataset.cskMsgId=t);const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--ai",s.innerHTML=R;const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.innerHTML="";const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(n),o.appendChild(a),o.appendChild(G(a,r)),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),{wrapper:r,bubble:a}}(ue,n,r);c=e,i=t,d=!0}i&&(i.textContent=l,function(e){if(e.querySelector(".csk-caret"))return;const n=document.createElement("span");n.className="csk-caret",n.setAttribute("aria-hidden","true"),e.appendChild(n)}(i)),ue&&Te()},()=>{if(c&&i){if(!d&&""===l)return void E(e).then(o).catch(a);l&&(i.innerHTML=ie(l)),J(c,i)}o(l)},e=>{l.length>0?(i&&(i.innerHTML=ie(l+"\n\n"+m("stream_interrupted")),c&&J(c,i)),o(l)):a(e)},le,t,s)})}(e,n,t,r):(s=await E(e),Ee&&Ee(),ue&&O(ue,s,n,ie,r));const a={id:r,role:"ai",content:s,timestamp:n};pe.push(a),re(de.integrateId,pe),ue&&Te(),function(e){if(!we)return;const n=e.length>120?e.substring(0,120)+"...":e;we.textContent=m("new_msg_announce")+":"+n}(s),ue&&ue.dispatchEvent(new CustomEvent("csk:newMessage",{bubbles:!0,detail:{msg:a}})),t&&async function(e,n){try{const t=await I(e,le);if(t.length>0){const e=t.map(e=>{var n,t;return{documentId:e.documentId||"",title:e.title||"",sourceName:e.sourceName||"",chunkIndex:null!==(n=e.chunkIndex)&&void 0!==n?n:0,score:null!==(t=e.score)&&void 0!==t?t:0,snippet:e.snippet||""}});if(n.sources=e,ue){const n=ue.querySelector(".csk-msg--ai:last-of-type");n&&Q(n,e)}de&&re(de.integrateId,pe)}}catch(e){o.warn("获取引用来源失败",e)}}(e,a)}catch(e){Ee&&Ee();const n=e instanceof w?e.message:m("error_send");if(ue){const e=document.createElement("div");e.className="csk-msg csk-msg--ai";const t=document.createElement("div");t.className="csk-msg__bubble",t.style.color="#DC2626",t.textContent=`⚠ ${n}`,e.appendChild(t),ue.appendChild(e)}o.error(`发送失败 integrateId=${de.integrateId}`,e)}finally{Ce=!1,Ie=null,De("send"),He()}}function Pe(){if(!ue)return;const e=ue.querySelector(".csk-history-panel");ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());for(const e of pe)if("user"===e.role)U(ue,e.content,e.timestamp);else{const n=O(ue,e.content,e.timestamp,ie,e.id);e.sources&&e.sources.length>0&&Q(n,e.sources),e.feedback&&V(n,e.feedback)}$e=!0,ee(ue),he&&pe.length>0&&(he.style.display="inline-flex"),ze(),e&&!ue.contains(e)&&ue.appendChild(e)}async function Ue(e){if(!de||!ue)return;o.info(`切换到会话 conversationId=${e}`),b(e),M(de.integrateId,de.userId,e),fe&&fe.classList.add("csk-history-panel--hidden"),pe=[];ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map(e=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`加载会话 ${e} 的 ${pe.length} 条消息`),re(de.integrateId,pe))}catch(n){o.warn(`加载会话消息失败 conversationId=${e}`,n)}he&&pe.length>0&&(he.style.display="inline-flex"),ze()}let Oe=null,Ye=!1,We=null,Ge=null,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,tn=null,rn=null,sn=null,on=null,an=null;function cn(){if(!rn||!We)return;const e=We.getBoundingClientRect();"left-bottom"===(null==Oe?void 0:Oe.position)?rn.style.left=`${e.left}px`:rn.style.right=window.innerWidth-e.right+"px",rn.style.bottom=window.innerHeight-e.top+8+"px"}function ln(){if(!rn)return;rn.classList.add("csk-teaser--hidden"),rn.removeEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.removeEventListener("click",pn)}function dn(e){e.target.closest(".csk-teaser__close")||(ln(),mn())}function pn(e){e.stopPropagation(),ln()}function un(){rn&&!rn.classList.contains("csk-teaser--hidden")&&cn()}const gn='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';function kn(e){"Escape"===e.key&&Ge&&!Ge.classList.contains("csk-window--hidden")&&hn(),function(e){if(!Ge||Ge.classList.contains("csk-window--hidden"))return;if("Tab"!==e.key)return;const n=Array.from(Ge.querySelectorAll(gn));if(0===n.length)return;const t=n[0],r=n[n.length-1];e.shiftKey?document.activeElement===t&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),t.focus())}(e)}function mn(){Ge&&(Ge.classList.remove("csk-window--hidden"),ln(),on&&on.classList.add("csk-launcher__badge--hidden"),setTimeout(()=>{Ke&&Ke.focus()},80))}function hn(){Ge&&Ge.classList.add("csk-window--hidden")}function bn(){Ge&&(Ge.classList.contains("csk-window--hidden")?mn():hn())}function fn(e){return`csk_position_${e}`}const yn={init:function(e){if(Ye)return void o.warn("SDK 已初始化,请先调用 destroy() 再重新初始化");const t=function(e){var n,t,r,s,i,g,k,m,h,b,f;if(!e.integrateId||"string"!=typeof e.integrateId&&"number"!=typeof e.integrateId||"string"==typeof e.integrateId&&""===e.integrateId.trim())return o.error('integrateId 是必传参数(对应后端 roleId 客服角色 ID),请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;if(!e.requestDomain||"string"!=typeof e.requestDomain||""===e.requestDomain.trim())return o.error('requestDomain 是必传参数,请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;try{new URL(e.requestDomain)}catch(n){return o.error(`requestDomain 不是合法的 URL 格式:${e.requestDomain}。请提供完整的域名,如 https://api.example.com`),null}const y=String(e.integrateId).trim(),x=e.launcherTheme||void 0;let v=e.launcherIcon||a,w=e.primaryColor||"#4F46E5";x&&!e.launcherIcon&&(v={"dream-purple":c,"mint-tech":l,"coral-peach":d,"sky-blue":p}[x]||a,e.primaryColor||(w=u[x]||"#4F46E5"));const _={integrateId:y,requestDomain:e.requestDomain.replace(/\/+$/,""),userId:e.userId,categoryId:e.categoryId,showCategorySwitch:null!==(n=e.showCategorySwitch)&&void 0!==n&&n,title:e.title||"AI 智能助手",width:null!==(t=e.width)&&void 0!==t?t:380,height:Math.max(300,null!==(r=e.height)&&void 0!==r?r:520),position:"left-bottom"===e.position?"left-bottom":"right-bottom",primaryColor:w,launcherTheme:x,launcherIcon:v,showClear:null===(s=e.showClear)||void 0===s||s,showAdminPanel:null!==(i=e.showAdminPanel)&&void 0!==i&&i,quickReplies:Array.isArray(e.quickReplies)?e.quickReplies.map(e=>String(e).trim()).filter(Boolean):[],theme:"dark"===e.theme?"dark":"light",showTeaser:null===(g=e.showTeaser)||void 0===g||g,teaserText:"string"==typeof e.teaserText&&e.teaserText.trim()||"",streaming:null===(k=e.streaming)||void 0===k||k,enableRag:null!==(m=e.enableRag)&&void 0!==m&&m,rewriteStrategy:e.rewriteStrategy||"REWRITE",locale:e.locale||"zh-CN",debug:null===(h=e.debug)||void 0===h||h,sound:null!==(b=e.sound)&&void 0!==b&&b,notification:null!==(f=e.notification)&&void 0!==f&&f,onError:"function"==typeof e.onError?e.onError:void 0,onReady:"function"==typeof e.onReady?e.onReady:void 0,onMessage:"function"==typeof e.onMessage?e.onMessage:void 0,chatId:""};return o.info(`配置解析完成 integrateId(=roleId)=${_.integrateId} userId(=accountId)=${_.userId||"(未设置)"} requestDomain=${_.requestDomain}`),_}(e);if(!t)return;var s;Oe=t,function(e){if(g[e])k=e;else{const n=e.split("-")[0],t=Object.keys(g).find(e=>e.startsWith(n));t&&(k=t)}}(Oe.locale),s=Oe.debug,n=s,r(Oe.onError),function(e){h=e}(Oe),q(Oe),We=P(Oe,bn),document.body.appendChild(We),on=We.querySelector(".csk-launcher__badge");const i=function(e){const n=document.createElement("div");n.id="csk-window",n.className=`csk-root csk-window csk-window--${"left-bottom"===e.position?"left":"right"} csk-window--hidden${"dark"===e.theme?" csk-dark":""}`,n.setAttribute("role","dialog"),n.setAttribute("aria-label",e.title),n.setAttribute("aria-modal","false");const t=document.createElement("div");t.className="csk-header";const r=document.createElement("div");r.className="csk-header__left";const s=document.createElement("div");s.className="csk-header__avatar",s.innerHTML=R;const o=document.createElement("div");o.className="csk-header__info";const a=document.createElement("span");a.className="csk-header__title",a.textContent=e.title;const i=document.createElement("span");i.className="csk-header__status",i.innerHTML=`${m("status_online")}`,o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o);const c=document.createElement("div");c.className="csk-header__actions";const l=document.createElement("button");l.className="csk-history-btn",l.setAttribute("title",m("history_title")),l.innerHTML='';const d=document.createElement("button");d.className="csk-header__btn csk-header__btn--minimize",d.setAttribute("title",m("minimize")),d.innerHTML='',d.addEventListener("click",()=>{n.classList.add("csk-window--hidden")});const p=document.createElement("button");p.className="csk-header__btn csk-header__btn--close",p.setAttribute("title",m("close")),p.innerHTML='',p.addEventListener("click",()=>{n.classList.add("csk-window--hidden")}),c.appendChild(l),c.appendChild(d),c.appendChild(p),t.appendChild(r),t.appendChild(c);const u=document.createElement("div");u.id="csk-messages",u.className="csk-messages";const g=document.createElement("div");if(g.className="csk-welcome",g.innerHTML=`\n
${R}
\n
${m("welcome_title")}
\n
${m("welcome_desc")}
\n `,e.quickReplies.length>0){const t=document.createElement("div");t.className="csk-quick-replies";for(const r of e.quickReplies){const e=document.createElement("button");e.type="button",e.className="csk-quick-reply",e.textContent=r,e.addEventListener("click",()=>{n.dispatchEvent(new CustomEvent("csk:quickReply",{detail:{text:r}}))}),t.appendChild(e)}g.appendChild(t)}u.appendChild(g);const k=document.createElement("button");k.type="button",k.className="csk-newmsg csk-newmsg--hidden",k.innerHTML=`\n \n ${m("new_message")}\n `,n.appendChild(k);const h=document.createElement("div");h.className="csk-history-panel csk-history-panel--hidden",h.innerHTML=`\n
\n ${m("history_title")}\n \n
\n
\n \n
\n
\n `,u.appendChild(h);const b=h.querySelector("#csk-history-back");b&&b.addEventListener("click",()=>{h.classList.add("csk-history-panel--hidden")}),l.addEventListener("click",e=>{e.stopPropagation();const t=h.classList.contains("csk-history-panel--hidden");h.classList.toggle("csk-history-panel--hidden"),t&&n.dispatchEvent(new CustomEvent("csk:loadHistory"))});let f=null;if(e.showCategorySwitch){const e=document.createElement("div");e.className="csk-category-bar";const r=document.createElement("span");r.className="csk-category-bar__label",r.textContent="📚",f=document.createElement("select"),f.id="csk-category-select",f.className="csk-category-select",f.innerHTML=``,f.addEventListener("change",()=>{const e=f.value;n.dispatchEvent(new CustomEvent("csk:categoryChange",{detail:{categoryId:e?Number(e):void 0}}))}),e.appendChild(r),e.appendChild(f),n.appendChild(t),n.appendChild(u),n.appendChild(e)}else n.appendChild(t),n.appendChild(u);const y=document.createElement("div");y.className="csk-input-area";const x=document.createElement("div");x.className="csk-input-wrap";const v=document.createElement("textarea");v.id="csk-input",v.className="csk-input",v.setAttribute("placeholder",m("placeholder")),v.setAttribute("rows","1"),v.setAttribute("autofocus","");const w=document.createElement("button");w.id="csk-send-btn",w.className="csk-send-btn",w.setAttribute("title",m("send")),w.setAttribute("disabled","true"),w.innerHTML='',x.appendChild(v),x.appendChild(w),y.appendChild(x),n.appendChild(y);let _=null;e.showClear&&(_=document.createElement("button"),_.className="csk-clear-btn",_.textContent=m("clear"),_.style.display="none",n.insertBefore(_,y));let E=null;const C=document.createElement("div");C.className="csk-sr-only",C.setAttribute("aria-live","polite"),C.setAttribute("aria-atomic","true"),n.appendChild(C);const I=h.querySelector("#csk-history-search"),$=document.createElement("div");return $.className=`csk-teaser csk-teaser--${"left-bottom"===e.position?"left":"right"} csk-teaser--hidden`,$.setAttribute("role","status"),$.innerHTML=`\n \n ${e.teaserText||m("teaser_text")}\n `,{window:n,messagesContainer:u,inputEl:v,sendBtn:w,clearBtn:_,categorySelect:f,historyPanel:h,welcomeEl:g,newMsgBtn:k,teaserEl:$,searchInput:I,ariaLiveEl:C,showLoading:function(){if(E)return E.style.display="flex",E;const e=document.createElement("div");return e.className="csk-loading",e.innerHTML=`\n
${R}
\n
\n
\n
\n
\n
\n `,u.appendChild(e),E=e,e},hideLoading:function(){E&&E.parentNode&&(E.parentNode.removeChild(E),E=null)}}}(Oe);Ge=i.window,Ve=i.messagesContainer,Ke=i.inputEl,Xe=i.sendBtn,Je=i.clearBtn,Qe=i.categorySelect,Ze=i.historyPanel,en=i.showLoading,nn=i.hideLoading,document.body.appendChild(Ge),rn=i.teaserEl,document.body.appendChild(rn),cn();const b=Ge.querySelector(".csk-header");if(b&&(tn=function(e,n,t){let r=!1,s=0,o=0,a=0,i=0;const c=e=>{if(e.target.closest("button"))return;r=!0,s=e.clientX,o=e.clientY;const t=n.getBoundingClientRect();a=s-t.left,i=o-t.top,document.addEventListener("mousemove",l),document.addEventListener("mouseup",d)},l=e=>{if(!r)return;const t=e.clientX-a,s=e.clientY-i,o=window.innerWidth-n.offsetWidth,c=window.innerHeight-n.offsetHeight;n.style.right="auto",n.style.bottom="auto",n.style.left=`${Math.max(0,Math.min(t,o))}px`,n.style.top=`${Math.max(0,Math.min(s,c))}px`},d=()=>{if(r=!1,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d),t){const e=n.getBoundingClientRect();t({x:e.left,y:e.top})}};return e.addEventListener("mousedown",c),()=>{e.removeEventListener("mousedown",c),document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d)}}(b,Ge,e=>{!function(e,n){try{localStorage.setItem(fn(e),JSON.stringify(n))}catch(e){}}(Oe.integrateId,e)})),function(e,n){try{const t=localStorage.getItem(fn(e));if(!t)return;const r=JSON.parse(t);if("number"!=typeof r.x||"number"!=typeof r.y)return;const s=window.innerWidth-n.offsetWidth,o=window.innerHeight-n.offsetHeight,a=Math.max(0,Math.min(r.x,s)),i=Math.max(0,Math.min(r.y,o));n.style.right="auto",n.style.bottom="auto",n.style.left=`${a}px`,n.style.top=`${i}px`}catch(e){}}(Oe.integrateId,Ge),Fe(Oe,{messagesContainer:Ve,inputEl:Ke,sendBtn:Xe,clearBtn:Je,categorySelect:Qe,historyPanel:Ze,welcomeEl:i.welcomeEl,newMsgBtn:i.newMsgBtn,searchInput:i.searchInput,ariaLiveEl:i.ariaLiveEl,showLoading:en,hideLoading:nn}),Ge.addEventListener("csk:categoryChange",e=>{var n;n=e.detail.categoryId,le=n,Se=void 0!==n,o.lifecycleCategoryChange(null!=n?n:"全部")}),Ge.addEventListener("csk:loadHistory",()=>{!async function(){if(!fe||!de)return;const e=fe.querySelector("#csk-history-list");if(e){e.innerHTML='
加载中...
';try{const n=await $(1,50,de.userId,de.integrateId);Ae=n.list.map(e=>({id:e.conversationId||"",chatId:e.conversationId||"",messageCount:e.messageCount,lastMessageTime:e.lastMessageTime,lastMessagePreview:e.lastMessagePreview,createdAt:e.firstMessageTime||e.createdAt})),Le="",ve&&(ve.value=""),Z(e,Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{confirm(m("history_delete_confirm"))&&await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}catch(n){o.error(m("history_load_error"),n),e.innerHTML=`
${m("history_load_error")}
`}}}()}),Ge.addEventListener("csk:quickReply",e=>{var n;n=e.detail.text,!ge||Ce?Promise.resolve():(ge.value=n,He(),je())}),Ge.addEventListener("csk:retry",e=>{!async function(e){if(!de||!ue||Ce)return;const n=pe.findIndex(n=>n.id===e&&"ai"===n.role);if(n<0)return;let t="";for(let e=n-1;e>=0;e--)if("user"===pe[e].role){t=pe[e].content;break}if(!t)return;const r=pe.splice(n),s=new Set(r.map(e=>e.id));ue.querySelectorAll(".csk-msg").forEach(e=>{const n=e.dataset.cskMsgId;n&&s.has(n)&&e.remove()}),re(de.integrateId,pe),ze(),await Re(t)}(e.detail.msgId)}),Ge.addEventListener("csk:feedback",e=>{qe(e.detail.msgId,e.detail.value)}),Ge.addEventListener("csk:newMessage",e=>{var n;if(Ge&&Ge.classList.contains("csk-window--hidden")&&(on&&on.classList.remove("csk-launcher__badge--hidden"),(null==Oe?void 0:Oe.sound)&&function(){try{an||(an=new(window.AudioContext||window.webkitAudioContext));const e=an;if("suspended"===e.state)return void e.resume();const n=e.currentTime;[0,.15].forEach((t,r)=>{const s=e.createOscillator(),o=e.createGain();s.type="sine",s.frequency.value=0===r?880:1100,o.gain.setValueAtTime(.15,n+t),o.gain.exponentialRampToValueAtTime(.001,n+t+.12),s.connect(o),o.connect(e.destination),s.start(n+t),s.stop(n+t+.12)})}catch(e){}}(),(null==Oe?void 0:Oe.notification)&&function(){try{if(!("Notification"in window))return;"granted"===Notification.permission?new Notification((null==Oe?void 0:Oe.title)||"AI 智能助手",{body:"收到新消息",icon:void 0,silent:!0}):"denied"!==Notification.permission&&Notification.requestPermission()}catch(e){}}()),(null==Oe?void 0:Oe.onMessage)&&(null===(n=e.detail)||void 0===n?void 0:n.msg))try{Oe.onMessage(e.detail.msg)}catch(e){}}),document.addEventListener("keydown",kn),window.addEventListener("resize",un),Ye=!0,o.lifecycleInit(Oe.integrateId,Oe.requestDomain),Oe.onReady)try{Oe.onReady()}catch(e){}Oe.showTeaser&&(sn=setTimeout(()=>{Ge&&Ge.classList.contains("csk-window--hidden")&&function(){if(!rn)return;cn(),rn.classList.remove("csk-teaser--hidden"),rn.addEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.addEventListener("click",pn)}()},1500)),Ne().catch(e=>{o.warn("chatId 初始化失败,将在发送消息时重试",e)})},destroy:function(){if(!Ye)return;sn&&(clearTimeout(sn),sn=null),ln(),rn&&rn.parentNode&&(rn.parentNode.removeChild(rn),rn=null),We&&We.parentNode&&(We.parentNode.removeChild(We),We=null),Ge&&Ge.parentNode&&(Ge.parentNode.removeChild(Ge),Ge=null),tn&&(tn(),tn=null),T&&T.parentNode&&(T.parentNode.removeChild(T),T=null),document.querySelectorAll("style[data-csk-sdk]").forEach(e=>e.remove()),document.removeEventListener("keydown",kn),window.removeEventListener("resize",un),r(void 0);const e=null==Oe?void 0:Oe.integrateId;Oe=null,Ye=!1,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,on=null,an=null,o.lifecycleDestroy(e||"")},open:mn,close:hn,toggle:bn,clearHistory:function(){Oe&&(Je?Je.click():confirm("确定清空所有对话记录?")&&se(Oe.integrateId))}};return"undefined"!=typeof window&&(window.ChatbotSDK=yn),yn}(); +var ChatbotSDK=function(){"use strict";const e="[ChatbotSDK]";let n=!0,t=null;function r(e){t=e||null}const s={},o={info(t,r){n&&console.log(e,t,void 0!==r?r:"")},warn(t,r){n&&console.warn(e,t,void 0!==r?r:"")},error(n,r){if(console.error(e,n,void 0!==r?r:""),t)try{const e=r instanceof Error&&r.type||"error";t({message:n,code:String(e),detail:r})}catch(e){}},time(e){s[e]=Date.now()},timeEnd(t,r){const o=s[t];if(void 0!==o){const a=Date.now()-o;if(delete s[t],n){const n=r?`${r} ${a}ms`:`${t} ${a}ms`;console.log(e,n)}return a}return 0},lifecycleInit(e,n){this.info(`初始化完成 integrateId=${e} requestDomain=${n}`)},lifecycleDestroy(e){this.info(`销毁实例 integrateId=${e}`)},lifecycleSend(e,n){this.info(`发送消息 integrateId=${e} length=${n}`),this.time(`send_${e}`)},lifecycleReply(e,n){const t=this.timeEnd(`send_${e}`,"AI 回复");this.info(`AI 回复 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleError(e,n,t){this.timeEnd(`send_${e}`),this.error(`请求失败 integrateId=${e} status=${n} message=${t}`)},lifecycleClear(e){this.info(`清空会话 integrateId=${e}`)},lifecycleStreamDone(e,n){const t=this.timeEnd(`send_${e}`,"流式回复");this.info(`流式回复完成 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleCategoryChange(e){this.info(`切换知识库分类 categoryId=${e}`)}},a='\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n';function i(e,n,t){return`\n \n \x3c!-- 高光渐变:模拟玻璃反射 --\x3e\n \n \n \n \n \x3c!-- 机器人身体渐变 --\x3e\n \n \n \n \n \n \x3c!-- 机器人主体(圆角矩形 + 对话气泡尾巴) --\x3e\n \n \n \x3c!-- 高光反射层(左上角弧形高光) --\x3e\n \n \x3c!-- 天线 + 能量球 --\x3e\n \n \n \x3c!-- 眼睛(会眨) --\x3e\n \n \n \x3c!-- 眼睛高光点 --\x3e\n \n \n \x3c!-- 微笑 --\x3e\n \n \x3c!-- 跳动气泡装饰(3 个小圆点) --\x3e\n \n \n \n`}const c=i("rgba(139,92,246,0.6)","rgba(139,92,246,0.45)","rgba(240,171,252,0.85)"),l=i("rgba(16,185,129,0.6)","rgba(16,185,129,0.45)","rgba(110,231,183,0.85)"),d=i("rgba(244,63,94,0.55)","rgba(244,63,94,0.4)","rgba(253,186,116,0.85)"),p=i("rgba(56,189,248,0.6)","rgba(56,189,248,0.45)","rgba(167,139,250,0.85)"),u={"dream-purple":"#A78BFA","mint-tech":"#34D399","coral-peach":"#FB7185","sky-blue":"#7DD3FC"};const g={"zh-CN":{title:"AI 智能助手",minimize:"最小化",close:"关闭",status_online:"在线",welcome_title:"你好,我是 AI 智能助手",welcome_desc:"有什么可以帮你的吗?在下方输入框开始提问吧~",placeholder:"输入您的问题...",send:"发送",stop:"停止生成",new_message:"新消息",copy:"复制",copied:"已复制",retry:"重新生成",retrying:"重新生成中...",loading:"正在思考...",stream_interrupted:"回复被中断",stream_unstable:"网络不稳定,内容可能不完整",category_placeholder:"选择知识库分类",category_all:"全部分类",category_load_error:"加载分类失败",source_title:"参考来源",source_count:"{n} 条参考来源",source_loading:"加载来源中...",clear:"清空对话",clear_confirm:"确定清空所有对话记录?",history_title:"历史会话",history_empty:"暂无历史会话",history_load_error:"加载会话列表失败",history_delete_confirm:"确定删除该会话?",history_export:"导出",history_delete:"删除",history_search:"搜索会话...",history_group_today:"今天",history_group_yesterday:"昨天",history_group_week:"本周",history_group_earlier:"更早",feedback_up:"有帮助",feedback_down:"没帮助",teaser_text:"有什么可以帮你的吗?",new_msg_announce:"收到新消息",error_network:"网络连接失败,请检查网络",error_timeout:"请求超时,请稍后重试",error_server:"服务器异常,请稍后重试",error_cors:"跨域请求被拦截,请联系管理员将当前域名加入 API 白名单",error_auth:"鉴权失败,请联系管理员",error_forbidden:"无访问权限,请联系管理员配置",error_not_found:"请求的资源不存在",error_rate_limit:"请求过于频繁,请稍后重试",error_unavailable:"服务暂不可用,请稍后重试",error_unknown:"请求发生未知错误",error_send:"发送失败,请稍后重试",error_stream_unsupported:"浏览器不支持流式读取"},en:{title:"AI Assistant",minimize:"Minimize",close:"Close",status_online:"Online",welcome_title:"Hi, I am your AI assistant",welcome_desc:"How can I help you? Type your question below to get started.",placeholder:"Type your question...",send:"Send",stop:"Stop generating",new_message:"New message",copy:"Copy",copied:"Copied",retry:"Regenerate",retrying:"Regenerating...",loading:"Thinking...",stream_interrupted:"Response interrupted",stream_unstable:"Network unstable, content may be incomplete",category_placeholder:"Select category",category_all:"All categories",category_load_error:"Failed to load categories",source_title:"Sources",source_count:"{n} source(s)",source_loading:"Loading sources...",clear:"Clear chat",clear_confirm:"Clear all conversation history?",history_title:"History",history_empty:"No conversations yet",history_load_error:"Failed to load conversations",history_delete_confirm:"Delete this conversation?",history_export:"Export",history_delete:"Delete",history_search:"Search conversations...",history_group_today:"Today",history_group_yesterday:"Yesterday",history_group_week:"This Week",history_group_earlier:"Earlier",feedback_up:"Helpful",feedback_down:"Not helpful",teaser_text:"How can I help you?",new_msg_announce:"New message received",error_network:"Network connection failed",error_timeout:"Request timed out, please try again",error_server:"Server error, please try again later",error_cors:"CORS request blocked. Please contact admin to whitelist your domain",error_auth:"Authentication failed, please contact admin",error_forbidden:"Access denied, please contact admin",error_not_found:"Resource not found",error_rate_limit:"Too many requests, please try again later",error_unavailable:"Service temporarily unavailable",error_unknown:"Unknown request error",error_send:"Failed to send, please try again",error_stream_unsupported:"Browser does not support streaming"}};let k="zh-CN";function m(e,n){let t=(g[k]||g["zh-CN"])[e]||g["zh-CN"][e]||e;if(n)for(const[e,r]of Object.entries(n))t=t.replace(`{${e}}`,String(r));return t}let h=null;function b(e){h&&(h.chatId=e)}function f(){return(null==h?void 0:h.chatId)||""}function y(e){if(!h)throw new Error("API 配置未初始化");return`${h.requestDomain.replace(/\/+$/,"")}${e.startsWith("/")?e:`/${e}`}`}function x(e,n,t){null!=t&&("string"==typeof t&&""===t.trim()||e.set(n,String(t)))}async function v(e,n={},t=3e4,r){const s=new AbortController,o=setTimeout(()=>s.abort(),t);r&&(r.aborted?s.abort():r.addEventListener("abort",()=>s.abort(),{once:!0}));try{return await fetch(e,Object.assign(Object.assign({},n),{signal:s.signal,mode:"cors",credentials:"include"}))}catch(e){if(null==r?void 0:r.aborted)throw new w("aborted","aborted");if(e instanceof DOMException&&"AbortError"===e.name)throw new w(m("error_timeout"),"timeout");if(e instanceof TypeError&&e.message.includes("Failed to fetch"))throw new w(m("error_cors"),"cors");throw new w(m("error_network"),"network")}finally{clearTimeout(o)}}class w extends Error{constructor(e,n){super(e),this.name="CskError",this.type=n}}function _(e){switch(e){case 401:return m("error_auth");case 403:return m("error_forbidden");case 404:return m("error_not_found");case 429:return m("error_rate_limit");case 500:return m("error_server");case 502:case 503:return m("error_unavailable");default:return`${m("error_unknown")}(${e})`}}async function E(e){const n=function(e){const n=new URLSearchParams;return n.set("message",e),n.set("chatId",h.chatId),x(n,"roleId",h.integrateId),x(n,"accountId",h.userId),y(`/ai/assistant_app/chat/sync?${n.toString()}`)}(e);o.lifecycleSend(h.integrateId,e.length);try{const e=await v(n);if(!e.ok){const n=_(e.status);throw o.lifecycleError(h.integrateId,String(e.status),n),new w(n,`http_${e.status}`)}const t=await e.text();return o.lifecycleReply(h.integrateId,t.length),t}catch(e){if(e instanceof w)throw e;throw o.lifecycleError(h.integrateId,"unknown",String(e)),new w(m("error_unknown"),"unknown")}}async function C(e,n,t,r,s,a,i){var c;const l=a?function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/rag/sse?${t.toString()}`)}(e,s):function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/sse?${t.toString()}`)}(e,s);let d="";o.lifecycleSend(h.integrateId,e.length);try{const e=await v(l,{},6e4,i);if(!e.ok){const n=_(e.status);return o.lifecycleError(h.integrateId,String(e.status),n),void r(new w(n,`http_${e.status}`))}const s=null===(c=e.body)||void 0===c?void 0:c.getReader();if(!s)return void r(new w(m("error_stream_unsupported"),"stream_unsupported"));const a=new TextDecoder("utf-8",{stream:!0});let p="";try{for(;;){const{done:e,value:t}=await s.read();if(e)break;p+=a.decode(t,{stream:!0});const r=p.split("\n");p=r.pop()||"";for(const e of r){const t=e.trim();if(t&&!t.startsWith(":"))if(t.startsWith("data:")){const e=t.substring(5).trim();e&&(d+=e,n(e))}else{if("[DONE]"===t)break;t.startsWith("event:")||t.startsWith("id:")||t.startsWith("retry:")||(d+=t,n(t))}}}if(p.trim()){const e=p.trim();if(e.startsWith("data:")){const t=e.substring(5).trim();t&&(d+=t,n(t))}else"[DONE]"!==e&&(d+=e,n(e))}}catch(e){if(null==i?void 0:i.aborted)o.info(`流式被用户中断,保留已生成内容 length=${d.length}`);else{if(!(d.length>0))throw e;n("\n\n"+m("stream_unstable"))}}finally{s.releaseLock()}o.lifecycleStreamDone(h.integrateId,d.length),t()}catch(e){if((null==i?void 0:i.aborted)||e instanceof w&&"aborted"===e.type)return void t();e instanceof w?r(e):(o.lifecycleError(h.integrateId,"unknown",String(e)),r(new w(m("error_network"),"network")))}}async function I(e,n){const t=function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/rag/sources?${t.toString()}`)}(e,n);try{const e=await v(t);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return n.success&&Array.isArray(n.data)?(o.info(`获取引用来源 count=${n.data.length}`),n.data):[]}catch(e){return o.error("获取引用来源失败",e),[]}}async function $(e=1,n=20,t,r){let s=`/conversation/list?page=${e}&size=${n}`;t&&(s+=`&accountId=${encodeURIComponent(t)}`),r&&(s+=`&roleId=${encodeURIComponent(r)}`);const a=y(s);try{const e=await v(a);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return{list:n.success&&Array.isArray(n.data)?n.data:[],total:n.total||0,pages:n.pages||0}}catch(e){return o.error("加载会话列表失败",e),{list:[],total:0,pages:0}}}async function A(e){const n=y(`/conversation/${e}/messages`);try{const e=await v(n);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const t=await e.json();return{messages:t.success&&Array.isArray(t.data)?t.data:[],total:t.total||0}}catch(e){return o.error("加载会话消息失败",e),{messages:[],total:0}}}async function L(e){const n=y(`/conversation/${e}`);try{const t=await v(n,{method:"DELETE"});if(!t.ok)throw new w(_(t.status),`http_${t.status}`);const r=await t.json();return o.info(`删除会话 id=${e} success=${r.success}`),r.success||!1}catch(e){return o.error("删除会话失败",e),!1}}function S(e){return y(`/conversation/${e}/export`)}async function F(){if(!h)return"";const e=function(e,n){try{return localStorage.getItem(N(e,n))||""}catch(e){return""}}(h.integrateId,h.userId);if(e)return h.chatId=e,o.info(`从缓存恢复 chatId=${e}`),e;try{const e=await $(1,5,h.userId,h.integrateId);if(e.list.length>0){const n=e.list[0],t=n.conversationId||n.chatId||"";if(t)return h.chatId=t,M(h.integrateId,h.userId,t),o.info(`从后端恢复会话 chatId=${t} messageCount=${n.messageCount}`),t}}catch(e){o.warn("查询后端会话列表失败,将生成新 chatId",e)}const n=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();return h.chatId=n,M(h.integrateId,h.userId,n),o.info(`生成新 chatId=${n}`),n}function N(e,n){return`csk_chatId_${e}${n?"_"+n:""}`}function M(e,n,t){try{t?localStorage.setItem(N(e,n),t):localStorage.removeItem(N(e,n))}catch(e){}}let T=null;function D(e){const n=B(e.primaryColor,-15),t=B(e.primaryColor,18),r=function(e){const n=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);return n?`${parseInt(n[1],16)}, ${parseInt(n[2],16)}, ${parseInt(n[3],16)}`:"79, 70, 229"}(e.primaryColor),s=e.launcherTheme?{"dream-purple":{grad1:"#A78BFA",grad2:"#F0ABFC",glow:"167, 139, 250"},"mint-tech":{grad1:"#6EE7B7",grad2:"#34D399",glow:"52, 211, 153"},"coral-peach":{grad1:"#FB7185",grad2:"#FDBA74",glow:"251, 113, 133"},"sky-blue":{grad1:"#7DD3FC",grad2:"#A78BFA",glow:"125, 211, 252"}}[e.launcherTheme]:null;return`\n --csk-primary: ${e.primaryColor};\n --csk-primary-hover: ${n};\n --csk-primary-light: ${t};\n --csk-primary-rgb: ${r};\n --csk-bg-user: linear-gradient(135deg, ${e.primaryColor}, ${n});\n --csk-bg-ai: #ffffff;\n --csk-text-user: #ffffff;\n --csk-text-ai: #1F2937;\n --csk-window-width: ${e.width}px;\n --csk-window-height: ${e.height}px;\n --csk-radius: 16px;\n --csk-shadow-window: 0 12px 48px rgba(15, 23, 42, 0.18), 0 2px 8px rgba(15, 23, 42, 0.06);\n --csk-shadow-bubble: 0 1px 2px rgba(15, 23, 42, 0.06);\n --csk-border: #ECEEF2;\n --csk-bg-app: #F6F7F9;\n ${s?`\n --csk-launcher-grad-1: ${s.grad1};\n --csk-launcher-grad-2: ${s.grad2};\n --csk-launcher-glow: ${s.glow};\n `:""}\n `}function B(e,n){const t=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!t)return e;const r=e=>Math.max(0,Math.min(255,e)),s=r(parseInt(t[1],16)+n),o=r(parseInt(t[2],16)+n),a=r(parseInt(t[3],16)+n);return`#${s.toString(16).padStart(2,"0")}${o.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}`}function q(e){document.querySelector("style[data-csk-sdk]")||(T=document.createElement("style"),T.setAttribute("data-csk-sdk",""),T.textContent=function(e){return`\n/* ChatbotSDK 样式 - csk- 命名空间 */\n.csk-root {\n ${D(e)}\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;\n font-size: 14px;\n line-height: 1.55;\n color: #1F2937;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n.csk-root *, .csk-root *::before, .csk-root *::after { box-sizing: border-box; }\n\n/* ========== 悬浮按钮 ========== */\n.csk-launcher {\n position: fixed;\n bottom: 24px;\n z-index: 9998;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n user-select: none;\n overflow: visible;\n /* 半透明白色光环边框,在白色页面上清晰分离按钮与背景 */\n border: 2.5px solid rgba(255, 255, 255, 0.55);\n /* 三层投影:接地阴影 + 彩色光晕,把按钮从白底「托」出来 */\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.25s ease,\n border-color 0.25s ease;\n animation: csk-launcher-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;\n}\n.csk-launcher--right { right: 24px; }\n.csk-launcher--left { left: 24px; }\n\n/* 高光扫过动效 */\n.csk-launcher::before {\n content: '';\n position: absolute;\n top: -50%;\n left: -50%;\n width: 40%;\n height: 200%;\n border-radius: 50%;\n background: linear-gradient(\n 105deg,\n transparent 30%,\n rgba(255, 255, 255, 0.28) 48%,\n rgba(255, 255, 255, 0.1) 52%,\n transparent 70%\n );\n transform: rotate(25deg);\n animation: csk-shimmer 4s ease-in-out infinite;\n pointer-events: none;\n}\n/* 呼吸色晕 — 配合接地阴影,强化白底上的立体存在感 */\n.csk-launcher::after {\n content: '';\n position: absolute;\n inset: -18px;\n border-radius: 50%;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.18) 0%, rgba(var(--csk-primary-rgb), 0.05) 45%, transparent 68%);\n animation: csk-breathe 3.5s ease-in-out infinite;\n pointer-events: none;\n}\n.csk-launcher:hover {\n transform: translateY(-3px) scale(1.08);\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.10),\n 0 8px 24px rgba(0, 0, 0, 0.14),\n 0 10px 36px rgba(var(--csk-primary-rgb), 0.32),\n 0 0 56px rgba(var(--csk-primary-rgb), 0.14);\n}\n.csk-launcher:hover::before { animation-play-state: paused; }\n.csk-launcher:hover::after {\n animation: none;\n inset: -22px;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.22) 0%, rgba(var(--csk-primary-rgb), 0.06) 45%, transparent 68%);\n}\n.csk-launcher:active { transform: scale(0.93); }\n.csk-launcher svg {\n width: 30px;\n height: 30px;\n position: relative;\n z-index: 1;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.15));\n}\n\n@keyframes csk-launcher-in {\n 0% { opacity: 0; transform: scale(0.5) translateY(16px); }\n 60% { transform: scale(1.06) translateY(-2px); }\n 100% { opacity: 1; transform: scale(1) translateY(0); }\n}\n@keyframes csk-shimmer {\n 0%, 100% { left: -60%; opacity: 0; }\n 20% { opacity: 1; }\n 60% { opacity: 1; }\n 80% { left: 120%; opacity: 0; }\n}\n@keyframes csk-breathe {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.15); opacity: 0.35; }\n}\n\n/* SVG 图标内部动效:眨眼 */\n.csk-launcher .csk-ico-eye {\n animation: csk-eye-blink 4s ease-in-out infinite;\n}\n@keyframes csk-eye-blink {\n 0%, 42%, 48%, 100% { opacity: 1; }\n 45% { opacity: 0.1; }\n}\n/* SVG 图标内部动效:天线能量闪烁 */\n.csk-launcher .csk-ico-antenna {\n animation: csk-antenna-glow 2s ease-in-out infinite;\n}\n@keyframes csk-antenna-glow {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n/* ========== 磨砂玻璃质感悬浮按钮 ========== */\n.csk-launcher--glass {\n background: linear-gradient(\n 135deg,\n var(--csk-launcher-grad-1, var(--csk-primary)) 0%,\n var(--csk-launcher-grad-2, var(--csk-primary-light)) 100%\n ) !important;\n backdrop-filter: blur(12px) saturate(180%);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n border: 1.5px solid rgba(255, 255, 255, 0.55) !important;\n /* 多层阴影:接地 + 彩色光晕 + 内阴影立体感 */\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.04),\n 0 6px 20px rgba(0, 0, 0, 0.08),\n 0 8px 32px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.30),\n inset 0 1px 1px rgba(255, 255, 255, 0.35),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n.csk-launcher--glass:hover {\n border-color: rgba(255, 255, 255, 0.75) !important;\n box-shadow:\n 0 4px 8px rgba(0, 0, 0, 0.06),\n 0 10px 28px rgba(0, 0, 0, 0.10),\n 0 12px 40px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.38),\n inset 0 1px 2px rgba(255, 255, 255, 0.45),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n\n/* 玻璃按钮的呼吸色晕 — 更鲜艳、更醒目 */\n.csk-launcher--glass::after {\n background: radial-gradient(\n circle,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.28) 0%,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.10) 40%,\n transparent 65%\n ) !important;\n animation: csk-breathe-glow 3.5s ease-in-out infinite;\n}\n@keyframes csk-breathe-glow {\n 0%, 100% { transform: scale(1); opacity: 0.8; }\n 50% { transform: scale(1.22); opacity: 0.25; }\n}\n\n/* 玻璃按钮的高光扫过 — 更柔和的玻璃质感 */\n.csk-launcher--glass::before {\n background: linear-gradient(\n 115deg,\n transparent 25%,\n rgba(255, 255, 255, 0.35) 45%,\n rgba(255, 255, 255, 0.15) 55%,\n transparent 75%\n ) !important;\n width: 50%;\n animation: csk-shimmer-glass 5s ease-in-out infinite;\n}\n@keyframes csk-shimmer-glass {\n 0%, 100% { left: -70%; opacity: 0; }\n 15% { opacity: 1; }\n 55% { opacity: 1; }\n 70% { left: 130%; opacity: 0; }\n}\n\n/* SVG 内部动效:跳动气泡(3 个小圆点交错弹跳) */\n.csk-launcher .csk-ico-bubble {\n animation: csk-bubble-jump 1.4s ease-in-out infinite;\n}\n.csk-launcher .csk-ico-bubble--1 { animation-delay: 0s; }\n.csk-launcher .csk-ico-bubble--2 { animation-delay: 0.18s; }\n.csk-launcher .csk-ico-bubble--3 { animation-delay: 0.36s; }\n@keyframes csk-bubble-jump {\n 0%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-3.5px); }\n 60% { transform: translateY(-1px); }\n}\n\n/* ========== 聊天弹窗 ========== */\n.csk-window {\n position: fixed;\n bottom: 24px;\n z-index: 9999;\n width: var(--csk-window-width);\n height: var(--csk-window-height);\n max-height: calc(100vh - 48px);\n background: #fff;\n border-radius: var(--csk-radius);\n box-shadow: var(--csk-shadow-window);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transform-origin: bottom right;\n transition: opacity 0.24s ease, transform 0.24s cubic-bezier(0.34, 1.2, 0.64, 1), visibility 0.24s;\n opacity: 1;\n transform: translateY(0) scale(1);\n visibility: visible;\n pointer-events: auto;\n}\n.csk-window--right { right: 24px; transform-origin: bottom right; }\n.csk-window--left { left: 24px; transform-origin: bottom left; }\n.csk-window--hidden {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n visibility: hidden;\n pointer-events: none;\n}\n\n/* ========== 头部 ========== */\n.csk-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n min-height: 60px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: move;\n user-select: none;\n position: relative;\n flex-shrink: 0;\n}\n.csk-header::after {\n content: '';\n position: absolute;\n left: 0; right: 0; bottom: 0;\n height: 24px;\n background: linear-gradient(to bottom, rgba(0,0,0,0.04), transparent);\n pointer-events: none;\n}\n.csk-header__left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n.csk-header__avatar {\n width: 38px;\n height: 38px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);\n}\n.csk-header__avatar svg { width: 22px; height: 22px; }\n.csk-header__info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.csk-header__title {\n font-size: 15px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n letter-spacing: 0.2px;\n}\n.csk-header__status {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 11.5px;\n opacity: 0.9;\n margin-top: 2px;\n}\n.csk-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #6EE7B7;\n box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7);\n animation: csk-status-pulse 2s infinite;\n}\n@keyframes csk-status-pulse {\n 0% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7); }\n 70% { box-shadow: 0 0 0 6px rgba(110, 231, 183, 0); }\n 100% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0); }\n}\n.csk-header__actions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n.csk-header__btn,\n.csk-history-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #fff;\n cursor: pointer;\n border-radius: 8px;\n transition: background 0.15s, transform 0.15s;\n}\n.csk-header__btn:hover,\n.csk-history-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n.csk-header__btn:active,\n.csk-history-btn:active { transform: scale(0.92); }\n\n/* ========== 消息区 ========== */\n.csk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 20px 16px 12px;\n background: var(--csk-bg-app);\n scroll-behavior: smooth;\n}\n.csk-messages::-webkit-scrollbar { width: 6px; }\n.csk-messages::-webkit-scrollbar-track { background: transparent; }\n.csk-messages::-webkit-scrollbar-thumb {\n background: #D8DCE3;\n border-radius: 3px;\n}\n.csk-messages::-webkit-scrollbar-thumb:hover { background: #C2C7D0; }\n\n/* 欢迎空状态 */\n.csk-welcome {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 48px 24px 32px;\n color: #6B7280;\n animation: csk-fade-in 0.3s ease;\n}\n.csk-welcome__avatar {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 14px;\n box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-welcome__avatar svg { width: 30px; height: 30px; }\n.csk-welcome__title {\n font-size: 15px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.csk-welcome__desc {\n font-size: 13px;\n color: #9CA3AF;\n line-height: 1.6;\n}\n\n/* 消息气泡 */\n.csk-msg {\n display: flex;\n margin-bottom: 18px;\n max-width: 100%;\n word-break: break-word;\n animation: csk-msg-in 0.28s cubic-bezier(0.22, 1, 0.36, 1);\n}\n.csk-msg--user {\n flex-direction: row-reverse;\n align-items: flex-end;\n}\n.csk-msg--ai {\n flex-direction: row;\n align-items: flex-start;\n}\n.csk-msg__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg__avatar svg { width: 18px; height: 18px; }\n.csk-msg__avatar--ai {\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n}\n.csk-msg__avatar--user {\n background: var(--csk-bg-user);\n color: #fff;\n}\n.csk-msg__content {\n display: flex;\n flex-direction: column;\n min-width: 0;\n max-width: calc(100% - 46px);\n}\n.csk-msg--user .csk-msg__content { align-items: flex-end; }\n.csk-msg--ai .csk-msg__content { align-items: flex-start; }\n.csk-msg__bubble {\n padding: 10px 14px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.6;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg--user .csk-msg__bubble {\n background: var(--csk-bg-user);\n color: var(--csk-text-user);\n border-radius: 16px 16px 4px 16px;\n}\n.csk-msg--ai .csk-msg__bubble {\n background: var(--csk-bg-ai);\n color: var(--csk-text-ai);\n border-radius: 16px 16px 16px 4px;\n border: 1px solid var(--csk-border);\n}\n.csk-msg__time {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 5px;\n padding: 0 4px;\n}\n\n@keyframes csk-msg-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes csk-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ========== Loading 动画 ========== */\n.csk-loading {\n display: flex;\n align-items: center;\n margin-bottom: 18px;\n animation: csk-msg-in 0.28s ease;\n}\n.csk-loading__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-loading__avatar svg { width: 18px; height: 18px; }\n.csk-loading__bubble {\n background: #fff;\n border: 1px solid var(--csk-border);\n border-radius: 16px 16px 16px 4px;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.csk-loading__dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #B4B9C2;\n animation: csk-bounce 1.4s ease-in-out infinite both;\n}\n.csk-loading__dot:nth-child(1) { animation-delay: 0s; }\n.csk-loading__dot:nth-child(2) { animation-delay: 0.16s; }\n.csk-loading__dot:nth-child(3) { animation-delay: 0.32s; }\n\n@keyframes csk-bounce {\n 0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }\n 40% { transform: scale(1); opacity: 1; }\n}\n\n/* ========== 输入区 ========== */\n.csk-input-area {\n padding: 10px 12px 14px;\n background: #fff;\n border-top: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-input-wrap {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n background: var(--csk-bg-app);\n border: 1px solid var(--csk-border);\n border-radius: 14px;\n padding: 6px 6px 6px 14px;\n transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;\n}\n.csk-input-wrap--focus {\n border-color: var(--csk-primary);\n background: #fff;\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n.csk-input {\n flex: 1;\n border: none;\n background: transparent;\n padding: 8px 0;\n font-size: 14px;\n outline: none;\n font-family: inherit;\n resize: none;\n min-height: 22px;\n max-height: 120px;\n line-height: 1.5;\n color: #1F2937;\n}\n.csk-input::placeholder { color: #9CA3AF; }\n.csk-root .csk-input:focus-visible { outline: none; }\n.csk-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n min-width: 36px;\n border: none;\n border-radius: 10px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: pointer;\n transition: transform 0.18s, box-shadow 0.18s, opacity 0.18s;\n box-shadow: 0 3px 10px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-send-btn:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 5px 14px rgba(var(--csk-primary-rgb), 0.4);\n}\n.csk-send-btn:active:not(:disabled) { transform: scale(0.92); }\n.csk-send-btn:disabled {\n background: #D1D5DB;\n box-shadow: none;\n cursor: not-allowed;\n opacity: 0.7;\n}\n.csk-send-btn svg { width: 18px; height: 18px; }\n\n/* ========== 清空按钮 ========== */\n.csk-clear-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 999px;\n background: #fff;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n margin: 0 auto 8px;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-clear-btn:hover {\n background: #FEF2F2;\n border-color: #FCA5A5;\n color: #DC2626;\n}\n\n/* ========== P1: 知识库分类下拉 ========== */\n.csk-category-bar {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n border-top: 1px solid var(--csk-border);\n background: #FBFBFC;\n gap: 8px;\n flex-shrink: 0;\n}\n.csk-category-bar__label {\n font-size: 13px;\n white-space: nowrap;\n}\n.csk-category-select {\n flex: 1;\n padding: 6px 28px 6px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n color: #374151;\n background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 9px center;\n appearance: none;\n -webkit-appearance: none;\n outline: none;\n cursor: pointer;\n font-family: inherit;\n transition: border-color 0.2s, box-shadow 0.2s;\n max-width: 220px;\n}\n.csk-category-select:focus {\n border-color: var(--csk-primary);\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n\n/* ========== P1: RAG 引用来源卡片 ========== */\n.csk-sources {\n margin-top: 8px;\n border: 1px solid var(--csk-border);\n border-radius: 12px;\n overflow: hidden;\n font-size: 12px;\n max-width: 100%;\n background: #FAFBFC;\n}\n.csk-sources__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: #F3F4F7;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s;\n}\n.csk-sources__header:hover { background: #ECEEF2; }\n.csk-sources__title {\n display: flex;\n align-items: center;\n gap: 5px;\n font-weight: 500;\n color: #374151;\n}\n.csk-sources__arrow {\n transition: transform 0.2s;\n color: #9CA3AF;\n font-size: 10px;\n}\n.csk-sources--collapsed .csk-sources__arrow { transform: rotate(-90deg); }\n.csk-sources__body {\n border-top: 1px solid var(--csk-border);\n padding: 0;\n}\n.csk-sources--collapsed .csk-sources__body { display: none; }\n.csk-source-item {\n padding: 9px 12px;\n border-bottom: 1px solid #F0F1F4;\n transition: background 0.15s;\n}\n.csk-source-item:last-child { border-bottom: none; }\n.csk-source-item:hover { background: #fff; }\n.csk-source-item__name {\n font-weight: 500;\n color: #1F2937;\n margin-bottom: 3px;\n}\n.csk-source-item__snippet {\n color: #6B7280;\n line-height: 1.5;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n.csk-source-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 4px;\n}\n\n/* ========== P1: Markdown 渲染样式 ========== */\n.csk-msg--ai .csk-msg__bubble .csk-md-p { margin: 0 0 8px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-p:last-child { margin-bottom: 0; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h1,\n.csk-msg--ai .csk-msg__bubble .csk-md-h2,\n.csk-msg--ai .csk-msg__bubble .csk-md-h3,\n.csk-msg--ai .csk-msg__bubble .csk-md-h4,\n.csk-msg--ai .csk-msg__bubble .csk-md-h5,\n.csk-msg--ai .csk-msg__bubble .csk-md-h6 {\n margin: 14px 0 6px;\n font-weight: 600;\n line-height: 1.3;\n color: #111827;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-h1 { font-size: 20px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h2 { font-size: 17px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h3 { font-size: 15px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h4 { font-size: 14px; }\n\n.csk-md-code-block {\n background: #1E293B;\n color: #E2E8F0;\n padding: 12px 14px;\n border-radius: 10px;\n overflow-x: auto;\n margin: 8px 0;\n font-size: 13px;\n line-height: 1.55;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-md-code-block code {\n background: none;\n padding: 0;\n border-radius: 0;\n font-size: inherit;\n color: inherit;\n}\n.csk-md-inline-code {\n background: rgba(var(--csk-primary-rgb), 0.1);\n color: var(--csk-primary);\n padding: 1px 6px;\n border-radius: 5px;\n font-size: 13px;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol {\n padding-left: 22px;\n margin: 6px 0;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul li,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol li { margin-bottom: 4px; }\n.csk-md-blockquote {\n border-left: 3px solid var(--csk-primary);\n padding: 2px 12px;\n margin: 8px 0;\n color: #6B7280;\n background: rgba(var(--csk-primary-rgb), 0.05);\n border-radius: 0 6px 6px 0;\n}\n.csk-md-link {\n color: var(--csk-primary);\n text-decoration: none;\n border-bottom: 1px solid rgba(var(--csk-primary-rgb), 0.3);\n transition: border-color 0.15s;\n}\n.csk-md-link:hover { border-bottom-color: var(--csk-primary); }\n.csk-md-hr {\n border: none;\n border-top: 1px solid var(--csk-border);\n margin: 12px 0;\n}\n\n/* ========== P2: 会话管理面板 ========== */\n.csk-history-panel {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: #fff;\n z-index: 10;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: csk-slide-in 0.24s ease;\n}\n.csk-history-panel--hidden { display: none; }\n@keyframes csk-slide-in {\n from { transform: translateX(100%); opacity: 0.4; }\n to { transform: translateX(0); opacity: 1; }\n}\n.csk-history-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--csk-border);\n background: var(--csk-bg-app);\n flex-shrink: 0;\n}\n.csk-history-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n}\n.csk-history-panel__back {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n background: #fff;\n color: #374151;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-history-panel__back:hover { background: #F3F4F6; }\n.csk-history-panel__list {\n flex: 1;\n overflow-y: auto;\n padding: 10px;\n}\n.csk-history-panel__list::-webkit-scrollbar { width: 5px; }\n.csk-history-panel__list::-webkit-scrollbar-thumb { background: #E5E7EB; border-radius: 2px; }\n.csk-history-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 11px 12px;\n border-radius: 10px;\n cursor: pointer;\n transition: background 0.15s;\n margin-bottom: 5px;\n border: 1px solid transparent;\n}\n.csk-history-item:hover { background: #F3F4F6; }\n.csk-history-item--active {\n background: rgba(var(--csk-primary-rgb), 0.08);\n border-color: rgba(var(--csk-primary-rgb), 0.2);\n}\n.csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.12); }\n.csk-history-item__info { flex: 1; min-width: 0; }\n.csk-history-item__id {\n font-size: 13px;\n font-weight: 500;\n color: #1F2937;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.csk-history-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 3px;\n}\n.csk-history-item__actions {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.csk-history-item:hover .csk-history-item__actions { opacity: 1; }\n.csk-history-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 7px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.15s;\n}\n.csk-history-action--export { background: #EFF6FF; color: #2563EB; }\n.csk-history-action--export:hover { background: #DBEAFE; }\n.csk-history-action--delete { background: #FEF2F2; color: #DC2626; }\n.csk-history-action--delete:hover { background: #FEE2E2; }\n.csk-history-panel__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 20px;\n color: #9CA3AF;\n font-size: 13px;\n text-align: center;\n}\n.csk-history-panel__empty-icon {\n font-size: 34px;\n margin-bottom: 10px;\n opacity: 0.5;\n}\n.csk-history-panel__loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n color: #9CA3AF;\n font-size: 13px;\n}\n.csk-history-panel__loadmore {\n display: block;\n width: 100%;\n padding: 10px;\n border: none;\n background: #F9FAFB;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n text-align: center;\n transition: background 0.15s;\n}\n.csk-history-panel__loadmore:hover { background: #F3F4F6; }\n\n/* ========== 快捷问题芯片 ========== */\n.csk-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n margin-top: 18px;\n max-width: 320px;\n}\n.csk-quick-reply {\n border: 1px solid var(--csk-border);\n background: #fff;\n color: #374151;\n font-size: 12.5px;\n padding: 7px 13px;\n border-radius: 999px;\n cursor: pointer;\n font-family: inherit;\n line-height: 1.3;\n transition: all 0.18s ease;\n max-width: 100%;\n}\n.csk-quick-reply:hover {\n border-color: var(--csk-primary);\n color: var(--csk-primary);\n background: rgba(var(--csk-primary-rgb), 0.06);\n transform: translateY(-1px);\n}\n.csk-quick-reply:active { transform: scale(0.96); }\n\n/* ========== AI 消息操作条 ========== */\n.csk-msg__actions {\n display: flex;\n gap: 2px;\n margin-top: 5px;\n padding: 0 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n.csk-msg--ai:hover .csk-msg__actions { opacity: 1; }\n.csk-msg--streaming .csk-msg__actions { display: none; }\n.csk-action-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.csk-action-btn:hover {\n background: #F3F4F6;\n color: #374151;\n}\n.csk-action-btn--done { color: #10B981; }\n.csk-action-btn:active { transform: scale(0.9); }\n\n/* ========== 流式打字光标 ========== */\n.csk-caret {\n display: inline-block;\n width: 7px;\n height: 15px;\n margin-left: 2px;\n vertical-align: text-bottom;\n background: var(--csk-primary);\n border-radius: 1px;\n animation: csk-caret-blink 1s step-end infinite;\n}\n@keyframes csk-caret-blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n/* ========== 代码块复制按钮 ========== */\n.csk-md-code-block { position: relative; }\n.csk-md-code-copy {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(255, 255, 255, 0.12);\n color: #CBD5E1;\n border-radius: 6px;\n cursor: pointer;\n opacity: 0;\n transition: all 0.15s ease;\n}\n.csk-md-code-block:hover .csk-md-code-copy { opacity: 1; }\n.csk-md-code-copy:hover { background: rgba(255, 255, 255, 0.22); color: #fff; }\n.csk-md-code-copy:active { transform: scale(0.9); }\n\n/* ========== 新消息提示按钮 ========== */\n.csk-newmsg {\n position: absolute;\n bottom: 82px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 5;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 7px 14px;\n border: none;\n background: var(--csk-primary);\n color: #fff;\n font-size: 12px;\n font-family: inherit;\n border-radius: 999px;\n cursor: pointer;\n box-shadow: 0 4px 14px rgba(var(--csk-primary-rgb), 0.38);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: csk-msg-in 0.25s ease;\n white-space: nowrap;\n}\n.csk-newmsg:hover { transform: translateX(-50%) translateY(-1px); box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.48); }\n.csk-newmsg:active { transform: translateX(-50%) scale(0.95); }\n.csk-newmsg--hidden { display: none; }\n\n/* ========== 发送按钮停止态 ========== */\n.csk-send-btn--stop {\n background: #EF4444 !important;\n box-shadow: 0 3px 10px rgba(239, 68, 68, 0.35) !important;\n}\n.csk-send-btn--stop:hover:not(:disabled) {\n box-shadow: 0 5px 14px rgba(239, 68, 68, 0.45) !important;\n}\n\n/* ========== 暗色模式 ========== */\n.csk-root.csk-dark {\n --csk-bg-ai: #1E1E2E;\n --csk-text-ai: #E2E8F0;\n --csk-border: #3B3B52;\n --csk-bg-app: #141421;\n color: #E2E8F0;\n}\n.csk-dark .csk-window {\n background: #1A1A2E;\n box-shadow: 0 12px 48px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.2);\n}\n.csk-dark .csk-header::after { background: linear-gradient(to bottom, rgba(0,0,0,0.12), transparent); }\n.csk-dark .csk-msg__avatar--ai {\n background: var(--csk-bg-ai);\n color: var(--csk-primary);\n border-color: var(--csk-border);\n}\n.csk-dark .csk-input-area { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-input-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-input-wrap--focus { background: #1A1A2E; border-color: var(--csk-primary); }\n.csk-dark .csk-input { color: #E2E8F0; }\n.csk-dark .csk-loading__avatar { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__bubble { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__dot { background: #6B7280; }\n.csk-dark .csk-category-bar { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-category-select { background-color: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-sources { background: #1E1E2E; border-color: var(--csk-border); }\n.csk-dark .csk-sources__header { background: #25253A; }\n.csk-dark .csk-sources__header:hover { background: #2D2D48; }\n.csk-dark .csk-source-item:hover { background: var(--csk-bg-ai); }\n.csk-dark .csk-source-item__name { color: #E2E8F0; }\n.csk-dark .csk-source-item__meta { color: #6B7280; }\n.csk-dark .csk-history-panel { background: #1A1A2E; }\n.csk-dark .csk-history-panel__header { background: var(--csk-bg-app); border-bottom-color: var(--csk-border); }\n.csk-dark .csk-history-panel__back { background: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-history-panel__back:hover { background: #2D2D48; }\n.csk-dark .csk-history-item:hover { background: #25253A; }\n.csk-dark .csk-history-item__id { color: #E2E8F0; }\n.csk-dark .csk-history-item__meta { color: #6B7280; }\n.csk-dark .csk-history-item--active { background: rgba(var(--csk-primary-rgb), 0.15); }\n.csk-dark .csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.22); }\n.csk-dark .csk-action-btn:hover { background: #2D2D48; color: #E2E8F0; }\n.csk-dark .csk-clear-btn { background: var(--csk-bg-app); border-color: var(--csk-border); color: #9CA3AF; }\n.csk-dark .csk-clear-btn:hover { background: #3B1A1A; border-color: #7F1D1D; color: #FCA5A5; }\n.csk-dark .csk-md-code-block { background: #0F0F1A; }\n.csk-dark .csk-md-blockquote { background: rgba(var(--csk-primary-rgb), 0.08); }\n.csk-dark .csk-md-link { color: var(--csk-primary-light); }\n.csk-dark .csk-msg--ai .csk-msg__bubble { background: var(--csk-bg-ai); color: var(--csk-text-ai); border-color: var(--csk-border); }\n.csk-dark .csk-welcome__title { color: #E2E8F0; }\n.csk-dark .csk-welcome__desc { color: #6B7280; }\n.csk-dark .csk-quick-reply { background: var(--csk-bg-app); border-color: var(--csk-border); color: #CBD5E1; }\n.csk-dark .csk-quick-reply:hover { background: rgba(var(--csk-primary-rgb), 0.12); border-color: var(--csk-primary); color: var(--csk-primary-light); }\n.csk-dark .csk-teaser { background: #2D2D48; color: #E2E8F0; box-shadow: 0 4px 20px rgba(0,0,0,0.35); }\n.csk-dark .csk-teaser::after { border-top-color: #2D2D48; }\n.csk-dark .csk-teaser__close { color: #6B7280; }\n.csk-dark .csk-teaser__close:hover { color: #9CA3AF; }\n.csk-dark .csk-feedback-btn { background: rgba(var(--csk-primary-rgb), 0.1); color: #9CA3AF; }\n.csk-dark .csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.2); color: var(--csk-primary-light); }\n.csk-dark .csk-feedback-btn--active { background: rgba(var(--csk-primary-rgb), 0.28); color: var(--csk-primary-light); }\n.csk-dark .csk-history-panel__search-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-history-panel__search-wrap:focus-within { border-color: var(--csk-primary); }\n.csk-dark .csk-history-panel__search { color: #E2E8F0; }\n.csk-dark .csk-launcher__badge { box-shadow: 0 0 0 2px #1A1A2E; }\n.csk-dark .csk-welcome__avatar { box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.25); }\n.csk-dark .csk-header__avatar { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.1); }\n\n/* ========== Launcher 未读徽章 ========== */\n.csk-launcher__badge {\n position: absolute;\n top: -2px;\n right: -2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #EF4444;\n border: 2px solid #fff;\n box-shadow: 0 0 0 2px #fff;\n animation: csk-badge-in 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);\n pointer-events: none;\n}\n.csk-launcher__badge--hidden { display: none; }\n@keyframes csk-badge-in {\n from { transform: scale(0); }\n to { transform: scale(1); }\n}\n\n/* ========== Launcher 提示气泡 ========== */\n.csk-teaser {\n position: fixed;\n bottom: 90px;\n z-index: 9997;\n max-width: 240px;\n padding: 10px 14px;\n background: #fff;\n color: #1F2937;\n font-size: 13px;\n line-height: 1.5;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(15, 23, 42, 0.15);\n animation: csk-teaser-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);\n cursor: pointer;\n user-select: none;\n}\n.csk-teaser--right { right: 24px; }\n.csk-teaser--left { left: 24px; }\n.csk-teaser::after {\n content: '';\n position: absolute;\n bottom: -6px;\n right: 28px;\n width: 12px;\n height: 12px;\n background: inherit;\n border-radius: 2px;\n transform: rotate(45deg);\n box-shadow: 2px 2px 4px rgba(15, 23, 42, 0.08);\n}\n.csk-teaser--left::after { right: auto; left: 28px; }\n.csk-teaser__close {\n position: absolute;\n top: 4px;\n right: 6px;\n background: none;\n border: none;\n font-size: 16px;\n color: #9CA3AF;\n cursor: pointer;\n padding: 2px 4px;\n line-height: 1;\n border-radius: 4px;\n}\n.csk-teaser__close:hover { color: #374151; }\n.csk-teaser--hidden { display: none; }\n@keyframes csk-teaser-in {\n from { opacity: 0; transform: translateY(8px) scale(0.95); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n/* ========== 消息反馈按钮(👍 / 👎) ========== */\n.csk-feedback-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(var(--csk-primary-rgb), 0.08);\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n padding: 0;\n}\n.csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.18); color: var(--csk-primary); }\n.csk-feedback-btn--active {\n background: rgba(var(--csk-primary-rgb), 0.28);\n color: var(--csk-primary);\n}\n.csk-feedback-btn--active.down { background: #FEF2F2; color: #EF4444; }\n.csk-feedback-btn:active { transform: scale(0.9); }\n.csk-msg--streaming .csk-feedback-btn { display: none; }\n\n/* ========== 历史会话搜索框 ========== */\n.csk-history-panel__search-wrap {\n padding: 8px 10px;\n border-bottom: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-history-panel__search-wrap:focus-within {\n border-bottom-color: var(--csk-primary);\n}\n.csk-history-panel__search {\n width: 100%;\n padding: 7px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n font-family: inherit;\n color: #1F2937;\n background: var(--csk-bg-app);\n outline: none;\n transition: border-color 0.2s;\n}\n.csk-history-panel__search:focus { border-color: var(--csk-primary); }\n.csk-history-panel__search::placeholder { color: #9CA3AF; }\n\n/* ========== a11y 焦点指示 ========== */\n.csk-root :focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n}\n.csk-root button:focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n border-radius: inherit;\n}\n/* 弹窗打开时隐藏 launcher 上的焦点环 */\n.csk-launcher:focus-visible {\n outline: none;\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12),\n 0 0 0 4px rgba(var(--csk-primary-rgb), 0.3);\n}\n\n/* ========== a11y aria-live 播报区(视觉隐藏) ========== */\n.csk-sr-only {\n position: absolute !important;\n width: 1px !important;\n height: 1px !important;\n padding: 0 !important;\n margin: -1px !important;\n overflow: hidden !important;\n clip: rect(0,0,0,0) !important;\n white-space: nowrap !important;\n border: 0 !important;\n}\n\n/* ========== 会话分组标题 ========== */\n.csk-history-group {\n margin-bottom: 4px;\n}\n.csk-history-group__label {\n font-size: 11px;\n font-weight: 600;\n color: #9CA3AF;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: 8px 12px 4px;\n user-select: none;\n}\n.csk-dark .csk-history-group__label { color: #6B7280; }\n\n/* ========== 移动端适配 ========== */\n@media (max-width: 480px) {\n .csk-window {\n width: 100vw !important;\n height: 100vh !important;\n max-height: 100vh;\n bottom: 0 !important;\n right: 0 !important;\n left: 0 !important;\n border-radius: 0;\n }\n .csk-window--hidden { transform: translateY(100%); }\n .csk-launcher { bottom: 20px; }\n .csk-launcher--right { right: 20px; }\n .csk-launcher--left { left: 20px; }\n}\n`}(e),document.head.appendChild(T))}function z(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const n=16*Math.random()|0;return("x"===e?n:3&n|8).toString(16)})}function H(e){const n={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,e=>n[e]||e)}function j(){return Date.now()}const R='';function P(e,n){const t=document.createElement("div");t.id="csk-launcher";const r=e.launcherTheme?" csk-launcher--glass":"";t.className=`csk-launcher csk-launcher--${"left-bottom"===e.position?"left":"right"}${r}`,t.setAttribute("title",e.title),t.setAttribute("aria-label",e.title),t.setAttribute("role","button"),t.setAttribute("tabindex","0"),t.innerHTML=e.launcherIcon;const s=document.createElement("div");s.className="csk-launcher__badge csk-launcher__badge--hidden",t.appendChild(s);const o=function(e,n){let t=null;return function(...r){null!==t&&clearTimeout(t),t=setTimeout(()=>{e.apply(this,r),t=null},n)}}(n,300);return t.addEventListener("click",o),t.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),o())}),t}function U(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--user";const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--user",s.innerHTML='';const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.textContent=n;const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(t),o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),r}function O(e,n,t,r,s){const o=document.createElement("div");o.className="csk-msg csk-msg--ai",s&&(o.dataset.cskMsgId=s);const a=document.createElement("div");a.className="csk-msg__avatar csk-msg__avatar--ai",a.innerHTML=R;const i=document.createElement("div");i.className="csk-msg__content";const c=document.createElement("div");c.className="csk-msg__bubble",r?c.innerHTML=r(n):c.textContent=n;const l=document.createElement("div");return l.className="csk-msg__time",l.textContent=ne(t),i.appendChild(c),i.appendChild(G(c,o)),i.appendChild(l),o.appendChild(a),o.appendChild(i),e.appendChild(o),X(c),o}const Y='',W='';function G(e,n){const t=document.createElement("div");t.className="csk-msg__actions";const r=document.createElement("button");r.type="button",r.className="csk-action-btn",r.setAttribute("title",m("copy")),r.setAttribute("aria-label",m("copy")),r.innerHTML=Y,r.addEventListener("click",async n=>{n.stopPropagation();const t=e.textContent||"";await K(t,r)});const s=document.createElement("button");s.type="button",s.className="csk-action-btn",s.setAttribute("title",m("retry")),s.setAttribute("aria-label",m("retry")),s.innerHTML=W,s.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:retry",{detail:{msgId:n.dataset.cskMsgId||""}}))});const o=document.createElement("button");o.type="button",o.className="csk-feedback-btn",o.setAttribute("title",m("feedback_up")),o.setAttribute("aria-label",m("feedback_up")),o.innerHTML='',o.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"up"}}))});const a=document.createElement("button");return a.type="button",a.className="csk-feedback-btn",a.setAttribute("title",m("feedback_down")),a.setAttribute("aria-label",m("feedback_down")),a.innerHTML='',a.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"down"}}))}),t.appendChild(r),t.appendChild(s),t.appendChild(o),t.appendChild(a),t}function V(e,n){const t=e.querySelectorAll(".csk-feedback-btn");t.length<2||(t.forEach(e=>e.classList.remove("csk-feedback-btn--active","down")),"up"===n&&t[0]&&t[0].classList.add("csk-feedback-btn--active"),"down"===n&&t[1]&&t[1].classList.add("csk-feedback-btn--active","down"))}async function K(e,n){const t=n.innerHTML;try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(e);else{const n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}n.innerHTML='',n.classList.add("csk-action-btn--done"),setTimeout(()=>{n.innerHTML=t,n.classList.remove("csk-action-btn--done")},1500)}catch(e){}}function X(e){e.querySelectorAll(".csk-md-code-block").forEach(e=>{if(e.querySelector(".csk-md-code-copy"))return;const n=e.querySelector("code"),t=document.createElement("button");t.type="button",t.className="csk-md-code-copy",t.setAttribute("title",m("copy")),t.setAttribute("aria-label",m("copy")),t.innerHTML=Y,t.addEventListener("click",async e=>{e.stopPropagation(),await K((null==n?void 0:n.textContent)||"",t)}),e.appendChild(t)})}function J(e,n){e.classList.remove("csk-msg--streaming");const t=n.querySelector(".csk-caret");t&&t.remove(),X(n)}function Q(e,n){const t=e.querySelector(".csk-sources");if(t&&t.remove(),!n||0===n.length)return;const r=document.createElement("div");r.className="csk-sources csk-sources--collapsed";const s=document.createElement("div");s.className="csk-sources__header";const o=document.createElement("span");o.className="csk-sources__title",o.textContent=`📚 ${m("source_count",{n:n.length})}`;const a=document.createElement("span");a.className="csk-sources__arrow",a.textContent="▼",s.appendChild(o),s.appendChild(a),s.addEventListener("click",()=>{r.classList.toggle("csk-sources--collapsed")});const i=document.createElement("div");i.className="csk-sources__body";for(const e of n){const n=document.createElement("div");n.className="csk-source-item";const t=document.createElement("div");if(t.className="csk-source-item__name",t.textContent=e.title||e.sourceName||"未知文档",e.snippet){const t=document.createElement("div");t.className="csk-source-item__snippet",t.textContent=e.snippet,n.appendChild(t)}const r=document.createElement("div");r.className="csk-source-item__meta";const s=[];e.sourceName&&s.push(e.sourceName),void 0!==e.chunkIndex&&s.push(`分块 #${e.chunkIndex}`),void 0!==e.score&&s.push(`相关度 ${(100*e.score).toFixed(0)}%`),r.textContent=s.join(" · "),n.appendChild(t),n.appendChild(r),i.appendChild(n)}r.appendChild(s),r.appendChild(i);const c=e.querySelector(".csk-msg__time");c&&c.parentNode?c.parentNode.insertBefore(r,c):e.appendChild(r)}function Z(e,n,t,r,s,o,a){if(e.innerHTML="",0===n.length){const n=document.createElement("div");return n.className="csk-history-panel__empty",n.innerHTML=`\n
💬
\n
${m("history_empty")}
\n `,void e.appendChild(n)}const i=function(e){const n=new Date,t=new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime(),r=t-864e5,s=t-864e5*(n.getDay()||7)+864e5,o={today:[],yesterday:[],week:[],earlier:[]};for(const n of e){const e=n.lastMessageTime||n.createdAt,a=e?new Date(e).getTime():0;a>=t?o.today.push(n):a>=r?o.yesterday.push(n):a>=s?o.week.push(n):o.earlier.push(n)}const a=[];return o.today.length&&a.push({label:m("history_group_today"),items:o.today}),o.yesterday.length&&a.push({label:m("history_group_yesterday"),items:o.yesterday}),o.week.length&&a.push({label:m("history_group_week"),items:o.week}),o.earlier.length&&a.push({label:m("history_group_earlier"),items:o.earlier}),a}(n);for(const n of i){if(i.length>1){const t=document.createElement("div");t.className="csk-history-group";const r=document.createElement("div");r.className="csk-history-group__label",r.textContent=n.label,t.appendChild(r),e.appendChild(t)}for(const a of n.items){const n=document.createElement("div");n.className="csk-history-item";const i=a.chatId||a.id;o&&i===o&&n.classList.add("csk-history-item--active");const c=document.createElement("div");c.className="csk-history-item__info";const l=document.createElement("div");l.className="csk-history-item__id",a.lastMessagePreview?l.textContent=a.lastMessagePreview.length>60?a.lastMessagePreview.substring(0,60)+"...":a.lastMessagePreview:l.textContent=i;const d=document.createElement("div");d.className="csk-history-item__meta";const p=[];void 0!==a.messageCount&&p.push(`${a.messageCount} 条消息`),a.lastMessageTime?p.push(a.lastMessageTime):a.createdAt&&p.push(a.createdAt),d.textContent=p.join(" · "),c.appendChild(l),c.appendChild(d);const u=document.createElement("div");u.className="csk-history-item__actions";const g=document.createElement("button");g.className="csk-history-action csk-history-action--export",g.setAttribute("title",m("history_export")),g.innerHTML='',g.addEventListener("click",e=>{e.stopPropagation(),r(a.id)});const k=document.createElement("button");k.className="csk-history-action csk-history-action--delete",k.setAttribute("title",m("history_delete")),k.innerHTML='',k.addEventListener("click",e=>{e.stopPropagation(),s(a.id)}),u.appendChild(g),u.appendChild(k),n.appendChild(c),n.appendChild(u),n.addEventListener("click",()=>{t(i)}),e.appendChild(n)}}}function ee(e){e.scrollTop=e.scrollHeight}function ne(e){const n=new Date(e);return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}function te(e){return`csk_history_${e}`}function re(e,n){try{let t=n;t.length>200&&(t=t.slice(50),o.warn(`消息数量达到上限,已裁剪最早 50 条,当前 ${t.length} 条`));const r={messages:t,updatedAt:Date.now()};localStorage.setItem(te(e),JSON.stringify(r))}catch(e){e instanceof Error&&"QuotaExceededError"===e.name?o.error("localStorage 空间不足,会话历史保存失败。建议清空历史记录。"):o.error("保存会话历史失败",e)}}function se(e){try{localStorage.removeItem(te(e))}catch(e){o.warn("清空会话历史失败",e)}}const oe="\0CODEBLOCK_",ae="\0INLINECODE_";function ie(e){if(!e||"string"!=typeof e)return"";const n=[];let t=e;t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(e,t,r)=>{const s=n.length,o=H(r.trimEnd()),a=t?` class="language-${H(t)}"`:"";return n.push(`
${o}
`),`${oe}${s}\0`});const r=[];t=t.replace(/`([^`\n]+)`/g,(e,n)=>{const t=r.length;return r.push(`${H(n)}`),`${ae}${t}\0`}),t=H(t),t=ce(t,oe,n),t=ce(t,ae,r);const s=t.split("\n"),o=[];let a=!1,i="",c=!1,l=[];for(let e=0;e')){p(),u(),g(),o.push(n);continue}const t=n.match(/^(#{1,6})\s+(.+)/);if(t){p(),u(),g();const e=t[1].length;o.push(`${t[2]}`);continue}const r=n.match(/^>\s?(.*)/);if(r){p(),u(),c||(c=!0,o.push('
')),o.push(`

${d(r[1])}

`);continue}c&&g();const k=n.match(/^[\-\*]\s+(.+)/);if(k){p(),g(),a&&"ul"===i||(u(),a=!0,i="ul",o.push('
    ')),o.push(`
  • ${d(k[1])}
  • `);continue}const m=n.match(/^\d+\.\s+(.+)/);m?(p(),g(),a&&"ol"===i||(u(),a=!0,i="ol",o.push('
      ')),o.push(`
    1. ${d(m[1])}
    2. `)):""!==n.trim()?/^(\*{3,}|-{3,}|_{3,})$/.test(n.trim())?(p(),u(),g(),o.push('
      ')):(u(),g(),l.push(d(n))):(p(),u())}return p(),u(),g(),o.join("\n");function d(e){return e=(e=(e=(e=(e=(e=e.replace(/\*\*(.+?)\*\*/g,"$1")).replace(/__(.+?)__/g,"$1")).replace(/\*(.+?)\*/g,"$1")).replace(/(?$1")).replace(/~~(.+?)~~/g,"$1")).replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,n,t)=>`${n}`)}function p(){l.length>0&&(o.push(`

      ${l.join("
      ")}

      `),l=[])}function u(){a&&(o.push("ul"===i?"
":""),a=!1,i="")}function g(){c&&(o.push("
"),c=!1)}}function ce(e,n,t){return e.replace(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"(\\d+)\0","g"),(e,n)=>t[parseInt(n)]||"")}let le,de=null,pe=[],ue=null,ge=null,ke=null,me=null,he=null,be=null,fe=null,ye=null,xe=null,ve=null,we=null,_e=null,Ee=null,Ce=!1,Ie=null,$e=!0,Ae=[],Le="",Se=!1;function Fe(e,n){de=e,ue=n.messagesContainer,ge=n.inputEl,ke=n.inputEl.parentElement,me=n.sendBtn,he=n.clearBtn,be=n.categorySelect,fe=n.historyPanel,ye=n.welcomeEl,xe=n.newMsgBtn,ve=n.searchInput,we=n.ariaLiveEl,_e=n.showLoading,Ee=n.hideLoading,le=e.categoryId,Se=e.enableRag,function(){if(!ge||!me)return;me.addEventListener("click",()=>{Ce&&Ie?Ie.abort():je()}),ge.addEventListener("keydown",e=>{"Enter"!==e.key||e.shiftKey||e.isComposing||(e.preventDefault(),je())}),ge.addEventListener("input",()=>{He(),function(){if(!ge)return;ge.style.height="auto",ge.style.height=`${Math.min(ge.scrollHeight,120)}px`}()}),ge.addEventListener("focus",()=>{ke&&ke.classList.add("csk-input-wrap--focus")}),ge.addEventListener("blur",()=>{ke&&ke.classList.remove("csk-input-wrap--focus")}),he&&he.addEventListener("click",()=>function(){if(!de)return;if(!confirm(m("clear_confirm")))return;if(pe=[],ue){ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove())}he&&(he.style.display="none");ze(),se(de.integrateId);const e=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();b(e),M(de.integrateId,de.userId,e),o.lifecycleClear(de.integrateId),o.info(`新 chatId=${e}`)}())}(),function(){if(!ue)return;ue.addEventListener("scroll",()=>{if(!ue)return;const{scrollTop:e,scrollHeight:n,clientHeight:t}=ue;$e=n-e-t<80,$e&&Me()}),xe&&xe.addEventListener("click",()=>{ue&&ee(ue),$e=!0,Me()})}(),function(){if(!ve)return;ve.addEventListener("input",()=>{Le=ve.value.trim().toLowerCase(),Be()})}(),e.showCategorySwitch&&be&&async function(){if(!be)return;try{const e=await async function(){const e=y("/category/tree");try{const n=await v(e);if(!n.ok)throw new w(_(n.status),`http_${n.status}`);const t=await n.json();return t.success&&Array.isArray(t.data)?(o.info(`加载分类树成功 count=${t.data.length}`),t.data):[]}catch(e){return e instanceof w?o.error(`加载分类树失败: ${e.message}`):o.error("加载分类树失败",e),[]}}();if(0===e.length)return;be.innerHTML=``;const n=(e,t=0)=>{for(const r of e){const e=document.createElement("option");e.value=String(r.id),e.textContent=`${" ".repeat(t)}${r.name}`,void 0!==le&&String(r.id)===String(le)&&(e.selected=!0),be.appendChild(e),r.children&&r.children.length>0&&n(r.children,t+1)}};n(e),o.info(`知识库分类加载成功 count=${e.length}`)}catch(e){o.error(m("category_load_error"),e)}}()}async function Ne(){if(de&&ue&&(await F(),await async function(){if(!de||!ue)return;const e=f();if(!e)return;try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map((e,n)=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`从后端加载 ${pe.length} 条历史消息`),re(de.integrateId,pe))}catch(e){o.warn("从后端加载历史消息失败",e)}}(),0===pe.length)){const e=function(e){try{const n=localStorage.getItem(te(e));if(!n)return[];const t=JSON.parse(n);return t&&Array.isArray(t.messages)?(o.info(`加载历史消息 integrateId=${e} count=${t.messages.length}`),t.messages):[]}catch(e){return o.warn("加载会话历史失败",e),[]}}(de.integrateId);e.length>0&&(pe=e,Pe(),o.info(`从本地缓存恢复 ${e.length} 条消息`))}}function Me(){xe&&xe.classList.add("csk-newmsg--hidden")}function Te(){ue&&($e?ee(ue):xe&&xe.classList.remove("csk-newmsg--hidden"))}function De(e){me&&("stop"===e?(me.classList.add("csk-send-btn--stop"),me.removeAttribute("disabled"),me.setAttribute("title",m("stop")),me.setAttribute("aria-label",m("stop")),me.innerHTML=''):(me.classList.remove("csk-send-btn--stop"),me.setAttribute("title",m("send")),me.setAttribute("aria-label",m("send")),me.innerHTML='',He()))}function Be(){const e=null==fe?void 0:fe.querySelector("#csk-history-list");if(!e||!de)return;Z(e,Le?Ae.filter(e=>(e.lastMessagePreview||e.chatId||e.id||"").toLowerCase().includes(Le)):Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{if(!confirm(m("history_delete_confirm")))return;await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}function qe(e,n){if(!ue)return;const t=pe.find(n=>n.id===e&&"ai"===n.role);if(!t)return;const r=t.feedback===n?void 0:n;t.feedback=r;const s=ue.querySelector(`[data-csk-msg-id="${e}"]`);if(s&&V(s,r),de&&re(de.integrateId,pe),r){const n="up"===r?"THUMBS_UP":"THUMBS_DOWN";(async function(e,n){if(!h)return!1;const t=y("/feedback");try{const r=await v(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messageId:String(e),conversationId:h.chatId,feedbackType:n})});return r.ok?(await r.json()).success||!1:(o.error(`反馈提交失败 status=${r.status}`),!1)}catch(e){return o.error("反馈提交异常",e),!1}})(String(e),n).then(n=>{n?o.info(`消息反馈已提交 msgId=${e} value=${r}`):o.warn(`消息反馈提交失败 msgId=${e}(本地状态已更新)`)})}else o.info(`消息反馈已取消 msgId=${e}`)}function ze(){if(!ye)return;const e=pe.length>0||ue&&ue.querySelector(".csk-msg");ye.style.display=e?"none":""}function He(){if(!me||!ge)return;ge.value.trim().length>0&&!Ce?me.removeAttribute("disabled"):me.setAttribute("disabled","true")}async function je(){if(!ge||!de||Ce)return;const e=ge.value.trim();if(""===e)return;ge.value="",He(),ge.style.height="auto";const n=j(),t={id:z(),role:"user",content:e,timestamp:n};ue&&U(ue,e,n),pe.push(t),ze(),he&&pe.length>0&&(he.style.display="inline-flex"),ue&&Te(),await Re(e)}async function Re(e){if(!de||!ue)return;Ce=!0,De("stop"),de.chatId||await F();const n=j(),t=Se;_e&&_e(),ue&&Te();const r=z();let s="";try{de.streaming?s=await async function(e,n,t,r){Ie=new AbortController;const s=Ie.signal;return new Promise((o,a)=>{let i=null,c=null,l="",d=!1;C(e,e=>{if(l+=e,!d&&ue){Ee&&Ee();const{wrapper:e,bubble:t}=function(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--ai csk-msg--streaming",t&&(r.dataset.cskMsgId=t);const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--ai",s.innerHTML=R;const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.innerHTML="";const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(n),o.appendChild(a),o.appendChild(G(a,r)),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),{wrapper:r,bubble:a}}(ue,n,r);c=e,i=t,d=!0}i&&(i.textContent=l,function(e){if(e.querySelector(".csk-caret"))return;const n=document.createElement("span");n.className="csk-caret",n.setAttribute("aria-hidden","true"),e.appendChild(n)}(i)),ue&&Te()},()=>{if(c&&i){if(!d&&""===l)return void E(e).then(o).catch(a);l&&(i.innerHTML=ie(l)),J(c,i)}o(l)},e=>{l.length>0?(i&&(i.innerHTML=ie(l+"\n\n"+m("stream_interrupted")),c&&J(c,i)),o(l)):a(e)},le,t,s)})}(e,n,t,r):(s=await E(e),Ee&&Ee(),ue&&O(ue,s,n,ie,r));const a={id:r,role:"ai",content:s,timestamp:n};pe.push(a),re(de.integrateId,pe),ue&&Te(),function(e){if(!we)return;const n=e.length>120?e.substring(0,120)+"...":e;we.textContent=m("new_msg_announce")+":"+n}(s),ue&&ue.dispatchEvent(new CustomEvent("csk:newMessage",{bubbles:!0,detail:{msg:a}})),t&&async function(e,n){try{const t=await I(e,le);if(t.length>0){const e=t.map(e=>{var n,t;return{documentId:e.documentId||"",title:e.title||"",sourceName:e.sourceName||"",chunkIndex:null!==(n=e.chunkIndex)&&void 0!==n?n:0,score:null!==(t=e.score)&&void 0!==t?t:0,snippet:e.snippet||""}});if(n.sources=e,ue){const n=ue.querySelector(".csk-msg--ai:last-of-type");n&&Q(n,e)}de&&re(de.integrateId,pe)}}catch(e){o.warn("获取引用来源失败",e)}}(e,a)}catch(e){Ee&&Ee();const n=e instanceof w?e.message:m("error_send");if(ue){const e=document.createElement("div");e.className="csk-msg csk-msg--ai";const t=document.createElement("div");t.className="csk-msg__bubble",t.style.color="#DC2626",t.textContent=`⚠ ${n}`,e.appendChild(t),ue.appendChild(e)}o.error(`发送失败 integrateId=${de.integrateId}`,e)}finally{Ce=!1,Ie=null,De("send"),He()}}function Pe(){if(!ue)return;const e=ue.querySelector(".csk-history-panel");ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());for(const e of pe)if("user"===e.role)U(ue,e.content,e.timestamp);else{const n=O(ue,e.content,e.timestamp,ie,e.id);e.sources&&e.sources.length>0&&Q(n,e.sources),e.feedback&&V(n,e.feedback)}$e=!0,ee(ue),he&&pe.length>0&&(he.style.display="inline-flex"),ze(),e&&!ue.contains(e)&&ue.appendChild(e)}async function Ue(e){if(!de||!ue)return;o.info(`切换到会话 conversationId=${e}`),b(e),M(de.integrateId,de.userId,e),fe&&fe.classList.add("csk-history-panel--hidden"),pe=[];ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map(e=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`加载会话 ${e} 的 ${pe.length} 条消息`),re(de.integrateId,pe))}catch(n){o.warn(`加载会话消息失败 conversationId=${e}`,n)}he&&pe.length>0&&(he.style.display="inline-flex"),ze()}let Oe=null,Ye=!1,We=null,Ge=null,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,tn=null,rn=null,sn=null,on=null,an=null;function cn(){if(!rn||!We)return;const e=We.getBoundingClientRect();"left-bottom"===(null==Oe?void 0:Oe.position)?rn.style.left=`${e.left}px`:rn.style.right=window.innerWidth-e.right+"px",rn.style.bottom=window.innerHeight-e.top+8+"px"}function ln(){if(!rn)return;rn.classList.add("csk-teaser--hidden"),rn.removeEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.removeEventListener("click",pn)}function dn(e){e.target.closest(".csk-teaser__close")||(ln(),mn())}function pn(e){e.stopPropagation(),ln()}function un(){rn&&!rn.classList.contains("csk-teaser--hidden")&&cn()}const gn='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';function kn(e){"Escape"===e.key&&Ge&&!Ge.classList.contains("csk-window--hidden")&&hn(),function(e){if(!Ge||Ge.classList.contains("csk-window--hidden"))return;if("Tab"!==e.key)return;const n=Array.from(Ge.querySelectorAll(gn));if(0===n.length)return;const t=n[0],r=n[n.length-1];e.shiftKey?document.activeElement===t&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),t.focus())}(e)}function mn(){Ge&&(Ge.classList.remove("csk-window--hidden"),ln(),on&&on.classList.add("csk-launcher__badge--hidden"),setTimeout(()=>{Ke&&Ke.focus()},80))}function hn(){Ge&&Ge.classList.add("csk-window--hidden")}function bn(){Ge&&(Ge.classList.contains("csk-window--hidden")?mn():hn())}function fn(e){return`csk_position_${e}`}const yn={init:function(e){if(Ye)return void o.warn("SDK 已初始化,请先调用 destroy() 再重新初始化");const t=function(e){var n,t,r,s,i,g,k,m,h,b,f;if(!e.integrateId||"string"!=typeof e.integrateId&&"number"!=typeof e.integrateId||"string"==typeof e.integrateId&&""===e.integrateId.trim())return o.error('integrateId 是必传参数(对应后端 roleId 客服角色 ID),请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;if(!e.requestDomain||"string"!=typeof e.requestDomain||""===e.requestDomain.trim())return o.error('requestDomain 是必传参数,请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;try{new URL(e.requestDomain)}catch(n){return o.error(`requestDomain 不是合法的 URL 格式:${e.requestDomain}。请提供完整的域名,如 https://api.example.com`),null}const y=String(e.integrateId).trim(),x=e.launcherTheme||void 0;let v=e.launcherIcon||a,w=e.primaryColor||"#4F46E5";x&&!e.launcherIcon&&(v={"dream-purple":c,"mint-tech":l,"coral-peach":d,"sky-blue":p}[x]||a,e.primaryColor||(w=u[x]||"#4F46E5"));const _={integrateId:y,requestDomain:e.requestDomain.replace(/\/+$/,""),userId:e.userId,categoryId:e.categoryId,showCategorySwitch:null!==(n=e.showCategorySwitch)&&void 0!==n&&n,title:e.title||"AI 智能助手",width:null!==(t=e.width)&&void 0!==t?t:380,height:Math.max(300,null!==(r=e.height)&&void 0!==r?r:520),position:"left-bottom"===e.position?"left-bottom":"right-bottom",primaryColor:w,launcherTheme:x,launcherIcon:v,showClear:null===(s=e.showClear)||void 0===s||s,showAdminPanel:null!==(i=e.showAdminPanel)&&void 0!==i&&i,quickReplies:Array.isArray(e.quickReplies)?e.quickReplies.map(e=>String(e).trim()).filter(Boolean):[],theme:"dark"===e.theme?"dark":"light",showTeaser:null===(g=e.showTeaser)||void 0===g||g,teaserText:"string"==typeof e.teaserText&&e.teaserText.trim()||"",streaming:null===(k=e.streaming)||void 0===k||k,enableRag:!1!==e.enableRag,rewriteStrategy:e.rewriteStrategy||"REWRITE",locale:e.locale||"zh-CN",debug:null===(h=e.debug)||void 0===h||h,sound:null!==(b=e.sound)&&void 0!==b&&b,notification:null!==(f=e.notification)&&void 0!==f&&f,onError:"function"==typeof e.onError?e.onError:void 0,onReady:"function"==typeof e.onReady?e.onReady:void 0,onMessage:"function"==typeof e.onMessage?e.onMessage:void 0,chatId:""};return o.info(`配置解析完成 integrateId(=roleId)=${_.integrateId} userId(=accountId)=${_.userId||"(未设置)"} requestDomain=${_.requestDomain}`),_}(e);if(!t)return;var s;Oe=t,function(e){if(g[e])k=e;else{const n=e.split("-")[0],t=Object.keys(g).find(e=>e.startsWith(n));t&&(k=t)}}(Oe.locale),s=Oe.debug,n=s,r(Oe.onError),function(e){h=e}(Oe),q(Oe),We=P(Oe,bn),document.body.appendChild(We),on=We.querySelector(".csk-launcher__badge");const i=function(e){const n=document.createElement("div");n.id="csk-window",n.className=`csk-root csk-window csk-window--${"left-bottom"===e.position?"left":"right"} csk-window--hidden${"dark"===e.theme?" csk-dark":""}`,n.setAttribute("role","dialog"),n.setAttribute("aria-label",e.title),n.setAttribute("aria-modal","false");const t=document.createElement("div");t.className="csk-header";const r=document.createElement("div");r.className="csk-header__left";const s=document.createElement("div");s.className="csk-header__avatar",s.innerHTML=R;const o=document.createElement("div");o.className="csk-header__info";const a=document.createElement("span");a.className="csk-header__title",a.textContent=e.title;const i=document.createElement("span");i.className="csk-header__status",i.innerHTML=`${m("status_online")}`,o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o);const c=document.createElement("div");c.className="csk-header__actions";const l=document.createElement("button");l.className="csk-history-btn",l.setAttribute("title",m("history_title")),l.innerHTML='';const d=document.createElement("button");d.className="csk-header__btn csk-header__btn--minimize",d.setAttribute("title",m("minimize")),d.innerHTML='',d.addEventListener("click",()=>{n.classList.add("csk-window--hidden")});const p=document.createElement("button");p.className="csk-header__btn csk-header__btn--close",p.setAttribute("title",m("close")),p.innerHTML='',p.addEventListener("click",()=>{n.classList.add("csk-window--hidden")}),c.appendChild(l),c.appendChild(d),c.appendChild(p),t.appendChild(r),t.appendChild(c);const u=document.createElement("div");u.id="csk-messages",u.className="csk-messages";const g=document.createElement("div");if(g.className="csk-welcome",g.innerHTML=`\n
${R}
\n
${m("welcome_title")}
\n
${m("welcome_desc")}
\n `,e.quickReplies.length>0){const t=document.createElement("div");t.className="csk-quick-replies";for(const r of e.quickReplies){const e=document.createElement("button");e.type="button",e.className="csk-quick-reply",e.textContent=r,e.addEventListener("click",()=>{n.dispatchEvent(new CustomEvent("csk:quickReply",{detail:{text:r}}))}),t.appendChild(e)}g.appendChild(t)}u.appendChild(g);const k=document.createElement("button");k.type="button",k.className="csk-newmsg csk-newmsg--hidden",k.innerHTML=`\n \n ${m("new_message")}\n `,n.appendChild(k);const h=document.createElement("div");h.className="csk-history-panel csk-history-panel--hidden",h.innerHTML=`\n
\n ${m("history_title")}\n \n
\n
\n \n
\n
\n `,u.appendChild(h);const b=h.querySelector("#csk-history-back");b&&b.addEventListener("click",()=>{h.classList.add("csk-history-panel--hidden")}),l.addEventListener("click",e=>{e.stopPropagation();const t=h.classList.contains("csk-history-panel--hidden");h.classList.toggle("csk-history-panel--hidden"),t&&n.dispatchEvent(new CustomEvent("csk:loadHistory"))});let f=null;if(e.showCategorySwitch){const e=document.createElement("div");e.className="csk-category-bar";const r=document.createElement("span");r.className="csk-category-bar__label",r.textContent="📚",f=document.createElement("select"),f.id="csk-category-select",f.className="csk-category-select",f.innerHTML=``,f.addEventListener("change",()=>{const e=f.value;n.dispatchEvent(new CustomEvent("csk:categoryChange",{detail:{categoryId:e?Number(e):void 0}}))}),e.appendChild(r),e.appendChild(f),n.appendChild(t),n.appendChild(u),n.appendChild(e)}else n.appendChild(t),n.appendChild(u);const y=document.createElement("div");y.className="csk-input-area";const x=document.createElement("div");x.className="csk-input-wrap";const v=document.createElement("textarea");v.id="csk-input",v.className="csk-input",v.setAttribute("placeholder",m("placeholder")),v.setAttribute("rows","1"),v.setAttribute("autofocus","");const w=document.createElement("button");w.id="csk-send-btn",w.className="csk-send-btn",w.setAttribute("title",m("send")),w.setAttribute("disabled","true"),w.innerHTML='',x.appendChild(v),x.appendChild(w),y.appendChild(x),n.appendChild(y);let _=null;e.showClear&&(_=document.createElement("button"),_.className="csk-clear-btn",_.textContent=m("clear"),_.style.display="none",n.insertBefore(_,y));let E=null;const C=document.createElement("div");C.className="csk-sr-only",C.setAttribute("aria-live","polite"),C.setAttribute("aria-atomic","true"),n.appendChild(C);const I=h.querySelector("#csk-history-search"),$=document.createElement("div");return $.className=`csk-teaser csk-teaser--${"left-bottom"===e.position?"left":"right"} csk-teaser--hidden`,$.setAttribute("role","status"),$.innerHTML=`\n \n ${e.teaserText||m("teaser_text")}\n `,{window:n,messagesContainer:u,inputEl:v,sendBtn:w,clearBtn:_,categorySelect:f,historyPanel:h,welcomeEl:g,newMsgBtn:k,teaserEl:$,searchInput:I,ariaLiveEl:C,showLoading:function(){if(E)return E.style.display="flex",E;const e=document.createElement("div");return e.className="csk-loading",e.innerHTML=`\n
${R}
\n
\n
\n
\n
\n
\n `,u.appendChild(e),E=e,e},hideLoading:function(){E&&E.parentNode&&(E.parentNode.removeChild(E),E=null)}}}(Oe);Ge=i.window,Ve=i.messagesContainer,Ke=i.inputEl,Xe=i.sendBtn,Je=i.clearBtn,Qe=i.categorySelect,Ze=i.historyPanel,en=i.showLoading,nn=i.hideLoading,document.body.appendChild(Ge),rn=i.teaserEl,document.body.appendChild(rn),cn();const b=Ge.querySelector(".csk-header");if(b&&(tn=function(e,n,t){let r=!1,s=0,o=0,a=0,i=0;const c=e=>{if(e.target.closest("button"))return;r=!0,s=e.clientX,o=e.clientY;const t=n.getBoundingClientRect();a=s-t.left,i=o-t.top,document.addEventListener("mousemove",l),document.addEventListener("mouseup",d)},l=e=>{if(!r)return;const t=e.clientX-a,s=e.clientY-i,o=window.innerWidth-n.offsetWidth,c=window.innerHeight-n.offsetHeight;n.style.right="auto",n.style.bottom="auto",n.style.left=`${Math.max(0,Math.min(t,o))}px`,n.style.top=`${Math.max(0,Math.min(s,c))}px`},d=()=>{if(r=!1,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d),t){const e=n.getBoundingClientRect();t({x:e.left,y:e.top})}};return e.addEventListener("mousedown",c),()=>{e.removeEventListener("mousedown",c),document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d)}}(b,Ge,e=>{!function(e,n){try{localStorage.setItem(fn(e),JSON.stringify(n))}catch(e){}}(Oe.integrateId,e)})),function(e,n){try{const t=localStorage.getItem(fn(e));if(!t)return;const r=JSON.parse(t);if("number"!=typeof r.x||"number"!=typeof r.y)return;const s=window.innerWidth-n.offsetWidth,o=window.innerHeight-n.offsetHeight,a=Math.max(0,Math.min(r.x,s)),i=Math.max(0,Math.min(r.y,o));n.style.right="auto",n.style.bottom="auto",n.style.left=`${a}px`,n.style.top=`${i}px`}catch(e){}}(Oe.integrateId,Ge),Fe(Oe,{messagesContainer:Ve,inputEl:Ke,sendBtn:Xe,clearBtn:Je,categorySelect:Qe,historyPanel:Ze,welcomeEl:i.welcomeEl,newMsgBtn:i.newMsgBtn,searchInput:i.searchInput,ariaLiveEl:i.ariaLiveEl,showLoading:en,hideLoading:nn}),Ge.addEventListener("csk:categoryChange",e=>{var n;n=e.detail.categoryId,le=n,Se=null==de||de.enableRag,o.lifecycleCategoryChange(null!=n?n:"全部")}),Ge.addEventListener("csk:loadHistory",()=>{!async function(){if(!fe||!de)return;const e=fe.querySelector("#csk-history-list");if(e){e.innerHTML='
加载中...
';try{const n=await $(1,50,de.userId,de.integrateId);Ae=n.list.map(e=>({id:e.conversationId||"",chatId:e.conversationId||"",messageCount:e.messageCount,lastMessageTime:e.lastMessageTime,lastMessagePreview:e.lastMessagePreview,createdAt:e.firstMessageTime||e.createdAt})),Le="",ve&&(ve.value=""),Z(e,Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{confirm(m("history_delete_confirm"))&&await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}catch(n){o.error(m("history_load_error"),n),e.innerHTML=`
${m("history_load_error")}
`}}}()}),Ge.addEventListener("csk:quickReply",e=>{var n;n=e.detail.text,!ge||Ce?Promise.resolve():(ge.value=n,He(),je())}),Ge.addEventListener("csk:retry",e=>{!async function(e){if(!de||!ue||Ce)return;const n=pe.findIndex(n=>n.id===e&&"ai"===n.role);if(n<0)return;let t="";for(let e=n-1;e>=0;e--)if("user"===pe[e].role){t=pe[e].content;break}if(!t)return;const r=pe.splice(n),s=new Set(r.map(e=>e.id));ue.querySelectorAll(".csk-msg").forEach(e=>{const n=e.dataset.cskMsgId;n&&s.has(n)&&e.remove()}),re(de.integrateId,pe),ze(),await Re(t)}(e.detail.msgId)}),Ge.addEventListener("csk:feedback",e=>{qe(e.detail.msgId,e.detail.value)}),Ge.addEventListener("csk:newMessage",e=>{var n;if(Ge&&Ge.classList.contains("csk-window--hidden")&&(on&&on.classList.remove("csk-launcher__badge--hidden"),(null==Oe?void 0:Oe.sound)&&function(){try{an||(an=new(window.AudioContext||window.webkitAudioContext));const e=an;if("suspended"===e.state)return void e.resume();const n=e.currentTime;[0,.15].forEach((t,r)=>{const s=e.createOscillator(),o=e.createGain();s.type="sine",s.frequency.value=0===r?880:1100,o.gain.setValueAtTime(.15,n+t),o.gain.exponentialRampToValueAtTime(.001,n+t+.12),s.connect(o),o.connect(e.destination),s.start(n+t),s.stop(n+t+.12)})}catch(e){}}(),(null==Oe?void 0:Oe.notification)&&function(){try{if(!("Notification"in window))return;"granted"===Notification.permission?new Notification((null==Oe?void 0:Oe.title)||"AI 智能助手",{body:"收到新消息",icon:void 0,silent:!0}):"denied"!==Notification.permission&&Notification.requestPermission()}catch(e){}}()),(null==Oe?void 0:Oe.onMessage)&&(null===(n=e.detail)||void 0===n?void 0:n.msg))try{Oe.onMessage(e.detail.msg)}catch(e){}}),document.addEventListener("keydown",kn),window.addEventListener("resize",un),Ye=!0,o.lifecycleInit(Oe.integrateId,Oe.requestDomain),Oe.onReady)try{Oe.onReady()}catch(e){}Oe.showTeaser&&(sn=setTimeout(()=>{Ge&&Ge.classList.contains("csk-window--hidden")&&function(){if(!rn)return;cn(),rn.classList.remove("csk-teaser--hidden"),rn.addEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.addEventListener("click",pn)}()},1500)),Ne().catch(e=>{o.warn("chatId 初始化失败,将在发送消息时重试",e)})},destroy:function(){if(!Ye)return;sn&&(clearTimeout(sn),sn=null),ln(),rn&&rn.parentNode&&(rn.parentNode.removeChild(rn),rn=null),We&&We.parentNode&&(We.parentNode.removeChild(We),We=null),Ge&&Ge.parentNode&&(Ge.parentNode.removeChild(Ge),Ge=null),tn&&(tn(),tn=null),T&&T.parentNode&&(T.parentNode.removeChild(T),T=null),document.querySelectorAll("style[data-csk-sdk]").forEach(e=>e.remove()),document.removeEventListener("keydown",kn),window.removeEventListener("resize",un),r(void 0);const e=null==Oe?void 0:Oe.integrateId;Oe=null,Ye=!1,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,on=null,an=null,o.lifecycleDestroy(e||"")},open:mn,close:hn,toggle:bn,clearHistory:function(){Oe&&(Je?Je.click():confirm("确定清空所有对话记录?")&&se(Oe.integrateId))}};return"undefined"!=typeof window&&(window.ChatbotSDK=yn),yn}(); //# sourceMappingURL=chatbot-sdk.min.js.map diff --git a/client/src/chat.ts b/client/src/chat.ts index 8f5a644..c03d328 100644 --- a/client/src/chat.ts +++ b/client/src/chat.ts @@ -111,7 +111,7 @@ export function initChat( // 初始化知识库分类 currentCategoryId = cfg.categoryId; - useRag = !!cfg.enableRag || !!cfg.categoryId || !!cfg.showCategorySwitch; + useRag = cfg.enableRag; // 绑定发送事件 bindSendEvents(); @@ -442,8 +442,8 @@ async function produceAIReply(userText: string): Promise { } const aiTimestamp = now(); - // RAG 启用条件:显式开启 enableRag,或已选择知识库分类 - const shouldUseRag = useRag && (config.enableRag || currentCategoryId !== undefined || config.categoryId !== undefined); + // RAG 启用条件:由 enableRag 控制 + const shouldUseRag = useRag; // 显示 loading if (showLoadingFn) showLoadingFn(); @@ -717,7 +717,7 @@ function generateNewChatId(): string { /** 设置当前知识库分类 */ export function setCategory(categoryId: number | undefined): void { currentCategoryId = categoryId; - useRag = categoryId !== undefined; + useRag = config?.enableRag ?? true; logger.lifecycleCategoryChange(categoryId ?? '全部'); } diff --git a/client/src/config.ts b/client/src/config.ts index 525db23..30200ec 100644 --- a/client/src/config.ts +++ b/client/src/config.ts @@ -179,7 +179,7 @@ export function parseConfig(raw: SDKConfig): ResolvedConfig | null { showTeaser: raw.showTeaser ?? true, teaserText: (typeof raw.teaserText === 'string' && raw.teaserText.trim()) || '', streaming: raw.streaming ?? true, - enableRag: raw.enableRag ?? false, + enableRag: raw.enableRag ?? true, rewriteStrategy: raw.rewriteStrategy || 'REWRITE', locale: raw.locale || 'zh-CN', debug: raw.debug ?? true, diff --git a/client/src/types.ts b/client/src/types.ts index 7437905..1b603b0 100644 --- a/client/src/types.ts +++ b/client/src/types.ts @@ -57,12 +57,12 @@ export interface SDKConfig { /** 是否启用流式输出,默认 true */ streaming?: boolean; /** - * 是否启用 RAG 知识库检索对话,默认 false。 + * 是否启用 RAG 知识库检索对话,默认 true。 * 开启后对话将使用 /chat/rag/sse 接口,后端会根据角色绑定的知识库分类自动检索。 * 如果角色未绑定知识库,后端自动降级为普通对话,不会报错。 */ enableRag?: boolean; - /** RAG 查询重写策略,默认 "REWRITE"(仅在 enableRag=true 时生效) */ + /** RAG 查询重写策略,默认 "REWRITE"(在 enableRag=true 时生效) */ rewriteStrategy?: 'NONE' | 'REWRITE' | 'TRANSLATION' | 'COMPRESSION' | 'MULTI_QUERY'; /** 界面语言,默认 "zh-CN" */ locale?: string; diff --git a/src/main/resources/static/sdk/chatbot-sdk.js b/src/main/resources/static/sdk/chatbot-sdk.js index 55a2995..a699d3d 100644 --- a/src/main/resources/static/sdk/chatbot-sdk.js +++ b/src/main/resources/static/sdk/chatbot-sdk.js @@ -3472,7 +3472,7 @@ var ChatbotSDK = (function () { hideLoadingFn$1 = dom.hideLoading; // 初始化知识库分类 currentCategoryId = cfg.categoryId; - useRag = !!cfg.enableRag || !!cfg.categoryId || !!cfg.showCategorySwitch; + useRag = cfg.enableRag; // 绑定发送事件 bindSendEvents(); // 绑定滚动监听(智能滚动 + 新消息提示) @@ -3784,8 +3784,8 @@ var ChatbotSDK = (function () { await initChatId(); } const aiTimestamp = now(); - // RAG 启用条件:显式开启 enableRag,或已选择知识库分类 - const shouldUseRag = useRag && (config$1.enableRag || currentCategoryId !== undefined || config$1.categoryId !== undefined); + // RAG 启用条件:由 enableRag 控制 + const shouldUseRag = useRag; // 显示 loading if (showLoadingFn$1) showLoadingFn$1(); @@ -4060,7 +4060,7 @@ var ChatbotSDK = (function () { /** 设置当前知识库分类 */ function setCategory(categoryId) { currentCategoryId = categoryId; - useRag = categoryId !== undefined; + useRag = config$1?.enableRag ?? true; logger.lifecycleCategoryChange(categoryId !== null && categoryId !== void 0 ? categoryId : '全部'); } // ==================== 会话管理面板 ==================== diff --git a/src/main/resources/static/sdk/chatbot-sdk.min.js b/src/main/resources/static/sdk/chatbot-sdk.min.js index c6ffa68..b1af946 100644 --- a/src/main/resources/static/sdk/chatbot-sdk.min.js +++ b/src/main/resources/static/sdk/chatbot-sdk.min.js @@ -1,2 +1,2 @@ -var ChatbotSDK=function(){"use strict";const e="[ChatbotSDK]";let n=!0,t=null;function r(e){t=e||null}const s={},o={info(t,r){n&&console.log(e,t,void 0!==r?r:"")},warn(t,r){n&&console.warn(e,t,void 0!==r?r:"")},error(n,r){if(console.error(e,n,void 0!==r?r:""),t)try{const e=r instanceof Error&&r.type||"error";t({message:n,code:String(e),detail:r})}catch(e){}},time(e){s[e]=Date.now()},timeEnd(t,r){const o=s[t];if(void 0!==o){const a=Date.now()-o;if(delete s[t],n){const n=r?`${r} ${a}ms`:`${t} ${a}ms`;console.log(e,n)}return a}return 0},lifecycleInit(e,n){this.info(`初始化完成 integrateId=${e} requestDomain=${n}`)},lifecycleDestroy(e){this.info(`销毁实例 integrateId=${e}`)},lifecycleSend(e,n){this.info(`发送消息 integrateId=${e} length=${n}`),this.time(`send_${e}`)},lifecycleReply(e,n){const t=this.timeEnd(`send_${e}`,"AI 回复");this.info(`AI 回复 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleError(e,n,t){this.timeEnd(`send_${e}`),this.error(`请求失败 integrateId=${e} status=${n} message=${t}`)},lifecycleClear(e){this.info(`清空会话 integrateId=${e}`)},lifecycleStreamDone(e,n){const t=this.timeEnd(`send_${e}`,"流式回复");this.info(`流式回复完成 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleCategoryChange(e){this.info(`切换知识库分类 categoryId=${e}`)}},a='\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n';function i(e,n,t){return`\n \n \x3c!-- 高光渐变:模拟玻璃反射 --\x3e\n \n \n \n \n \x3c!-- 机器人身体渐变 --\x3e\n \n \n \n \n \n \x3c!-- 机器人主体(圆角矩形 + 对话气泡尾巴) --\x3e\n \n \n \x3c!-- 高光反射层(左上角弧形高光) --\x3e\n \n \x3c!-- 天线 + 能量球 --\x3e\n \n \n \x3c!-- 眼睛(会眨) --\x3e\n \n \n \x3c!-- 眼睛高光点 --\x3e\n \n \n \x3c!-- 微笑 --\x3e\n \n \x3c!-- 跳动气泡装饰(3 个小圆点) --\x3e\n \n \n \n`}const c=i("rgba(139,92,246,0.6)","rgba(139,92,246,0.45)","rgba(240,171,252,0.85)"),l=i("rgba(16,185,129,0.6)","rgba(16,185,129,0.45)","rgba(110,231,183,0.85)"),d=i("rgba(244,63,94,0.55)","rgba(244,63,94,0.4)","rgba(253,186,116,0.85)"),p=i("rgba(56,189,248,0.6)","rgba(56,189,248,0.45)","rgba(167,139,250,0.85)"),u={"dream-purple":"#A78BFA","mint-tech":"#34D399","coral-peach":"#FB7185","sky-blue":"#7DD3FC"};const g={"zh-CN":{title:"AI 智能助手",minimize:"最小化",close:"关闭",status_online:"在线",welcome_title:"你好,我是 AI 智能助手",welcome_desc:"有什么可以帮你的吗?在下方输入框开始提问吧~",placeholder:"输入您的问题...",send:"发送",stop:"停止生成",new_message:"新消息",copy:"复制",copied:"已复制",retry:"重新生成",retrying:"重新生成中...",loading:"正在思考...",stream_interrupted:"回复被中断",stream_unstable:"网络不稳定,内容可能不完整",category_placeholder:"选择知识库分类",category_all:"全部分类",category_load_error:"加载分类失败",source_title:"参考来源",source_count:"{n} 条参考来源",source_loading:"加载来源中...",clear:"清空对话",clear_confirm:"确定清空所有对话记录?",history_title:"历史会话",history_empty:"暂无历史会话",history_load_error:"加载会话列表失败",history_delete_confirm:"确定删除该会话?",history_export:"导出",history_delete:"删除",history_search:"搜索会话...",history_group_today:"今天",history_group_yesterday:"昨天",history_group_week:"本周",history_group_earlier:"更早",feedback_up:"有帮助",feedback_down:"没帮助",teaser_text:"有什么可以帮你的吗?",new_msg_announce:"收到新消息",error_network:"网络连接失败,请检查网络",error_timeout:"请求超时,请稍后重试",error_server:"服务器异常,请稍后重试",error_cors:"跨域请求被拦截,请联系管理员将当前域名加入 API 白名单",error_auth:"鉴权失败,请联系管理员",error_forbidden:"无访问权限,请联系管理员配置",error_not_found:"请求的资源不存在",error_rate_limit:"请求过于频繁,请稍后重试",error_unavailable:"服务暂不可用,请稍后重试",error_unknown:"请求发生未知错误",error_send:"发送失败,请稍后重试",error_stream_unsupported:"浏览器不支持流式读取"},en:{title:"AI Assistant",minimize:"Minimize",close:"Close",status_online:"Online",welcome_title:"Hi, I am your AI assistant",welcome_desc:"How can I help you? Type your question below to get started.",placeholder:"Type your question...",send:"Send",stop:"Stop generating",new_message:"New message",copy:"Copy",copied:"Copied",retry:"Regenerate",retrying:"Regenerating...",loading:"Thinking...",stream_interrupted:"Response interrupted",stream_unstable:"Network unstable, content may be incomplete",category_placeholder:"Select category",category_all:"All categories",category_load_error:"Failed to load categories",source_title:"Sources",source_count:"{n} source(s)",source_loading:"Loading sources...",clear:"Clear chat",clear_confirm:"Clear all conversation history?",history_title:"History",history_empty:"No conversations yet",history_load_error:"Failed to load conversations",history_delete_confirm:"Delete this conversation?",history_export:"Export",history_delete:"Delete",history_search:"Search conversations...",history_group_today:"Today",history_group_yesterday:"Yesterday",history_group_week:"This Week",history_group_earlier:"Earlier",feedback_up:"Helpful",feedback_down:"Not helpful",teaser_text:"How can I help you?",new_msg_announce:"New message received",error_network:"Network connection failed",error_timeout:"Request timed out, please try again",error_server:"Server error, please try again later",error_cors:"CORS request blocked. Please contact admin to whitelist your domain",error_auth:"Authentication failed, please contact admin",error_forbidden:"Access denied, please contact admin",error_not_found:"Resource not found",error_rate_limit:"Too many requests, please try again later",error_unavailable:"Service temporarily unavailable",error_unknown:"Unknown request error",error_send:"Failed to send, please try again",error_stream_unsupported:"Browser does not support streaming"}};let k="zh-CN";function m(e,n){let t=(g[k]||g["zh-CN"])[e]||g["zh-CN"][e]||e;if(n)for(const[e,r]of Object.entries(n))t=t.replace(`{${e}}`,String(r));return t}let h=null;function b(e){h&&(h.chatId=e)}function f(){return(null==h?void 0:h.chatId)||""}function y(e){if(!h)throw new Error("API 配置未初始化");return`${h.requestDomain.replace(/\/+$/,"")}${e.startsWith("/")?e:`/${e}`}`}function x(e,n,t){null!=t&&("string"==typeof t&&""===t.trim()||e.set(n,String(t)))}async function v(e,n={},t=3e4,r){const s=new AbortController,o=setTimeout(()=>s.abort(),t);r&&(r.aborted?s.abort():r.addEventListener("abort",()=>s.abort(),{once:!0}));try{return await fetch(e,Object.assign(Object.assign({},n),{signal:s.signal,mode:"cors",credentials:"include"}))}catch(e){if(null==r?void 0:r.aborted)throw new w("aborted","aborted");if(e instanceof DOMException&&"AbortError"===e.name)throw new w(m("error_timeout"),"timeout");if(e instanceof TypeError&&e.message.includes("Failed to fetch"))throw new w(m("error_cors"),"cors");throw new w(m("error_network"),"network")}finally{clearTimeout(o)}}class w extends Error{constructor(e,n){super(e),this.name="CskError",this.type=n}}function _(e){switch(e){case 401:return m("error_auth");case 403:return m("error_forbidden");case 404:return m("error_not_found");case 429:return m("error_rate_limit");case 500:return m("error_server");case 502:case 503:return m("error_unavailable");default:return`${m("error_unknown")}(${e})`}}async function E(e){const n=function(e){const n=new URLSearchParams;return n.set("message",e),n.set("chatId",h.chatId),x(n,"roleId",h.integrateId),x(n,"accountId",h.userId),y(`/ai/assistant_app/chat/sync?${n.toString()}`)}(e);o.lifecycleSend(h.integrateId,e.length);try{const e=await v(n);if(!e.ok){const n=_(e.status);throw o.lifecycleError(h.integrateId,String(e.status),n),new w(n,`http_${e.status}`)}const t=await e.text();return o.lifecycleReply(h.integrateId,t.length),t}catch(e){if(e instanceof w)throw e;throw o.lifecycleError(h.integrateId,"unknown",String(e)),new w(m("error_unknown"),"unknown")}}async function C(e,n,t,r,s,a,i){var c;const l=a?function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/rag/sse?${t.toString()}`)}(e,s):function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/sse?${t.toString()}`)}(e,s);let d="";o.lifecycleSend(h.integrateId,e.length);try{const e=await v(l,{},6e4,i);if(!e.ok){const n=_(e.status);return o.lifecycleError(h.integrateId,String(e.status),n),void r(new w(n,`http_${e.status}`))}const s=null===(c=e.body)||void 0===c?void 0:c.getReader();if(!s)return void r(new w(m("error_stream_unsupported"),"stream_unsupported"));const a=new TextDecoder("utf-8",{stream:!0});let p="";try{for(;;){const{done:e,value:t}=await s.read();if(e)break;p+=a.decode(t,{stream:!0});const r=p.split("\n");p=r.pop()||"";for(const e of r){const t=e.trim();if(t&&!t.startsWith(":"))if(t.startsWith("data:")){const e=t.substring(5).trim();e&&(d+=e,n(e))}else{if("[DONE]"===t)break;t.startsWith("event:")||t.startsWith("id:")||t.startsWith("retry:")||(d+=t,n(t))}}}if(p.trim()){const e=p.trim();if(e.startsWith("data:")){const t=e.substring(5).trim();t&&(d+=t,n(t))}else"[DONE]"!==e&&(d+=e,n(e))}}catch(e){if(null==i?void 0:i.aborted)o.info(`流式被用户中断,保留已生成内容 length=${d.length}`);else{if(!(d.length>0))throw e;n("\n\n"+m("stream_unstable"))}}finally{s.releaseLock()}o.lifecycleStreamDone(h.integrateId,d.length),t()}catch(e){if((null==i?void 0:i.aborted)||e instanceof w&&"aborted"===e.type)return void t();e instanceof w?r(e):(o.lifecycleError(h.integrateId,"unknown",String(e)),r(new w(m("error_network"),"network")))}}async function I(e,n){const t=function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/rag/sources?${t.toString()}`)}(e,n);try{const e=await v(t);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return n.success&&Array.isArray(n.data)?(o.info(`获取引用来源 count=${n.data.length}`),n.data):[]}catch(e){return o.error("获取引用来源失败",e),[]}}async function $(e=1,n=20,t,r){let s=`/conversation/list?page=${e}&size=${n}`;t&&(s+=`&accountId=${encodeURIComponent(t)}`),r&&(s+=`&roleId=${encodeURIComponent(r)}`);const a=y(s);try{const e=await v(a);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return{list:n.success&&Array.isArray(n.data)?n.data:[],total:n.total||0,pages:n.pages||0}}catch(e){return o.error("加载会话列表失败",e),{list:[],total:0,pages:0}}}async function A(e){const n=y(`/conversation/${e}/messages`);try{const e=await v(n);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const t=await e.json();return{messages:t.success&&Array.isArray(t.data)?t.data:[],total:t.total||0}}catch(e){return o.error("加载会话消息失败",e),{messages:[],total:0}}}async function L(e){const n=y(`/conversation/${e}`);try{const t=await v(n,{method:"DELETE"});if(!t.ok)throw new w(_(t.status),`http_${t.status}`);const r=await t.json();return o.info(`删除会话 id=${e} success=${r.success}`),r.success||!1}catch(e){return o.error("删除会话失败",e),!1}}function S(e){return y(`/conversation/${e}/export`)}async function F(){if(!h)return"";const e=function(e,n){try{return localStorage.getItem(N(e,n))||""}catch(e){return""}}(h.integrateId,h.userId);if(e)return h.chatId=e,o.info(`从缓存恢复 chatId=${e}`),e;try{const e=await $(1,5,h.userId,h.integrateId);if(e.list.length>0){const n=e.list[0],t=n.conversationId||n.chatId||"";if(t)return h.chatId=t,M(h.integrateId,h.userId,t),o.info(`从后端恢复会话 chatId=${t} messageCount=${n.messageCount}`),t}}catch(e){o.warn("查询后端会话列表失败,将生成新 chatId",e)}const n=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();return h.chatId=n,M(h.integrateId,h.userId,n),o.info(`生成新 chatId=${n}`),n}function N(e,n){return`csk_chatId_${e}${n?"_"+n:""}`}function M(e,n,t){try{t?localStorage.setItem(N(e,n),t):localStorage.removeItem(N(e,n))}catch(e){}}let T=null;function D(e){const n=B(e.primaryColor,-15),t=B(e.primaryColor,18),r=function(e){const n=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);return n?`${parseInt(n[1],16)}, ${parseInt(n[2],16)}, ${parseInt(n[3],16)}`:"79, 70, 229"}(e.primaryColor),s=e.launcherTheme?{"dream-purple":{grad1:"#A78BFA",grad2:"#F0ABFC",glow:"167, 139, 250"},"mint-tech":{grad1:"#6EE7B7",grad2:"#34D399",glow:"52, 211, 153"},"coral-peach":{grad1:"#FB7185",grad2:"#FDBA74",glow:"251, 113, 133"},"sky-blue":{grad1:"#7DD3FC",grad2:"#A78BFA",glow:"125, 211, 252"}}[e.launcherTheme]:null;return`\n --csk-primary: ${e.primaryColor};\n --csk-primary-hover: ${n};\n --csk-primary-light: ${t};\n --csk-primary-rgb: ${r};\n --csk-bg-user: linear-gradient(135deg, ${e.primaryColor}, ${n});\n --csk-bg-ai: #ffffff;\n --csk-text-user: #ffffff;\n --csk-text-ai: #1F2937;\n --csk-window-width: ${e.width}px;\n --csk-window-height: ${e.height}px;\n --csk-radius: 16px;\n --csk-shadow-window: 0 12px 48px rgba(15, 23, 42, 0.18), 0 2px 8px rgba(15, 23, 42, 0.06);\n --csk-shadow-bubble: 0 1px 2px rgba(15, 23, 42, 0.06);\n --csk-border: #ECEEF2;\n --csk-bg-app: #F6F7F9;\n ${s?`\n --csk-launcher-grad-1: ${s.grad1};\n --csk-launcher-grad-2: ${s.grad2};\n --csk-launcher-glow: ${s.glow};\n `:""}\n `}function B(e,n){const t=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!t)return e;const r=e=>Math.max(0,Math.min(255,e)),s=r(parseInt(t[1],16)+n),o=r(parseInt(t[2],16)+n),a=r(parseInt(t[3],16)+n);return`#${s.toString(16).padStart(2,"0")}${o.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}`}function q(e){document.querySelector("style[data-csk-sdk]")||(T=document.createElement("style"),T.setAttribute("data-csk-sdk",""),T.textContent=function(e){return`\n/* ChatbotSDK 样式 - csk- 命名空间 */\n.csk-root {\n ${D(e)}\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;\n font-size: 14px;\n line-height: 1.55;\n color: #1F2937;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n.csk-root *, .csk-root *::before, .csk-root *::after { box-sizing: border-box; }\n\n/* ========== 悬浮按钮 ========== */\n.csk-launcher {\n position: fixed;\n bottom: 24px;\n z-index: 9998;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n user-select: none;\n overflow: visible;\n /* 半透明白色光环边框,在白色页面上清晰分离按钮与背景 */\n border: 2.5px solid rgba(255, 255, 255, 0.55);\n /* 三层投影:接地阴影 + 彩色光晕,把按钮从白底「托」出来 */\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.25s ease,\n border-color 0.25s ease;\n animation: csk-launcher-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;\n}\n.csk-launcher--right { right: 24px; }\n.csk-launcher--left { left: 24px; }\n\n/* 高光扫过动效 */\n.csk-launcher::before {\n content: '';\n position: absolute;\n top: -50%;\n left: -50%;\n width: 40%;\n height: 200%;\n border-radius: 50%;\n background: linear-gradient(\n 105deg,\n transparent 30%,\n rgba(255, 255, 255, 0.28) 48%,\n rgba(255, 255, 255, 0.1) 52%,\n transparent 70%\n );\n transform: rotate(25deg);\n animation: csk-shimmer 4s ease-in-out infinite;\n pointer-events: none;\n}\n/* 呼吸色晕 — 配合接地阴影,强化白底上的立体存在感 */\n.csk-launcher::after {\n content: '';\n position: absolute;\n inset: -18px;\n border-radius: 50%;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.18) 0%, rgba(var(--csk-primary-rgb), 0.05) 45%, transparent 68%);\n animation: csk-breathe 3.5s ease-in-out infinite;\n pointer-events: none;\n}\n.csk-launcher:hover {\n transform: translateY(-3px) scale(1.08);\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.10),\n 0 8px 24px rgba(0, 0, 0, 0.14),\n 0 10px 36px rgba(var(--csk-primary-rgb), 0.32),\n 0 0 56px rgba(var(--csk-primary-rgb), 0.14);\n}\n.csk-launcher:hover::before { animation-play-state: paused; }\n.csk-launcher:hover::after {\n animation: none;\n inset: -22px;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.22) 0%, rgba(var(--csk-primary-rgb), 0.06) 45%, transparent 68%);\n}\n.csk-launcher:active { transform: scale(0.93); }\n.csk-launcher svg {\n width: 30px;\n height: 30px;\n position: relative;\n z-index: 1;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.15));\n}\n\n@keyframes csk-launcher-in {\n 0% { opacity: 0; transform: scale(0.5) translateY(16px); }\n 60% { transform: scale(1.06) translateY(-2px); }\n 100% { opacity: 1; transform: scale(1) translateY(0); }\n}\n@keyframes csk-shimmer {\n 0%, 100% { left: -60%; opacity: 0; }\n 20% { opacity: 1; }\n 60% { opacity: 1; }\n 80% { left: 120%; opacity: 0; }\n}\n@keyframes csk-breathe {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.15); opacity: 0.35; }\n}\n\n/* SVG 图标内部动效:眨眼 */\n.csk-launcher .csk-ico-eye {\n animation: csk-eye-blink 4s ease-in-out infinite;\n}\n@keyframes csk-eye-blink {\n 0%, 42%, 48%, 100% { opacity: 1; }\n 45% { opacity: 0.1; }\n}\n/* SVG 图标内部动效:天线能量闪烁 */\n.csk-launcher .csk-ico-antenna {\n animation: csk-antenna-glow 2s ease-in-out infinite;\n}\n@keyframes csk-antenna-glow {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n/* ========== 磨砂玻璃质感悬浮按钮 ========== */\n.csk-launcher--glass {\n background: linear-gradient(\n 135deg,\n var(--csk-launcher-grad-1, var(--csk-primary)) 0%,\n var(--csk-launcher-grad-2, var(--csk-primary-light)) 100%\n ) !important;\n backdrop-filter: blur(12px) saturate(180%);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n border: 1.5px solid rgba(255, 255, 255, 0.55) !important;\n /* 多层阴影:接地 + 彩色光晕 + 内阴影立体感 */\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.04),\n 0 6px 20px rgba(0, 0, 0, 0.08),\n 0 8px 32px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.30),\n inset 0 1px 1px rgba(255, 255, 255, 0.35),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n.csk-launcher--glass:hover {\n border-color: rgba(255, 255, 255, 0.75) !important;\n box-shadow:\n 0 4px 8px rgba(0, 0, 0, 0.06),\n 0 10px 28px rgba(0, 0, 0, 0.10),\n 0 12px 40px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.38),\n inset 0 1px 2px rgba(255, 255, 255, 0.45),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n\n/* 玻璃按钮的呼吸色晕 — 更鲜艳、更醒目 */\n.csk-launcher--glass::after {\n background: radial-gradient(\n circle,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.28) 0%,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.10) 40%,\n transparent 65%\n ) !important;\n animation: csk-breathe-glow 3.5s ease-in-out infinite;\n}\n@keyframes csk-breathe-glow {\n 0%, 100% { transform: scale(1); opacity: 0.8; }\n 50% { transform: scale(1.22); opacity: 0.25; }\n}\n\n/* 玻璃按钮的高光扫过 — 更柔和的玻璃质感 */\n.csk-launcher--glass::before {\n background: linear-gradient(\n 115deg,\n transparent 25%,\n rgba(255, 255, 255, 0.35) 45%,\n rgba(255, 255, 255, 0.15) 55%,\n transparent 75%\n ) !important;\n width: 50%;\n animation: csk-shimmer-glass 5s ease-in-out infinite;\n}\n@keyframes csk-shimmer-glass {\n 0%, 100% { left: -70%; opacity: 0; }\n 15% { opacity: 1; }\n 55% { opacity: 1; }\n 70% { left: 130%; opacity: 0; }\n}\n\n/* SVG 内部动效:跳动气泡(3 个小圆点交错弹跳) */\n.csk-launcher .csk-ico-bubble {\n animation: csk-bubble-jump 1.4s ease-in-out infinite;\n}\n.csk-launcher .csk-ico-bubble--1 { animation-delay: 0s; }\n.csk-launcher .csk-ico-bubble--2 { animation-delay: 0.18s; }\n.csk-launcher .csk-ico-bubble--3 { animation-delay: 0.36s; }\n@keyframes csk-bubble-jump {\n 0%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-3.5px); }\n 60% { transform: translateY(-1px); }\n}\n\n/* ========== 聊天弹窗 ========== */\n.csk-window {\n position: fixed;\n bottom: 24px;\n z-index: 9999;\n width: var(--csk-window-width);\n height: var(--csk-window-height);\n max-height: calc(100vh - 48px);\n background: #fff;\n border-radius: var(--csk-radius);\n box-shadow: var(--csk-shadow-window);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transform-origin: bottom right;\n transition: opacity 0.24s ease, transform 0.24s cubic-bezier(0.34, 1.2, 0.64, 1), visibility 0.24s;\n opacity: 1;\n transform: translateY(0) scale(1);\n visibility: visible;\n pointer-events: auto;\n}\n.csk-window--right { right: 24px; transform-origin: bottom right; }\n.csk-window--left { left: 24px; transform-origin: bottom left; }\n.csk-window--hidden {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n visibility: hidden;\n pointer-events: none;\n}\n\n/* ========== 头部 ========== */\n.csk-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n min-height: 60px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: move;\n user-select: none;\n position: relative;\n flex-shrink: 0;\n}\n.csk-header::after {\n content: '';\n position: absolute;\n left: 0; right: 0; bottom: 0;\n height: 24px;\n background: linear-gradient(to bottom, rgba(0,0,0,0.04), transparent);\n pointer-events: none;\n}\n.csk-header__left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n.csk-header__avatar {\n width: 38px;\n height: 38px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);\n}\n.csk-header__avatar svg { width: 22px; height: 22px; }\n.csk-header__info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.csk-header__title {\n font-size: 15px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n letter-spacing: 0.2px;\n}\n.csk-header__status {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 11.5px;\n opacity: 0.9;\n margin-top: 2px;\n}\n.csk-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #6EE7B7;\n box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7);\n animation: csk-status-pulse 2s infinite;\n}\n@keyframes csk-status-pulse {\n 0% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7); }\n 70% { box-shadow: 0 0 0 6px rgba(110, 231, 183, 0); }\n 100% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0); }\n}\n.csk-header__actions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n.csk-header__btn,\n.csk-history-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #fff;\n cursor: pointer;\n border-radius: 8px;\n transition: background 0.15s, transform 0.15s;\n}\n.csk-header__btn:hover,\n.csk-history-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n.csk-header__btn:active,\n.csk-history-btn:active { transform: scale(0.92); }\n\n/* ========== 消息区 ========== */\n.csk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 20px 16px 12px;\n background: var(--csk-bg-app);\n scroll-behavior: smooth;\n}\n.csk-messages::-webkit-scrollbar { width: 6px; }\n.csk-messages::-webkit-scrollbar-track { background: transparent; }\n.csk-messages::-webkit-scrollbar-thumb {\n background: #D8DCE3;\n border-radius: 3px;\n}\n.csk-messages::-webkit-scrollbar-thumb:hover { background: #C2C7D0; }\n\n/* 欢迎空状态 */\n.csk-welcome {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 48px 24px 32px;\n color: #6B7280;\n animation: csk-fade-in 0.3s ease;\n}\n.csk-welcome__avatar {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 14px;\n box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-welcome__avatar svg { width: 30px; height: 30px; }\n.csk-welcome__title {\n font-size: 15px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.csk-welcome__desc {\n font-size: 13px;\n color: #9CA3AF;\n line-height: 1.6;\n}\n\n/* 消息气泡 */\n.csk-msg {\n display: flex;\n margin-bottom: 18px;\n max-width: 100%;\n word-break: break-word;\n animation: csk-msg-in 0.28s cubic-bezier(0.22, 1, 0.36, 1);\n}\n.csk-msg--user {\n flex-direction: row-reverse;\n align-items: flex-end;\n}\n.csk-msg--ai {\n flex-direction: row;\n align-items: flex-start;\n}\n.csk-msg__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg__avatar svg { width: 18px; height: 18px; }\n.csk-msg__avatar--ai {\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n}\n.csk-msg__avatar--user {\n background: var(--csk-bg-user);\n color: #fff;\n}\n.csk-msg__content {\n display: flex;\n flex-direction: column;\n min-width: 0;\n max-width: calc(100% - 46px);\n}\n.csk-msg--user .csk-msg__content { align-items: flex-end; }\n.csk-msg--ai .csk-msg__content { align-items: flex-start; }\n.csk-msg__bubble {\n padding: 10px 14px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.6;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg--user .csk-msg__bubble {\n background: var(--csk-bg-user);\n color: var(--csk-text-user);\n border-radius: 16px 16px 4px 16px;\n}\n.csk-msg--ai .csk-msg__bubble {\n background: var(--csk-bg-ai);\n color: var(--csk-text-ai);\n border-radius: 16px 16px 16px 4px;\n border: 1px solid var(--csk-border);\n}\n.csk-msg__time {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 5px;\n padding: 0 4px;\n}\n\n@keyframes csk-msg-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes csk-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ========== Loading 动画 ========== */\n.csk-loading {\n display: flex;\n align-items: center;\n margin-bottom: 18px;\n animation: csk-msg-in 0.28s ease;\n}\n.csk-loading__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-loading__avatar svg { width: 18px; height: 18px; }\n.csk-loading__bubble {\n background: #fff;\n border: 1px solid var(--csk-border);\n border-radius: 16px 16px 16px 4px;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.csk-loading__dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #B4B9C2;\n animation: csk-bounce 1.4s ease-in-out infinite both;\n}\n.csk-loading__dot:nth-child(1) { animation-delay: 0s; }\n.csk-loading__dot:nth-child(2) { animation-delay: 0.16s; }\n.csk-loading__dot:nth-child(3) { animation-delay: 0.32s; }\n\n@keyframes csk-bounce {\n 0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }\n 40% { transform: scale(1); opacity: 1; }\n}\n\n/* ========== 输入区 ========== */\n.csk-input-area {\n padding: 10px 12px 14px;\n background: #fff;\n border-top: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-input-wrap {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n background: var(--csk-bg-app);\n border: 1px solid var(--csk-border);\n border-radius: 14px;\n padding: 6px 6px 6px 14px;\n transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;\n}\n.csk-input-wrap--focus {\n border-color: var(--csk-primary);\n background: #fff;\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n.csk-input {\n flex: 1;\n border: none;\n background: transparent;\n padding: 8px 0;\n font-size: 14px;\n outline: none;\n font-family: inherit;\n resize: none;\n min-height: 22px;\n max-height: 120px;\n line-height: 1.5;\n color: #1F2937;\n}\n.csk-input::placeholder { color: #9CA3AF; }\n.csk-root .csk-input:focus-visible { outline: none; }\n.csk-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n min-width: 36px;\n border: none;\n border-radius: 10px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: pointer;\n transition: transform 0.18s, box-shadow 0.18s, opacity 0.18s;\n box-shadow: 0 3px 10px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-send-btn:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 5px 14px rgba(var(--csk-primary-rgb), 0.4);\n}\n.csk-send-btn:active:not(:disabled) { transform: scale(0.92); }\n.csk-send-btn:disabled {\n background: #D1D5DB;\n box-shadow: none;\n cursor: not-allowed;\n opacity: 0.7;\n}\n.csk-send-btn svg { width: 18px; height: 18px; }\n\n/* ========== 清空按钮 ========== */\n.csk-clear-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 999px;\n background: #fff;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n margin: 0 auto 8px;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-clear-btn:hover {\n background: #FEF2F2;\n border-color: #FCA5A5;\n color: #DC2626;\n}\n\n/* ========== P1: 知识库分类下拉 ========== */\n.csk-category-bar {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n border-top: 1px solid var(--csk-border);\n background: #FBFBFC;\n gap: 8px;\n flex-shrink: 0;\n}\n.csk-category-bar__label {\n font-size: 13px;\n white-space: nowrap;\n}\n.csk-category-select {\n flex: 1;\n padding: 6px 28px 6px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n color: #374151;\n background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 9px center;\n appearance: none;\n -webkit-appearance: none;\n outline: none;\n cursor: pointer;\n font-family: inherit;\n transition: border-color 0.2s, box-shadow 0.2s;\n max-width: 220px;\n}\n.csk-category-select:focus {\n border-color: var(--csk-primary);\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n\n/* ========== P1: RAG 引用来源卡片 ========== */\n.csk-sources {\n margin-top: 8px;\n border: 1px solid var(--csk-border);\n border-radius: 12px;\n overflow: hidden;\n font-size: 12px;\n max-width: 100%;\n background: #FAFBFC;\n}\n.csk-sources__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: #F3F4F7;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s;\n}\n.csk-sources__header:hover { background: #ECEEF2; }\n.csk-sources__title {\n display: flex;\n align-items: center;\n gap: 5px;\n font-weight: 500;\n color: #374151;\n}\n.csk-sources__arrow {\n transition: transform 0.2s;\n color: #9CA3AF;\n font-size: 10px;\n}\n.csk-sources--collapsed .csk-sources__arrow { transform: rotate(-90deg); }\n.csk-sources__body {\n border-top: 1px solid var(--csk-border);\n padding: 0;\n}\n.csk-sources--collapsed .csk-sources__body { display: none; }\n.csk-source-item {\n padding: 9px 12px;\n border-bottom: 1px solid #F0F1F4;\n transition: background 0.15s;\n}\n.csk-source-item:last-child { border-bottom: none; }\n.csk-source-item:hover { background: #fff; }\n.csk-source-item__name {\n font-weight: 500;\n color: #1F2937;\n margin-bottom: 3px;\n}\n.csk-source-item__snippet {\n color: #6B7280;\n line-height: 1.5;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n.csk-source-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 4px;\n}\n\n/* ========== P1: Markdown 渲染样式 ========== */\n.csk-msg--ai .csk-msg__bubble .csk-md-p { margin: 0 0 8px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-p:last-child { margin-bottom: 0; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h1,\n.csk-msg--ai .csk-msg__bubble .csk-md-h2,\n.csk-msg--ai .csk-msg__bubble .csk-md-h3,\n.csk-msg--ai .csk-msg__bubble .csk-md-h4,\n.csk-msg--ai .csk-msg__bubble .csk-md-h5,\n.csk-msg--ai .csk-msg__bubble .csk-md-h6 {\n margin: 14px 0 6px;\n font-weight: 600;\n line-height: 1.3;\n color: #111827;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-h1 { font-size: 20px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h2 { font-size: 17px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h3 { font-size: 15px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h4 { font-size: 14px; }\n\n.csk-md-code-block {\n background: #1E293B;\n color: #E2E8F0;\n padding: 12px 14px;\n border-radius: 10px;\n overflow-x: auto;\n margin: 8px 0;\n font-size: 13px;\n line-height: 1.55;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-md-code-block code {\n background: none;\n padding: 0;\n border-radius: 0;\n font-size: inherit;\n color: inherit;\n}\n.csk-md-inline-code {\n background: rgba(var(--csk-primary-rgb), 0.1);\n color: var(--csk-primary);\n padding: 1px 6px;\n border-radius: 5px;\n font-size: 13px;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol {\n padding-left: 22px;\n margin: 6px 0;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul li,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol li { margin-bottom: 4px; }\n.csk-md-blockquote {\n border-left: 3px solid var(--csk-primary);\n padding: 2px 12px;\n margin: 8px 0;\n color: #6B7280;\n background: rgba(var(--csk-primary-rgb), 0.05);\n border-radius: 0 6px 6px 0;\n}\n.csk-md-link {\n color: var(--csk-primary);\n text-decoration: none;\n border-bottom: 1px solid rgba(var(--csk-primary-rgb), 0.3);\n transition: border-color 0.15s;\n}\n.csk-md-link:hover { border-bottom-color: var(--csk-primary); }\n.csk-md-hr {\n border: none;\n border-top: 1px solid var(--csk-border);\n margin: 12px 0;\n}\n\n/* ========== P2: 会话管理面板 ========== */\n.csk-history-panel {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: #fff;\n z-index: 10;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: csk-slide-in 0.24s ease;\n}\n.csk-history-panel--hidden { display: none; }\n@keyframes csk-slide-in {\n from { transform: translateX(100%); opacity: 0.4; }\n to { transform: translateX(0); opacity: 1; }\n}\n.csk-history-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--csk-border);\n background: var(--csk-bg-app);\n flex-shrink: 0;\n}\n.csk-history-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n}\n.csk-history-panel__back {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n background: #fff;\n color: #374151;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-history-panel__back:hover { background: #F3F4F6; }\n.csk-history-panel__list {\n flex: 1;\n overflow-y: auto;\n padding: 10px;\n}\n.csk-history-panel__list::-webkit-scrollbar { width: 5px; }\n.csk-history-panel__list::-webkit-scrollbar-thumb { background: #E5E7EB; border-radius: 2px; }\n.csk-history-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 11px 12px;\n border-radius: 10px;\n cursor: pointer;\n transition: background 0.15s;\n margin-bottom: 5px;\n border: 1px solid transparent;\n}\n.csk-history-item:hover { background: #F3F4F6; }\n.csk-history-item--active {\n background: rgba(var(--csk-primary-rgb), 0.08);\n border-color: rgba(var(--csk-primary-rgb), 0.2);\n}\n.csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.12); }\n.csk-history-item__info { flex: 1; min-width: 0; }\n.csk-history-item__id {\n font-size: 13px;\n font-weight: 500;\n color: #1F2937;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.csk-history-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 3px;\n}\n.csk-history-item__actions {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.csk-history-item:hover .csk-history-item__actions { opacity: 1; }\n.csk-history-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 7px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.15s;\n}\n.csk-history-action--export { background: #EFF6FF; color: #2563EB; }\n.csk-history-action--export:hover { background: #DBEAFE; }\n.csk-history-action--delete { background: #FEF2F2; color: #DC2626; }\n.csk-history-action--delete:hover { background: #FEE2E2; }\n.csk-history-panel__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 20px;\n color: #9CA3AF;\n font-size: 13px;\n text-align: center;\n}\n.csk-history-panel__empty-icon {\n font-size: 34px;\n margin-bottom: 10px;\n opacity: 0.5;\n}\n.csk-history-panel__loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n color: #9CA3AF;\n font-size: 13px;\n}\n.csk-history-panel__loadmore {\n display: block;\n width: 100%;\n padding: 10px;\n border: none;\n background: #F9FAFB;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n text-align: center;\n transition: background 0.15s;\n}\n.csk-history-panel__loadmore:hover { background: #F3F4F6; }\n\n/* ========== 快捷问题芯片 ========== */\n.csk-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n margin-top: 18px;\n max-width: 320px;\n}\n.csk-quick-reply {\n border: 1px solid var(--csk-border);\n background: #fff;\n color: #374151;\n font-size: 12.5px;\n padding: 7px 13px;\n border-radius: 999px;\n cursor: pointer;\n font-family: inherit;\n line-height: 1.3;\n transition: all 0.18s ease;\n max-width: 100%;\n}\n.csk-quick-reply:hover {\n border-color: var(--csk-primary);\n color: var(--csk-primary);\n background: rgba(var(--csk-primary-rgb), 0.06);\n transform: translateY(-1px);\n}\n.csk-quick-reply:active { transform: scale(0.96); }\n\n/* ========== AI 消息操作条 ========== */\n.csk-msg__actions {\n display: flex;\n gap: 2px;\n margin-top: 5px;\n padding: 0 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n.csk-msg--ai:hover .csk-msg__actions { opacity: 1; }\n.csk-msg--streaming .csk-msg__actions { display: none; }\n.csk-action-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.csk-action-btn:hover {\n background: #F3F4F6;\n color: #374151;\n}\n.csk-action-btn--done { color: #10B981; }\n.csk-action-btn:active { transform: scale(0.9); }\n\n/* ========== 流式打字光标 ========== */\n.csk-caret {\n display: inline-block;\n width: 7px;\n height: 15px;\n margin-left: 2px;\n vertical-align: text-bottom;\n background: var(--csk-primary);\n border-radius: 1px;\n animation: csk-caret-blink 1s step-end infinite;\n}\n@keyframes csk-caret-blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n/* ========== 代码块复制按钮 ========== */\n.csk-md-code-block { position: relative; }\n.csk-md-code-copy {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(255, 255, 255, 0.12);\n color: #CBD5E1;\n border-radius: 6px;\n cursor: pointer;\n opacity: 0;\n transition: all 0.15s ease;\n}\n.csk-md-code-block:hover .csk-md-code-copy { opacity: 1; }\n.csk-md-code-copy:hover { background: rgba(255, 255, 255, 0.22); color: #fff; }\n.csk-md-code-copy:active { transform: scale(0.9); }\n\n/* ========== 新消息提示按钮 ========== */\n.csk-newmsg {\n position: absolute;\n bottom: 82px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 5;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 7px 14px;\n border: none;\n background: var(--csk-primary);\n color: #fff;\n font-size: 12px;\n font-family: inherit;\n border-radius: 999px;\n cursor: pointer;\n box-shadow: 0 4px 14px rgba(var(--csk-primary-rgb), 0.38);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: csk-msg-in 0.25s ease;\n white-space: nowrap;\n}\n.csk-newmsg:hover { transform: translateX(-50%) translateY(-1px); box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.48); }\n.csk-newmsg:active { transform: translateX(-50%) scale(0.95); }\n.csk-newmsg--hidden { display: none; }\n\n/* ========== 发送按钮停止态 ========== */\n.csk-send-btn--stop {\n background: #EF4444 !important;\n box-shadow: 0 3px 10px rgba(239, 68, 68, 0.35) !important;\n}\n.csk-send-btn--stop:hover:not(:disabled) {\n box-shadow: 0 5px 14px rgba(239, 68, 68, 0.45) !important;\n}\n\n/* ========== 暗色模式 ========== */\n.csk-root.csk-dark {\n --csk-bg-ai: #1E1E2E;\n --csk-text-ai: #E2E8F0;\n --csk-border: #3B3B52;\n --csk-bg-app: #141421;\n color: #E2E8F0;\n}\n.csk-dark .csk-window {\n background: #1A1A2E;\n box-shadow: 0 12px 48px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.2);\n}\n.csk-dark .csk-header::after { background: linear-gradient(to bottom, rgba(0,0,0,0.12), transparent); }\n.csk-dark .csk-msg__avatar--ai {\n background: var(--csk-bg-ai);\n color: var(--csk-primary);\n border-color: var(--csk-border);\n}\n.csk-dark .csk-input-area { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-input-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-input-wrap--focus { background: #1A1A2E; border-color: var(--csk-primary); }\n.csk-dark .csk-input { color: #E2E8F0; }\n.csk-dark .csk-loading__avatar { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__bubble { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__dot { background: #6B7280; }\n.csk-dark .csk-category-bar { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-category-select { background-color: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-sources { background: #1E1E2E; border-color: var(--csk-border); }\n.csk-dark .csk-sources__header { background: #25253A; }\n.csk-dark .csk-sources__header:hover { background: #2D2D48; }\n.csk-dark .csk-source-item:hover { background: var(--csk-bg-ai); }\n.csk-dark .csk-source-item__name { color: #E2E8F0; }\n.csk-dark .csk-source-item__meta { color: #6B7280; }\n.csk-dark .csk-history-panel { background: #1A1A2E; }\n.csk-dark .csk-history-panel__header { background: var(--csk-bg-app); border-bottom-color: var(--csk-border); }\n.csk-dark .csk-history-panel__back { background: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-history-panel__back:hover { background: #2D2D48; }\n.csk-dark .csk-history-item:hover { background: #25253A; }\n.csk-dark .csk-history-item__id { color: #E2E8F0; }\n.csk-dark .csk-history-item__meta { color: #6B7280; }\n.csk-dark .csk-history-item--active { background: rgba(var(--csk-primary-rgb), 0.15); }\n.csk-dark .csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.22); }\n.csk-dark .csk-action-btn:hover { background: #2D2D48; color: #E2E8F0; }\n.csk-dark .csk-clear-btn { background: var(--csk-bg-app); border-color: var(--csk-border); color: #9CA3AF; }\n.csk-dark .csk-clear-btn:hover { background: #3B1A1A; border-color: #7F1D1D; color: #FCA5A5; }\n.csk-dark .csk-md-code-block { background: #0F0F1A; }\n.csk-dark .csk-md-blockquote { background: rgba(var(--csk-primary-rgb), 0.08); }\n.csk-dark .csk-md-link { color: var(--csk-primary-light); }\n.csk-dark .csk-msg--ai .csk-msg__bubble { background: var(--csk-bg-ai); color: var(--csk-text-ai); border-color: var(--csk-border); }\n.csk-dark .csk-welcome__title { color: #E2E8F0; }\n.csk-dark .csk-welcome__desc { color: #6B7280; }\n.csk-dark .csk-quick-reply { background: var(--csk-bg-app); border-color: var(--csk-border); color: #CBD5E1; }\n.csk-dark .csk-quick-reply:hover { background: rgba(var(--csk-primary-rgb), 0.12); border-color: var(--csk-primary); color: var(--csk-primary-light); }\n.csk-dark .csk-teaser { background: #2D2D48; color: #E2E8F0; box-shadow: 0 4px 20px rgba(0,0,0,0.35); }\n.csk-dark .csk-teaser::after { border-top-color: #2D2D48; }\n.csk-dark .csk-teaser__close { color: #6B7280; }\n.csk-dark .csk-teaser__close:hover { color: #9CA3AF; }\n.csk-dark .csk-feedback-btn { background: rgba(var(--csk-primary-rgb), 0.1); color: #9CA3AF; }\n.csk-dark .csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.2); color: var(--csk-primary-light); }\n.csk-dark .csk-feedback-btn--active { background: rgba(var(--csk-primary-rgb), 0.28); color: var(--csk-primary-light); }\n.csk-dark .csk-history-panel__search-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-history-panel__search-wrap:focus-within { border-color: var(--csk-primary); }\n.csk-dark .csk-history-panel__search { color: #E2E8F0; }\n.csk-dark .csk-launcher__badge { box-shadow: 0 0 0 2px #1A1A2E; }\n.csk-dark .csk-welcome__avatar { box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.25); }\n.csk-dark .csk-header__avatar { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.1); }\n\n/* ========== Launcher 未读徽章 ========== */\n.csk-launcher__badge {\n position: absolute;\n top: -2px;\n right: -2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #EF4444;\n border: 2px solid #fff;\n box-shadow: 0 0 0 2px #fff;\n animation: csk-badge-in 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);\n pointer-events: none;\n}\n.csk-launcher__badge--hidden { display: none; }\n@keyframes csk-badge-in {\n from { transform: scale(0); }\n to { transform: scale(1); }\n}\n\n/* ========== Launcher 提示气泡 ========== */\n.csk-teaser {\n position: fixed;\n bottom: 90px;\n z-index: 9997;\n max-width: 240px;\n padding: 10px 14px;\n background: #fff;\n color: #1F2937;\n font-size: 13px;\n line-height: 1.5;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(15, 23, 42, 0.15);\n animation: csk-teaser-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);\n cursor: pointer;\n user-select: none;\n}\n.csk-teaser--right { right: 24px; }\n.csk-teaser--left { left: 24px; }\n.csk-teaser::after {\n content: '';\n position: absolute;\n bottom: -6px;\n right: 28px;\n width: 12px;\n height: 12px;\n background: inherit;\n border-radius: 2px;\n transform: rotate(45deg);\n box-shadow: 2px 2px 4px rgba(15, 23, 42, 0.08);\n}\n.csk-teaser--left::after { right: auto; left: 28px; }\n.csk-teaser__close {\n position: absolute;\n top: 4px;\n right: 6px;\n background: none;\n border: none;\n font-size: 16px;\n color: #9CA3AF;\n cursor: pointer;\n padding: 2px 4px;\n line-height: 1;\n border-radius: 4px;\n}\n.csk-teaser__close:hover { color: #374151; }\n.csk-teaser--hidden { display: none; }\n@keyframes csk-teaser-in {\n from { opacity: 0; transform: translateY(8px) scale(0.95); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n/* ========== 消息反馈按钮(👍 / 👎) ========== */\n.csk-feedback-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(var(--csk-primary-rgb), 0.08);\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n padding: 0;\n}\n.csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.18); color: var(--csk-primary); }\n.csk-feedback-btn--active {\n background: rgba(var(--csk-primary-rgb), 0.28);\n color: var(--csk-primary);\n}\n.csk-feedback-btn--active.down { background: #FEF2F2; color: #EF4444; }\n.csk-feedback-btn:active { transform: scale(0.9); }\n.csk-msg--streaming .csk-feedback-btn { display: none; }\n\n/* ========== 历史会话搜索框 ========== */\n.csk-history-panel__search-wrap {\n padding: 8px 10px;\n border-bottom: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-history-panel__search-wrap:focus-within {\n border-bottom-color: var(--csk-primary);\n}\n.csk-history-panel__search {\n width: 100%;\n padding: 7px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n font-family: inherit;\n color: #1F2937;\n background: var(--csk-bg-app);\n outline: none;\n transition: border-color 0.2s;\n}\n.csk-history-panel__search:focus { border-color: var(--csk-primary); }\n.csk-history-panel__search::placeholder { color: #9CA3AF; }\n\n/* ========== a11y 焦点指示 ========== */\n.csk-root :focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n}\n.csk-root button:focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n border-radius: inherit;\n}\n/* 弹窗打开时隐藏 launcher 上的焦点环 */\n.csk-launcher:focus-visible {\n outline: none;\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12),\n 0 0 0 4px rgba(var(--csk-primary-rgb), 0.3);\n}\n\n/* ========== a11y aria-live 播报区(视觉隐藏) ========== */\n.csk-sr-only {\n position: absolute !important;\n width: 1px !important;\n height: 1px !important;\n padding: 0 !important;\n margin: -1px !important;\n overflow: hidden !important;\n clip: rect(0,0,0,0) !important;\n white-space: nowrap !important;\n border: 0 !important;\n}\n\n/* ========== 会话分组标题 ========== */\n.csk-history-group {\n margin-bottom: 4px;\n}\n.csk-history-group__label {\n font-size: 11px;\n font-weight: 600;\n color: #9CA3AF;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: 8px 12px 4px;\n user-select: none;\n}\n.csk-dark .csk-history-group__label { color: #6B7280; }\n\n/* ========== 移动端适配 ========== */\n@media (max-width: 480px) {\n .csk-window {\n width: 100vw !important;\n height: 100vh !important;\n max-height: 100vh;\n bottom: 0 !important;\n right: 0 !important;\n left: 0 !important;\n border-radius: 0;\n }\n .csk-window--hidden { transform: translateY(100%); }\n .csk-launcher { bottom: 20px; }\n .csk-launcher--right { right: 20px; }\n .csk-launcher--left { left: 20px; }\n}\n`}(e),document.head.appendChild(T))}function z(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const n=16*Math.random()|0;return("x"===e?n:3&n|8).toString(16)})}function H(e){const n={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,e=>n[e]||e)}function j(){return Date.now()}const R='';function P(e,n){const t=document.createElement("div");t.id="csk-launcher";const r=e.launcherTheme?" csk-launcher--glass":"";t.className=`csk-launcher csk-launcher--${"left-bottom"===e.position?"left":"right"}${r}`,t.setAttribute("title",e.title),t.setAttribute("aria-label",e.title),t.setAttribute("role","button"),t.setAttribute("tabindex","0"),t.innerHTML=e.launcherIcon;const s=document.createElement("div");s.className="csk-launcher__badge csk-launcher__badge--hidden",t.appendChild(s);const o=function(e,n){let t=null;return function(...r){null!==t&&clearTimeout(t),t=setTimeout(()=>{e.apply(this,r),t=null},n)}}(n,300);return t.addEventListener("click",o),t.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),o())}),t}function U(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--user";const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--user",s.innerHTML='';const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.textContent=n;const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(t),o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),r}function O(e,n,t,r,s){const o=document.createElement("div");o.className="csk-msg csk-msg--ai",s&&(o.dataset.cskMsgId=s);const a=document.createElement("div");a.className="csk-msg__avatar csk-msg__avatar--ai",a.innerHTML=R;const i=document.createElement("div");i.className="csk-msg__content";const c=document.createElement("div");c.className="csk-msg__bubble",r?c.innerHTML=r(n):c.textContent=n;const l=document.createElement("div");return l.className="csk-msg__time",l.textContent=ne(t),i.appendChild(c),i.appendChild(G(c,o)),i.appendChild(l),o.appendChild(a),o.appendChild(i),e.appendChild(o),X(c),o}const Y='',W='';function G(e,n){const t=document.createElement("div");t.className="csk-msg__actions";const r=document.createElement("button");r.type="button",r.className="csk-action-btn",r.setAttribute("title",m("copy")),r.setAttribute("aria-label",m("copy")),r.innerHTML=Y,r.addEventListener("click",async n=>{n.stopPropagation();const t=e.textContent||"";await K(t,r)});const s=document.createElement("button");s.type="button",s.className="csk-action-btn",s.setAttribute("title",m("retry")),s.setAttribute("aria-label",m("retry")),s.innerHTML=W,s.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:retry",{detail:{msgId:n.dataset.cskMsgId||""}}))});const o=document.createElement("button");o.type="button",o.className="csk-feedback-btn",o.setAttribute("title",m("feedback_up")),o.setAttribute("aria-label",m("feedback_up")),o.innerHTML='',o.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"up"}}))});const a=document.createElement("button");return a.type="button",a.className="csk-feedback-btn",a.setAttribute("title",m("feedback_down")),a.setAttribute("aria-label",m("feedback_down")),a.innerHTML='',a.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"down"}}))}),t.appendChild(r),t.appendChild(s),t.appendChild(o),t.appendChild(a),t}function V(e,n){const t=e.querySelectorAll(".csk-feedback-btn");t.length<2||(t.forEach(e=>e.classList.remove("csk-feedback-btn--active","down")),"up"===n&&t[0]&&t[0].classList.add("csk-feedback-btn--active"),"down"===n&&t[1]&&t[1].classList.add("csk-feedback-btn--active","down"))}async function K(e,n){const t=n.innerHTML;try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(e);else{const n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}n.innerHTML='',n.classList.add("csk-action-btn--done"),setTimeout(()=>{n.innerHTML=t,n.classList.remove("csk-action-btn--done")},1500)}catch(e){}}function X(e){e.querySelectorAll(".csk-md-code-block").forEach(e=>{if(e.querySelector(".csk-md-code-copy"))return;const n=e.querySelector("code"),t=document.createElement("button");t.type="button",t.className="csk-md-code-copy",t.setAttribute("title",m("copy")),t.setAttribute("aria-label",m("copy")),t.innerHTML=Y,t.addEventListener("click",async e=>{e.stopPropagation(),await K((null==n?void 0:n.textContent)||"",t)}),e.appendChild(t)})}function J(e,n){e.classList.remove("csk-msg--streaming");const t=n.querySelector(".csk-caret");t&&t.remove(),X(n)}function Q(e,n){const t=e.querySelector(".csk-sources");if(t&&t.remove(),!n||0===n.length)return;const r=document.createElement("div");r.className="csk-sources csk-sources--collapsed";const s=document.createElement("div");s.className="csk-sources__header";const o=document.createElement("span");o.className="csk-sources__title",o.textContent=`📚 ${m("source_count",{n:n.length})}`;const a=document.createElement("span");a.className="csk-sources__arrow",a.textContent="▼",s.appendChild(o),s.appendChild(a),s.addEventListener("click",()=>{r.classList.toggle("csk-sources--collapsed")});const i=document.createElement("div");i.className="csk-sources__body";for(const e of n){const n=document.createElement("div");n.className="csk-source-item";const t=document.createElement("div");if(t.className="csk-source-item__name",t.textContent=e.title||e.sourceName||"未知文档",e.snippet){const t=document.createElement("div");t.className="csk-source-item__snippet",t.textContent=e.snippet,n.appendChild(t)}const r=document.createElement("div");r.className="csk-source-item__meta";const s=[];e.sourceName&&s.push(e.sourceName),void 0!==e.chunkIndex&&s.push(`分块 #${e.chunkIndex}`),void 0!==e.score&&s.push(`相关度 ${(100*e.score).toFixed(0)}%`),r.textContent=s.join(" · "),n.appendChild(t),n.appendChild(r),i.appendChild(n)}r.appendChild(s),r.appendChild(i);const c=e.querySelector(".csk-msg__time");c&&c.parentNode?c.parentNode.insertBefore(r,c):e.appendChild(r)}function Z(e,n,t,r,s,o,a){if(e.innerHTML="",0===n.length){const n=document.createElement("div");return n.className="csk-history-panel__empty",n.innerHTML=`\n
💬
\n
${m("history_empty")}
\n `,void e.appendChild(n)}const i=function(e){const n=new Date,t=new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime(),r=t-864e5,s=t-864e5*(n.getDay()||7)+864e5,o={today:[],yesterday:[],week:[],earlier:[]};for(const n of e){const e=n.lastMessageTime||n.createdAt,a=e?new Date(e).getTime():0;a>=t?o.today.push(n):a>=r?o.yesterday.push(n):a>=s?o.week.push(n):o.earlier.push(n)}const a=[];return o.today.length&&a.push({label:m("history_group_today"),items:o.today}),o.yesterday.length&&a.push({label:m("history_group_yesterday"),items:o.yesterday}),o.week.length&&a.push({label:m("history_group_week"),items:o.week}),o.earlier.length&&a.push({label:m("history_group_earlier"),items:o.earlier}),a}(n);for(const n of i){if(i.length>1){const t=document.createElement("div");t.className="csk-history-group";const r=document.createElement("div");r.className="csk-history-group__label",r.textContent=n.label,t.appendChild(r),e.appendChild(t)}for(const a of n.items){const n=document.createElement("div");n.className="csk-history-item";const i=a.chatId||a.id;o&&i===o&&n.classList.add("csk-history-item--active");const c=document.createElement("div");c.className="csk-history-item__info";const l=document.createElement("div");l.className="csk-history-item__id",a.lastMessagePreview?l.textContent=a.lastMessagePreview.length>60?a.lastMessagePreview.substring(0,60)+"...":a.lastMessagePreview:l.textContent=i;const d=document.createElement("div");d.className="csk-history-item__meta";const p=[];void 0!==a.messageCount&&p.push(`${a.messageCount} 条消息`),a.lastMessageTime?p.push(a.lastMessageTime):a.createdAt&&p.push(a.createdAt),d.textContent=p.join(" · "),c.appendChild(l),c.appendChild(d);const u=document.createElement("div");u.className="csk-history-item__actions";const g=document.createElement("button");g.className="csk-history-action csk-history-action--export",g.setAttribute("title",m("history_export")),g.innerHTML='',g.addEventListener("click",e=>{e.stopPropagation(),r(a.id)});const k=document.createElement("button");k.className="csk-history-action csk-history-action--delete",k.setAttribute("title",m("history_delete")),k.innerHTML='',k.addEventListener("click",e=>{e.stopPropagation(),s(a.id)}),u.appendChild(g),u.appendChild(k),n.appendChild(c),n.appendChild(u),n.addEventListener("click",()=>{t(i)}),e.appendChild(n)}}}function ee(e){e.scrollTop=e.scrollHeight}function ne(e){const n=new Date(e);return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}function te(e){return`csk_history_${e}`}function re(e,n){try{let t=n;t.length>200&&(t=t.slice(50),o.warn(`消息数量达到上限,已裁剪最早 50 条,当前 ${t.length} 条`));const r={messages:t,updatedAt:Date.now()};localStorage.setItem(te(e),JSON.stringify(r))}catch(e){e instanceof Error&&"QuotaExceededError"===e.name?o.error("localStorage 空间不足,会话历史保存失败。建议清空历史记录。"):o.error("保存会话历史失败",e)}}function se(e){try{localStorage.removeItem(te(e))}catch(e){o.warn("清空会话历史失败",e)}}const oe="\0CODEBLOCK_",ae="\0INLINECODE_";function ie(e){if(!e||"string"!=typeof e)return"";const n=[];let t=e;t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(e,t,r)=>{const s=n.length,o=H(r.trimEnd()),a=t?` class="language-${H(t)}"`:"";return n.push(`
${o}
`),`${oe}${s}\0`});const r=[];t=t.replace(/`([^`\n]+)`/g,(e,n)=>{const t=r.length;return r.push(`${H(n)}`),`${ae}${t}\0`}),t=H(t),t=ce(t,oe,n),t=ce(t,ae,r);const s=t.split("\n"),o=[];let a=!1,i="",c=!1,l=[];for(let e=0;e')){p(),u(),g(),o.push(n);continue}const t=n.match(/^(#{1,6})\s+(.+)/);if(t){p(),u(),g();const e=t[1].length;o.push(`${t[2]}`);continue}const r=n.match(/^>\s?(.*)/);if(r){p(),u(),c||(c=!0,o.push('
')),o.push(`

${d(r[1])}

`);continue}c&&g();const k=n.match(/^[\-\*]\s+(.+)/);if(k){p(),g(),a&&"ul"===i||(u(),a=!0,i="ul",o.push('
    ')),o.push(`
  • ${d(k[1])}
  • `);continue}const m=n.match(/^\d+\.\s+(.+)/);m?(p(),g(),a&&"ol"===i||(u(),a=!0,i="ol",o.push('
      ')),o.push(`
    1. ${d(m[1])}
    2. `)):""!==n.trim()?/^(\*{3,}|-{3,}|_{3,})$/.test(n.trim())?(p(),u(),g(),o.push('
      ')):(u(),g(),l.push(d(n))):(p(),u())}return p(),u(),g(),o.join("\n");function d(e){return e=(e=(e=(e=(e=(e=e.replace(/\*\*(.+?)\*\*/g,"$1")).replace(/__(.+?)__/g,"$1")).replace(/\*(.+?)\*/g,"$1")).replace(/(?$1")).replace(/~~(.+?)~~/g,"$1")).replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,n,t)=>`${n}`)}function p(){l.length>0&&(o.push(`

      ${l.join("
      ")}

      `),l=[])}function u(){a&&(o.push("ul"===i?"
":""),a=!1,i="")}function g(){c&&(o.push("
"),c=!1)}}function ce(e,n,t){return e.replace(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"(\\d+)\0","g"),(e,n)=>t[parseInt(n)]||"")}let le,de=null,pe=[],ue=null,ge=null,ke=null,me=null,he=null,be=null,fe=null,ye=null,xe=null,ve=null,we=null,_e=null,Ee=null,Ce=!1,Ie=null,$e=!0,Ae=[],Le="",Se=!1;function Fe(e,n){de=e,ue=n.messagesContainer,ge=n.inputEl,ke=n.inputEl.parentElement,me=n.sendBtn,he=n.clearBtn,be=n.categorySelect,fe=n.historyPanel,ye=n.welcomeEl,xe=n.newMsgBtn,ve=n.searchInput,we=n.ariaLiveEl,_e=n.showLoading,Ee=n.hideLoading,le=e.categoryId,Se=!!e.enableRag||!!e.categoryId||!!e.showCategorySwitch,function(){if(!ge||!me)return;me.addEventListener("click",()=>{Ce&&Ie?Ie.abort():je()}),ge.addEventListener("keydown",e=>{"Enter"!==e.key||e.shiftKey||e.isComposing||(e.preventDefault(),je())}),ge.addEventListener("input",()=>{He(),function(){if(!ge)return;ge.style.height="auto",ge.style.height=`${Math.min(ge.scrollHeight,120)}px`}()}),ge.addEventListener("focus",()=>{ke&&ke.classList.add("csk-input-wrap--focus")}),ge.addEventListener("blur",()=>{ke&&ke.classList.remove("csk-input-wrap--focus")}),he&&he.addEventListener("click",()=>function(){if(!de)return;if(!confirm(m("clear_confirm")))return;if(pe=[],ue){ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove())}he&&(he.style.display="none");ze(),se(de.integrateId);const e=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();b(e),M(de.integrateId,de.userId,e),o.lifecycleClear(de.integrateId),o.info(`新 chatId=${e}`)}())}(),function(){if(!ue)return;ue.addEventListener("scroll",()=>{if(!ue)return;const{scrollTop:e,scrollHeight:n,clientHeight:t}=ue;$e=n-e-t<80,$e&&Me()}),xe&&xe.addEventListener("click",()=>{ue&&ee(ue),$e=!0,Me()})}(),function(){if(!ve)return;ve.addEventListener("input",()=>{Le=ve.value.trim().toLowerCase(),Be()})}(),e.showCategorySwitch&&be&&async function(){if(!be)return;try{const e=await async function(){const e=y("/category/tree");try{const n=await v(e);if(!n.ok)throw new w(_(n.status),`http_${n.status}`);const t=await n.json();return t.success&&Array.isArray(t.data)?(o.info(`加载分类树成功 count=${t.data.length}`),t.data):[]}catch(e){return e instanceof w?o.error(`加载分类树失败: ${e.message}`):o.error("加载分类树失败",e),[]}}();if(0===e.length)return;be.innerHTML=``;const n=(e,t=0)=>{for(const r of e){const e=document.createElement("option");e.value=String(r.id),e.textContent=`${" ".repeat(t)}${r.name}`,void 0!==le&&String(r.id)===String(le)&&(e.selected=!0),be.appendChild(e),r.children&&r.children.length>0&&n(r.children,t+1)}};n(e),o.info(`知识库分类加载成功 count=${e.length}`)}catch(e){o.error(m("category_load_error"),e)}}()}async function Ne(){if(de&&ue&&(await F(),await async function(){if(!de||!ue)return;const e=f();if(!e)return;try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map((e,n)=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`从后端加载 ${pe.length} 条历史消息`),re(de.integrateId,pe))}catch(e){o.warn("从后端加载历史消息失败",e)}}(),0===pe.length)){const e=function(e){try{const n=localStorage.getItem(te(e));if(!n)return[];const t=JSON.parse(n);return t&&Array.isArray(t.messages)?(o.info(`加载历史消息 integrateId=${e} count=${t.messages.length}`),t.messages):[]}catch(e){return o.warn("加载会话历史失败",e),[]}}(de.integrateId);e.length>0&&(pe=e,Pe(),o.info(`从本地缓存恢复 ${e.length} 条消息`))}}function Me(){xe&&xe.classList.add("csk-newmsg--hidden")}function Te(){ue&&($e?ee(ue):xe&&xe.classList.remove("csk-newmsg--hidden"))}function De(e){me&&("stop"===e?(me.classList.add("csk-send-btn--stop"),me.removeAttribute("disabled"),me.setAttribute("title",m("stop")),me.setAttribute("aria-label",m("stop")),me.innerHTML=''):(me.classList.remove("csk-send-btn--stop"),me.setAttribute("title",m("send")),me.setAttribute("aria-label",m("send")),me.innerHTML='',He()))}function Be(){const e=null==fe?void 0:fe.querySelector("#csk-history-list");if(!e||!de)return;Z(e,Le?Ae.filter(e=>(e.lastMessagePreview||e.chatId||e.id||"").toLowerCase().includes(Le)):Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{if(!confirm(m("history_delete_confirm")))return;await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}function qe(e,n){if(!ue)return;const t=pe.find(n=>n.id===e&&"ai"===n.role);if(!t)return;const r=t.feedback===n?void 0:n;t.feedback=r;const s=ue.querySelector(`[data-csk-msg-id="${e}"]`);if(s&&V(s,r),de&&re(de.integrateId,pe),r){const n="up"===r?"THUMBS_UP":"THUMBS_DOWN";(async function(e,n){if(!h)return!1;const t=y("/feedback");try{const r=await v(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messageId:String(e),conversationId:h.chatId,feedbackType:n})});return r.ok?(await r.json()).success||!1:(o.error(`反馈提交失败 status=${r.status}`),!1)}catch(e){return o.error("反馈提交异常",e),!1}})(String(e),n).then(n=>{n?o.info(`消息反馈已提交 msgId=${e} value=${r}`):o.warn(`消息反馈提交失败 msgId=${e}(本地状态已更新)`)})}else o.info(`消息反馈已取消 msgId=${e}`)}function ze(){if(!ye)return;const e=pe.length>0||ue&&ue.querySelector(".csk-msg");ye.style.display=e?"none":""}function He(){if(!me||!ge)return;ge.value.trim().length>0&&!Ce?me.removeAttribute("disabled"):me.setAttribute("disabled","true")}async function je(){if(!ge||!de||Ce)return;const e=ge.value.trim();if(""===e)return;ge.value="",He(),ge.style.height="auto";const n=j(),t={id:z(),role:"user",content:e,timestamp:n};ue&&U(ue,e,n),pe.push(t),ze(),he&&pe.length>0&&(he.style.display="inline-flex"),ue&&Te(),await Re(e)}async function Re(e){if(!de||!ue)return;Ce=!0,De("stop"),de.chatId||await F();const n=j(),t=Se&&(de.enableRag||void 0!==le||void 0!==de.categoryId);_e&&_e(),ue&&Te();const r=z();let s="";try{de.streaming?s=await async function(e,n,t,r){Ie=new AbortController;const s=Ie.signal;return new Promise((o,a)=>{let i=null,c=null,l="",d=!1;C(e,e=>{if(l+=e,!d&&ue){Ee&&Ee();const{wrapper:e,bubble:t}=function(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--ai csk-msg--streaming",t&&(r.dataset.cskMsgId=t);const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--ai",s.innerHTML=R;const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.innerHTML="";const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(n),o.appendChild(a),o.appendChild(G(a,r)),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),{wrapper:r,bubble:a}}(ue,n,r);c=e,i=t,d=!0}i&&(i.textContent=l,function(e){if(e.querySelector(".csk-caret"))return;const n=document.createElement("span");n.className="csk-caret",n.setAttribute("aria-hidden","true"),e.appendChild(n)}(i)),ue&&Te()},()=>{if(c&&i){if(!d&&""===l)return void E(e).then(o).catch(a);l&&(i.innerHTML=ie(l)),J(c,i)}o(l)},e=>{l.length>0?(i&&(i.innerHTML=ie(l+"\n\n"+m("stream_interrupted")),c&&J(c,i)),o(l)):a(e)},le,t,s)})}(e,n,t,r):(s=await E(e),Ee&&Ee(),ue&&O(ue,s,n,ie,r));const a={id:r,role:"ai",content:s,timestamp:n};pe.push(a),re(de.integrateId,pe),ue&&Te(),function(e){if(!we)return;const n=e.length>120?e.substring(0,120)+"...":e;we.textContent=m("new_msg_announce")+":"+n}(s),ue&&ue.dispatchEvent(new CustomEvent("csk:newMessage",{bubbles:!0,detail:{msg:a}})),t&&async function(e,n){try{const t=await I(e,le);if(t.length>0){const e=t.map(e=>{var n,t;return{documentId:e.documentId||"",title:e.title||"",sourceName:e.sourceName||"",chunkIndex:null!==(n=e.chunkIndex)&&void 0!==n?n:0,score:null!==(t=e.score)&&void 0!==t?t:0,snippet:e.snippet||""}});if(n.sources=e,ue){const n=ue.querySelector(".csk-msg--ai:last-of-type");n&&Q(n,e)}de&&re(de.integrateId,pe)}}catch(e){o.warn("获取引用来源失败",e)}}(e,a)}catch(e){Ee&&Ee();const n=e instanceof w?e.message:m("error_send");if(ue){const e=document.createElement("div");e.className="csk-msg csk-msg--ai";const t=document.createElement("div");t.className="csk-msg__bubble",t.style.color="#DC2626",t.textContent=`⚠ ${n}`,e.appendChild(t),ue.appendChild(e)}o.error(`发送失败 integrateId=${de.integrateId}`,e)}finally{Ce=!1,Ie=null,De("send"),He()}}function Pe(){if(!ue)return;const e=ue.querySelector(".csk-history-panel");ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());for(const e of pe)if("user"===e.role)U(ue,e.content,e.timestamp);else{const n=O(ue,e.content,e.timestamp,ie,e.id);e.sources&&e.sources.length>0&&Q(n,e.sources),e.feedback&&V(n,e.feedback)}$e=!0,ee(ue),he&&pe.length>0&&(he.style.display="inline-flex"),ze(),e&&!ue.contains(e)&&ue.appendChild(e)}async function Ue(e){if(!de||!ue)return;o.info(`切换到会话 conversationId=${e}`),b(e),M(de.integrateId,de.userId,e),fe&&fe.classList.add("csk-history-panel--hidden"),pe=[];ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map(e=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`加载会话 ${e} 的 ${pe.length} 条消息`),re(de.integrateId,pe))}catch(n){o.warn(`加载会话消息失败 conversationId=${e}`,n)}he&&pe.length>0&&(he.style.display="inline-flex"),ze()}let Oe=null,Ye=!1,We=null,Ge=null,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,tn=null,rn=null,sn=null,on=null,an=null;function cn(){if(!rn||!We)return;const e=We.getBoundingClientRect();"left-bottom"===(null==Oe?void 0:Oe.position)?rn.style.left=`${e.left}px`:rn.style.right=window.innerWidth-e.right+"px",rn.style.bottom=window.innerHeight-e.top+8+"px"}function ln(){if(!rn)return;rn.classList.add("csk-teaser--hidden"),rn.removeEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.removeEventListener("click",pn)}function dn(e){e.target.closest(".csk-teaser__close")||(ln(),mn())}function pn(e){e.stopPropagation(),ln()}function un(){rn&&!rn.classList.contains("csk-teaser--hidden")&&cn()}const gn='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';function kn(e){"Escape"===e.key&&Ge&&!Ge.classList.contains("csk-window--hidden")&&hn(),function(e){if(!Ge||Ge.classList.contains("csk-window--hidden"))return;if("Tab"!==e.key)return;const n=Array.from(Ge.querySelectorAll(gn));if(0===n.length)return;const t=n[0],r=n[n.length-1];e.shiftKey?document.activeElement===t&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),t.focus())}(e)}function mn(){Ge&&(Ge.classList.remove("csk-window--hidden"),ln(),on&&on.classList.add("csk-launcher__badge--hidden"),setTimeout(()=>{Ke&&Ke.focus()},80))}function hn(){Ge&&Ge.classList.add("csk-window--hidden")}function bn(){Ge&&(Ge.classList.contains("csk-window--hidden")?mn():hn())}function fn(e){return`csk_position_${e}`}const yn={init:function(e){if(Ye)return void o.warn("SDK 已初始化,请先调用 destroy() 再重新初始化");const t=function(e){var n,t,r,s,i,g,k,m,h,b,f;if(!e.integrateId||"string"!=typeof e.integrateId&&"number"!=typeof e.integrateId||"string"==typeof e.integrateId&&""===e.integrateId.trim())return o.error('integrateId 是必传参数(对应后端 roleId 客服角色 ID),请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;if(!e.requestDomain||"string"!=typeof e.requestDomain||""===e.requestDomain.trim())return o.error('requestDomain 是必传参数,请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;try{new URL(e.requestDomain)}catch(n){return o.error(`requestDomain 不是合法的 URL 格式:${e.requestDomain}。请提供完整的域名,如 https://api.example.com`),null}const y=String(e.integrateId).trim(),x=e.launcherTheme||void 0;let v=e.launcherIcon||a,w=e.primaryColor||"#4F46E5";x&&!e.launcherIcon&&(v={"dream-purple":c,"mint-tech":l,"coral-peach":d,"sky-blue":p}[x]||a,e.primaryColor||(w=u[x]||"#4F46E5"));const _={integrateId:y,requestDomain:e.requestDomain.replace(/\/+$/,""),userId:e.userId,categoryId:e.categoryId,showCategorySwitch:null!==(n=e.showCategorySwitch)&&void 0!==n&&n,title:e.title||"AI 智能助手",width:null!==(t=e.width)&&void 0!==t?t:380,height:Math.max(300,null!==(r=e.height)&&void 0!==r?r:520),position:"left-bottom"===e.position?"left-bottom":"right-bottom",primaryColor:w,launcherTheme:x,launcherIcon:v,showClear:null===(s=e.showClear)||void 0===s||s,showAdminPanel:null!==(i=e.showAdminPanel)&&void 0!==i&&i,quickReplies:Array.isArray(e.quickReplies)?e.quickReplies.map(e=>String(e).trim()).filter(Boolean):[],theme:"dark"===e.theme?"dark":"light",showTeaser:null===(g=e.showTeaser)||void 0===g||g,teaserText:"string"==typeof e.teaserText&&e.teaserText.trim()||"",streaming:null===(k=e.streaming)||void 0===k||k,enableRag:null!==(m=e.enableRag)&&void 0!==m&&m,rewriteStrategy:e.rewriteStrategy||"REWRITE",locale:e.locale||"zh-CN",debug:null===(h=e.debug)||void 0===h||h,sound:null!==(b=e.sound)&&void 0!==b&&b,notification:null!==(f=e.notification)&&void 0!==f&&f,onError:"function"==typeof e.onError?e.onError:void 0,onReady:"function"==typeof e.onReady?e.onReady:void 0,onMessage:"function"==typeof e.onMessage?e.onMessage:void 0,chatId:""};return o.info(`配置解析完成 integrateId(=roleId)=${_.integrateId} userId(=accountId)=${_.userId||"(未设置)"} requestDomain=${_.requestDomain}`),_}(e);if(!t)return;var s;Oe=t,function(e){if(g[e])k=e;else{const n=e.split("-")[0],t=Object.keys(g).find(e=>e.startsWith(n));t&&(k=t)}}(Oe.locale),s=Oe.debug,n=s,r(Oe.onError),function(e){h=e}(Oe),q(Oe),We=P(Oe,bn),document.body.appendChild(We),on=We.querySelector(".csk-launcher__badge");const i=function(e){const n=document.createElement("div");n.id="csk-window",n.className=`csk-root csk-window csk-window--${"left-bottom"===e.position?"left":"right"} csk-window--hidden${"dark"===e.theme?" csk-dark":""}`,n.setAttribute("role","dialog"),n.setAttribute("aria-label",e.title),n.setAttribute("aria-modal","false");const t=document.createElement("div");t.className="csk-header";const r=document.createElement("div");r.className="csk-header__left";const s=document.createElement("div");s.className="csk-header__avatar",s.innerHTML=R;const o=document.createElement("div");o.className="csk-header__info";const a=document.createElement("span");a.className="csk-header__title",a.textContent=e.title;const i=document.createElement("span");i.className="csk-header__status",i.innerHTML=`${m("status_online")}`,o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o);const c=document.createElement("div");c.className="csk-header__actions";const l=document.createElement("button");l.className="csk-history-btn",l.setAttribute("title",m("history_title")),l.innerHTML='';const d=document.createElement("button");d.className="csk-header__btn csk-header__btn--minimize",d.setAttribute("title",m("minimize")),d.innerHTML='',d.addEventListener("click",()=>{n.classList.add("csk-window--hidden")});const p=document.createElement("button");p.className="csk-header__btn csk-header__btn--close",p.setAttribute("title",m("close")),p.innerHTML='',p.addEventListener("click",()=>{n.classList.add("csk-window--hidden")}),c.appendChild(l),c.appendChild(d),c.appendChild(p),t.appendChild(r),t.appendChild(c);const u=document.createElement("div");u.id="csk-messages",u.className="csk-messages";const g=document.createElement("div");if(g.className="csk-welcome",g.innerHTML=`\n
${R}
\n
${m("welcome_title")}
\n
${m("welcome_desc")}
\n `,e.quickReplies.length>0){const t=document.createElement("div");t.className="csk-quick-replies";for(const r of e.quickReplies){const e=document.createElement("button");e.type="button",e.className="csk-quick-reply",e.textContent=r,e.addEventListener("click",()=>{n.dispatchEvent(new CustomEvent("csk:quickReply",{detail:{text:r}}))}),t.appendChild(e)}g.appendChild(t)}u.appendChild(g);const k=document.createElement("button");k.type="button",k.className="csk-newmsg csk-newmsg--hidden",k.innerHTML=`\n \n ${m("new_message")}\n `,n.appendChild(k);const h=document.createElement("div");h.className="csk-history-panel csk-history-panel--hidden",h.innerHTML=`\n
\n ${m("history_title")}\n \n
\n
\n \n
\n
\n `,u.appendChild(h);const b=h.querySelector("#csk-history-back");b&&b.addEventListener("click",()=>{h.classList.add("csk-history-panel--hidden")}),l.addEventListener("click",e=>{e.stopPropagation();const t=h.classList.contains("csk-history-panel--hidden");h.classList.toggle("csk-history-panel--hidden"),t&&n.dispatchEvent(new CustomEvent("csk:loadHistory"))});let f=null;if(e.showCategorySwitch){const e=document.createElement("div");e.className="csk-category-bar";const r=document.createElement("span");r.className="csk-category-bar__label",r.textContent="📚",f=document.createElement("select"),f.id="csk-category-select",f.className="csk-category-select",f.innerHTML=``,f.addEventListener("change",()=>{const e=f.value;n.dispatchEvent(new CustomEvent("csk:categoryChange",{detail:{categoryId:e?Number(e):void 0}}))}),e.appendChild(r),e.appendChild(f),n.appendChild(t),n.appendChild(u),n.appendChild(e)}else n.appendChild(t),n.appendChild(u);const y=document.createElement("div");y.className="csk-input-area";const x=document.createElement("div");x.className="csk-input-wrap";const v=document.createElement("textarea");v.id="csk-input",v.className="csk-input",v.setAttribute("placeholder",m("placeholder")),v.setAttribute("rows","1"),v.setAttribute("autofocus","");const w=document.createElement("button");w.id="csk-send-btn",w.className="csk-send-btn",w.setAttribute("title",m("send")),w.setAttribute("disabled","true"),w.innerHTML='',x.appendChild(v),x.appendChild(w),y.appendChild(x),n.appendChild(y);let _=null;e.showClear&&(_=document.createElement("button"),_.className="csk-clear-btn",_.textContent=m("clear"),_.style.display="none",n.insertBefore(_,y));let E=null;const C=document.createElement("div");C.className="csk-sr-only",C.setAttribute("aria-live","polite"),C.setAttribute("aria-atomic","true"),n.appendChild(C);const I=h.querySelector("#csk-history-search"),$=document.createElement("div");return $.className=`csk-teaser csk-teaser--${"left-bottom"===e.position?"left":"right"} csk-teaser--hidden`,$.setAttribute("role","status"),$.innerHTML=`\n \n ${e.teaserText||m("teaser_text")}\n `,{window:n,messagesContainer:u,inputEl:v,sendBtn:w,clearBtn:_,categorySelect:f,historyPanel:h,welcomeEl:g,newMsgBtn:k,teaserEl:$,searchInput:I,ariaLiveEl:C,showLoading:function(){if(E)return E.style.display="flex",E;const e=document.createElement("div");return e.className="csk-loading",e.innerHTML=`\n
${R}
\n
\n
\n
\n
\n
\n `,u.appendChild(e),E=e,e},hideLoading:function(){E&&E.parentNode&&(E.parentNode.removeChild(E),E=null)}}}(Oe);Ge=i.window,Ve=i.messagesContainer,Ke=i.inputEl,Xe=i.sendBtn,Je=i.clearBtn,Qe=i.categorySelect,Ze=i.historyPanel,en=i.showLoading,nn=i.hideLoading,document.body.appendChild(Ge),rn=i.teaserEl,document.body.appendChild(rn),cn();const b=Ge.querySelector(".csk-header");if(b&&(tn=function(e,n,t){let r=!1,s=0,o=0,a=0,i=0;const c=e=>{if(e.target.closest("button"))return;r=!0,s=e.clientX,o=e.clientY;const t=n.getBoundingClientRect();a=s-t.left,i=o-t.top,document.addEventListener("mousemove",l),document.addEventListener("mouseup",d)},l=e=>{if(!r)return;const t=e.clientX-a,s=e.clientY-i,o=window.innerWidth-n.offsetWidth,c=window.innerHeight-n.offsetHeight;n.style.right="auto",n.style.bottom="auto",n.style.left=`${Math.max(0,Math.min(t,o))}px`,n.style.top=`${Math.max(0,Math.min(s,c))}px`},d=()=>{if(r=!1,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d),t){const e=n.getBoundingClientRect();t({x:e.left,y:e.top})}};return e.addEventListener("mousedown",c),()=>{e.removeEventListener("mousedown",c),document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d)}}(b,Ge,e=>{!function(e,n){try{localStorage.setItem(fn(e),JSON.stringify(n))}catch(e){}}(Oe.integrateId,e)})),function(e,n){try{const t=localStorage.getItem(fn(e));if(!t)return;const r=JSON.parse(t);if("number"!=typeof r.x||"number"!=typeof r.y)return;const s=window.innerWidth-n.offsetWidth,o=window.innerHeight-n.offsetHeight,a=Math.max(0,Math.min(r.x,s)),i=Math.max(0,Math.min(r.y,o));n.style.right="auto",n.style.bottom="auto",n.style.left=`${a}px`,n.style.top=`${i}px`}catch(e){}}(Oe.integrateId,Ge),Fe(Oe,{messagesContainer:Ve,inputEl:Ke,sendBtn:Xe,clearBtn:Je,categorySelect:Qe,historyPanel:Ze,welcomeEl:i.welcomeEl,newMsgBtn:i.newMsgBtn,searchInput:i.searchInput,ariaLiveEl:i.ariaLiveEl,showLoading:en,hideLoading:nn}),Ge.addEventListener("csk:categoryChange",e=>{var n;n=e.detail.categoryId,le=n,Se=void 0!==n,o.lifecycleCategoryChange(null!=n?n:"全部")}),Ge.addEventListener("csk:loadHistory",()=>{!async function(){if(!fe||!de)return;const e=fe.querySelector("#csk-history-list");if(e){e.innerHTML='
加载中...
';try{const n=await $(1,50,de.userId,de.integrateId);Ae=n.list.map(e=>({id:e.conversationId||"",chatId:e.conversationId||"",messageCount:e.messageCount,lastMessageTime:e.lastMessageTime,lastMessagePreview:e.lastMessagePreview,createdAt:e.firstMessageTime||e.createdAt})),Le="",ve&&(ve.value=""),Z(e,Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{confirm(m("history_delete_confirm"))&&await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}catch(n){o.error(m("history_load_error"),n),e.innerHTML=`
${m("history_load_error")}
`}}}()}),Ge.addEventListener("csk:quickReply",e=>{var n;n=e.detail.text,!ge||Ce?Promise.resolve():(ge.value=n,He(),je())}),Ge.addEventListener("csk:retry",e=>{!async function(e){if(!de||!ue||Ce)return;const n=pe.findIndex(n=>n.id===e&&"ai"===n.role);if(n<0)return;let t="";for(let e=n-1;e>=0;e--)if("user"===pe[e].role){t=pe[e].content;break}if(!t)return;const r=pe.splice(n),s=new Set(r.map(e=>e.id));ue.querySelectorAll(".csk-msg").forEach(e=>{const n=e.dataset.cskMsgId;n&&s.has(n)&&e.remove()}),re(de.integrateId,pe),ze(),await Re(t)}(e.detail.msgId)}),Ge.addEventListener("csk:feedback",e=>{qe(e.detail.msgId,e.detail.value)}),Ge.addEventListener("csk:newMessage",e=>{var n;if(Ge&&Ge.classList.contains("csk-window--hidden")&&(on&&on.classList.remove("csk-launcher__badge--hidden"),(null==Oe?void 0:Oe.sound)&&function(){try{an||(an=new(window.AudioContext||window.webkitAudioContext));const e=an;if("suspended"===e.state)return void e.resume();const n=e.currentTime;[0,.15].forEach((t,r)=>{const s=e.createOscillator(),o=e.createGain();s.type="sine",s.frequency.value=0===r?880:1100,o.gain.setValueAtTime(.15,n+t),o.gain.exponentialRampToValueAtTime(.001,n+t+.12),s.connect(o),o.connect(e.destination),s.start(n+t),s.stop(n+t+.12)})}catch(e){}}(),(null==Oe?void 0:Oe.notification)&&function(){try{if(!("Notification"in window))return;"granted"===Notification.permission?new Notification((null==Oe?void 0:Oe.title)||"AI 智能助手",{body:"收到新消息",icon:void 0,silent:!0}):"denied"!==Notification.permission&&Notification.requestPermission()}catch(e){}}()),(null==Oe?void 0:Oe.onMessage)&&(null===(n=e.detail)||void 0===n?void 0:n.msg))try{Oe.onMessage(e.detail.msg)}catch(e){}}),document.addEventListener("keydown",kn),window.addEventListener("resize",un),Ye=!0,o.lifecycleInit(Oe.integrateId,Oe.requestDomain),Oe.onReady)try{Oe.onReady()}catch(e){}Oe.showTeaser&&(sn=setTimeout(()=>{Ge&&Ge.classList.contains("csk-window--hidden")&&function(){if(!rn)return;cn(),rn.classList.remove("csk-teaser--hidden"),rn.addEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.addEventListener("click",pn)}()},1500)),Ne().catch(e=>{o.warn("chatId 初始化失败,将在发送消息时重试",e)})},destroy:function(){if(!Ye)return;sn&&(clearTimeout(sn),sn=null),ln(),rn&&rn.parentNode&&(rn.parentNode.removeChild(rn),rn=null),We&&We.parentNode&&(We.parentNode.removeChild(We),We=null),Ge&&Ge.parentNode&&(Ge.parentNode.removeChild(Ge),Ge=null),tn&&(tn(),tn=null),T&&T.parentNode&&(T.parentNode.removeChild(T),T=null),document.querySelectorAll("style[data-csk-sdk]").forEach(e=>e.remove()),document.removeEventListener("keydown",kn),window.removeEventListener("resize",un),r(void 0);const e=null==Oe?void 0:Oe.integrateId;Oe=null,Ye=!1,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,on=null,an=null,o.lifecycleDestroy(e||"")},open:mn,close:hn,toggle:bn,clearHistory:function(){Oe&&(Je?Je.click():confirm("确定清空所有对话记录?")&&se(Oe.integrateId))}};return"undefined"!=typeof window&&(window.ChatbotSDK=yn),yn}(); +var ChatbotSDK=function(){"use strict";const e="[ChatbotSDK]";let n=!0,t=null;function r(e){t=e||null}const s={},o={info(t,r){n&&console.log(e,t,void 0!==r?r:"")},warn(t,r){n&&console.warn(e,t,void 0!==r?r:"")},error(n,r){if(console.error(e,n,void 0!==r?r:""),t)try{const e=r instanceof Error&&r.type||"error";t({message:n,code:String(e),detail:r})}catch(e){}},time(e){s[e]=Date.now()},timeEnd(t,r){const o=s[t];if(void 0!==o){const a=Date.now()-o;if(delete s[t],n){const n=r?`${r} ${a}ms`:`${t} ${a}ms`;console.log(e,n)}return a}return 0},lifecycleInit(e,n){this.info(`初始化完成 integrateId=${e} requestDomain=${n}`)},lifecycleDestroy(e){this.info(`销毁实例 integrateId=${e}`)},lifecycleSend(e,n){this.info(`发送消息 integrateId=${e} length=${n}`),this.time(`send_${e}`)},lifecycleReply(e,n){const t=this.timeEnd(`send_${e}`,"AI 回复");this.info(`AI 回复 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleError(e,n,t){this.timeEnd(`send_${e}`),this.error(`请求失败 integrateId=${e} status=${n} message=${t}`)},lifecycleClear(e){this.info(`清空会话 integrateId=${e}`)},lifecycleStreamDone(e,n){const t=this.timeEnd(`send_${e}`,"流式回复");this.info(`流式回复完成 integrateId=${e} length=${n} duration=${t}ms`)},lifecycleCategoryChange(e){this.info(`切换知识库分类 categoryId=${e}`)}},a='\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n';function i(e,n,t){return`\n \n \x3c!-- 高光渐变:模拟玻璃反射 --\x3e\n \n \n \n \n \x3c!-- 机器人身体渐变 --\x3e\n \n \n \n \n \n \x3c!-- 机器人主体(圆角矩形 + 对话气泡尾巴) --\x3e\n \n \n \x3c!-- 高光反射层(左上角弧形高光) --\x3e\n \n \x3c!-- 天线 + 能量球 --\x3e\n \n \n \x3c!-- 眼睛(会眨) --\x3e\n \n \n \x3c!-- 眼睛高光点 --\x3e\n \n \n \x3c!-- 微笑 --\x3e\n \n \x3c!-- 跳动气泡装饰(3 个小圆点) --\x3e\n \n \n \n`}const c=i("rgba(139,92,246,0.6)","rgba(139,92,246,0.45)","rgba(240,171,252,0.85)"),l=i("rgba(16,185,129,0.6)","rgba(16,185,129,0.45)","rgba(110,231,183,0.85)"),d=i("rgba(244,63,94,0.55)","rgba(244,63,94,0.4)","rgba(253,186,116,0.85)"),p=i("rgba(56,189,248,0.6)","rgba(56,189,248,0.45)","rgba(167,139,250,0.85)"),u={"dream-purple":"#A78BFA","mint-tech":"#34D399","coral-peach":"#FB7185","sky-blue":"#7DD3FC"};const g={"zh-CN":{title:"AI 智能助手",minimize:"最小化",close:"关闭",status_online:"在线",welcome_title:"你好,我是 AI 智能助手",welcome_desc:"有什么可以帮你的吗?在下方输入框开始提问吧~",placeholder:"输入您的问题...",send:"发送",stop:"停止生成",new_message:"新消息",copy:"复制",copied:"已复制",retry:"重新生成",retrying:"重新生成中...",loading:"正在思考...",stream_interrupted:"回复被中断",stream_unstable:"网络不稳定,内容可能不完整",category_placeholder:"选择知识库分类",category_all:"全部分类",category_load_error:"加载分类失败",source_title:"参考来源",source_count:"{n} 条参考来源",source_loading:"加载来源中...",clear:"清空对话",clear_confirm:"确定清空所有对话记录?",history_title:"历史会话",history_empty:"暂无历史会话",history_load_error:"加载会话列表失败",history_delete_confirm:"确定删除该会话?",history_export:"导出",history_delete:"删除",history_search:"搜索会话...",history_group_today:"今天",history_group_yesterday:"昨天",history_group_week:"本周",history_group_earlier:"更早",feedback_up:"有帮助",feedback_down:"没帮助",teaser_text:"有什么可以帮你的吗?",new_msg_announce:"收到新消息",error_network:"网络连接失败,请检查网络",error_timeout:"请求超时,请稍后重试",error_server:"服务器异常,请稍后重试",error_cors:"跨域请求被拦截,请联系管理员将当前域名加入 API 白名单",error_auth:"鉴权失败,请联系管理员",error_forbidden:"无访问权限,请联系管理员配置",error_not_found:"请求的资源不存在",error_rate_limit:"请求过于频繁,请稍后重试",error_unavailable:"服务暂不可用,请稍后重试",error_unknown:"请求发生未知错误",error_send:"发送失败,请稍后重试",error_stream_unsupported:"浏览器不支持流式读取"},en:{title:"AI Assistant",minimize:"Minimize",close:"Close",status_online:"Online",welcome_title:"Hi, I am your AI assistant",welcome_desc:"How can I help you? Type your question below to get started.",placeholder:"Type your question...",send:"Send",stop:"Stop generating",new_message:"New message",copy:"Copy",copied:"Copied",retry:"Regenerate",retrying:"Regenerating...",loading:"Thinking...",stream_interrupted:"Response interrupted",stream_unstable:"Network unstable, content may be incomplete",category_placeholder:"Select category",category_all:"All categories",category_load_error:"Failed to load categories",source_title:"Sources",source_count:"{n} source(s)",source_loading:"Loading sources...",clear:"Clear chat",clear_confirm:"Clear all conversation history?",history_title:"History",history_empty:"No conversations yet",history_load_error:"Failed to load conversations",history_delete_confirm:"Delete this conversation?",history_export:"Export",history_delete:"Delete",history_search:"Search conversations...",history_group_today:"Today",history_group_yesterday:"Yesterday",history_group_week:"This Week",history_group_earlier:"Earlier",feedback_up:"Helpful",feedback_down:"Not helpful",teaser_text:"How can I help you?",new_msg_announce:"New message received",error_network:"Network connection failed",error_timeout:"Request timed out, please try again",error_server:"Server error, please try again later",error_cors:"CORS request blocked. Please contact admin to whitelist your domain",error_auth:"Authentication failed, please contact admin",error_forbidden:"Access denied, please contact admin",error_not_found:"Resource not found",error_rate_limit:"Too many requests, please try again later",error_unavailable:"Service temporarily unavailable",error_unknown:"Unknown request error",error_send:"Failed to send, please try again",error_stream_unsupported:"Browser does not support streaming"}};let k="zh-CN";function m(e,n){let t=(g[k]||g["zh-CN"])[e]||g["zh-CN"][e]||e;if(n)for(const[e,r]of Object.entries(n))t=t.replace(`{${e}}`,String(r));return t}let h=null;function b(e){h&&(h.chatId=e)}function f(){return(null==h?void 0:h.chatId)||""}function y(e){if(!h)throw new Error("API 配置未初始化");return`${h.requestDomain.replace(/\/+$/,"")}${e.startsWith("/")?e:`/${e}`}`}function x(e,n,t){null!=t&&("string"==typeof t&&""===t.trim()||e.set(n,String(t)))}async function v(e,n={},t=3e4,r){const s=new AbortController,o=setTimeout(()=>s.abort(),t);r&&(r.aborted?s.abort():r.addEventListener("abort",()=>s.abort(),{once:!0}));try{return await fetch(e,Object.assign(Object.assign({},n),{signal:s.signal,mode:"cors",credentials:"include"}))}catch(e){if(null==r?void 0:r.aborted)throw new w("aborted","aborted");if(e instanceof DOMException&&"AbortError"===e.name)throw new w(m("error_timeout"),"timeout");if(e instanceof TypeError&&e.message.includes("Failed to fetch"))throw new w(m("error_cors"),"cors");throw new w(m("error_network"),"network")}finally{clearTimeout(o)}}class w extends Error{constructor(e,n){super(e),this.name="CskError",this.type=n}}function _(e){switch(e){case 401:return m("error_auth");case 403:return m("error_forbidden");case 404:return m("error_not_found");case 429:return m("error_rate_limit");case 500:return m("error_server");case 502:case 503:return m("error_unavailable");default:return`${m("error_unknown")}(${e})`}}async function E(e){const n=function(e){const n=new URLSearchParams;return n.set("message",e),n.set("chatId",h.chatId),x(n,"roleId",h.integrateId),x(n,"accountId",h.userId),y(`/ai/assistant_app/chat/sync?${n.toString()}`)}(e);o.lifecycleSend(h.integrateId,e.length);try{const e=await v(n);if(!e.ok){const n=_(e.status);throw o.lifecycleError(h.integrateId,String(e.status),n),new w(n,`http_${e.status}`)}const t=await e.text();return o.lifecycleReply(h.integrateId,t.length),t}catch(e){if(e instanceof w)throw e;throw o.lifecycleError(h.integrateId,"unknown",String(e)),new w(m("error_unknown"),"unknown")}}async function C(e,n,t,r,s,a,i){var c;const l=a?function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/rag/sse?${t.toString()}`)}(e,s):function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/chat/sse?${t.toString()}`)}(e,s);let d="";o.lifecycleSend(h.integrateId,e.length);try{const e=await v(l,{},6e4,i);if(!e.ok){const n=_(e.status);return o.lifecycleError(h.integrateId,String(e.status),n),void r(new w(n,`http_${e.status}`))}const s=null===(c=e.body)||void 0===c?void 0:c.getReader();if(!s)return void r(new w(m("error_stream_unsupported"),"stream_unsupported"));const a=new TextDecoder("utf-8",{stream:!0});let p="";try{for(;;){const{done:e,value:t}=await s.read();if(e)break;p+=a.decode(t,{stream:!0});const r=p.split("\n");p=r.pop()||"";for(const e of r){const t=e.trim();if(t&&!t.startsWith(":"))if(t.startsWith("data:")){const e=t.substring(5).trim();e&&(d+=e,n(e))}else{if("[DONE]"===t)break;t.startsWith("event:")||t.startsWith("id:")||t.startsWith("retry:")||(d+=t,n(t))}}}if(p.trim()){const e=p.trim();if(e.startsWith("data:")){const t=e.substring(5).trim();t&&(d+=t,n(t))}else"[DONE]"!==e&&(d+=e,n(e))}}catch(e){if(null==i?void 0:i.aborted)o.info(`流式被用户中断,保留已生成内容 length=${d.length}`);else{if(!(d.length>0))throw e;n("\n\n"+m("stream_unstable"))}}finally{s.releaseLock()}o.lifecycleStreamDone(h.integrateId,d.length),t()}catch(e){if((null==i?void 0:i.aborted)||e instanceof w&&"aborted"===e.type)return void t();e instanceof w?r(e):(o.lifecycleError(h.integrateId,"unknown",String(e)),r(new w(m("error_network"),"network")))}}async function I(e,n){const t=function(e,n){const t=new URLSearchParams;return t.set("message",e),t.set("chatId",h.chatId),t.set("rewriteStrategy",h.rewriteStrategy||"REWRITE"),x(t,"roleId",h.integrateId),x(t,"accountId",h.userId),x(t,"categoryId",null!=n?n:h.categoryId),y(`/ai/assistant_app/rag/sources?${t.toString()}`)}(e,n);try{const e=await v(t);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return n.success&&Array.isArray(n.data)?(o.info(`获取引用来源 count=${n.data.length}`),n.data):[]}catch(e){return o.error("获取引用来源失败",e),[]}}async function $(e=1,n=20,t,r){let s=`/conversation/list?page=${e}&size=${n}`;t&&(s+=`&accountId=${encodeURIComponent(t)}`),r&&(s+=`&roleId=${encodeURIComponent(r)}`);const a=y(s);try{const e=await v(a);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const n=await e.json();return{list:n.success&&Array.isArray(n.data)?n.data:[],total:n.total||0,pages:n.pages||0}}catch(e){return o.error("加载会话列表失败",e),{list:[],total:0,pages:0}}}async function A(e){const n=y(`/conversation/${e}/messages`);try{const e=await v(n);if(!e.ok)throw new w(_(e.status),`http_${e.status}`);const t=await e.json();return{messages:t.success&&Array.isArray(t.data)?t.data:[],total:t.total||0}}catch(e){return o.error("加载会话消息失败",e),{messages:[],total:0}}}async function L(e){const n=y(`/conversation/${e}`);try{const t=await v(n,{method:"DELETE"});if(!t.ok)throw new w(_(t.status),`http_${t.status}`);const r=await t.json();return o.info(`删除会话 id=${e} success=${r.success}`),r.success||!1}catch(e){return o.error("删除会话失败",e),!1}}function S(e){return y(`/conversation/${e}/export`)}async function F(){if(!h)return"";const e=function(e,n){try{return localStorage.getItem(N(e,n))||""}catch(e){return""}}(h.integrateId,h.userId);if(e)return h.chatId=e,o.info(`从缓存恢复 chatId=${e}`),e;try{const e=await $(1,5,h.userId,h.integrateId);if(e.list.length>0){const n=e.list[0],t=n.conversationId||n.chatId||"";if(t)return h.chatId=t,M(h.integrateId,h.userId,t),o.info(`从后端恢复会话 chatId=${t} messageCount=${n.messageCount}`),t}}catch(e){o.warn("查询后端会话列表失败,将生成新 chatId",e)}const n=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();return h.chatId=n,M(h.integrateId,h.userId,n),o.info(`生成新 chatId=${n}`),n}function N(e,n){return`csk_chatId_${e}${n?"_"+n:""}`}function M(e,n,t){try{t?localStorage.setItem(N(e,n),t):localStorage.removeItem(N(e,n))}catch(e){}}let T=null;function D(e){const n=B(e.primaryColor,-15),t=B(e.primaryColor,18),r=function(e){const n=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);return n?`${parseInt(n[1],16)}, ${parseInt(n[2],16)}, ${parseInt(n[3],16)}`:"79, 70, 229"}(e.primaryColor),s=e.launcherTheme?{"dream-purple":{grad1:"#A78BFA",grad2:"#F0ABFC",glow:"167, 139, 250"},"mint-tech":{grad1:"#6EE7B7",grad2:"#34D399",glow:"52, 211, 153"},"coral-peach":{grad1:"#FB7185",grad2:"#FDBA74",glow:"251, 113, 133"},"sky-blue":{grad1:"#7DD3FC",grad2:"#A78BFA",glow:"125, 211, 252"}}[e.launcherTheme]:null;return`\n --csk-primary: ${e.primaryColor};\n --csk-primary-hover: ${n};\n --csk-primary-light: ${t};\n --csk-primary-rgb: ${r};\n --csk-bg-user: linear-gradient(135deg, ${e.primaryColor}, ${n});\n --csk-bg-ai: #ffffff;\n --csk-text-user: #ffffff;\n --csk-text-ai: #1F2937;\n --csk-window-width: ${e.width}px;\n --csk-window-height: ${e.height}px;\n --csk-radius: 16px;\n --csk-shadow-window: 0 12px 48px rgba(15, 23, 42, 0.18), 0 2px 8px rgba(15, 23, 42, 0.06);\n --csk-shadow-bubble: 0 1px 2px rgba(15, 23, 42, 0.06);\n --csk-border: #ECEEF2;\n --csk-bg-app: #F6F7F9;\n ${s?`\n --csk-launcher-grad-1: ${s.grad1};\n --csk-launcher-grad-2: ${s.grad2};\n --csk-launcher-glow: ${s.glow};\n `:""}\n `}function B(e,n){const t=e.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!t)return e;const r=e=>Math.max(0,Math.min(255,e)),s=r(parseInt(t[1],16)+n),o=r(parseInt(t[2],16)+n),a=r(parseInt(t[3],16)+n);return`#${s.toString(16).padStart(2,"0")}${o.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}`}function q(e){document.querySelector("style[data-csk-sdk]")||(T=document.createElement("style"),T.setAttribute("data-csk-sdk",""),T.textContent=function(e){return`\n/* ChatbotSDK 样式 - csk- 命名空间 */\n.csk-root {\n ${D(e)}\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;\n font-size: 14px;\n line-height: 1.55;\n color: #1F2937;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n.csk-root *, .csk-root *::before, .csk-root *::after { box-sizing: border-box; }\n\n/* ========== 悬浮按钮 ========== */\n.csk-launcher {\n position: fixed;\n bottom: 24px;\n z-index: 9998;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n user-select: none;\n overflow: visible;\n /* 半透明白色光环边框,在白色页面上清晰分离按钮与背景 */\n border: 2.5px solid rgba(255, 255, 255, 0.55);\n /* 三层投影:接地阴影 + 彩色光晕,把按钮从白底「托」出来 */\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.25s ease,\n border-color 0.25s ease;\n animation: csk-launcher-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;\n}\n.csk-launcher--right { right: 24px; }\n.csk-launcher--left { left: 24px; }\n\n/* 高光扫过动效 */\n.csk-launcher::before {\n content: '';\n position: absolute;\n top: -50%;\n left: -50%;\n width: 40%;\n height: 200%;\n border-radius: 50%;\n background: linear-gradient(\n 105deg,\n transparent 30%,\n rgba(255, 255, 255, 0.28) 48%,\n rgba(255, 255, 255, 0.1) 52%,\n transparent 70%\n );\n transform: rotate(25deg);\n animation: csk-shimmer 4s ease-in-out infinite;\n pointer-events: none;\n}\n/* 呼吸色晕 — 配合接地阴影,强化白底上的立体存在感 */\n.csk-launcher::after {\n content: '';\n position: absolute;\n inset: -18px;\n border-radius: 50%;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.18) 0%, rgba(var(--csk-primary-rgb), 0.05) 45%, transparent 68%);\n animation: csk-breathe 3.5s ease-in-out infinite;\n pointer-events: none;\n}\n.csk-launcher:hover {\n transform: translateY(-3px) scale(1.08);\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.10),\n 0 8px 24px rgba(0, 0, 0, 0.14),\n 0 10px 36px rgba(var(--csk-primary-rgb), 0.32),\n 0 0 56px rgba(var(--csk-primary-rgb), 0.14);\n}\n.csk-launcher:hover::before { animation-play-state: paused; }\n.csk-launcher:hover::after {\n animation: none;\n inset: -22px;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.22) 0%, rgba(var(--csk-primary-rgb), 0.06) 45%, transparent 68%);\n}\n.csk-launcher:active { transform: scale(0.93); }\n.csk-launcher svg {\n width: 30px;\n height: 30px;\n position: relative;\n z-index: 1;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.15));\n}\n\n@keyframes csk-launcher-in {\n 0% { opacity: 0; transform: scale(0.5) translateY(16px); }\n 60% { transform: scale(1.06) translateY(-2px); }\n 100% { opacity: 1; transform: scale(1) translateY(0); }\n}\n@keyframes csk-shimmer {\n 0%, 100% { left: -60%; opacity: 0; }\n 20% { opacity: 1; }\n 60% { opacity: 1; }\n 80% { left: 120%; opacity: 0; }\n}\n@keyframes csk-breathe {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.15); opacity: 0.35; }\n}\n\n/* SVG 图标内部动效:眨眼 */\n.csk-launcher .csk-ico-eye {\n animation: csk-eye-blink 4s ease-in-out infinite;\n}\n@keyframes csk-eye-blink {\n 0%, 42%, 48%, 100% { opacity: 1; }\n 45% { opacity: 0.1; }\n}\n/* SVG 图标内部动效:天线能量闪烁 */\n.csk-launcher .csk-ico-antenna {\n animation: csk-antenna-glow 2s ease-in-out infinite;\n}\n@keyframes csk-antenna-glow {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n/* ========== 磨砂玻璃质感悬浮按钮 ========== */\n.csk-launcher--glass {\n background: linear-gradient(\n 135deg,\n var(--csk-launcher-grad-1, var(--csk-primary)) 0%,\n var(--csk-launcher-grad-2, var(--csk-primary-light)) 100%\n ) !important;\n backdrop-filter: blur(12px) saturate(180%);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n border: 1.5px solid rgba(255, 255, 255, 0.55) !important;\n /* 多层阴影:接地 + 彩色光晕 + 内阴影立体感 */\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.04),\n 0 6px 20px rgba(0, 0, 0, 0.08),\n 0 8px 32px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.30),\n inset 0 1px 1px rgba(255, 255, 255, 0.35),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n.csk-launcher--glass:hover {\n border-color: rgba(255, 255, 255, 0.75) !important;\n box-shadow:\n 0 4px 8px rgba(0, 0, 0, 0.06),\n 0 10px 28px rgba(0, 0, 0, 0.10),\n 0 12px 40px rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.38),\n inset 0 1px 2px rgba(255, 255, 255, 0.45),\n inset 0 -1px 1px rgba(0, 0, 0, 0.04) !important;\n}\n\n/* 玻璃按钮的呼吸色晕 — 更鲜艳、更醒目 */\n.csk-launcher--glass::after {\n background: radial-gradient(\n circle,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.28) 0%,\n rgba(var(--csk-launcher-glow, var(--csk-primary-rgb)), 0.10) 40%,\n transparent 65%\n ) !important;\n animation: csk-breathe-glow 3.5s ease-in-out infinite;\n}\n@keyframes csk-breathe-glow {\n 0%, 100% { transform: scale(1); opacity: 0.8; }\n 50% { transform: scale(1.22); opacity: 0.25; }\n}\n\n/* 玻璃按钮的高光扫过 — 更柔和的玻璃质感 */\n.csk-launcher--glass::before {\n background: linear-gradient(\n 115deg,\n transparent 25%,\n rgba(255, 255, 255, 0.35) 45%,\n rgba(255, 255, 255, 0.15) 55%,\n transparent 75%\n ) !important;\n width: 50%;\n animation: csk-shimmer-glass 5s ease-in-out infinite;\n}\n@keyframes csk-shimmer-glass {\n 0%, 100% { left: -70%; opacity: 0; }\n 15% { opacity: 1; }\n 55% { opacity: 1; }\n 70% { left: 130%; opacity: 0; }\n}\n\n/* SVG 内部动效:跳动气泡(3 个小圆点交错弹跳) */\n.csk-launcher .csk-ico-bubble {\n animation: csk-bubble-jump 1.4s ease-in-out infinite;\n}\n.csk-launcher .csk-ico-bubble--1 { animation-delay: 0s; }\n.csk-launcher .csk-ico-bubble--2 { animation-delay: 0.18s; }\n.csk-launcher .csk-ico-bubble--3 { animation-delay: 0.36s; }\n@keyframes csk-bubble-jump {\n 0%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-3.5px); }\n 60% { transform: translateY(-1px); }\n}\n\n/* ========== 聊天弹窗 ========== */\n.csk-window {\n position: fixed;\n bottom: 24px;\n z-index: 9999;\n width: var(--csk-window-width);\n height: var(--csk-window-height);\n max-height: calc(100vh - 48px);\n background: #fff;\n border-radius: var(--csk-radius);\n box-shadow: var(--csk-shadow-window);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transform-origin: bottom right;\n transition: opacity 0.24s ease, transform 0.24s cubic-bezier(0.34, 1.2, 0.64, 1), visibility 0.24s;\n opacity: 1;\n transform: translateY(0) scale(1);\n visibility: visible;\n pointer-events: auto;\n}\n.csk-window--right { right: 24px; transform-origin: bottom right; }\n.csk-window--left { left: 24px; transform-origin: bottom left; }\n.csk-window--hidden {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n visibility: hidden;\n pointer-events: none;\n}\n\n/* ========== 头部 ========== */\n.csk-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n min-height: 60px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: move;\n user-select: none;\n position: relative;\n flex-shrink: 0;\n}\n.csk-header::after {\n content: '';\n position: absolute;\n left: 0; right: 0; bottom: 0;\n height: 24px;\n background: linear-gradient(to bottom, rgba(0,0,0,0.04), transparent);\n pointer-events: none;\n}\n.csk-header__left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n.csk-header__avatar {\n width: 38px;\n height: 38px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);\n}\n.csk-header__avatar svg { width: 22px; height: 22px; }\n.csk-header__info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.csk-header__title {\n font-size: 15px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n letter-spacing: 0.2px;\n}\n.csk-header__status {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 11.5px;\n opacity: 0.9;\n margin-top: 2px;\n}\n.csk-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #6EE7B7;\n box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7);\n animation: csk-status-pulse 2s infinite;\n}\n@keyframes csk-status-pulse {\n 0% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7); }\n 70% { box-shadow: 0 0 0 6px rgba(110, 231, 183, 0); }\n 100% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0); }\n}\n.csk-header__actions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n.csk-header__btn,\n.csk-history-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #fff;\n cursor: pointer;\n border-radius: 8px;\n transition: background 0.15s, transform 0.15s;\n}\n.csk-header__btn:hover,\n.csk-history-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n.csk-header__btn:active,\n.csk-history-btn:active { transform: scale(0.92); }\n\n/* ========== 消息区 ========== */\n.csk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 20px 16px 12px;\n background: var(--csk-bg-app);\n scroll-behavior: smooth;\n}\n.csk-messages::-webkit-scrollbar { width: 6px; }\n.csk-messages::-webkit-scrollbar-track { background: transparent; }\n.csk-messages::-webkit-scrollbar-thumb {\n background: #D8DCE3;\n border-radius: 3px;\n}\n.csk-messages::-webkit-scrollbar-thumb:hover { background: #C2C7D0; }\n\n/* 欢迎空状态 */\n.csk-welcome {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 48px 24px 32px;\n color: #6B7280;\n animation: csk-fade-in 0.3s ease;\n}\n.csk-welcome__avatar {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 14px;\n box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-welcome__avatar svg { width: 30px; height: 30px; }\n.csk-welcome__title {\n font-size: 15px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.csk-welcome__desc {\n font-size: 13px;\n color: #9CA3AF;\n line-height: 1.6;\n}\n\n/* 消息气泡 */\n.csk-msg {\n display: flex;\n margin-bottom: 18px;\n max-width: 100%;\n word-break: break-word;\n animation: csk-msg-in 0.28s cubic-bezier(0.22, 1, 0.36, 1);\n}\n.csk-msg--user {\n flex-direction: row-reverse;\n align-items: flex-end;\n}\n.csk-msg--ai {\n flex-direction: row;\n align-items: flex-start;\n}\n.csk-msg__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg__avatar svg { width: 18px; height: 18px; }\n.csk-msg__avatar--ai {\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n}\n.csk-msg__avatar--user {\n background: var(--csk-bg-user);\n color: #fff;\n}\n.csk-msg__content {\n display: flex;\n flex-direction: column;\n min-width: 0;\n max-width: calc(100% - 46px);\n}\n.csk-msg--user .csk-msg__content { align-items: flex-end; }\n.csk-msg--ai .csk-msg__content { align-items: flex-start; }\n.csk-msg__bubble {\n padding: 10px 14px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.6;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg--user .csk-msg__bubble {\n background: var(--csk-bg-user);\n color: var(--csk-text-user);\n border-radius: 16px 16px 4px 16px;\n}\n.csk-msg--ai .csk-msg__bubble {\n background: var(--csk-bg-ai);\n color: var(--csk-text-ai);\n border-radius: 16px 16px 16px 4px;\n border: 1px solid var(--csk-border);\n}\n.csk-msg__time {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 5px;\n padding: 0 4px;\n}\n\n@keyframes csk-msg-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes csk-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ========== Loading 动画 ========== */\n.csk-loading {\n display: flex;\n align-items: center;\n margin-bottom: 18px;\n animation: csk-msg-in 0.28s ease;\n}\n.csk-loading__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-loading__avatar svg { width: 18px; height: 18px; }\n.csk-loading__bubble {\n background: #fff;\n border: 1px solid var(--csk-border);\n border-radius: 16px 16px 16px 4px;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.csk-loading__dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #B4B9C2;\n animation: csk-bounce 1.4s ease-in-out infinite both;\n}\n.csk-loading__dot:nth-child(1) { animation-delay: 0s; }\n.csk-loading__dot:nth-child(2) { animation-delay: 0.16s; }\n.csk-loading__dot:nth-child(3) { animation-delay: 0.32s; }\n\n@keyframes csk-bounce {\n 0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }\n 40% { transform: scale(1); opacity: 1; }\n}\n\n/* ========== 输入区 ========== */\n.csk-input-area {\n padding: 10px 12px 14px;\n background: #fff;\n border-top: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-input-wrap {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n background: var(--csk-bg-app);\n border: 1px solid var(--csk-border);\n border-radius: 14px;\n padding: 6px 6px 6px 14px;\n transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;\n}\n.csk-input-wrap--focus {\n border-color: var(--csk-primary);\n background: #fff;\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n.csk-input {\n flex: 1;\n border: none;\n background: transparent;\n padding: 8px 0;\n font-size: 14px;\n outline: none;\n font-family: inherit;\n resize: none;\n min-height: 22px;\n max-height: 120px;\n line-height: 1.5;\n color: #1F2937;\n}\n.csk-input::placeholder { color: #9CA3AF; }\n.csk-root .csk-input:focus-visible { outline: none; }\n.csk-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n min-width: 36px;\n border: none;\n border-radius: 10px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: pointer;\n transition: transform 0.18s, box-shadow 0.18s, opacity 0.18s;\n box-shadow: 0 3px 10px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-send-btn:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 5px 14px rgba(var(--csk-primary-rgb), 0.4);\n}\n.csk-send-btn:active:not(:disabled) { transform: scale(0.92); }\n.csk-send-btn:disabled {\n background: #D1D5DB;\n box-shadow: none;\n cursor: not-allowed;\n opacity: 0.7;\n}\n.csk-send-btn svg { width: 18px; height: 18px; }\n\n/* ========== 清空按钮 ========== */\n.csk-clear-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 999px;\n background: #fff;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n margin: 0 auto 8px;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-clear-btn:hover {\n background: #FEF2F2;\n border-color: #FCA5A5;\n color: #DC2626;\n}\n\n/* ========== P1: 知识库分类下拉 ========== */\n.csk-category-bar {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n border-top: 1px solid var(--csk-border);\n background: #FBFBFC;\n gap: 8px;\n flex-shrink: 0;\n}\n.csk-category-bar__label {\n font-size: 13px;\n white-space: nowrap;\n}\n.csk-category-select {\n flex: 1;\n padding: 6px 28px 6px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n color: #374151;\n background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 9px center;\n appearance: none;\n -webkit-appearance: none;\n outline: none;\n cursor: pointer;\n font-family: inherit;\n transition: border-color 0.2s, box-shadow 0.2s;\n max-width: 220px;\n}\n.csk-category-select:focus {\n border-color: var(--csk-primary);\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n\n/* ========== P1: RAG 引用来源卡片 ========== */\n.csk-sources {\n margin-top: 8px;\n border: 1px solid var(--csk-border);\n border-radius: 12px;\n overflow: hidden;\n font-size: 12px;\n max-width: 100%;\n background: #FAFBFC;\n}\n.csk-sources__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: #F3F4F7;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s;\n}\n.csk-sources__header:hover { background: #ECEEF2; }\n.csk-sources__title {\n display: flex;\n align-items: center;\n gap: 5px;\n font-weight: 500;\n color: #374151;\n}\n.csk-sources__arrow {\n transition: transform 0.2s;\n color: #9CA3AF;\n font-size: 10px;\n}\n.csk-sources--collapsed .csk-sources__arrow { transform: rotate(-90deg); }\n.csk-sources__body {\n border-top: 1px solid var(--csk-border);\n padding: 0;\n}\n.csk-sources--collapsed .csk-sources__body { display: none; }\n.csk-source-item {\n padding: 9px 12px;\n border-bottom: 1px solid #F0F1F4;\n transition: background 0.15s;\n}\n.csk-source-item:last-child { border-bottom: none; }\n.csk-source-item:hover { background: #fff; }\n.csk-source-item__name {\n font-weight: 500;\n color: #1F2937;\n margin-bottom: 3px;\n}\n.csk-source-item__snippet {\n color: #6B7280;\n line-height: 1.5;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n.csk-source-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 4px;\n}\n\n/* ========== P1: Markdown 渲染样式 ========== */\n.csk-msg--ai .csk-msg__bubble .csk-md-p { margin: 0 0 8px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-p:last-child { margin-bottom: 0; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h1,\n.csk-msg--ai .csk-msg__bubble .csk-md-h2,\n.csk-msg--ai .csk-msg__bubble .csk-md-h3,\n.csk-msg--ai .csk-msg__bubble .csk-md-h4,\n.csk-msg--ai .csk-msg__bubble .csk-md-h5,\n.csk-msg--ai .csk-msg__bubble .csk-md-h6 {\n margin: 14px 0 6px;\n font-weight: 600;\n line-height: 1.3;\n color: #111827;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-h1 { font-size: 20px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h2 { font-size: 17px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h3 { font-size: 15px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h4 { font-size: 14px; }\n\n.csk-md-code-block {\n background: #1E293B;\n color: #E2E8F0;\n padding: 12px 14px;\n border-radius: 10px;\n overflow-x: auto;\n margin: 8px 0;\n font-size: 13px;\n line-height: 1.55;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-md-code-block code {\n background: none;\n padding: 0;\n border-radius: 0;\n font-size: inherit;\n color: inherit;\n}\n.csk-md-inline-code {\n background: rgba(var(--csk-primary-rgb), 0.1);\n color: var(--csk-primary);\n padding: 1px 6px;\n border-radius: 5px;\n font-size: 13px;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol {\n padding-left: 22px;\n margin: 6px 0;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul li,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol li { margin-bottom: 4px; }\n.csk-md-blockquote {\n border-left: 3px solid var(--csk-primary);\n padding: 2px 12px;\n margin: 8px 0;\n color: #6B7280;\n background: rgba(var(--csk-primary-rgb), 0.05);\n border-radius: 0 6px 6px 0;\n}\n.csk-md-link {\n color: var(--csk-primary);\n text-decoration: none;\n border-bottom: 1px solid rgba(var(--csk-primary-rgb), 0.3);\n transition: border-color 0.15s;\n}\n.csk-md-link:hover { border-bottom-color: var(--csk-primary); }\n.csk-md-hr {\n border: none;\n border-top: 1px solid var(--csk-border);\n margin: 12px 0;\n}\n\n/* ========== P2: 会话管理面板 ========== */\n.csk-history-panel {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: #fff;\n z-index: 10;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: csk-slide-in 0.24s ease;\n}\n.csk-history-panel--hidden { display: none; }\n@keyframes csk-slide-in {\n from { transform: translateX(100%); opacity: 0.4; }\n to { transform: translateX(0); opacity: 1; }\n}\n.csk-history-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--csk-border);\n background: var(--csk-bg-app);\n flex-shrink: 0;\n}\n.csk-history-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n}\n.csk-history-panel__back {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n background: #fff;\n color: #374151;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-history-panel__back:hover { background: #F3F4F6; }\n.csk-history-panel__list {\n flex: 1;\n overflow-y: auto;\n padding: 10px;\n}\n.csk-history-panel__list::-webkit-scrollbar { width: 5px; }\n.csk-history-panel__list::-webkit-scrollbar-thumb { background: #E5E7EB; border-radius: 2px; }\n.csk-history-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 11px 12px;\n border-radius: 10px;\n cursor: pointer;\n transition: background 0.15s;\n margin-bottom: 5px;\n border: 1px solid transparent;\n}\n.csk-history-item:hover { background: #F3F4F6; }\n.csk-history-item--active {\n background: rgba(var(--csk-primary-rgb), 0.08);\n border-color: rgba(var(--csk-primary-rgb), 0.2);\n}\n.csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.12); }\n.csk-history-item__info { flex: 1; min-width: 0; }\n.csk-history-item__id {\n font-size: 13px;\n font-weight: 500;\n color: #1F2937;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.csk-history-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 3px;\n}\n.csk-history-item__actions {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.csk-history-item:hover .csk-history-item__actions { opacity: 1; }\n.csk-history-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 7px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.15s;\n}\n.csk-history-action--export { background: #EFF6FF; color: #2563EB; }\n.csk-history-action--export:hover { background: #DBEAFE; }\n.csk-history-action--delete { background: #FEF2F2; color: #DC2626; }\n.csk-history-action--delete:hover { background: #FEE2E2; }\n.csk-history-panel__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 20px;\n color: #9CA3AF;\n font-size: 13px;\n text-align: center;\n}\n.csk-history-panel__empty-icon {\n font-size: 34px;\n margin-bottom: 10px;\n opacity: 0.5;\n}\n.csk-history-panel__loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n color: #9CA3AF;\n font-size: 13px;\n}\n.csk-history-panel__loadmore {\n display: block;\n width: 100%;\n padding: 10px;\n border: none;\n background: #F9FAFB;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n text-align: center;\n transition: background 0.15s;\n}\n.csk-history-panel__loadmore:hover { background: #F3F4F6; }\n\n/* ========== 快捷问题芯片 ========== */\n.csk-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n margin-top: 18px;\n max-width: 320px;\n}\n.csk-quick-reply {\n border: 1px solid var(--csk-border);\n background: #fff;\n color: #374151;\n font-size: 12.5px;\n padding: 7px 13px;\n border-radius: 999px;\n cursor: pointer;\n font-family: inherit;\n line-height: 1.3;\n transition: all 0.18s ease;\n max-width: 100%;\n}\n.csk-quick-reply:hover {\n border-color: var(--csk-primary);\n color: var(--csk-primary);\n background: rgba(var(--csk-primary-rgb), 0.06);\n transform: translateY(-1px);\n}\n.csk-quick-reply:active { transform: scale(0.96); }\n\n/* ========== AI 消息操作条 ========== */\n.csk-msg__actions {\n display: flex;\n gap: 2px;\n margin-top: 5px;\n padding: 0 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n.csk-msg--ai:hover .csk-msg__actions { opacity: 1; }\n.csk-msg--streaming .csk-msg__actions { display: none; }\n.csk-action-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.csk-action-btn:hover {\n background: #F3F4F6;\n color: #374151;\n}\n.csk-action-btn--done { color: #10B981; }\n.csk-action-btn:active { transform: scale(0.9); }\n\n/* ========== 流式打字光标 ========== */\n.csk-caret {\n display: inline-block;\n width: 7px;\n height: 15px;\n margin-left: 2px;\n vertical-align: text-bottom;\n background: var(--csk-primary);\n border-radius: 1px;\n animation: csk-caret-blink 1s step-end infinite;\n}\n@keyframes csk-caret-blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n/* ========== 代码块复制按钮 ========== */\n.csk-md-code-block { position: relative; }\n.csk-md-code-copy {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(255, 255, 255, 0.12);\n color: #CBD5E1;\n border-radius: 6px;\n cursor: pointer;\n opacity: 0;\n transition: all 0.15s ease;\n}\n.csk-md-code-block:hover .csk-md-code-copy { opacity: 1; }\n.csk-md-code-copy:hover { background: rgba(255, 255, 255, 0.22); color: #fff; }\n.csk-md-code-copy:active { transform: scale(0.9); }\n\n/* ========== 新消息提示按钮 ========== */\n.csk-newmsg {\n position: absolute;\n bottom: 82px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 5;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 7px 14px;\n border: none;\n background: var(--csk-primary);\n color: #fff;\n font-size: 12px;\n font-family: inherit;\n border-radius: 999px;\n cursor: pointer;\n box-shadow: 0 4px 14px rgba(var(--csk-primary-rgb), 0.38);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: csk-msg-in 0.25s ease;\n white-space: nowrap;\n}\n.csk-newmsg:hover { transform: translateX(-50%) translateY(-1px); box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.48); }\n.csk-newmsg:active { transform: translateX(-50%) scale(0.95); }\n.csk-newmsg--hidden { display: none; }\n\n/* ========== 发送按钮停止态 ========== */\n.csk-send-btn--stop {\n background: #EF4444 !important;\n box-shadow: 0 3px 10px rgba(239, 68, 68, 0.35) !important;\n}\n.csk-send-btn--stop:hover:not(:disabled) {\n box-shadow: 0 5px 14px rgba(239, 68, 68, 0.45) !important;\n}\n\n/* ========== 暗色模式 ========== */\n.csk-root.csk-dark {\n --csk-bg-ai: #1E1E2E;\n --csk-text-ai: #E2E8F0;\n --csk-border: #3B3B52;\n --csk-bg-app: #141421;\n color: #E2E8F0;\n}\n.csk-dark .csk-window {\n background: #1A1A2E;\n box-shadow: 0 12px 48px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.2);\n}\n.csk-dark .csk-header::after { background: linear-gradient(to bottom, rgba(0,0,0,0.12), transparent); }\n.csk-dark .csk-msg__avatar--ai {\n background: var(--csk-bg-ai);\n color: var(--csk-primary);\n border-color: var(--csk-border);\n}\n.csk-dark .csk-input-area { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-input-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-input-wrap--focus { background: #1A1A2E; border-color: var(--csk-primary); }\n.csk-dark .csk-input { color: #E2E8F0; }\n.csk-dark .csk-loading__avatar { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__bubble { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__dot { background: #6B7280; }\n.csk-dark .csk-category-bar { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-category-select { background-color: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-sources { background: #1E1E2E; border-color: var(--csk-border); }\n.csk-dark .csk-sources__header { background: #25253A; }\n.csk-dark .csk-sources__header:hover { background: #2D2D48; }\n.csk-dark .csk-source-item:hover { background: var(--csk-bg-ai); }\n.csk-dark .csk-source-item__name { color: #E2E8F0; }\n.csk-dark .csk-source-item__meta { color: #6B7280; }\n.csk-dark .csk-history-panel { background: #1A1A2E; }\n.csk-dark .csk-history-panel__header { background: var(--csk-bg-app); border-bottom-color: var(--csk-border); }\n.csk-dark .csk-history-panel__back { background: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-history-panel__back:hover { background: #2D2D48; }\n.csk-dark .csk-history-item:hover { background: #25253A; }\n.csk-dark .csk-history-item__id { color: #E2E8F0; }\n.csk-dark .csk-history-item__meta { color: #6B7280; }\n.csk-dark .csk-history-item--active { background: rgba(var(--csk-primary-rgb), 0.15); }\n.csk-dark .csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.22); }\n.csk-dark .csk-action-btn:hover { background: #2D2D48; color: #E2E8F0; }\n.csk-dark .csk-clear-btn { background: var(--csk-bg-app); border-color: var(--csk-border); color: #9CA3AF; }\n.csk-dark .csk-clear-btn:hover { background: #3B1A1A; border-color: #7F1D1D; color: #FCA5A5; }\n.csk-dark .csk-md-code-block { background: #0F0F1A; }\n.csk-dark .csk-md-blockquote { background: rgba(var(--csk-primary-rgb), 0.08); }\n.csk-dark .csk-md-link { color: var(--csk-primary-light); }\n.csk-dark .csk-msg--ai .csk-msg__bubble { background: var(--csk-bg-ai); color: var(--csk-text-ai); border-color: var(--csk-border); }\n.csk-dark .csk-welcome__title { color: #E2E8F0; }\n.csk-dark .csk-welcome__desc { color: #6B7280; }\n.csk-dark .csk-quick-reply { background: var(--csk-bg-app); border-color: var(--csk-border); color: #CBD5E1; }\n.csk-dark .csk-quick-reply:hover { background: rgba(var(--csk-primary-rgb), 0.12); border-color: var(--csk-primary); color: var(--csk-primary-light); }\n.csk-dark .csk-teaser { background: #2D2D48; color: #E2E8F0; box-shadow: 0 4px 20px rgba(0,0,0,0.35); }\n.csk-dark .csk-teaser::after { border-top-color: #2D2D48; }\n.csk-dark .csk-teaser__close { color: #6B7280; }\n.csk-dark .csk-teaser__close:hover { color: #9CA3AF; }\n.csk-dark .csk-feedback-btn { background: rgba(var(--csk-primary-rgb), 0.1); color: #9CA3AF; }\n.csk-dark .csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.2); color: var(--csk-primary-light); }\n.csk-dark .csk-feedback-btn--active { background: rgba(var(--csk-primary-rgb), 0.28); color: var(--csk-primary-light); }\n.csk-dark .csk-history-panel__search-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-history-panel__search-wrap:focus-within { border-color: var(--csk-primary); }\n.csk-dark .csk-history-panel__search { color: #E2E8F0; }\n.csk-dark .csk-launcher__badge { box-shadow: 0 0 0 2px #1A1A2E; }\n.csk-dark .csk-welcome__avatar { box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.25); }\n.csk-dark .csk-header__avatar { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.1); }\n\n/* ========== Launcher 未读徽章 ========== */\n.csk-launcher__badge {\n position: absolute;\n top: -2px;\n right: -2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #EF4444;\n border: 2px solid #fff;\n box-shadow: 0 0 0 2px #fff;\n animation: csk-badge-in 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);\n pointer-events: none;\n}\n.csk-launcher__badge--hidden { display: none; }\n@keyframes csk-badge-in {\n from { transform: scale(0); }\n to { transform: scale(1); }\n}\n\n/* ========== Launcher 提示气泡 ========== */\n.csk-teaser {\n position: fixed;\n bottom: 90px;\n z-index: 9997;\n max-width: 240px;\n padding: 10px 14px;\n background: #fff;\n color: #1F2937;\n font-size: 13px;\n line-height: 1.5;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(15, 23, 42, 0.15);\n animation: csk-teaser-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);\n cursor: pointer;\n user-select: none;\n}\n.csk-teaser--right { right: 24px; }\n.csk-teaser--left { left: 24px; }\n.csk-teaser::after {\n content: '';\n position: absolute;\n bottom: -6px;\n right: 28px;\n width: 12px;\n height: 12px;\n background: inherit;\n border-radius: 2px;\n transform: rotate(45deg);\n box-shadow: 2px 2px 4px rgba(15, 23, 42, 0.08);\n}\n.csk-teaser--left::after { right: auto; left: 28px; }\n.csk-teaser__close {\n position: absolute;\n top: 4px;\n right: 6px;\n background: none;\n border: none;\n font-size: 16px;\n color: #9CA3AF;\n cursor: pointer;\n padding: 2px 4px;\n line-height: 1;\n border-radius: 4px;\n}\n.csk-teaser__close:hover { color: #374151; }\n.csk-teaser--hidden { display: none; }\n@keyframes csk-teaser-in {\n from { opacity: 0; transform: translateY(8px) scale(0.95); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n/* ========== 消息反馈按钮(👍 / 👎) ========== */\n.csk-feedback-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(var(--csk-primary-rgb), 0.08);\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n padding: 0;\n}\n.csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.18); color: var(--csk-primary); }\n.csk-feedback-btn--active {\n background: rgba(var(--csk-primary-rgb), 0.28);\n color: var(--csk-primary);\n}\n.csk-feedback-btn--active.down { background: #FEF2F2; color: #EF4444; }\n.csk-feedback-btn:active { transform: scale(0.9); }\n.csk-msg--streaming .csk-feedback-btn { display: none; }\n\n/* ========== 历史会话搜索框 ========== */\n.csk-history-panel__search-wrap {\n padding: 8px 10px;\n border-bottom: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-history-panel__search-wrap:focus-within {\n border-bottom-color: var(--csk-primary);\n}\n.csk-history-panel__search {\n width: 100%;\n padding: 7px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n font-family: inherit;\n color: #1F2937;\n background: var(--csk-bg-app);\n outline: none;\n transition: border-color 0.2s;\n}\n.csk-history-panel__search:focus { border-color: var(--csk-primary); }\n.csk-history-panel__search::placeholder { color: #9CA3AF; }\n\n/* ========== a11y 焦点指示 ========== */\n.csk-root :focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n}\n.csk-root button:focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n border-radius: inherit;\n}\n/* 弹窗打开时隐藏 launcher 上的焦点环 */\n.csk-launcher:focus-visible {\n outline: none;\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12),\n 0 0 0 4px rgba(var(--csk-primary-rgb), 0.3);\n}\n\n/* ========== a11y aria-live 播报区(视觉隐藏) ========== */\n.csk-sr-only {\n position: absolute !important;\n width: 1px !important;\n height: 1px !important;\n padding: 0 !important;\n margin: -1px !important;\n overflow: hidden !important;\n clip: rect(0,0,0,0) !important;\n white-space: nowrap !important;\n border: 0 !important;\n}\n\n/* ========== 会话分组标题 ========== */\n.csk-history-group {\n margin-bottom: 4px;\n}\n.csk-history-group__label {\n font-size: 11px;\n font-weight: 600;\n color: #9CA3AF;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: 8px 12px 4px;\n user-select: none;\n}\n.csk-dark .csk-history-group__label { color: #6B7280; }\n\n/* ========== 移动端适配 ========== */\n@media (max-width: 480px) {\n .csk-window {\n width: 100vw !important;\n height: 100vh !important;\n max-height: 100vh;\n bottom: 0 !important;\n right: 0 !important;\n left: 0 !important;\n border-radius: 0;\n }\n .csk-window--hidden { transform: translateY(100%); }\n .csk-launcher { bottom: 20px; }\n .csk-launcher--right { right: 20px; }\n .csk-launcher--left { left: 20px; }\n}\n`}(e),document.head.appendChild(T))}function z(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const n=16*Math.random()|0;return("x"===e?n:3&n|8).toString(16)})}function H(e){const n={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,e=>n[e]||e)}function j(){return Date.now()}const R='';function P(e,n){const t=document.createElement("div");t.id="csk-launcher";const r=e.launcherTheme?" csk-launcher--glass":"";t.className=`csk-launcher csk-launcher--${"left-bottom"===e.position?"left":"right"}${r}`,t.setAttribute("title",e.title),t.setAttribute("aria-label",e.title),t.setAttribute("role","button"),t.setAttribute("tabindex","0"),t.innerHTML=e.launcherIcon;const s=document.createElement("div");s.className="csk-launcher__badge csk-launcher__badge--hidden",t.appendChild(s);const o=function(e,n){let t=null;return function(...r){null!==t&&clearTimeout(t),t=setTimeout(()=>{e.apply(this,r),t=null},n)}}(n,300);return t.addEventListener("click",o),t.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),o())}),t}function U(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--user";const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--user",s.innerHTML='';const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.textContent=n;const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(t),o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),r}function O(e,n,t,r,s){const o=document.createElement("div");o.className="csk-msg csk-msg--ai",s&&(o.dataset.cskMsgId=s);const a=document.createElement("div");a.className="csk-msg__avatar csk-msg__avatar--ai",a.innerHTML=R;const i=document.createElement("div");i.className="csk-msg__content";const c=document.createElement("div");c.className="csk-msg__bubble",r?c.innerHTML=r(n):c.textContent=n;const l=document.createElement("div");return l.className="csk-msg__time",l.textContent=ne(t),i.appendChild(c),i.appendChild(G(c,o)),i.appendChild(l),o.appendChild(a),o.appendChild(i),e.appendChild(o),X(c),o}const Y='',W='';function G(e,n){const t=document.createElement("div");t.className="csk-msg__actions";const r=document.createElement("button");r.type="button",r.className="csk-action-btn",r.setAttribute("title",m("copy")),r.setAttribute("aria-label",m("copy")),r.innerHTML=Y,r.addEventListener("click",async n=>{n.stopPropagation();const t=e.textContent||"";await K(t,r)});const s=document.createElement("button");s.type="button",s.className="csk-action-btn",s.setAttribute("title",m("retry")),s.setAttribute("aria-label",m("retry")),s.innerHTML=W,s.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:retry",{detail:{msgId:n.dataset.cskMsgId||""}}))});const o=document.createElement("button");o.type="button",o.className="csk-feedback-btn",o.setAttribute("title",m("feedback_up")),o.setAttribute("aria-label",m("feedback_up")),o.innerHTML='',o.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"up"}}))});const a=document.createElement("button");return a.type="button",a.className="csk-feedback-btn",a.setAttribute("title",m("feedback_down")),a.setAttribute("aria-label",m("feedback_down")),a.innerHTML='',a.addEventListener("click",e=>{e.stopPropagation();const t=n.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:n.dataset.cskMsgId||"",value:"down"}}))}),t.appendChild(r),t.appendChild(s),t.appendChild(o),t.appendChild(a),t}function V(e,n){const t=e.querySelectorAll(".csk-feedback-btn");t.length<2||(t.forEach(e=>e.classList.remove("csk-feedback-btn--active","down")),"up"===n&&t[0]&&t[0].classList.add("csk-feedback-btn--active"),"down"===n&&t[1]&&t[1].classList.add("csk-feedback-btn--active","down"))}async function K(e,n){const t=n.innerHTML;try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(e);else{const n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}n.innerHTML='',n.classList.add("csk-action-btn--done"),setTimeout(()=>{n.innerHTML=t,n.classList.remove("csk-action-btn--done")},1500)}catch(e){}}function X(e){e.querySelectorAll(".csk-md-code-block").forEach(e=>{if(e.querySelector(".csk-md-code-copy"))return;const n=e.querySelector("code"),t=document.createElement("button");t.type="button",t.className="csk-md-code-copy",t.setAttribute("title",m("copy")),t.setAttribute("aria-label",m("copy")),t.innerHTML=Y,t.addEventListener("click",async e=>{e.stopPropagation(),await K((null==n?void 0:n.textContent)||"",t)}),e.appendChild(t)})}function J(e,n){e.classList.remove("csk-msg--streaming");const t=n.querySelector(".csk-caret");t&&t.remove(),X(n)}function Q(e,n){const t=e.querySelector(".csk-sources");if(t&&t.remove(),!n||0===n.length)return;const r=document.createElement("div");r.className="csk-sources csk-sources--collapsed";const s=document.createElement("div");s.className="csk-sources__header";const o=document.createElement("span");o.className="csk-sources__title",o.textContent=`📚 ${m("source_count",{n:n.length})}`;const a=document.createElement("span");a.className="csk-sources__arrow",a.textContent="▼",s.appendChild(o),s.appendChild(a),s.addEventListener("click",()=>{r.classList.toggle("csk-sources--collapsed")});const i=document.createElement("div");i.className="csk-sources__body";for(const e of n){const n=document.createElement("div");n.className="csk-source-item";const t=document.createElement("div");if(t.className="csk-source-item__name",t.textContent=e.title||e.sourceName||"未知文档",e.snippet){const t=document.createElement("div");t.className="csk-source-item__snippet",t.textContent=e.snippet,n.appendChild(t)}const r=document.createElement("div");r.className="csk-source-item__meta";const s=[];e.sourceName&&s.push(e.sourceName),void 0!==e.chunkIndex&&s.push(`分块 #${e.chunkIndex}`),void 0!==e.score&&s.push(`相关度 ${(100*e.score).toFixed(0)}%`),r.textContent=s.join(" · "),n.appendChild(t),n.appendChild(r),i.appendChild(n)}r.appendChild(s),r.appendChild(i);const c=e.querySelector(".csk-msg__time");c&&c.parentNode?c.parentNode.insertBefore(r,c):e.appendChild(r)}function Z(e,n,t,r,s,o,a){if(e.innerHTML="",0===n.length){const n=document.createElement("div");return n.className="csk-history-panel__empty",n.innerHTML=`\n
💬
\n
${m("history_empty")}
\n `,void e.appendChild(n)}const i=function(e){const n=new Date,t=new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime(),r=t-864e5,s=t-864e5*(n.getDay()||7)+864e5,o={today:[],yesterday:[],week:[],earlier:[]};for(const n of e){const e=n.lastMessageTime||n.createdAt,a=e?new Date(e).getTime():0;a>=t?o.today.push(n):a>=r?o.yesterday.push(n):a>=s?o.week.push(n):o.earlier.push(n)}const a=[];return o.today.length&&a.push({label:m("history_group_today"),items:o.today}),o.yesterday.length&&a.push({label:m("history_group_yesterday"),items:o.yesterday}),o.week.length&&a.push({label:m("history_group_week"),items:o.week}),o.earlier.length&&a.push({label:m("history_group_earlier"),items:o.earlier}),a}(n);for(const n of i){if(i.length>1){const t=document.createElement("div");t.className="csk-history-group";const r=document.createElement("div");r.className="csk-history-group__label",r.textContent=n.label,t.appendChild(r),e.appendChild(t)}for(const a of n.items){const n=document.createElement("div");n.className="csk-history-item";const i=a.chatId||a.id;o&&i===o&&n.classList.add("csk-history-item--active");const c=document.createElement("div");c.className="csk-history-item__info";const l=document.createElement("div");l.className="csk-history-item__id",a.lastMessagePreview?l.textContent=a.lastMessagePreview.length>60?a.lastMessagePreview.substring(0,60)+"...":a.lastMessagePreview:l.textContent=i;const d=document.createElement("div");d.className="csk-history-item__meta";const p=[];void 0!==a.messageCount&&p.push(`${a.messageCount} 条消息`),a.lastMessageTime?p.push(a.lastMessageTime):a.createdAt&&p.push(a.createdAt),d.textContent=p.join(" · "),c.appendChild(l),c.appendChild(d);const u=document.createElement("div");u.className="csk-history-item__actions";const g=document.createElement("button");g.className="csk-history-action csk-history-action--export",g.setAttribute("title",m("history_export")),g.innerHTML='',g.addEventListener("click",e=>{e.stopPropagation(),r(a.id)});const k=document.createElement("button");k.className="csk-history-action csk-history-action--delete",k.setAttribute("title",m("history_delete")),k.innerHTML='',k.addEventListener("click",e=>{e.stopPropagation(),s(a.id)}),u.appendChild(g),u.appendChild(k),n.appendChild(c),n.appendChild(u),n.addEventListener("click",()=>{t(i)}),e.appendChild(n)}}}function ee(e){e.scrollTop=e.scrollHeight}function ne(e){const n=new Date(e);return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}function te(e){return`csk_history_${e}`}function re(e,n){try{let t=n;t.length>200&&(t=t.slice(50),o.warn(`消息数量达到上限,已裁剪最早 50 条,当前 ${t.length} 条`));const r={messages:t,updatedAt:Date.now()};localStorage.setItem(te(e),JSON.stringify(r))}catch(e){e instanceof Error&&"QuotaExceededError"===e.name?o.error("localStorage 空间不足,会话历史保存失败。建议清空历史记录。"):o.error("保存会话历史失败",e)}}function se(e){try{localStorage.removeItem(te(e))}catch(e){o.warn("清空会话历史失败",e)}}const oe="\0CODEBLOCK_",ae="\0INLINECODE_";function ie(e){if(!e||"string"!=typeof e)return"";const n=[];let t=e;t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(e,t,r)=>{const s=n.length,o=H(r.trimEnd()),a=t?` class="language-${H(t)}"`:"";return n.push(`
${o}
`),`${oe}${s}\0`});const r=[];t=t.replace(/`([^`\n]+)`/g,(e,n)=>{const t=r.length;return r.push(`${H(n)}`),`${ae}${t}\0`}),t=H(t),t=ce(t,oe,n),t=ce(t,ae,r);const s=t.split("\n"),o=[];let a=!1,i="",c=!1,l=[];for(let e=0;e')){p(),u(),g(),o.push(n);continue}const t=n.match(/^(#{1,6})\s+(.+)/);if(t){p(),u(),g();const e=t[1].length;o.push(`${t[2]}`);continue}const r=n.match(/^>\s?(.*)/);if(r){p(),u(),c||(c=!0,o.push('
')),o.push(`

${d(r[1])}

`);continue}c&&g();const k=n.match(/^[\-\*]\s+(.+)/);if(k){p(),g(),a&&"ul"===i||(u(),a=!0,i="ul",o.push('
    ')),o.push(`
  • ${d(k[1])}
  • `);continue}const m=n.match(/^\d+\.\s+(.+)/);m?(p(),g(),a&&"ol"===i||(u(),a=!0,i="ol",o.push('
      ')),o.push(`
    1. ${d(m[1])}
    2. `)):""!==n.trim()?/^(\*{3,}|-{3,}|_{3,})$/.test(n.trim())?(p(),u(),g(),o.push('
      ')):(u(),g(),l.push(d(n))):(p(),u())}return p(),u(),g(),o.join("\n");function d(e){return e=(e=(e=(e=(e=(e=e.replace(/\*\*(.+?)\*\*/g,"$1")).replace(/__(.+?)__/g,"$1")).replace(/\*(.+?)\*/g,"$1")).replace(/(?$1")).replace(/~~(.+?)~~/g,"$1")).replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,n,t)=>`${n}`)}function p(){l.length>0&&(o.push(`

      ${l.join("
      ")}

      `),l=[])}function u(){a&&(o.push("ul"===i?"
":""),a=!1,i="")}function g(){c&&(o.push("
"),c=!1)}}function ce(e,n,t){return e.replace(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"(\\d+)\0","g"),(e,n)=>t[parseInt(n)]||"")}let le,de=null,pe=[],ue=null,ge=null,ke=null,me=null,he=null,be=null,fe=null,ye=null,xe=null,ve=null,we=null,_e=null,Ee=null,Ce=!1,Ie=null,$e=!0,Ae=[],Le="",Se=!1;function Fe(e,n){de=e,ue=n.messagesContainer,ge=n.inputEl,ke=n.inputEl.parentElement,me=n.sendBtn,he=n.clearBtn,be=n.categorySelect,fe=n.historyPanel,ye=n.welcomeEl,xe=n.newMsgBtn,ve=n.searchInput,we=n.ariaLiveEl,_e=n.showLoading,Ee=n.hideLoading,le=e.categoryId,Se=e.enableRag,function(){if(!ge||!me)return;me.addEventListener("click",()=>{Ce&&Ie?Ie.abort():je()}),ge.addEventListener("keydown",e=>{"Enter"!==e.key||e.shiftKey||e.isComposing||(e.preventDefault(),je())}),ge.addEventListener("input",()=>{He(),function(){if(!ge)return;ge.style.height="auto",ge.style.height=`${Math.min(ge.scrollHeight,120)}px`}()}),ge.addEventListener("focus",()=>{ke&&ke.classList.add("csk-input-wrap--focus")}),ge.addEventListener("blur",()=>{ke&&ke.classList.remove("csk-input-wrap--focus")}),he&&he.addEventListener("click",()=>function(){if(!de)return;if(!confirm(m("clear_confirm")))return;if(pe=[],ue){ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove())}he&&(he.style.display="none");ze(),se(de.integrateId);const e=function(){const e="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${e}`}();b(e),M(de.integrateId,de.userId,e),o.lifecycleClear(de.integrateId),o.info(`新 chatId=${e}`)}())}(),function(){if(!ue)return;ue.addEventListener("scroll",()=>{if(!ue)return;const{scrollTop:e,scrollHeight:n,clientHeight:t}=ue;$e=n-e-t<80,$e&&Me()}),xe&&xe.addEventListener("click",()=>{ue&&ee(ue),$e=!0,Me()})}(),function(){if(!ve)return;ve.addEventListener("input",()=>{Le=ve.value.trim().toLowerCase(),Be()})}(),e.showCategorySwitch&&be&&async function(){if(!be)return;try{const e=await async function(){const e=y("/category/tree");try{const n=await v(e);if(!n.ok)throw new w(_(n.status),`http_${n.status}`);const t=await n.json();return t.success&&Array.isArray(t.data)?(o.info(`加载分类树成功 count=${t.data.length}`),t.data):[]}catch(e){return e instanceof w?o.error(`加载分类树失败: ${e.message}`):o.error("加载分类树失败",e),[]}}();if(0===e.length)return;be.innerHTML=``;const n=(e,t=0)=>{for(const r of e){const e=document.createElement("option");e.value=String(r.id),e.textContent=`${" ".repeat(t)}${r.name}`,void 0!==le&&String(r.id)===String(le)&&(e.selected=!0),be.appendChild(e),r.children&&r.children.length>0&&n(r.children,t+1)}};n(e),o.info(`知识库分类加载成功 count=${e.length}`)}catch(e){o.error(m("category_load_error"),e)}}()}async function Ne(){if(de&&ue&&(await F(),await async function(){if(!de||!ue)return;const e=f();if(!e)return;try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map((e,n)=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`从后端加载 ${pe.length} 条历史消息`),re(de.integrateId,pe))}catch(e){o.warn("从后端加载历史消息失败",e)}}(),0===pe.length)){const e=function(e){try{const n=localStorage.getItem(te(e));if(!n)return[];const t=JSON.parse(n);return t&&Array.isArray(t.messages)?(o.info(`加载历史消息 integrateId=${e} count=${t.messages.length}`),t.messages):[]}catch(e){return o.warn("加载会话历史失败",e),[]}}(de.integrateId);e.length>0&&(pe=e,Pe(),o.info(`从本地缓存恢复 ${e.length} 条消息`))}}function Me(){xe&&xe.classList.add("csk-newmsg--hidden")}function Te(){ue&&($e?ee(ue):xe&&xe.classList.remove("csk-newmsg--hidden"))}function De(e){me&&("stop"===e?(me.classList.add("csk-send-btn--stop"),me.removeAttribute("disabled"),me.setAttribute("title",m("stop")),me.setAttribute("aria-label",m("stop")),me.innerHTML=''):(me.classList.remove("csk-send-btn--stop"),me.setAttribute("title",m("send")),me.setAttribute("aria-label",m("send")),me.innerHTML='',He()))}function Be(){const e=null==fe?void 0:fe.querySelector("#csk-history-list");if(!e||!de)return;Z(e,Le?Ae.filter(e=>(e.lastMessagePreview||e.chatId||e.id||"").toLowerCase().includes(Le)):Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{if(!confirm(m("history_delete_confirm")))return;await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}function qe(e,n){if(!ue)return;const t=pe.find(n=>n.id===e&&"ai"===n.role);if(!t)return;const r=t.feedback===n?void 0:n;t.feedback=r;const s=ue.querySelector(`[data-csk-msg-id="${e}"]`);if(s&&V(s,r),de&&re(de.integrateId,pe),r){const n="up"===r?"THUMBS_UP":"THUMBS_DOWN";(async function(e,n){if(!h)return!1;const t=y("/feedback");try{const r=await v(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messageId:String(e),conversationId:h.chatId,feedbackType:n})});return r.ok?(await r.json()).success||!1:(o.error(`反馈提交失败 status=${r.status}`),!1)}catch(e){return o.error("反馈提交异常",e),!1}})(String(e),n).then(n=>{n?o.info(`消息反馈已提交 msgId=${e} value=${r}`):o.warn(`消息反馈提交失败 msgId=${e}(本地状态已更新)`)})}else o.info(`消息反馈已取消 msgId=${e}`)}function ze(){if(!ye)return;const e=pe.length>0||ue&&ue.querySelector(".csk-msg");ye.style.display=e?"none":""}function He(){if(!me||!ge)return;ge.value.trim().length>0&&!Ce?me.removeAttribute("disabled"):me.setAttribute("disabled","true")}async function je(){if(!ge||!de||Ce)return;const e=ge.value.trim();if(""===e)return;ge.value="",He(),ge.style.height="auto";const n=j(),t={id:z(),role:"user",content:e,timestamp:n};ue&&U(ue,e,n),pe.push(t),ze(),he&&pe.length>0&&(he.style.display="inline-flex"),ue&&Te(),await Re(e)}async function Re(e){if(!de||!ue)return;Ce=!0,De("stop"),de.chatId||await F();const n=j(),t=Se;_e&&_e(),ue&&Te();const r=z();let s="";try{de.streaming?s=await async function(e,n,t,r){Ie=new AbortController;const s=Ie.signal;return new Promise((o,a)=>{let i=null,c=null,l="",d=!1;C(e,e=>{if(l+=e,!d&&ue){Ee&&Ee();const{wrapper:e,bubble:t}=function(e,n,t){const r=document.createElement("div");r.className="csk-msg csk-msg--ai csk-msg--streaming",t&&(r.dataset.cskMsgId=t);const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--ai",s.innerHTML=R;const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.innerHTML="";const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=ne(n),o.appendChild(a),o.appendChild(G(a,r)),o.appendChild(i),r.appendChild(s),r.appendChild(o),e.appendChild(r),{wrapper:r,bubble:a}}(ue,n,r);c=e,i=t,d=!0}i&&(i.textContent=l,function(e){if(e.querySelector(".csk-caret"))return;const n=document.createElement("span");n.className="csk-caret",n.setAttribute("aria-hidden","true"),e.appendChild(n)}(i)),ue&&Te()},()=>{if(c&&i){if(!d&&""===l)return void E(e).then(o).catch(a);l&&(i.innerHTML=ie(l)),J(c,i)}o(l)},e=>{l.length>0?(i&&(i.innerHTML=ie(l+"\n\n"+m("stream_interrupted")),c&&J(c,i)),o(l)):a(e)},le,t,s)})}(e,n,t,r):(s=await E(e),Ee&&Ee(),ue&&O(ue,s,n,ie,r));const a={id:r,role:"ai",content:s,timestamp:n};pe.push(a),re(de.integrateId,pe),ue&&Te(),function(e){if(!we)return;const n=e.length>120?e.substring(0,120)+"...":e;we.textContent=m("new_msg_announce")+":"+n}(s),ue&&ue.dispatchEvent(new CustomEvent("csk:newMessage",{bubbles:!0,detail:{msg:a}})),t&&async function(e,n){try{const t=await I(e,le);if(t.length>0){const e=t.map(e=>{var n,t;return{documentId:e.documentId||"",title:e.title||"",sourceName:e.sourceName||"",chunkIndex:null!==(n=e.chunkIndex)&&void 0!==n?n:0,score:null!==(t=e.score)&&void 0!==t?t:0,snippet:e.snippet||""}});if(n.sources=e,ue){const n=ue.querySelector(".csk-msg--ai:last-of-type");n&&Q(n,e)}de&&re(de.integrateId,pe)}}catch(e){o.warn("获取引用来源失败",e)}}(e,a)}catch(e){Ee&&Ee();const n=e instanceof w?e.message:m("error_send");if(ue){const e=document.createElement("div");e.className="csk-msg csk-msg--ai";const t=document.createElement("div");t.className="csk-msg__bubble",t.style.color="#DC2626",t.textContent=`⚠ ${n}`,e.appendChild(t),ue.appendChild(e)}o.error(`发送失败 integrateId=${de.integrateId}`,e)}finally{Ce=!1,Ie=null,De("send"),He()}}function Pe(){if(!ue)return;const e=ue.querySelector(".csk-history-panel");ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());for(const e of pe)if("user"===e.role)U(ue,e.content,e.timestamp);else{const n=O(ue,e.content,e.timestamp,ie,e.id);e.sources&&e.sources.length>0&&Q(n,e.sources),e.feedback&&V(n,e.feedback)}$e=!0,ee(ue),he&&pe.length>0&&(he.style.display="inline-flex"),ze(),e&&!ue.contains(e)&&ue.appendChild(e)}async function Ue(e){if(!de||!ue)return;o.info(`切换到会话 conversationId=${e}`),b(e),M(de.integrateId,de.userId,e),fe&&fe.classList.add("csk-history-panel--hidden"),pe=[];ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove());try{const n=await A(e);n.messages.length>0&&(pe=n.messages.map(e=>({id:z(),role:"USER"===e.messageType?"user":"ai",content:e.content,timestamp:new Date(e.createTime).getTime()})),Pe(),o.info(`加载会话 ${e} 的 ${pe.length} 条消息`),re(de.integrateId,pe))}catch(n){o.warn(`加载会话消息失败 conversationId=${e}`,n)}he&&pe.length>0&&(he.style.display="inline-flex"),ze()}let Oe=null,Ye=!1,We=null,Ge=null,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,tn=null,rn=null,sn=null,on=null,an=null;function cn(){if(!rn||!We)return;const e=We.getBoundingClientRect();"left-bottom"===(null==Oe?void 0:Oe.position)?rn.style.left=`${e.left}px`:rn.style.right=window.innerWidth-e.right+"px",rn.style.bottom=window.innerHeight-e.top+8+"px"}function ln(){if(!rn)return;rn.classList.add("csk-teaser--hidden"),rn.removeEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.removeEventListener("click",pn)}function dn(e){e.target.closest(".csk-teaser__close")||(ln(),mn())}function pn(e){e.stopPropagation(),ln()}function un(){rn&&!rn.classList.contains("csk-teaser--hidden")&&cn()}const gn='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';function kn(e){"Escape"===e.key&&Ge&&!Ge.classList.contains("csk-window--hidden")&&hn(),function(e){if(!Ge||Ge.classList.contains("csk-window--hidden"))return;if("Tab"!==e.key)return;const n=Array.from(Ge.querySelectorAll(gn));if(0===n.length)return;const t=n[0],r=n[n.length-1];e.shiftKey?document.activeElement===t&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),t.focus())}(e)}function mn(){Ge&&(Ge.classList.remove("csk-window--hidden"),ln(),on&&on.classList.add("csk-launcher__badge--hidden"),setTimeout(()=>{Ke&&Ke.focus()},80))}function hn(){Ge&&Ge.classList.add("csk-window--hidden")}function bn(){Ge&&(Ge.classList.contains("csk-window--hidden")?mn():hn())}function fn(e){return`csk_position_${e}`}const yn={init:function(e){if(Ye)return void o.warn("SDK 已初始化,请先调用 destroy() 再重新初始化");const t=function(e){var n,t,r,s,i,g,k,m,h,b,f;if(!e.integrateId||"string"!=typeof e.integrateId&&"number"!=typeof e.integrateId||"string"==typeof e.integrateId&&""===e.integrateId.trim())return o.error('integrateId 是必传参数(对应后端 roleId 客服角色 ID),请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;if(!e.requestDomain||"string"!=typeof e.requestDomain||""===e.requestDomain.trim())return o.error('requestDomain 是必传参数,请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;try{new URL(e.requestDomain)}catch(n){return o.error(`requestDomain 不是合法的 URL 格式:${e.requestDomain}。请提供完整的域名,如 https://api.example.com`),null}const y=String(e.integrateId).trim(),x=e.launcherTheme||void 0;let v=e.launcherIcon||a,w=e.primaryColor||"#4F46E5";x&&!e.launcherIcon&&(v={"dream-purple":c,"mint-tech":l,"coral-peach":d,"sky-blue":p}[x]||a,e.primaryColor||(w=u[x]||"#4F46E5"));const _={integrateId:y,requestDomain:e.requestDomain.replace(/\/+$/,""),userId:e.userId,categoryId:e.categoryId,showCategorySwitch:null!==(n=e.showCategorySwitch)&&void 0!==n&&n,title:e.title||"AI 智能助手",width:null!==(t=e.width)&&void 0!==t?t:380,height:Math.max(300,null!==(r=e.height)&&void 0!==r?r:520),position:"left-bottom"===e.position?"left-bottom":"right-bottom",primaryColor:w,launcherTheme:x,launcherIcon:v,showClear:null===(s=e.showClear)||void 0===s||s,showAdminPanel:null!==(i=e.showAdminPanel)&&void 0!==i&&i,quickReplies:Array.isArray(e.quickReplies)?e.quickReplies.map(e=>String(e).trim()).filter(Boolean):[],theme:"dark"===e.theme?"dark":"light",showTeaser:null===(g=e.showTeaser)||void 0===g||g,teaserText:"string"==typeof e.teaserText&&e.teaserText.trim()||"",streaming:null===(k=e.streaming)||void 0===k||k,enableRag:!1!==e.enableRag,rewriteStrategy:e.rewriteStrategy||"REWRITE",locale:e.locale||"zh-CN",debug:null===(h=e.debug)||void 0===h||h,sound:null!==(b=e.sound)&&void 0!==b&&b,notification:null!==(f=e.notification)&&void 0!==f&&f,onError:"function"==typeof e.onError?e.onError:void 0,onReady:"function"==typeof e.onReady?e.onReady:void 0,onMessage:"function"==typeof e.onMessage?e.onMessage:void 0,chatId:""};return o.info(`配置解析完成 integrateId(=roleId)=${_.integrateId} userId(=accountId)=${_.userId||"(未设置)"} requestDomain=${_.requestDomain}`),_}(e);if(!t)return;var s;Oe=t,function(e){if(g[e])k=e;else{const n=e.split("-")[0],t=Object.keys(g).find(e=>e.startsWith(n));t&&(k=t)}}(Oe.locale),s=Oe.debug,n=s,r(Oe.onError),function(e){h=e}(Oe),q(Oe),We=P(Oe,bn),document.body.appendChild(We),on=We.querySelector(".csk-launcher__badge");const i=function(e){const n=document.createElement("div");n.id="csk-window",n.className=`csk-root csk-window csk-window--${"left-bottom"===e.position?"left":"right"} csk-window--hidden${"dark"===e.theme?" csk-dark":""}`,n.setAttribute("role","dialog"),n.setAttribute("aria-label",e.title),n.setAttribute("aria-modal","false");const t=document.createElement("div");t.className="csk-header";const r=document.createElement("div");r.className="csk-header__left";const s=document.createElement("div");s.className="csk-header__avatar",s.innerHTML=R;const o=document.createElement("div");o.className="csk-header__info";const a=document.createElement("span");a.className="csk-header__title",a.textContent=e.title;const i=document.createElement("span");i.className="csk-header__status",i.innerHTML=`${m("status_online")}`,o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o);const c=document.createElement("div");c.className="csk-header__actions";const l=document.createElement("button");l.className="csk-history-btn",l.setAttribute("title",m("history_title")),l.innerHTML='';const d=document.createElement("button");d.className="csk-header__btn csk-header__btn--minimize",d.setAttribute("title",m("minimize")),d.innerHTML='',d.addEventListener("click",()=>{n.classList.add("csk-window--hidden")});const p=document.createElement("button");p.className="csk-header__btn csk-header__btn--close",p.setAttribute("title",m("close")),p.innerHTML='',p.addEventListener("click",()=>{n.classList.add("csk-window--hidden")}),c.appendChild(l),c.appendChild(d),c.appendChild(p),t.appendChild(r),t.appendChild(c);const u=document.createElement("div");u.id="csk-messages",u.className="csk-messages";const g=document.createElement("div");if(g.className="csk-welcome",g.innerHTML=`\n
${R}
\n
${m("welcome_title")}
\n
${m("welcome_desc")}
\n `,e.quickReplies.length>0){const t=document.createElement("div");t.className="csk-quick-replies";for(const r of e.quickReplies){const e=document.createElement("button");e.type="button",e.className="csk-quick-reply",e.textContent=r,e.addEventListener("click",()=>{n.dispatchEvent(new CustomEvent("csk:quickReply",{detail:{text:r}}))}),t.appendChild(e)}g.appendChild(t)}u.appendChild(g);const k=document.createElement("button");k.type="button",k.className="csk-newmsg csk-newmsg--hidden",k.innerHTML=`\n \n ${m("new_message")}\n `,n.appendChild(k);const h=document.createElement("div");h.className="csk-history-panel csk-history-panel--hidden",h.innerHTML=`\n
\n ${m("history_title")}\n \n
\n
\n \n
\n
\n `,u.appendChild(h);const b=h.querySelector("#csk-history-back");b&&b.addEventListener("click",()=>{h.classList.add("csk-history-panel--hidden")}),l.addEventListener("click",e=>{e.stopPropagation();const t=h.classList.contains("csk-history-panel--hidden");h.classList.toggle("csk-history-panel--hidden"),t&&n.dispatchEvent(new CustomEvent("csk:loadHistory"))});let f=null;if(e.showCategorySwitch){const e=document.createElement("div");e.className="csk-category-bar";const r=document.createElement("span");r.className="csk-category-bar__label",r.textContent="📚",f=document.createElement("select"),f.id="csk-category-select",f.className="csk-category-select",f.innerHTML=``,f.addEventListener("change",()=>{const e=f.value;n.dispatchEvent(new CustomEvent("csk:categoryChange",{detail:{categoryId:e?Number(e):void 0}}))}),e.appendChild(r),e.appendChild(f),n.appendChild(t),n.appendChild(u),n.appendChild(e)}else n.appendChild(t),n.appendChild(u);const y=document.createElement("div");y.className="csk-input-area";const x=document.createElement("div");x.className="csk-input-wrap";const v=document.createElement("textarea");v.id="csk-input",v.className="csk-input",v.setAttribute("placeholder",m("placeholder")),v.setAttribute("rows","1"),v.setAttribute("autofocus","");const w=document.createElement("button");w.id="csk-send-btn",w.className="csk-send-btn",w.setAttribute("title",m("send")),w.setAttribute("disabled","true"),w.innerHTML='',x.appendChild(v),x.appendChild(w),y.appendChild(x),n.appendChild(y);let _=null;e.showClear&&(_=document.createElement("button"),_.className="csk-clear-btn",_.textContent=m("clear"),_.style.display="none",n.insertBefore(_,y));let E=null;const C=document.createElement("div");C.className="csk-sr-only",C.setAttribute("aria-live","polite"),C.setAttribute("aria-atomic","true"),n.appendChild(C);const I=h.querySelector("#csk-history-search"),$=document.createElement("div");return $.className=`csk-teaser csk-teaser--${"left-bottom"===e.position?"left":"right"} csk-teaser--hidden`,$.setAttribute("role","status"),$.innerHTML=`\n \n ${e.teaserText||m("teaser_text")}\n `,{window:n,messagesContainer:u,inputEl:v,sendBtn:w,clearBtn:_,categorySelect:f,historyPanel:h,welcomeEl:g,newMsgBtn:k,teaserEl:$,searchInput:I,ariaLiveEl:C,showLoading:function(){if(E)return E.style.display="flex",E;const e=document.createElement("div");return e.className="csk-loading",e.innerHTML=`\n
${R}
\n
\n
\n
\n
\n
\n `,u.appendChild(e),E=e,e},hideLoading:function(){E&&E.parentNode&&(E.parentNode.removeChild(E),E=null)}}}(Oe);Ge=i.window,Ve=i.messagesContainer,Ke=i.inputEl,Xe=i.sendBtn,Je=i.clearBtn,Qe=i.categorySelect,Ze=i.historyPanel,en=i.showLoading,nn=i.hideLoading,document.body.appendChild(Ge),rn=i.teaserEl,document.body.appendChild(rn),cn();const b=Ge.querySelector(".csk-header");if(b&&(tn=function(e,n,t){let r=!1,s=0,o=0,a=0,i=0;const c=e=>{if(e.target.closest("button"))return;r=!0,s=e.clientX,o=e.clientY;const t=n.getBoundingClientRect();a=s-t.left,i=o-t.top,document.addEventListener("mousemove",l),document.addEventListener("mouseup",d)},l=e=>{if(!r)return;const t=e.clientX-a,s=e.clientY-i,o=window.innerWidth-n.offsetWidth,c=window.innerHeight-n.offsetHeight;n.style.right="auto",n.style.bottom="auto",n.style.left=`${Math.max(0,Math.min(t,o))}px`,n.style.top=`${Math.max(0,Math.min(s,c))}px`},d=()=>{if(r=!1,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d),t){const e=n.getBoundingClientRect();t({x:e.left,y:e.top})}};return e.addEventListener("mousedown",c),()=>{e.removeEventListener("mousedown",c),document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d)}}(b,Ge,e=>{!function(e,n){try{localStorage.setItem(fn(e),JSON.stringify(n))}catch(e){}}(Oe.integrateId,e)})),function(e,n){try{const t=localStorage.getItem(fn(e));if(!t)return;const r=JSON.parse(t);if("number"!=typeof r.x||"number"!=typeof r.y)return;const s=window.innerWidth-n.offsetWidth,o=window.innerHeight-n.offsetHeight,a=Math.max(0,Math.min(r.x,s)),i=Math.max(0,Math.min(r.y,o));n.style.right="auto",n.style.bottom="auto",n.style.left=`${a}px`,n.style.top=`${i}px`}catch(e){}}(Oe.integrateId,Ge),Fe(Oe,{messagesContainer:Ve,inputEl:Ke,sendBtn:Xe,clearBtn:Je,categorySelect:Qe,historyPanel:Ze,welcomeEl:i.welcomeEl,newMsgBtn:i.newMsgBtn,searchInput:i.searchInput,ariaLiveEl:i.ariaLiveEl,showLoading:en,hideLoading:nn}),Ge.addEventListener("csk:categoryChange",e=>{var n;n=e.detail.categoryId,le=n,Se=null==de||de.enableRag,o.lifecycleCategoryChange(null!=n?n:"全部")}),Ge.addEventListener("csk:loadHistory",()=>{!async function(){if(!fe||!de)return;const e=fe.querySelector("#csk-history-list");if(e){e.innerHTML='
加载中...
';try{const n=await $(1,50,de.userId,de.integrateId);Ae=n.list.map(e=>({id:e.conversationId||"",chatId:e.conversationId||"",messageCount:e.messageCount,lastMessageTime:e.lastMessageTime,lastMessagePreview:e.lastMessagePreview,createdAt:e.firstMessageTime||e.createdAt})),Le="",ve&&(ve.value=""),Z(e,Ae,e=>{Ue(e)},e=>{window.open(S(e),"_blank")},async e=>{confirm(m("history_delete_confirm"))&&await L(e)&&(e===f()&&(pe=[],ue&&ue.querySelectorAll(".csk-msg, .csk-loading").forEach(e=>e.remove()),he&&(he.style.display="none"),ze()),Ae=Ae.filter(n=>(n.chatId||n.id)!==e),Be())},f())}catch(n){o.error(m("history_load_error"),n),e.innerHTML=`
${m("history_load_error")}
`}}}()}),Ge.addEventListener("csk:quickReply",e=>{var n;n=e.detail.text,!ge||Ce?Promise.resolve():(ge.value=n,He(),je())}),Ge.addEventListener("csk:retry",e=>{!async function(e){if(!de||!ue||Ce)return;const n=pe.findIndex(n=>n.id===e&&"ai"===n.role);if(n<0)return;let t="";for(let e=n-1;e>=0;e--)if("user"===pe[e].role){t=pe[e].content;break}if(!t)return;const r=pe.splice(n),s=new Set(r.map(e=>e.id));ue.querySelectorAll(".csk-msg").forEach(e=>{const n=e.dataset.cskMsgId;n&&s.has(n)&&e.remove()}),re(de.integrateId,pe),ze(),await Re(t)}(e.detail.msgId)}),Ge.addEventListener("csk:feedback",e=>{qe(e.detail.msgId,e.detail.value)}),Ge.addEventListener("csk:newMessage",e=>{var n;if(Ge&&Ge.classList.contains("csk-window--hidden")&&(on&&on.classList.remove("csk-launcher__badge--hidden"),(null==Oe?void 0:Oe.sound)&&function(){try{an||(an=new(window.AudioContext||window.webkitAudioContext));const e=an;if("suspended"===e.state)return void e.resume();const n=e.currentTime;[0,.15].forEach((t,r)=>{const s=e.createOscillator(),o=e.createGain();s.type="sine",s.frequency.value=0===r?880:1100,o.gain.setValueAtTime(.15,n+t),o.gain.exponentialRampToValueAtTime(.001,n+t+.12),s.connect(o),o.connect(e.destination),s.start(n+t),s.stop(n+t+.12)})}catch(e){}}(),(null==Oe?void 0:Oe.notification)&&function(){try{if(!("Notification"in window))return;"granted"===Notification.permission?new Notification((null==Oe?void 0:Oe.title)||"AI 智能助手",{body:"收到新消息",icon:void 0,silent:!0}):"denied"!==Notification.permission&&Notification.requestPermission()}catch(e){}}()),(null==Oe?void 0:Oe.onMessage)&&(null===(n=e.detail)||void 0===n?void 0:n.msg))try{Oe.onMessage(e.detail.msg)}catch(e){}}),document.addEventListener("keydown",kn),window.addEventListener("resize",un),Ye=!0,o.lifecycleInit(Oe.integrateId,Oe.requestDomain),Oe.onReady)try{Oe.onReady()}catch(e){}Oe.showTeaser&&(sn=setTimeout(()=>{Ge&&Ge.classList.contains("csk-window--hidden")&&function(){if(!rn)return;cn(),rn.classList.remove("csk-teaser--hidden"),rn.addEventListener("click",dn);const e=rn.querySelector(".csk-teaser__close");e&&e.addEventListener("click",pn)}()},1500)),Ne().catch(e=>{o.warn("chatId 初始化失败,将在发送消息时重试",e)})},destroy:function(){if(!Ye)return;sn&&(clearTimeout(sn),sn=null),ln(),rn&&rn.parentNode&&(rn.parentNode.removeChild(rn),rn=null),We&&We.parentNode&&(We.parentNode.removeChild(We),We=null),Ge&&Ge.parentNode&&(Ge.parentNode.removeChild(Ge),Ge=null),tn&&(tn(),tn=null),T&&T.parentNode&&(T.parentNode.removeChild(T),T=null),document.querySelectorAll("style[data-csk-sdk]").forEach(e=>e.remove()),document.removeEventListener("keydown",kn),window.removeEventListener("resize",un),r(void 0);const e=null==Oe?void 0:Oe.integrateId;Oe=null,Ye=!1,Ve=null,Ke=null,Xe=null,Je=null,Qe=null,Ze=null,en=null,nn=null,on=null,an=null,o.lifecycleDestroy(e||"")},open:mn,close:hn,toggle:bn,clearHistory:function(){Oe&&(Je?Je.click():confirm("确定清空所有对话记录?")&&se(Oe.integrateId))}};return"undefined"!=typeof window&&(window.ChatbotSDK=yn),yn}(); //# sourceMappingURL=chatbot-sdk.min.js.map diff --git a/src/main/resources/static/sdk/test.html b/src/main/resources/static/sdk/test.html index 54ac5cf..4630b2f 100644 --- a/src/main/resources/static/sdk/test.html +++ b/src/main/resources/static/sdk/test.html @@ -162,7 +162,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
- +
@@ -204,7 +204,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S 3. chatId 自动管理:从 /conversation/list 获取或自动生成
4. 对话历史从后端加载(点击头部时钟图标查看)
5. AI 回复支持 Markdown 渲染
- 6. 开启 showCategorySwitch 可选择知识库分类 + 6. SDK 默认启用 RAG 检索;开启 showCategorySwitch 可选择知识库分类

@@ -330,7 +330,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S streaming: true, locale: 'zh-CN', showCategorySwitch: false, - enableRag: false, + enableRag: true, }; // 生成 Script 片段代码(纯文本)