@kine-design/ai-chat 0.0.1-beta.1

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.
@@ -0,0 +1,436 @@
1
+ import { computed, createTextVNode, createVNode, defineComponent, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
2
+ import KLoading from "kine-ui/components/loading/KLoading.tsx";
3
+ //#region composables/useChat.ts
4
+ /**
5
+ * @description Core chat composable — manages message clusters and server events
6
+ * @author 阿怪
7
+ * @date 2026/5/7
8
+ * @version v0.0.1
9
+ *
10
+ * 江湖的业务千篇一律,复杂的代码好几百行。
11
+ */
12
+ function useChat(options) {
13
+ const { transport } = options;
14
+ const clusters = ref([]);
15
+ const phase = ref("idle");
16
+ const transportStatus = ref("disconnected");
17
+ const conversationId = ref(options.conversationId);
18
+ function findOrCreateCluster(clusterId, role) {
19
+ const existing = clusters.value.find((c) => c.id === clusterId);
20
+ if (existing) return existing;
21
+ const cluster = {
22
+ id: clusterId,
23
+ role,
24
+ messages: [],
25
+ timestamp: Date.now()
26
+ };
27
+ clusters.value.push(cluster);
28
+ return cluster;
29
+ }
30
+ function handleFragment(data) {
31
+ const cluster = findOrCreateCluster(data.clusterId, data.role);
32
+ const existing = cluster.messages.find((m) => m.id === data.messageId);
33
+ if (existing) {
34
+ if (data.status === "streaming") existing.content += data.content;
35
+ else existing.content = data.content;
36
+ existing.status = data.status;
37
+ } else cluster.messages.push({
38
+ id: data.messageId,
39
+ role: data.role,
40
+ content: data.content,
41
+ status: data.status,
42
+ timestamp: Date.now(),
43
+ clusterId: data.clusterId
44
+ });
45
+ }
46
+ function handlePhaseChange(data) {
47
+ phase.value = data.phase;
48
+ }
49
+ function handleEvent(event) {
50
+ if (conversationId.value && event.conversationId !== conversationId.value) return;
51
+ switch (event.type) {
52
+ case "fragment":
53
+ handleFragment(event.data);
54
+ break;
55
+ case "fragment_end":
56
+ handleFragment({
57
+ ...event.data,
58
+ status: "complete"
59
+ });
60
+ break;
61
+ case "phase_change":
62
+ handlePhaseChange(event.data);
63
+ break;
64
+ }
65
+ }
66
+ transport.onEvent(handleEvent);
67
+ transport.onStatusChange((status) => {
68
+ transportStatus.value = status;
69
+ });
70
+ function send(content) {
71
+ if (!conversationId.value) return;
72
+ const clusterId = `user-${Date.now()}`;
73
+ const messageId = `msg-${Date.now()}`;
74
+ findOrCreateCluster(clusterId, "user").messages.push({
75
+ id: messageId,
76
+ role: "user",
77
+ content,
78
+ status: "complete",
79
+ timestamp: Date.now(),
80
+ clusterId
81
+ });
82
+ transport.send({
83
+ conversationId: conversationId.value,
84
+ content,
85
+ timestamp: Date.now()
86
+ });
87
+ }
88
+ function switchConversation(id) {
89
+ conversationId.value = id;
90
+ clusters.value = [];
91
+ phase.value = "idle";
92
+ }
93
+ function clear() {
94
+ clusters.value = [];
95
+ phase.value = "idle";
96
+ }
97
+ onUnmounted(() => {
98
+ transport.disconnect();
99
+ });
100
+ return {
101
+ clusters,
102
+ phase,
103
+ transportStatus,
104
+ conversationId,
105
+ send,
106
+ switchConversation,
107
+ clear
108
+ };
109
+ }
110
+ //#endregion
111
+ //#region composables/useChatHistory.ts
112
+ /**
113
+ * @description Chat history composable — multi-conversation management
114
+ * @author 阿怪
115
+ * @date 2026/5/7
116
+ * @version v0.0.1
117
+ *
118
+ * 江湖的业务千篇一律,复杂的代码好几百行。
119
+ */
120
+ function generateId() {
121
+ return `conv-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
122
+ }
123
+ function useChatHistory(options = {}) {
124
+ const storageKey = options.storageKey ?? "kine-ai-chat-history";
125
+ const conversations = ref([]);
126
+ const current = ref();
127
+ function load() {
128
+ try {
129
+ const raw = localStorage.getItem(storageKey);
130
+ if (raw) conversations.value = JSON.parse(raw);
131
+ } catch {
132
+ conversations.value = [];
133
+ }
134
+ }
135
+ function persist() {
136
+ try {
137
+ localStorage.setItem(storageKey, JSON.stringify(conversations.value));
138
+ } catch {}
139
+ }
140
+ load();
141
+ watch(conversations, persist, { deep: true });
142
+ function create(title) {
143
+ const now = Date.now();
144
+ const conversation = {
145
+ id: generateId(),
146
+ title: title ?? `对话 ${conversations.value.length + 1}`,
147
+ clusters: [],
148
+ createdAt: now,
149
+ updatedAt: now
150
+ };
151
+ conversations.value.unshift(conversation);
152
+ current.value = conversation;
153
+ return conversation;
154
+ }
155
+ function remove(id) {
156
+ const idx = conversations.value.findIndex((c) => c.id === id);
157
+ if (idx === -1) return;
158
+ conversations.value.splice(idx, 1);
159
+ if (current.value?.id === id) current.value = conversations.value[0];
160
+ }
161
+ function rename(id, title) {
162
+ const conv = conversations.value.find((c) => c.id === id);
163
+ if (conv) {
164
+ conv.title = title;
165
+ conv.updatedAt = Date.now();
166
+ }
167
+ }
168
+ function select(id) {
169
+ current.value = conversations.value.find((c) => c.id === id);
170
+ }
171
+ return {
172
+ conversations,
173
+ current,
174
+ create,
175
+ remove,
176
+ rename,
177
+ select
178
+ };
179
+ }
180
+ //#endregion
181
+ //#region composables/createWebSocketTransport.ts
182
+ function createWebSocketTransport() {
183
+ let ws = null;
184
+ let url = "";
185
+ let options = {};
186
+ let reconnectAttempts = 0;
187
+ let reconnectTimer = null;
188
+ const eventHandlers = [];
189
+ const statusHandlers = [];
190
+ function emitStatus(status) {
191
+ statusHandlers.forEach((h) => h(status));
192
+ }
193
+ function handleMessage(raw) {
194
+ try {
195
+ const event = JSON.parse(raw.data);
196
+ eventHandlers.forEach((h) => h(event));
197
+ } catch {}
198
+ }
199
+ function tryReconnect() {
200
+ if (!options.reconnect) return;
201
+ const max = options.maxReconnectAttempts ?? 5;
202
+ if (reconnectAttempts >= max) {
203
+ emitStatus("disconnected");
204
+ return;
205
+ }
206
+ reconnectAttempts++;
207
+ emitStatus("reconnecting");
208
+ const interval = options.reconnectInterval ?? 3e3;
209
+ reconnectTimer = setTimeout(() => connect(url, options), interval);
210
+ }
211
+ function connect(targetUrl, opts = {}) {
212
+ url = targetUrl;
213
+ options = opts;
214
+ emitStatus("connecting");
215
+ ws = new WebSocket(targetUrl, opts.protocols);
216
+ ws.onopen = () => {
217
+ reconnectAttempts = 0;
218
+ emitStatus("connected");
219
+ };
220
+ ws.onmessage = handleMessage;
221
+ ws.onclose = () => {
222
+ ws = null;
223
+ tryReconnect();
224
+ };
225
+ ws.onerror = () => {
226
+ ws?.close();
227
+ };
228
+ }
229
+ function disconnect() {
230
+ if (reconnectTimer) {
231
+ clearTimeout(reconnectTimer);
232
+ reconnectTimer = null;
233
+ }
234
+ options.reconnect = false;
235
+ ws?.close();
236
+ ws = null;
237
+ emitStatus("disconnected");
238
+ }
239
+ function send(message) {
240
+ if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(message));
241
+ }
242
+ function onEvent(handler) {
243
+ eventHandlers.push(handler);
244
+ }
245
+ function onStatusChange(handler) {
246
+ statusHandlers.push(handler);
247
+ }
248
+ return {
249
+ connect,
250
+ disconnect,
251
+ send,
252
+ onEvent,
253
+ onStatusChange
254
+ };
255
+ }
256
+ //#endregion
257
+ //#region components/KMessageBubble.tsx
258
+ /**
259
+ * @description Single message bubble — supports streaming content
260
+ * @author 阿怪
261
+ * @date 2026/5/7
262
+ * @version v0.0.1
263
+ *
264
+ * 江湖的业务千篇一律,复杂的代码好几百行。
265
+ */
266
+ var KMessageBubble = /* @__PURE__ */ defineComponent({
267
+ name: "KMessageBubble",
268
+ props: { message: {
269
+ type: Object,
270
+ required: true
271
+ } },
272
+ setup(props, { slots }) {
273
+ return () => {
274
+ const msg = props.message;
275
+ return createVNode("div", { "class": [
276
+ "k-message-bubble",
277
+ `k-message-bubble--${msg.role}`,
278
+ `k-message-bubble--${msg.status}`
279
+ ] }, [createVNode("div", { "class": "k-message-bubble__content" }, [slots.default ? slots.default({ message: msg }) : msg.content])]);
280
+ };
281
+ }
282
+ });
283
+ //#endregion
284
+ //#region components/KMessageCluster.tsx
285
+ /**
286
+ * @description Message cluster — groups fragmented messages from the same sender
287
+ * @author 阿怪
288
+ * @date 2026/5/7
289
+ * @version v0.0.1
290
+ *
291
+ * 江湖的业务千篇一律,复杂的代码好几百行。
292
+ */
293
+ var KMessageCluster = /* @__PURE__ */ defineComponent({
294
+ name: "KMessageCluster",
295
+ props: { cluster: {
296
+ type: Object,
297
+ required: true
298
+ } },
299
+ setup(props) {
300
+ return () => createVNode("div", { "class": ["k-message-cluster", `k-message-cluster--${props.cluster.role}`] }, [props.cluster.messages.map((msg) => createVNode(KMessageBubble, {
301
+ "key": msg.id,
302
+ "message": msg
303
+ }, null))]);
304
+ }
305
+ });
306
+ //#endregion
307
+ //#region components/KPhaseIndicator.tsx
308
+ /**
309
+ * @description Phase indicator — shows current chat phase with KLoading
310
+ * @author 阿怪
311
+ * @date 2026/5/7
312
+ * @version v0.0.1
313
+ *
314
+ * 江湖的业务千篇一律,复杂的代码好几百行。
315
+ */
316
+ var PHASE_LABELS = {
317
+ idle: "",
318
+ aggregating: "正在输入…",
319
+ thinking: "思考中…",
320
+ streaming: "回复中…",
321
+ sending: "发送中…"
322
+ };
323
+ var KPhaseIndicator = /* @__PURE__ */ defineComponent({
324
+ name: "KPhaseIndicator",
325
+ props: { phase: {
326
+ type: String,
327
+ required: true
328
+ } },
329
+ setup(props) {
330
+ const label = computed(() => PHASE_LABELS[props.phase]);
331
+ const visible = computed(() => props.phase !== "idle");
332
+ return () => visible.value ? createVNode("div", { "class": ["k-phase-indicator", `k-phase-indicator--${props.phase}`] }, [createVNode(KLoading, { "size": "small" }, null), createVNode("span", null, [label.value])]) : null;
333
+ }
334
+ });
335
+ //#endregion
336
+ //#region components/KChatPanel.tsx
337
+ /**
338
+ * @description Main chat panel — renders message clusters with phase indicator
339
+ * @author 阿怪
340
+ * @date 2026/5/7
341
+ * @version v0.0.1
342
+ *
343
+ * 江湖的业务千篇一律,复杂的代码好几百行。
344
+ */
345
+ var KChatPanel = /* @__PURE__ */ defineComponent({
346
+ name: "KChatPanel",
347
+ props: {
348
+ clusters: {
349
+ type: Array,
350
+ required: true
351
+ },
352
+ phase: {
353
+ type: String,
354
+ default: "idle"
355
+ }
356
+ },
357
+ setup(props, { slots }) {
358
+ const scrollRef = ref();
359
+ function scrollToBottom() {
360
+ nextTick(() => {
361
+ const el = scrollRef.value;
362
+ if (el) el.scrollTop = el.scrollHeight;
363
+ });
364
+ }
365
+ onMounted(scrollToBottom);
366
+ watch(() => props.clusters.length, scrollToBottom);
367
+ watch(() => {
368
+ const last = props.clusters[props.clusters.length - 1];
369
+ if (!last) return 0;
370
+ return last.messages[last.messages.length - 1]?.content.length ?? 0;
371
+ }, scrollToBottom);
372
+ return () => createVNode("div", { "class": "k-chat-panel" }, [createVNode("div", {
373
+ "class": "k-chat-panel__messages",
374
+ "ref": scrollRef
375
+ }, [props.clusters.map((cluster) => createVNode(KMessageCluster, {
376
+ "key": cluster.id,
377
+ "cluster": cluster
378
+ }, null)), slots.default?.()]), createVNode(KPhaseIndicator, { "phase": props.phase }, null)]);
379
+ }
380
+ });
381
+ //#endregion
382
+ //#region components/KChatInput.tsx
383
+ /**
384
+ * @description Chat input — supports multi-line and Enter to send
385
+ * @author 阿怪
386
+ * @date 2026/5/7
387
+ * @version v0.0.1
388
+ *
389
+ * 江湖的业务千篇一律,复杂的代码好几百行。
390
+ */
391
+ var KChatInput = /* @__PURE__ */ defineComponent({
392
+ name: "KChatInput",
393
+ props: {
394
+ placeholder: {
395
+ type: String,
396
+ default: "输入消息…"
397
+ },
398
+ disabled: {
399
+ type: Boolean,
400
+ default: false
401
+ }
402
+ },
403
+ emits: ["send"],
404
+ setup(props, { emit }) {
405
+ const text = ref("");
406
+ function handleSend() {
407
+ const trimmed = text.value.trim();
408
+ if (!trimmed || props.disabled) return;
409
+ emit("send", trimmed);
410
+ text.value = "";
411
+ }
412
+ function handleKeydown(e) {
413
+ if (e.key === "Enter" && !e.shiftKey) {
414
+ e.preventDefault();
415
+ handleSend();
416
+ }
417
+ }
418
+ return () => createVNode("div", { "class": "k-chat-input" }, [createVNode("textarea", {
419
+ "class": "k-chat-input__textarea",
420
+ "value": text.value,
421
+ "onInput": (e) => {
422
+ text.value = e.target.value;
423
+ },
424
+ "onKeydown": handleKeydown,
425
+ "placeholder": props.placeholder,
426
+ "disabled": props.disabled,
427
+ "rows": 1
428
+ }, null), createVNode("button", {
429
+ "class": "k-chat-input__send",
430
+ "onClick": handleSend,
431
+ "disabled": props.disabled || !text.value.trim()
432
+ }, [createTextVNode("发送")])]);
433
+ }
434
+ });
435
+ //#endregion
436
+ export { KChatInput, KChatPanel, KMessageBubble, KMessageCluster, KPhaseIndicator, createWebSocketTransport, useChat, useChatHistory };
@@ -0,0 +1,24 @@
1
+ export declare const KChatInput: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
2
+ placeholder: {
3
+ type: StringConstructor;
4
+ default: string;
5
+ };
6
+ disabled: {
7
+ type: BooleanConstructor;
8
+ default: boolean;
9
+ };
10
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, "send"[], "send", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
11
+ placeholder: {
12
+ type: StringConstructor;
13
+ default: string;
14
+ };
15
+ disabled: {
16
+ type: BooleanConstructor;
17
+ default: boolean;
18
+ };
19
+ }>> & Readonly<{
20
+ onSend?: ((...args: any[]) => any) | undefined;
21
+ }>, {
22
+ placeholder: string;
23
+ disabled: boolean;
24
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,23 @@
1
+ import { PropType } from 'vue';
2
+ import { MessageCluster, ChatPhase } from '../composables/types';
3
+ export declare const KChatPanel: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
+ clusters: {
5
+ type: PropType<MessageCluster[]>;
6
+ required: true;
7
+ };
8
+ phase: {
9
+ type: PropType<ChatPhase>;
10
+ default: string;
11
+ };
12
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
13
+ clusters: {
14
+ type: PropType<MessageCluster[]>;
15
+ required: true;
16
+ };
17
+ phase: {
18
+ type: PropType<ChatPhase>;
19
+ default: string;
20
+ };
21
+ }>> & Readonly<{}>, {
22
+ phase: ChatPhase;
23
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,13 @@
1
+ import { PropType } from 'vue';
2
+ import { ChatMessage } from '../composables/types';
3
+ export declare const KMessageBubble: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
+ message: {
5
+ type: PropType<ChatMessage>;
6
+ required: true;
7
+ };
8
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
9
+ message: {
10
+ type: PropType<ChatMessage>;
11
+ required: true;
12
+ };
13
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,13 @@
1
+ import { PropType } from 'vue';
2
+ import { MessageCluster } from '../composables/types';
3
+ export declare const KMessageCluster: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
+ cluster: {
5
+ type: PropType<MessageCluster>;
6
+ required: true;
7
+ };
8
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
9
+ cluster: {
10
+ type: PropType<MessageCluster>;
11
+ required: true;
12
+ };
13
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,13 @@
1
+ import { PropType } from 'vue';
2
+ import { ChatPhase } from '../composables/types';
3
+ export declare const KPhaseIndicator: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
+ phase: {
5
+ type: PropType<ChatPhase>;
6
+ required: true;
7
+ };
8
+ }>, () => import("vue/jsx-runtime").JSX.Element | null, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
9
+ phase: {
10
+ type: PropType<ChatPhase>;
11
+ required: true;
12
+ };
13
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,2 @@
1
+ import { ChatTransport } from './types';
2
+ export declare function createWebSocketTransport(): ChatTransport;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @description AI Chat type definitions — fragmented streaming dialogue model
3
+ * @author 阿怪
4
+ * @date 2026/5/7
5
+ * @version v0.0.1
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ export type MessageRole = 'user' | 'assistant' | 'system';
10
+ export type MessageStatus = 'pending' | 'streaming' | 'complete' | 'interrupted';
11
+ export interface ChatMessage {
12
+ id: string;
13
+ role: MessageRole;
14
+ content: string;
15
+ status: MessageStatus;
16
+ timestamp: number;
17
+ clusterId?: string;
18
+ }
19
+ export interface MessageCluster {
20
+ id: string;
21
+ role: MessageRole;
22
+ messages: ChatMessage[];
23
+ timestamp: number;
24
+ }
25
+ export type ChatPhase = 'idle' | 'aggregating' | 'thinking' | 'streaming' | 'sending';
26
+ export interface Conversation {
27
+ id: string;
28
+ title: string;
29
+ clusters: MessageCluster[];
30
+ createdAt: number;
31
+ updatedAt: number;
32
+ }
33
+ export interface ServerPushEvent {
34
+ type: 'fragment' | 'fragment_end' | 'phase_change' | 'conversation_meta';
35
+ conversationId: string;
36
+ data: FragmentEvent | PhaseChangeEvent | ConversationMetaEvent;
37
+ }
38
+ export interface FragmentEvent {
39
+ messageId: string;
40
+ clusterId: string;
41
+ role: MessageRole;
42
+ content: string;
43
+ status: MessageStatus;
44
+ }
45
+ export interface PhaseChangeEvent {
46
+ phase: ChatPhase;
47
+ }
48
+ export interface ConversationMetaEvent {
49
+ title?: string;
50
+ }
51
+ export interface ChatTransport {
52
+ connect(url: string, options?: TransportOptions): void;
53
+ disconnect(): void;
54
+ send(message: OutgoingMessage): void;
55
+ onEvent(handler: (event: ServerPushEvent) => void): void;
56
+ onStatusChange(handler: (status: TransportStatus) => void): void;
57
+ }
58
+ export type TransportStatus = 'connecting' | 'connected' | 'disconnected' | 'reconnecting';
59
+ export interface TransportOptions {
60
+ protocols?: string[];
61
+ headers?: Record<string, string>;
62
+ reconnect?: boolean;
63
+ reconnectInterval?: number;
64
+ maxReconnectAttempts?: number;
65
+ }
66
+ export interface OutgoingMessage {
67
+ conversationId: string;
68
+ content: string;
69
+ timestamp: number;
70
+ }
71
+ export interface UseChatOptions {
72
+ transport: ChatTransport;
73
+ conversationId?: string;
74
+ }
75
+ export interface UseChatReturn {
76
+ clusters: import('vue').Ref<MessageCluster[]>;
77
+ phase: import('vue').Ref<ChatPhase>;
78
+ transportStatus: import('vue').Ref<TransportStatus>;
79
+ conversationId: import('vue').Ref<string | undefined>;
80
+ send: (content: string) => void;
81
+ switchConversation: (id: string) => void;
82
+ clear: () => void;
83
+ }
84
+ export interface UseChatHistoryOptions {
85
+ storageKey?: string;
86
+ }
87
+ export interface UseChatHistoryReturn {
88
+ conversations: import('vue').Ref<Conversation[]>;
89
+ current: import('vue').Ref<Conversation | undefined>;
90
+ create: (title?: string) => Conversation;
91
+ remove: (id: string) => void;
92
+ rename: (id: string, title: string) => void;
93
+ select: (id: string) => void;
94
+ }
@@ -0,0 +1,2 @@
1
+ import { UseChatOptions, UseChatReturn } from './types';
2
+ export declare function useChat(options: UseChatOptions): UseChatReturn;
@@ -0,0 +1,2 @@
1
+ import { UseChatHistoryOptions, UseChatHistoryReturn } from './types';
2
+ export declare function useChatHistory(options?: UseChatHistoryOptions): UseChatHistoryReturn;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @description @kine-design/ai-chat entry
3
+ * @author 阿怪
4
+ * @date 2026/5/7
5
+ * @version v0.0.1
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ export { useChat } from './composables/useChat';
10
+ export { useChatHistory } from './composables/useChatHistory';
11
+ export { createWebSocketTransport } from './composables/createWebSocketTransport';
12
+ export type { MessageRole, MessageStatus, ChatMessage, MessageCluster, ChatPhase, Conversation, ServerPushEvent, FragmentEvent, PhaseChangeEvent, ConversationMetaEvent, ChatTransport, TransportStatus, TransportOptions, OutgoingMessage, UseChatOptions, UseChatReturn, UseChatHistoryOptions, UseChatHistoryReturn, } from './composables/types';
13
+ export { KChatPanel } from './components/KChatPanel';
14
+ export { KMessageCluster } from './components/KMessageCluster';
15
+ export { KMessageBubble } from './components/KMessageBubble';
16
+ export { KPhaseIndicator } from './components/KPhaseIndicator';
17
+ export { KChatInput } from './components/KChatInput';
@@ -0,0 +1,2 @@
1
+ declare const _default: import('vite').UserConfig;
2
+ export default _default;
package/index.ts ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @description @kine-design/ai-chat entry
3
+ * @author 阿怪
4
+ * @date 2026/5/7
5
+ * @version v0.0.1
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+
10
+ export { useChat } from './composables/useChat';
11
+ export { useChatHistory } from './composables/useChatHistory';
12
+ export { createWebSocketTransport } from './composables/createWebSocketTransport';
13
+
14
+ export type {
15
+ MessageRole,
16
+ MessageStatus,
17
+ ChatMessage,
18
+ MessageCluster,
19
+ ChatPhase,
20
+ Conversation,
21
+ ServerPushEvent,
22
+ FragmentEvent,
23
+ PhaseChangeEvent,
24
+ ConversationMetaEvent,
25
+ ChatTransport,
26
+ TransportStatus,
27
+ TransportOptions,
28
+ OutgoingMessage,
29
+ UseChatOptions,
30
+ UseChatReturn,
31
+ UseChatHistoryOptions,
32
+ UseChatHistoryReturn,
33
+ } from './composables/types';
34
+
35
+ export { KChatPanel } from './components/KChatPanel';
36
+ export { KMessageCluster } from './components/KMessageCluster';
37
+ export { KMessageBubble } from './components/KMessageBubble';
38
+ export { KPhaseIndicator } from './components/KPhaseIndicator';
39
+ export { KChatInput } from './components/KChatInput';