@xto/chat 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/ChatContainer/index.d.ts +1 -0
- package/es/ChatContainer/index.vue.d.ts +45 -0
- package/es/ChatContainer/types.d.ts +27 -0
- package/es/CodeBlock/index.d.ts +1 -0
- package/es/CodeBlock/index.vue.d.ts +10 -0
- package/es/FeedbackButtons/index.d.ts +1 -0
- package/es/FeedbackButtons/index.vue.d.ts +11 -0
- package/es/FileUpload/index.d.ts +1 -0
- package/es/FileUpload/index.vue.d.ts +42 -0
- package/es/MarkdownRenderer/index.d.ts +1 -0
- package/es/MarkdownRenderer/index.vue.d.ts +9 -0
- package/es/MessageInput/index.d.ts +1 -0
- package/es/MessageInput/index.vue.d.ts +25 -0
- package/es/MessageItem/index.d.ts +1 -0
- package/es/MessageItem/index.vue.d.ts +17 -0
- package/es/MessageList/index.d.ts +1 -0
- package/es/MessageList/index.vue.d.ts +20 -0
- package/es/SuggestedQuestions/index.d.ts +1 -0
- package/es/SuggestedQuestions/index.vue.d.ts +11 -0
- package/es/ThinkingChain/index.d.ts +1 -0
- package/es/ThinkingChain/index.vue.d.ts +10 -0
- package/es/ToolCallDisplay/index.d.ts +1 -0
- package/es/ToolCallDisplay/index.vue.d.ts +8 -0
- package/es/composables/useAutoScroll.d.ts +11 -0
- package/es/composables/useChat.d.ts +83 -0
- package/es/composables/useSSE.d.ts +12 -0
- package/es/index.d.ts +22 -0
- package/es/index.mjs +682 -0
- package/es/style.css +1 -0
- package/es/types/index.d.ts +60 -0
- package/es/utils/index.d.ts +37 -0
- package/lib/index.cjs +1 -0
- package/lib/style.css +1 -0
- package/package.json +60 -0
package/es/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.x-markdown-renderer{font-size:14px;line-height:1.6}.x-markdown-renderer h1,.x-markdown-renderer h2,.x-markdown-renderer h3,.x-markdown-renderer h4,.x-markdown-renderer h5,.x-markdown-renderer h6{margin:12px 0 6px;font-weight:600}.x-markdown-renderer h1{font-size:1.5em}.x-markdown-renderer h2{font-size:1.3em}.x-markdown-renderer h3{font-size:1.1em}.x-markdown-renderer p{margin:6px 0}.x-markdown-renderer ul,.x-markdown-renderer ol{padding-left:20px;margin:6px 0}.x-markdown-renderer code{background:#f0f0f0;padding:2px 4px;border-radius:2px;font-family:Monaco,Consolas,monospace;font-size:.9em}.x-markdown-renderer pre{margin:8px 0;border-radius:4px;overflow:hidden}.x-markdown-renderer pre code{display:block;padding:8px 12px;background:#1e1e1e;color:#d4d4d4}.x-markdown-renderer blockquote{border-left:3px solid #d0d0d0;padding-left:12px;margin:8px 0;color:#666}.x-markdown-renderer table{border-collapse:collapse;margin:8px 0}.x-markdown-renderer table th,.x-markdown-renderer table td{border:1px solid #d0d0d0;padding:6px 10px}.x-markdown-renderer table th{background:#f5f5f5}.x-markdown-renderer a{color:#155eef;text-decoration:none}.x-markdown-renderer a:hover{text-decoration:underline}.x-markdown-renderer img{max-width:100%;border-radius:4px}.x-markdown-renderer hr{border:none;border-top:1px solid #e0e0e0;margin:12px 0}.x-thinking-chain{background:#fafafa;border:1px solid #e8e8e8;border-radius:4px;margin-bottom:8px;font-size:12px}.x-thinking-chain__header{display:flex;align-items:center;gap:6px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none}.x-thinking-chain__icon{font-size:14px}.x-thinking-chain__title{font-weight:600;color:#666}.x-thinking-chain__toggle{margin-left:auto;color:#999}.x-thinking-chain__steps{padding:0 10px 8px}.x-thinking-chain__step{border-left:2px solid #d0d0d0;padding-left:8px;margin-bottom:6px}.x-thinking-chain__step:last-child{margin-bottom:0}.x-thinking-chain__field{display:flex;gap:4px;margin-bottom:2px}.x-thinking-chain__label{color:#999;font-weight:600;flex-shrink:0}.x-thinking-chain__value{color:#333;word-break:break-word}.x-thinking-chain__value--action{color:#155eef;font-weight:500}.x-tool-call-display{background:#f9f9f9;border:1px solid #e8e8e8;border-radius:4px;margin-bottom:8px;font-size:12px}.x-tool-call-display__item{border-bottom:1px solid #f0f0f0}.x-tool-call-display__item:last-child{border-bottom:none}.x-tool-call-display__header{display:flex;align-items:center;gap:6px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none}.x-tool-call-display__icon{font-size:12px}.x-tool-call-display__name{font-weight:600;color:#333}.x-tool-call-display__status{font-size:11px;padding:1px 6px;border-radius:2px}.x-tool-call-display__status--success{background:#d1fae5;color:#10b981}.x-tool-call-display__status--failed{background:#fee2e2;color:#ef4444}.x-tool-call-display__time{color:#999;font-size:11px}.x-tool-call-display__toggle{margin-left:auto;color:#999}.x-tool-call-display__body{padding:8px 10px;background:#fafafa}.x-tool-call-display__section{margin-bottom:6px}.x-tool-call-display__label{color:#999;margin-bottom:2px}.x-tool-call-display__code{background:#1e1e1e;color:#d4d4d4;padding:6px;border-radius:2px;font-size:11px;overflow-x:auto;margin:0}.x-tool-call-display__error{color:#ef4444;background:#fef2f2;padding:4px 6px;border-radius:2px}.x-feedback-buttons{display:flex;gap:4px;margin-top:4px}.x-feedback-buttons__btn{background:none;border:1px solid transparent;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px}.x-feedback-buttons__btn:hover{background:#f5f5f5}.x-feedback-buttons__btn--active{background:#f0f7ff;border-color:#155eef}.x-message-item{display:flex;gap:12px}.x-message-item--user{flex-direction:row-reverse}.x-message-item__avatar{width:32px;height:32px;border-radius:50%;background:#155eef;color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0}.x-message-item--user .x-message-item__avatar{background:#10b981}.x-message-item__body{flex:1;max-width:80%}.x-message-item--user .x-message-item__body{text-align:right}.x-message-item__meta{font-size:11px;color:#999;margin-bottom:4px;display:flex;gap:8px}.x-message-item__content{background:#f5f5f5;padding:12px 16px;border-radius:8px;font-size:14px;line-height:1.6;text-align:left;word-break:break-word}.x-message-item--user .x-message-item__content{background:#155eef;color:#fff}.x-message-item__cursor{animation:blink 1s infinite;font-weight:700}@keyframes blink{0%,50%{opacity:1}51%,to{opacity:0}}.x-message-list{display:flex;flex-direction:column;gap:16px}.x-message-list__loading{display:flex;gap:4px;align-items:center;padding:8px}.x-message-list__dot{width:8px;height:8px;background:#999;border-radius:50%;animation:bounce 1.4s infinite ease-in-out}.x-message-list__dot:nth-child(1){animation-delay:-.32s}.x-message-list__dot:nth-child(2){animation-delay:-.16s}@keyframes bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.x-message-input__attachments{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px}.x-message-input__attachment{display:flex;align-items:center;gap:4px;padding:4px 8px;background:#f5f5f5;border-radius:4px;font-size:12px}.x-message-input__attachment-remove{background:none;border:none;cursor:pointer;color:#999}.x-message-input__row{display:flex;gap:8px;align-items:flex-end}.x-message-input__upload{cursor:pointer;padding:8px;background:#f5f5f5;border-radius:4px}.x-message-input__upload input{display:none}.x-message-input__textarea{flex:1;padding:10px 12px;border:1px solid #d0d0d0;border-radius:8px;resize:none;font-size:14px;line-height:1.5;font-family:inherit;max-height:200px;overflow-y:auto}.x-message-input__textarea:focus{outline:none;border-color:#155eef}.x-message-input__textarea:disabled{background:#f5f5f5;cursor:not-allowed}.x-message-input__actions{display:flex;flex-direction:column;align-items:flex-end;gap:4px}.x-message-input__count{font-size:11px;color:#999}.x-message-input__btn{padding:8px 16px;border:none;border-radius:6px;cursor:pointer;font-size:13px}.x-message-input__btn--send{background:#155eef;color:#fff}.x-message-input__btn--send:disabled{background:#ccc;cursor:not-allowed}.x-message-input__btn--stop{background:#ef4444;color:#fff}.x-suggested-questions__label{font-size:11px;color:#999;margin-bottom:4px}.x-suggested-questions__list{display:flex;flex-wrap:wrap;gap:6px}.x-suggested-questions__item{padding:4px 10px;border:1px solid #d0d0d0;border-radius:12px;background:#fff;color:#155eef;cursor:pointer;font-size:12px;transition:all .2s}.x-suggested-questions__item:hover{background:#155eef;color:#fff;border-color:#155eef}.x-chat-container{display:flex;flex-direction:column;height:100%;background:#fff}.x-chat-container__messages{flex:1;overflow-y:auto;padding:16px}.x-chat-container__suggested{padding:8px 16px;border-top:1px solid #f0f0f0}.x-chat-container__input{border-top:1px solid #e0e0e0;padding:12px 16px}.x-code-block{border-radius:4px;overflow:hidden;margin:8px 0}.x-code-block__header{display:flex;justify-content:space-between;align-items:center;background:#2d2d2d;color:#ccc;padding:4px 8px;font-size:11px}.x-code-block__language{text-transform:uppercase}.x-code-block__copy{background:none;border:1px solid #555;color:#ccc;padding:2px 8px;border-radius:2px;cursor:pointer;font-size:11px}.x-code-block__copy:hover{background:#444}.x-code-block__pre{background:#1e1e1e;color:#d4d4d4;padding:8px 12px;margin:0;overflow-x:auto;font-family:Monaco,Consolas,monospace;font-size:12px;line-height:1.5}.x-file-upload__dropzone{border:2px dashed #d0d0d0;border-radius:6px;padding:16px;text-align:center;cursor:pointer;transition:all .2s;position:relative}.x-file-upload__dropzone:hover,.x-file-upload__dropzone--active{border-color:#155eef;background:#f0f7ff}.x-file-upload__dropzone input[type=file]{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;cursor:pointer}.x-file-upload__hint{font-size:13px;color:#666}.x-file-upload__hint span{display:block}.x-file-upload__max{font-size:11px;color:#999;margin-top:4px}.x-file-upload__list{margin-top:8px;display:flex;flex-direction:column;gap:4px}.x-file-upload__item{display:flex;align-items:center;gap:8px;padding:6px 10px;background:#f5f5f5;border-radius:4px;font-size:12px}.x-file-upload__name{flex:1;color:#333}.x-file-upload__size{color:#999}.x-file-upload__remove{background:none;border:none;cursor:pointer;color:#ef4444;font-size:16px}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 聊天类型定义。
|
|
3
|
+
*/
|
|
4
|
+
export type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
|
|
5
|
+
export type MessageStatus = 'pending' | 'streaming' | 'completed' | 'failed';
|
|
6
|
+
export interface Message {
|
|
7
|
+
id?: string;
|
|
8
|
+
role: MessageRole;
|
|
9
|
+
content: string;
|
|
10
|
+
status?: MessageStatus;
|
|
11
|
+
thinkingChain?: ThinkingStep[];
|
|
12
|
+
toolCalls?: ToolCall[];
|
|
13
|
+
tokenUsage?: number;
|
|
14
|
+
latency?: number;
|
|
15
|
+
attachments?: MessageAttachment[];
|
|
16
|
+
feedback?: 'like' | 'dislike' | null;
|
|
17
|
+
timestamp?: number;
|
|
18
|
+
toolCallId?: string;
|
|
19
|
+
toolName?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface MessageAttachment {
|
|
22
|
+
referenceId: string;
|
|
23
|
+
fileName: string;
|
|
24
|
+
mimeType: string;
|
|
25
|
+
size: number;
|
|
26
|
+
}
|
|
27
|
+
export interface ChatSession {
|
|
28
|
+
id: string;
|
|
29
|
+
title: string;
|
|
30
|
+
messages: Message[];
|
|
31
|
+
variables?: Record<string, unknown>;
|
|
32
|
+
summary?: string;
|
|
33
|
+
status: 'active' | 'archived';
|
|
34
|
+
createdAt: number;
|
|
35
|
+
updatedAt: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ChatEvent {
|
|
38
|
+
type: 'message_started' | 'message_chunk' | 'message_completed' | 'message_failed' | 'thinking_step' | 'tool_call_started' | 'tool_call_completed';
|
|
39
|
+
message?: Message;
|
|
40
|
+
chunk?: string;
|
|
41
|
+
thinkingStep?: ThinkingStep;
|
|
42
|
+
toolCall?: ToolCall;
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ThinkingStep {
|
|
46
|
+
thought?: string;
|
|
47
|
+
action?: string;
|
|
48
|
+
actionInput?: string;
|
|
49
|
+
observation?: string;
|
|
50
|
+
timestamp?: number;
|
|
51
|
+
}
|
|
52
|
+
export interface ToolCall {
|
|
53
|
+
id?: string;
|
|
54
|
+
name: string;
|
|
55
|
+
arguments?: Record<string, unknown>;
|
|
56
|
+
result?: unknown;
|
|
57
|
+
elapsedMs?: number;
|
|
58
|
+
success?: boolean;
|
|
59
|
+
errorMessage?: string;
|
|
60
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Message } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* 消息格式化工具。
|
|
4
|
+
*/
|
|
5
|
+
export declare const messageFormatter: {
|
|
6
|
+
/**
|
|
7
|
+
* 格式化时间戳为本地时间字符串。
|
|
8
|
+
*/
|
|
9
|
+
formatTime(timestamp: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* 格式化耗时为人类可读字符串。
|
|
12
|
+
*/
|
|
13
|
+
formatLatency(ms: number): string;
|
|
14
|
+
/**
|
|
15
|
+
* 粗略估算 token 数(中文按字数 / 英文按单词数 * 1.3)。
|
|
16
|
+
*/
|
|
17
|
+
estimateTokens(text: string): number;
|
|
18
|
+
/**
|
|
19
|
+
* 提取消息中的代码块。
|
|
20
|
+
*/
|
|
21
|
+
extractCodeBlocks(content: string): Array<{
|
|
22
|
+
language: string;
|
|
23
|
+
code: string;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* 截断长消息。
|
|
27
|
+
*/
|
|
28
|
+
truncate(message: Message, maxLength: number): Message;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Token 计数器。
|
|
32
|
+
*/
|
|
33
|
+
export declare const tokenCounter: {
|
|
34
|
+
count(text: string): number;
|
|
35
|
+
countMessage(message: Message): number;
|
|
36
|
+
countMessages(messages: Message[]): number;
|
|
37
|
+
};
|
package/lib/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),L=require("markdown-it"),$=require("highlight.js"),w=require("dompurify"),A=require("dayjs"),z=["innerHTML"],x=e.defineComponent({name:"XMarkdownRenderer",__name:"index",props:{content:{default:""},enableHighlight:{type:Boolean,default:!0}},setup(t){const l=t,o=e.computed(()=>{const s=new L({html:!1,linkify:!0,breaks:!0,highlight(a,n){if(n&&l.enableHighlight&&$.getLanguage(n))try{return`<pre class="hljs"><code>${$.highlight(a,{language:n}).value}</code></pre>`}catch{}return`<pre class="hljs"><code>${s.utils.escapeHtml(a)}</code></pre>`}});return s}),c=e.computed(()=>{if(!l.content)return"";const s=o.value.render(l.content);return w.sanitize(s,{ADD_ATTR:["target"],ALLOWED_TAGS:w.config.ALLOWED_TAGS})});return e.watch(c,()=>{}),(s,a)=>(e.openBlock(),e.createElementBlock("div",{class:"x-markdown-renderer",innerHTML:c.value},null,8,z))}}),I={class:"x-thinking-chain"},U={class:"x-thinking-chain__title"},q={class:"x-thinking-chain__toggle"},H={key:0,class:"x-thinking-chain__steps"},X={key:0,class:"x-thinking-chain__field"},O={class:"x-thinking-chain__value"},Q={key:1,class:"x-thinking-chain__field"},j={class:"x-thinking-chain__value x-thinking-chain__value--action"},R={key:2,class:"x-thinking-chain__field"},K={class:"x-thinking-chain__value"},G={key:3,class:"x-thinking-chain__field"},J={class:"x-thinking-chain__value"},B=e.defineComponent({name:"XThinkingChain",__name:"index",props:{steps:{default:()=>[]},collapsed:{type:Boolean,default:!1}},setup(t){const l=t,o=e.ref(l.collapsed),c=()=>{o.value=!o.value},s=e.computed(()=>l.steps.length);return(a,n)=>(e.openBlock(),e.createElementBlock("div",I,[e.createElementVNode("div",{class:"x-thinking-chain__header",onClick:c},[n[0]||(n[0]=e.createElementVNode("span",{class:"x-thinking-chain__icon"},"🧠",-1)),e.createElementVNode("span",U,"思维链 ("+e.toDisplayString(s.value)+" 步)",1),e.createElementVNode("span",q,e.toDisplayString(o.value?"▶":"▼"),1)]),o.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",H,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.steps,(i,m)=>(e.openBlock(),e.createElementBlock("div",{key:m,class:"x-thinking-chain__step"},[i.thought?(e.openBlock(),e.createElementBlock("div",X,[n[1]||(n[1]=e.createElementVNode("span",{class:"x-thinking-chain__label"},"Thought:",-1)),e.createElementVNode("span",O,e.toDisplayString(i.thought),1)])):e.createCommentVNode("",!0),i.action?(e.openBlock(),e.createElementBlock("div",Q,[n[2]||(n[2]=e.createElementVNode("span",{class:"x-thinking-chain__label"},"Action:",-1)),e.createElementVNode("span",j,e.toDisplayString(i.action),1)])):e.createCommentVNode("",!0),i.actionInput?(e.openBlock(),e.createElementBlock("div",R,[n[3]||(n[3]=e.createElementVNode("span",{class:"x-thinking-chain__label"},"Action Input:",-1)),e.createElementVNode("span",K,e.toDisplayString(i.actionInput),1)])):e.createCommentVNode("",!0),i.observation?(e.openBlock(),e.createElementBlock("div",G,[n[4]||(n[4]=e.createElementVNode("span",{class:"x-thinking-chain__label"},"Observation:",-1)),e.createElementVNode("span",J,e.toDisplayString(i.observation),1)])):e.createCommentVNode("",!0)]))),128))]))]))}}),P={key:0,class:"x-tool-call-display"},W=["onClick"],Y={class:"x-tool-call-display__name"},Z={key:0,class:"x-tool-call-display__time"},ee={class:"x-tool-call-display__toggle"},te={key:0,class:"x-tool-call-display__body"},ne={key:0,class:"x-tool-call-display__section"},se={class:"x-tool-call-display__code"},ae={key:1,class:"x-tool-call-display__section"},le={class:"x-tool-call-display__code"},oe={key:2,class:"x-tool-call-display__error"},y=e.defineComponent({name:"XToolCallDisplay",__name:"index",props:{toolCalls:{default:()=>[]}},setup(t){const l=e.ref(new Set),o=s=>{l.value.has(s)?l.value.delete(s):l.value.add(s)},c=s=>l.value.has(s);return(s,a)=>t.toolCalls.length?(e.openBlock(),e.createElementBlock("div",P,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.toolCalls,(n,i)=>(e.openBlock(),e.createElementBlock("div",{key:i,class:"x-tool-call-display__item"},[e.createElementVNode("div",{class:"x-tool-call-display__header",onClick:m=>o(i)},[a[0]||(a[0]=e.createElementVNode("span",{class:"x-tool-call-display__icon"},"🔧",-1)),e.createElementVNode("span",Y,e.toDisplayString(n.name),1),e.createElementVNode("span",{class:e.normalizeClass(["x-tool-call-display__status",`x-tool-call-display__status--${n.success?"success":"failed"}`])},e.toDisplayString(n.success===!1?"失败":"成功"),3),n.elapsedMs?(e.openBlock(),e.createElementBlock("span",Z,e.toDisplayString(n.elapsedMs)+"ms",1)):e.createCommentVNode("",!0),e.createElementVNode("span",ee,e.toDisplayString(c(i)?"▼":"▶"),1)],8,W),c(i)?(e.openBlock(),e.createElementBlock("div",te,[n.arguments?(e.openBlock(),e.createElementBlock("div",ne,[a[1]||(a[1]=e.createElementVNode("div",{class:"x-tool-call-display__label"},"参数:",-1)),e.createElementVNode("pre",se,e.toDisplayString(JSON.stringify(n.arguments,null,2)),1)])):e.createCommentVNode("",!0),n.result!==void 0?(e.openBlock(),e.createElementBlock("div",ae,[a[2]||(a[2]=e.createElementVNode("div",{class:"x-tool-call-display__label"},"结果:",-1)),e.createElementVNode("pre",le,e.toDisplayString(typeof n.result=="string"?n.result:JSON.stringify(n.result,null,2)),1)])):e.createCommentVNode("",!0),n.errorMessage?(e.openBlock(),e.createElementBlock("div",oe,e.toDisplayString(n.errorMessage),1)):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0)]))),128))])):e.createCommentVNode("",!0)}}),ce={class:"x-feedback-buttons"},E=e.defineComponent({name:"XFeedbackButtons",__name:"index",props:{current:{default:null}},emits:["feedback"],setup(t,{emit:l}){const o=l;return(c,s)=>(e.openBlock(),e.createElementBlock("div",ce,[e.createElementVNode("button",{class:e.normalizeClass(["x-feedback-buttons__btn",{"x-feedback-buttons__btn--active":t.current==="like"}]),onClick:s[0]||(s[0]=a=>o("feedback","like"))},"👍",2),e.createElementVNode("button",{class:e.normalizeClass(["x-feedback-buttons__btn",{"x-feedback-buttons__btn--active":t.current==="dislike"}]),onClick:s[1]||(s[1]=a=>o("feedback","dislike"))},"👎",2)]))}}),ie={key:0,class:"x-message-item__avatar"},re={key:0},de={key:1},ue={key:2},me={class:"x-message-item__body"},ge={key:0,class:"x-message-item__meta"},pe={class:"x-message-item__time"},he={key:0,class:"x-message-item__latency"},ke={key:1,class:"x-message-item__tokens"},_e={class:"x-message-item__content"},fe={key:3,class:"x-message-item__cursor"},b=e.defineComponent({name:"XMessageItem",__name:"index",props:{message:{},showAvatar:{type:Boolean,default:!0},showTimestamp:{type:Boolean,default:!0},showFeedback:{type:Boolean,default:!0}},emits:["feedback"],setup(t,{emit:l}){const o=t,c=l,s=e.computed(()=>o.message.role==="user"),a=e.computed(()=>o.message.role==="assistant"),n=e.computed(()=>o.message.timestamp?A(o.message.timestamp).format("HH:mm:ss"):""),i=m=>{o.message.id&&c("feedback",o.message.id,m)};return(m,d)=>{var p,h;return e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["x-message-item",`x-message-item--${t.message.role}`])},[t.showAvatar?(e.openBlock(),e.createElementBlock("div",ie,[s.value?(e.openBlock(),e.createElementBlock("span",re,"U")):a.value?(e.openBlock(),e.createElementBlock("span",de,"AI")):(e.openBlock(),e.createElementBlock("span",ue,"S"))])):e.createCommentVNode("",!0),e.createElementVNode("div",me,[t.showTimestamp?(e.openBlock(),e.createElementBlock("div",ge,[e.createElementVNode("span",pe,e.toDisplayString(n.value),1),t.message.latency?(e.openBlock(),e.createElementBlock("span",he,e.toDisplayString((t.message.latency/1e3).toFixed(2))+"s",1)):e.createCommentVNode("",!0),t.message.tokenUsage?(e.openBlock(),e.createElementBlock("span",ke,e.toDisplayString(t.message.tokenUsage)+" tokens",1)):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),e.createElementVNode("div",_e,[(p=t.message.thinkingChain)!=null&&p.length?(e.openBlock(),e.createBlock(B,{key:0,steps:t.message.thinkingChain},null,8,["steps"])):e.createCommentVNode("",!0),(h=t.message.toolCalls)!=null&&h.length?(e.openBlock(),e.createBlock(y,{key:1,"tool-calls":t.message.toolCalls},null,8,["tool-calls"])):e.createCommentVNode("",!0),t.message.content?(e.openBlock(),e.createBlock(x,{key:2,content:t.message.content},null,8,["content"])):e.createCommentVNode("",!0),t.message.status==="streaming"?(e.openBlock(),e.createElementBlock("span",fe,"|")):e.createCommentVNode("",!0)]),t.showFeedback&&a.value&&t.message.status==="completed"?(e.openBlock(),e.createBlock(E,{key:1,current:t.message.feedback||null,onFeedback:i},null,8,["current"])):e.createCommentVNode("",!0)])],2)}}}),ve={class:"x-message-list"},xe={key:0,class:"x-message-list__loading"},C=e.defineComponent({name:"XMessageList",__name:"index",props:{messages:{default:()=>[]},loading:{type:Boolean,default:!1},showAvatar:{type:Boolean,default:!0},showTimestamp:{type:Boolean,default:!0},showFeedback:{type:Boolean,default:!0}},emits:["feedback"],setup(t,{emit:l}){const o=l,c=(s,a)=>o("feedback",s,a);return(s,a)=>(e.openBlock(),e.createElementBlock("div",ve,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.messages,n=>(e.openBlock(),e.createBlock(b,{key:n.id||n.timestamp,message:n,"show-avatar":t.showAvatar,"show-timestamp":t.showTimestamp,"show-feedback":t.showFeedback,onFeedback:c},null,8,["message","show-avatar","show-timestamp","show-feedback"]))),128)),t.loading?(e.openBlock(),e.createElementBlock("div",xe,[...a[0]||(a[0]=[e.createElementVNode("span",{class:"x-message-list__dot"},null,-1),e.createElementVNode("span",{class:"x-message-list__dot"},null,-1),e.createElementVNode("span",{class:"x-message-list__dot"},null,-1)])])):e.createCommentVNode("",!0)]))}}),Be={class:"x-message-input"},ye={key:0,class:"x-message-input__attachments"},Ee={class:"x-message-input__attachment-name"},be=["onClick"],Ce={class:"x-message-input__row"},Ne={key:0,class:"x-message-input__upload"},Ve=["placeholder","disabled","maxlength"],$e={class:"x-message-input__actions"},we={class:"x-message-input__count"},Se=["disabled"],N=e.defineComponent({name:"XMessageInput",__name:"index",props:{placeholder:{default:"请输入消息..."},maxLength:{default:4e3},disabled:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},enableFileUpload:{type:Boolean,default:!1}},emits:["send","stop","regenerate"],setup(t,{emit:l}){const o=t,c=l,s=e.ref(""),a=e.ref(null),n=e.ref([]),i=e.computed(()=>s.value.length),m=e.computed(()=>s.value.trim().length>0&&!o.disabled),d=()=>{a.value&&(a.value.style.height="auto",a.value.style.height=Math.min(a.value.scrollHeight,200)+"px")},p=()=>{d(),s.value.length>o.maxLength&&(s.value=s.value.substring(0,o.maxLength))},h=()=>{m.value&&(c("send",s.value.trim(),n.value.length?n.value:void 0),s.value="",n.value=[],e.nextTick(()=>d()))},_=r=>{r.key==="Enter"&&!r.shiftKey&&(r.preventDefault(),h())},f=r=>{const u=r.target;u.files&&(n.value=[...n.value,...Array.from(u.files)])},g=r=>{n.value.splice(r,1)};return(r,u)=>(e.openBlock(),e.createElementBlock("div",Be,[n.value.length?(e.openBlock(),e.createElementBlock("div",ye,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.value,(k,v)=>(e.openBlock(),e.createElementBlock("div",{key:v,class:"x-message-input__attachment"},[e.createElementVNode("span",Ee,e.toDisplayString(k.name),1),e.createElementVNode("button",{class:"x-message-input__attachment-remove",onClick:T=>g(v)},"×",8,be)]))),128))])):e.createCommentVNode("",!0),e.createElementVNode("div",Ce,[t.enableFileUpload?(e.openBlock(),e.createElementBlock("label",Ne,[e.createElementVNode("input",{type:"file",multiple:"",onChange:f},null,32),u[2]||(u[2]=e.createElementVNode("span",null,"📎",-1))])):e.createCommentVNode("",!0),e.withDirectives(e.createElementVNode("textarea",{ref_key:"textareaRef",ref:a,"onUpdate:modelValue":u[0]||(u[0]=k=>s.value=k),placeholder:t.placeholder,disabled:t.disabled,maxlength:t.maxLength,class:"x-message-input__textarea",rows:"1",onInput:p,onKeydown:_},null,40,Ve),[[e.vModelText,s.value]]),e.createElementVNode("div",$e,[e.createElementVNode("span",we,e.toDisplayString(i.value)+"/"+e.toDisplayString(t.maxLength),1),t.loading?(e.openBlock(),e.createElementBlock("button",{key:0,class:"x-message-input__btn x-message-input__btn--stop",onClick:u[1]||(u[1]=k=>c("stop"))},"停止")):(e.openBlock(),e.createElementBlock("button",{key:1,class:"x-message-input__btn x-message-input__btn--send",disabled:!m.value,onClick:h},"发送",8,Se))])])]))}}),De={key:0,class:"x-suggested-questions"},Me={class:"x-suggested-questions__list"},Fe=["onClick"],V=e.defineComponent({name:"XSuggestedQuestions",__name:"index",props:{questions:{default:()=>[]}},emits:["select"],setup(t,{emit:l}){const o=l,c=s=>o("select",s);return(s,a)=>t.questions.length?(e.openBlock(),e.createElementBlock("div",De,[a[0]||(a[0]=e.createElementVNode("div",{class:"x-suggested-questions__label"},"推荐问题:",-1)),e.createElementVNode("div",Me,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.questions,(n,i)=>(e.openBlock(),e.createElementBlock("button",{key:i,class:"x-suggested-questions__item",onClick:m=>c(n)},e.toDisplayString(n),9,Fe))),128))])])):e.createCommentVNode("",!0)}});function S(t){const l=e.ref(!0);let o=0;const c=()=>{if(!t.value)return;const{scrollTop:n,scrollHeight:i,clientHeight:m}=t.value,d=i-n-m<50;n<o&&!d?l.value=!1:d&&(l.value=!0),o=n},s=()=>{e.nextTick(()=>{t.value&&(t.value.scrollTop=t.value.scrollHeight)})},a=()=>{l.value=!0,s()};return t.value&&t.value.addEventListener("scroll",c),e.watch(t,(n,i,m)=>{n&&(n.addEventListener("scroll",c),m(()=>n.removeEventListener("scroll",c)))}),{autoScroll:l,scrollToBottom:s,enableAutoScroll:a}}const Te={class:"x-chat-container__messages"},Le={key:0,class:"x-chat-container__suggested"},Ae={class:"x-chat-container__input"},D=e.defineComponent({name:"XChatContainer",__name:"index",props:{messages:{default:()=>[]},loading:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},showAvatar:{type:Boolean,default:!0},showTimestamp:{type:Boolean,default:!0},showFeedback:{type:Boolean,default:!0},suggestedQuestions:{default:()=>[]},placeholder:{default:"请输入消息..."},maxLength:{default:4e3},enableFileUpload:{type:Boolean,default:!1}},emits:["send","stop","regenerate","feedback","selectQuestion"],setup(t,{expose:l,emit:o}){const c=t,s=o,a=e.ref(null),{autoScroll:n,scrollToBottom:i}=S(a),m=e.computed(()=>c.messages),d=(g,r)=>s("send",g,r),p=()=>s("stop"),h=()=>s("regenerate"),_=(g,r)=>s("feedback",g,r),f=g=>s("selectQuestion",g);return e.watch(()=>c.messages.length,()=>{n.value&&e.nextTick(()=>i())}),l({clearMessages:()=>s("send","__clear__"),scrollToBottom:i,appendMessage:g=>{c.messages.push(g)},updateLastMessage:g=>{c.messages.length>0&&(c.messages[c.messages.length-1]=g)}}),(g,r)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"containerRef",ref:a,class:"x-chat-container"},[e.createElementVNode("div",Te,[e.createVNode(C,{messages:m.value,loading:t.loading,"show-avatar":t.showAvatar,"show-timestamp":t.showTimestamp,"show-feedback":t.showFeedback,onFeedback:_},null,8,["messages","loading","show-avatar","show-timestamp","show-feedback"])]),t.suggestedQuestions.length?(e.openBlock(),e.createElementBlock("div",Le,[e.createVNode(V,{questions:t.suggestedQuestions,onSelect:f},null,8,["questions"])])):e.createCommentVNode("",!0),e.createElementVNode("div",Ae,[e.createVNode(N,{placeholder:t.placeholder,"max-length":t.maxLength,disabled:t.loading||t.readonly,"enable-file-upload":t.enableFileUpload,onSend:d,onStop:p,onRegenerate:h,loading:t.loading},null,8,["placeholder","max-length","disabled","enable-file-upload","loading"])])],512))}}),ze={class:"x-code-block"},Ie={class:"x-code-block__header"},Ue={class:"x-code-block__language"},qe={class:"x-code-block__pre"},M=e.defineComponent({name:"XCodeBlock",__name:"index",props:{code:{},language:{default:"plaintext"},showCopy:{type:Boolean,default:!0}},setup(t){const l=t,o=e.ref(!1),c=async()=>{try{await navigator.clipboard.writeText(l.code),o.value=!0,setTimeout(()=>{o.value=!1},2e3)}catch{}};return(s,a)=>(e.openBlock(),e.createElementBlock("div",ze,[e.createElementVNode("div",Ie,[e.createElementVNode("span",Ue,e.toDisplayString(t.language),1),t.showCopy?(e.openBlock(),e.createElementBlock("button",{key:0,class:"x-code-block__copy",onClick:c},e.toDisplayString(o.value?"已复制":"复制"),1)):e.createCommentVNode("",!0)]),e.createElementVNode("pre",qe,[e.createElementVNode("code",{class:e.normalizeClass(`language-${t.language}`)},e.toDisplayString(t.code),3)])]))}}),He={class:"x-file-upload"},Xe=["accept","multiple"],Oe={class:"x-file-upload__hint"},Qe={class:"x-file-upload__max"},je={key:0,class:"x-file-upload__list"},Re={class:"x-file-upload__name"},Ke={class:"x-file-upload__size"},Ge=["onClick"],F=e.defineComponent({name:"XFileUpload",__name:"index",props:{accept:{default:""},multiple:{type:Boolean,default:!0},maxSize:{default:50}},emits:["change","exceed"],setup(t,{expose:l,emit:o}){const c=t,s=o,a=e.ref([]),n=e.ref(!1),i=r=>r<1024?r+"B":r<1024*1024?(r/1024).toFixed(1)+"KB":(r/1024/1024).toFixed(1)+"MB",m=r=>{if(!r)return;const u=[];for(const k of Array.from(r)){if(k.size>c.maxSize*1024*1024){s("exceed",k);continue}u.push(k)}c.multiple?a.value=[...a.value,...u]:a.value=u,s("change",a.value)},d=r=>{const u=r.target;m(u.files)},p=r=>{var u;n.value=!1,(u=r.dataTransfer)!=null&&u.files&&m(r.dataTransfer.files)},h=()=>{n.value=!0},_=()=>{n.value=!1},f=r=>{a.value.splice(r,1),s("change",a.value)};return l({files:a,clear:()=>{a.value=[],s("change",a.value)}}),(r,u)=>(e.openBlock(),e.createElementBlock("div",He,[e.createElementVNode("div",{class:e.normalizeClass(["x-file-upload__dropzone",{"x-file-upload__dropzone--active":n.value}]),onDrop:e.withModifiers(p,["prevent"]),onDragover:e.withModifiers(h,["prevent"]),onDragleave:e.withModifiers(_,["prevent"])},[e.createElementVNode("input",{type:"file",accept:t.accept,multiple:t.multiple,onChange:d},null,40,Xe),e.createElementVNode("div",Oe,[u[0]||(u[0]=e.createElementVNode("span",null,"📎 拖拽文件到此处,或点击选择",-1)),e.createElementVNode("span",Qe,"最大 "+e.toDisplayString(t.maxSize)+"MB",1)])],34),a.value.length?(e.openBlock(),e.createElementBlock("div",je,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.value,(k,v)=>(e.openBlock(),e.createElementBlock("div",{key:v,class:"x-file-upload__item"},[e.createElementVNode("span",Re,e.toDisplayString(k.name),1),e.createElementVNode("span",Ke,e.toDisplayString(i(k.size)),1),e.createElementVNode("button",{class:"x-file-upload__remove",onClick:T=>f(v)},"×",8,Ge)]))),128))])):e.createCommentVNode("",!0)]))}});function Je(t){const l=e.ref([]),o=e.ref(!1),c=e.ref(null);return{messages:l,loading:o,error:c,send:async i=>{if(!i.trim()||o.value)return;const m={id:`user-${Date.now()}`,role:"user",content:i,status:"completed",timestamp:Date.now()};l.value.push(m);const d={id:`assistant-${Date.now()}`,role:"assistant",content:"",status:"pending",timestamp:Date.now()};l.value.push(d),o.value=!0,c.value=null;try{if(t!=null&&t.sendMessage){const p=await t.sendMessage(i);if(p instanceof ReadableStream){const h=p.getReader();let _="";for(;;){const{done:f,value:g}=await h.read();if(f)break;g&&(_+=g.content||"",d.content=_,d.status="streaming")}d.status="completed"}else Object.assign(d,p),d.status="completed"}else d.content="No sendMessage handler configured.",d.status="failed"}catch(p){d.status="failed",d.content=`Error: ${p.message||"Unknown error"}`,c.value=p.message}finally{o.value=!1}},stop:()=>{o.value=!1;const i=l.value[l.value.length-1];i&&i.status==="streaming"&&(i.status="completed")},clear:()=>{l.value=[],c.value=null}}}function Pe(){const t=e.ref(!1);let l=null;const o=(s,a,n)=>{c(),l=new EventSource(s),t.value=!0,l.onmessage=i=>{a(i.data)},l.onerror=i=>{t.value=!1,n==null||n(i)},l.onopen=()=>{t.value=!0}},c=()=>{l&&(l.close(),l=null,t.value=!1)};return e.onBeforeUnmount(()=>{c()}),{isConnected:t,connect:o,disconnect:c}}const We={ChatContainer:D,MessageList:C,MessageItem:b,MessageInput:N,ThinkingChain:B,ToolCallDisplay:y,MarkdownRenderer:x,CodeBlock:M,SuggestedQuestions:V,FileUpload:F,FeedbackButtons:E},Ye={install(t){Object.entries(We).forEach(([l,o])=>{t.component(l,o)})}};exports.ChatContainer=D;exports.CodeBlock=M;exports.FeedbackButtons=E;exports.FileUpload=F;exports.MarkdownRenderer=x;exports.MessageInput=N;exports.MessageItem=b;exports.MessageList=C;exports.SuggestedQuestions=V;exports.ThinkingChain=B;exports.ToolCallDisplay=y;exports.default=Ye;exports.useAutoScroll=S;exports.useChat=Je;exports.useSSE=Pe;
|
package/lib/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.x-markdown-renderer{font-size:14px;line-height:1.6}.x-markdown-renderer h1,.x-markdown-renderer h2,.x-markdown-renderer h3,.x-markdown-renderer h4,.x-markdown-renderer h5,.x-markdown-renderer h6{margin:12px 0 6px;font-weight:600}.x-markdown-renderer h1{font-size:1.5em}.x-markdown-renderer h2{font-size:1.3em}.x-markdown-renderer h3{font-size:1.1em}.x-markdown-renderer p{margin:6px 0}.x-markdown-renderer ul,.x-markdown-renderer ol{padding-left:20px;margin:6px 0}.x-markdown-renderer code{background:#f0f0f0;padding:2px 4px;border-radius:2px;font-family:Monaco,Consolas,monospace;font-size:.9em}.x-markdown-renderer pre{margin:8px 0;border-radius:4px;overflow:hidden}.x-markdown-renderer pre code{display:block;padding:8px 12px;background:#1e1e1e;color:#d4d4d4}.x-markdown-renderer blockquote{border-left:3px solid #d0d0d0;padding-left:12px;margin:8px 0;color:#666}.x-markdown-renderer table{border-collapse:collapse;margin:8px 0}.x-markdown-renderer table th,.x-markdown-renderer table td{border:1px solid #d0d0d0;padding:6px 10px}.x-markdown-renderer table th{background:#f5f5f5}.x-markdown-renderer a{color:#155eef;text-decoration:none}.x-markdown-renderer a:hover{text-decoration:underline}.x-markdown-renderer img{max-width:100%;border-radius:4px}.x-markdown-renderer hr{border:none;border-top:1px solid #e0e0e0;margin:12px 0}.x-thinking-chain{background:#fafafa;border:1px solid #e8e8e8;border-radius:4px;margin-bottom:8px;font-size:12px}.x-thinking-chain__header{display:flex;align-items:center;gap:6px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none}.x-thinking-chain__icon{font-size:14px}.x-thinking-chain__title{font-weight:600;color:#666}.x-thinking-chain__toggle{margin-left:auto;color:#999}.x-thinking-chain__steps{padding:0 10px 8px}.x-thinking-chain__step{border-left:2px solid #d0d0d0;padding-left:8px;margin-bottom:6px}.x-thinking-chain__step:last-child{margin-bottom:0}.x-thinking-chain__field{display:flex;gap:4px;margin-bottom:2px}.x-thinking-chain__label{color:#999;font-weight:600;flex-shrink:0}.x-thinking-chain__value{color:#333;word-break:break-word}.x-thinking-chain__value--action{color:#155eef;font-weight:500}.x-tool-call-display{background:#f9f9f9;border:1px solid #e8e8e8;border-radius:4px;margin-bottom:8px;font-size:12px}.x-tool-call-display__item{border-bottom:1px solid #f0f0f0}.x-tool-call-display__item:last-child{border-bottom:none}.x-tool-call-display__header{display:flex;align-items:center;gap:6px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none}.x-tool-call-display__icon{font-size:12px}.x-tool-call-display__name{font-weight:600;color:#333}.x-tool-call-display__status{font-size:11px;padding:1px 6px;border-radius:2px}.x-tool-call-display__status--success{background:#d1fae5;color:#10b981}.x-tool-call-display__status--failed{background:#fee2e2;color:#ef4444}.x-tool-call-display__time{color:#999;font-size:11px}.x-tool-call-display__toggle{margin-left:auto;color:#999}.x-tool-call-display__body{padding:8px 10px;background:#fafafa}.x-tool-call-display__section{margin-bottom:6px}.x-tool-call-display__label{color:#999;margin-bottom:2px}.x-tool-call-display__code{background:#1e1e1e;color:#d4d4d4;padding:6px;border-radius:2px;font-size:11px;overflow-x:auto;margin:0}.x-tool-call-display__error{color:#ef4444;background:#fef2f2;padding:4px 6px;border-radius:2px}.x-feedback-buttons{display:flex;gap:4px;margin-top:4px}.x-feedback-buttons__btn{background:none;border:1px solid transparent;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px}.x-feedback-buttons__btn:hover{background:#f5f5f5}.x-feedback-buttons__btn--active{background:#f0f7ff;border-color:#155eef}.x-message-item{display:flex;gap:12px}.x-message-item--user{flex-direction:row-reverse}.x-message-item__avatar{width:32px;height:32px;border-radius:50%;background:#155eef;color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0}.x-message-item--user .x-message-item__avatar{background:#10b981}.x-message-item__body{flex:1;max-width:80%}.x-message-item--user .x-message-item__body{text-align:right}.x-message-item__meta{font-size:11px;color:#999;margin-bottom:4px;display:flex;gap:8px}.x-message-item__content{background:#f5f5f5;padding:12px 16px;border-radius:8px;font-size:14px;line-height:1.6;text-align:left;word-break:break-word}.x-message-item--user .x-message-item__content{background:#155eef;color:#fff}.x-message-item__cursor{animation:blink 1s infinite;font-weight:700}@keyframes blink{0%,50%{opacity:1}51%,to{opacity:0}}.x-message-list{display:flex;flex-direction:column;gap:16px}.x-message-list__loading{display:flex;gap:4px;align-items:center;padding:8px}.x-message-list__dot{width:8px;height:8px;background:#999;border-radius:50%;animation:bounce 1.4s infinite ease-in-out}.x-message-list__dot:nth-child(1){animation-delay:-.32s}.x-message-list__dot:nth-child(2){animation-delay:-.16s}@keyframes bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.x-message-input__attachments{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px}.x-message-input__attachment{display:flex;align-items:center;gap:4px;padding:4px 8px;background:#f5f5f5;border-radius:4px;font-size:12px}.x-message-input__attachment-remove{background:none;border:none;cursor:pointer;color:#999}.x-message-input__row{display:flex;gap:8px;align-items:flex-end}.x-message-input__upload{cursor:pointer;padding:8px;background:#f5f5f5;border-radius:4px}.x-message-input__upload input{display:none}.x-message-input__textarea{flex:1;padding:10px 12px;border:1px solid #d0d0d0;border-radius:8px;resize:none;font-size:14px;line-height:1.5;font-family:inherit;max-height:200px;overflow-y:auto}.x-message-input__textarea:focus{outline:none;border-color:#155eef}.x-message-input__textarea:disabled{background:#f5f5f5;cursor:not-allowed}.x-message-input__actions{display:flex;flex-direction:column;align-items:flex-end;gap:4px}.x-message-input__count{font-size:11px;color:#999}.x-message-input__btn{padding:8px 16px;border:none;border-radius:6px;cursor:pointer;font-size:13px}.x-message-input__btn--send{background:#155eef;color:#fff}.x-message-input__btn--send:disabled{background:#ccc;cursor:not-allowed}.x-message-input__btn--stop{background:#ef4444;color:#fff}.x-suggested-questions__label{font-size:11px;color:#999;margin-bottom:4px}.x-suggested-questions__list{display:flex;flex-wrap:wrap;gap:6px}.x-suggested-questions__item{padding:4px 10px;border:1px solid #d0d0d0;border-radius:12px;background:#fff;color:#155eef;cursor:pointer;font-size:12px;transition:all .2s}.x-suggested-questions__item:hover{background:#155eef;color:#fff;border-color:#155eef}.x-chat-container{display:flex;flex-direction:column;height:100%;background:#fff}.x-chat-container__messages{flex:1;overflow-y:auto;padding:16px}.x-chat-container__suggested{padding:8px 16px;border-top:1px solid #f0f0f0}.x-chat-container__input{border-top:1px solid #e0e0e0;padding:12px 16px}.x-code-block{border-radius:4px;overflow:hidden;margin:8px 0}.x-code-block__header{display:flex;justify-content:space-between;align-items:center;background:#2d2d2d;color:#ccc;padding:4px 8px;font-size:11px}.x-code-block__language{text-transform:uppercase}.x-code-block__copy{background:none;border:1px solid #555;color:#ccc;padding:2px 8px;border-radius:2px;cursor:pointer;font-size:11px}.x-code-block__copy:hover{background:#444}.x-code-block__pre{background:#1e1e1e;color:#d4d4d4;padding:8px 12px;margin:0;overflow-x:auto;font-family:Monaco,Consolas,monospace;font-size:12px;line-height:1.5}.x-file-upload__dropzone{border:2px dashed #d0d0d0;border-radius:6px;padding:16px;text-align:center;cursor:pointer;transition:all .2s;position:relative}.x-file-upload__dropzone:hover,.x-file-upload__dropzone--active{border-color:#155eef;background:#f0f7ff}.x-file-upload__dropzone input[type=file]{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;cursor:pointer}.x-file-upload__hint{font-size:13px;color:#666}.x-file-upload__hint span{display:block}.x-file-upload__max{font-size:11px;color:#999;margin-top:4px}.x-file-upload__list{margin-top:8px;display:flex;flex-direction:column;gap:4px}.x-file-upload__item{display:flex;align-items:center;gap:8px;padding:6px 10px;background:#f5f5f5;border-radius:4px;font-size:12px}.x-file-upload__name{flex:1;color:#333}.x-file-upload__size{color:#999}.x-file-upload__remove{background:none;border:none;cursor:pointer;color:#ef4444;font-size:16px}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xto/chat",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Xto Chat - AI Chat Interface Components (message list, streaming, thinking chain, tool calls)",
|
|
5
|
+
"homepage": "https://jinguchu.github.io/xto-ui/",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/jinguchu/xto-ui.git",
|
|
9
|
+
"directory": "packages/chat"
|
|
10
|
+
},
|
|
11
|
+
"main": "./lib/index.cjs",
|
|
12
|
+
"module": "./es/index.mjs",
|
|
13
|
+
"types": "./es/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": "./es/index.mjs",
|
|
17
|
+
"require": "./lib/index.cjs",
|
|
18
|
+
"types": "./es/index.d.ts"
|
|
19
|
+
},
|
|
20
|
+
"./es/style.css": "./es/style.css",
|
|
21
|
+
"./lib/style.css": "./lib/style.css"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"es",
|
|
25
|
+
"lib"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "vite build",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@vueuse/core": "^11.0.0",
|
|
37
|
+
"markdown-it": "^14.1.0",
|
|
38
|
+
"highlight.js": "^11.10.0",
|
|
39
|
+
"dompurify": "^3.1.6",
|
|
40
|
+
"dayjs": "^1.11.13",
|
|
41
|
+
"@xto/base": "^1.4.1",
|
|
42
|
+
"@xto/core": "^1.2.4",
|
|
43
|
+
"@xto/form": "^1.4.1",
|
|
44
|
+
"@xto/feedback": "^1.2.6",
|
|
45
|
+
"@xto/data": "^1.2.2"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"vue": "^3.4.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@vitejs/plugin-vue": "^5.0.4",
|
|
52
|
+
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
|
53
|
+
"@xto/build": "workspace:*",
|
|
54
|
+
"typescript": "^5.4.2",
|
|
55
|
+
"vite": "^5.2.0",
|
|
56
|
+
"vite-plugin-dts": "^4.5.4",
|
|
57
|
+
"vitest": "^1.4.0",
|
|
58
|
+
"vue": "^3.4.21"
|
|
59
|
+
}
|
|
60
|
+
}
|