@lingshuai/chat-vue 0.1.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.
@@ -0,0 +1,239 @@
1
+ import * as vue from 'vue';
2
+ import { Ref } from 'vue';
3
+ import * as _lingshuai_chat_core from '@lingshuai/chat-core';
4
+ import { ChatConfig, Message, Conversation, ChatClient, ChatEventType, ChatEventListener, ChatState } from '@lingshuai/chat-core';
5
+ export { ApiClient, ChatClient, ChatConfig, ChatEventListener, ChatEventMap, ChatEventType, ChatState, Conversation, EventEmitter, Message, MessageRole, MessageStatus, SendMessageRequest, SendMessageResponse, StateListener, StateManager, ThemeConfig, WidgetConfig } from '@lingshuai/chat-core';
6
+
7
+ /**
8
+ * useChat Composable - 提供完整的聊天功能
9
+ *
10
+ * @example
11
+ * ```vue
12
+ * <script setup>
13
+ * import { useChat } from '@lingshuai/chat-vue';
14
+ *
15
+ * const {
16
+ * messages,
17
+ * isSending,
18
+ * input,
19
+ * sendMessage,
20
+ * } = useChat({
21
+ * apiKey: 'your-api-key',
22
+ * appId: 'your-app-id',
23
+ * });
24
+ * </script>
25
+ *
26
+ * <template>
27
+ * <div>
28
+ * <div v-for="msg in messages" :key="msg.id">
29
+ * {{ msg.content }}
30
+ * </div>
31
+ * <input v-model="input" @keydown.enter="sendMessage(input)" />
32
+ * <button @click="sendMessage(input)" :disabled="isSending">发送</button>
33
+ * </div>
34
+ * </template>
35
+ * ```
36
+ */
37
+ declare function useChat(config: ChatConfig): {
38
+ messages: Ref<{
39
+ id: string;
40
+ conversationId: string;
41
+ role: _lingshuai_chat_core.MessageRole;
42
+ content: string;
43
+ status: _lingshuai_chat_core.MessageStatus;
44
+ createdAt: Date;
45
+ metadata?: Record<string, unknown> | undefined;
46
+ }[], Message[] | {
47
+ id: string;
48
+ conversationId: string;
49
+ role: _lingshuai_chat_core.MessageRole;
50
+ content: string;
51
+ status: _lingshuai_chat_core.MessageStatus;
52
+ createdAt: Date;
53
+ metadata?: Record<string, unknown> | undefined;
54
+ }[]>;
55
+ conversations: Ref<{
56
+ id: string;
57
+ title?: string | undefined;
58
+ messages: {
59
+ id: string;
60
+ conversationId: string;
61
+ role: _lingshuai_chat_core.MessageRole;
62
+ content: string;
63
+ status: _lingshuai_chat_core.MessageStatus;
64
+ createdAt: Date;
65
+ metadata?: Record<string, unknown> | undefined;
66
+ }[];
67
+ createdAt: Date;
68
+ updatedAt: Date;
69
+ }[], Conversation[] | {
70
+ id: string;
71
+ title?: string | undefined;
72
+ messages: {
73
+ id: string;
74
+ conversationId: string;
75
+ role: _lingshuai_chat_core.MessageRole;
76
+ content: string;
77
+ status: _lingshuai_chat_core.MessageStatus;
78
+ createdAt: Date;
79
+ metadata?: Record<string, unknown> | undefined;
80
+ }[];
81
+ createdAt: Date;
82
+ updatedAt: Date;
83
+ }[]>;
84
+ currentConversation: Ref<{
85
+ id: string;
86
+ title?: string | undefined;
87
+ messages: {
88
+ id: string;
89
+ conversationId: string;
90
+ role: _lingshuai_chat_core.MessageRole;
91
+ content: string;
92
+ status: _lingshuai_chat_core.MessageStatus;
93
+ createdAt: Date;
94
+ metadata?: Record<string, unknown> | undefined;
95
+ }[];
96
+ createdAt: Date;
97
+ updatedAt: Date;
98
+ } | null, Conversation | {
99
+ id: string;
100
+ title?: string | undefined;
101
+ messages: {
102
+ id: string;
103
+ conversationId: string;
104
+ role: _lingshuai_chat_core.MessageRole;
105
+ content: string;
106
+ status: _lingshuai_chat_core.MessageStatus;
107
+ createdAt: Date;
108
+ metadata?: Record<string, unknown> | undefined;
109
+ }[];
110
+ createdAt: Date;
111
+ updatedAt: Date;
112
+ } | null>;
113
+ isSending: Ref<boolean, boolean>;
114
+ isLoading: Ref<boolean, boolean>;
115
+ error: Ref<Error | null, Error | null>;
116
+ input: Ref<string, string>;
117
+ sendMessage: (content: string) => Promise<void>;
118
+ abort: () => void;
119
+ newConversation: () => void;
120
+ switchConversation: (conversationId: string) => Promise<void>;
121
+ deleteConversation: (conversationId: string) => Promise<void>;
122
+ getConversations: () => Promise<never[] | Conversation[]>;
123
+ client: vue.ShallowRef<ChatClient | null, ChatClient | null>;
124
+ };
125
+ /**
126
+ * useChatClient Composable - 创建 ChatClient 实例
127
+ *
128
+ * @example
129
+ * ```vue
130
+ * <script setup>
131
+ * import { useChatClient } from '@lingshuai/chat-vue';
132
+ *
133
+ * const client = useChatClient({
134
+ * apiKey: 'your-api-key',
135
+ * appId: 'your-app-id',
136
+ * });
137
+ *
138
+ * client.on('message:received', ({ message }) => {
139
+ * console.log('收到消息:', message.content);
140
+ * });
141
+ * </script>
142
+ * ```
143
+ */
144
+ declare function useChatClient(config: ChatConfig): Ref<ChatClient | null>;
145
+ /**
146
+ * useChatEvent Composable - 监听聊天事件
147
+ *
148
+ * @example
149
+ * ```vue
150
+ * <script setup>
151
+ * import { useChatClient, useChatEvent } from '@lingshuai/chat-vue';
152
+ *
153
+ * const client = useChatClient({ apiKey: 'xxx', appId: 'xxx' });
154
+ *
155
+ * useChatEvent(client, 'message:stream:chunk', ({ fullContent }) => {
156
+ * console.log('流式内容:', fullContent);
157
+ * });
158
+ * </script>
159
+ * ```
160
+ */
161
+ declare function useChatEvent<T extends ChatEventType>(client: Ref<ChatClient | null>, event: T, listener: ChatEventListener<T>): void;
162
+ /**
163
+ * useChatState Composable - 订阅聊天状态
164
+ */
165
+ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
166
+ currentConversation: {
167
+ id: string;
168
+ title?: string | undefined;
169
+ messages: {
170
+ id: string;
171
+ conversationId: string;
172
+ role: _lingshuai_chat_core.MessageRole;
173
+ content: string;
174
+ status: _lingshuai_chat_core.MessageStatus;
175
+ createdAt: Date;
176
+ metadata?: Record<string, unknown> | undefined;
177
+ }[];
178
+ createdAt: Date;
179
+ updatedAt: Date;
180
+ } | null;
181
+ conversations: {
182
+ id: string;
183
+ title?: string | undefined;
184
+ messages: {
185
+ id: string;
186
+ conversationId: string;
187
+ role: _lingshuai_chat_core.MessageRole;
188
+ content: string;
189
+ status: _lingshuai_chat_core.MessageStatus;
190
+ createdAt: Date;
191
+ metadata?: Record<string, unknown> | undefined;
192
+ }[];
193
+ createdAt: Date;
194
+ updatedAt: Date;
195
+ }[];
196
+ isSending: boolean;
197
+ isLoading: boolean;
198
+ isConnected: boolean;
199
+ error: Error | null;
200
+ inputValue: string;
201
+ }, ChatState | {
202
+ currentConversation: {
203
+ id: string;
204
+ title?: string | undefined;
205
+ messages: {
206
+ id: string;
207
+ conversationId: string;
208
+ role: _lingshuai_chat_core.MessageRole;
209
+ content: string;
210
+ status: _lingshuai_chat_core.MessageStatus;
211
+ createdAt: Date;
212
+ metadata?: Record<string, unknown> | undefined;
213
+ }[];
214
+ createdAt: Date;
215
+ updatedAt: Date;
216
+ } | null;
217
+ conversations: {
218
+ id: string;
219
+ title?: string | undefined;
220
+ messages: {
221
+ id: string;
222
+ conversationId: string;
223
+ role: _lingshuai_chat_core.MessageRole;
224
+ content: string;
225
+ status: _lingshuai_chat_core.MessageStatus;
226
+ createdAt: Date;
227
+ metadata?: Record<string, unknown> | undefined;
228
+ }[];
229
+ createdAt: Date;
230
+ updatedAt: Date;
231
+ }[];
232
+ isSending: boolean;
233
+ isLoading: boolean;
234
+ isConnected: boolean;
235
+ error: Error | null;
236
+ inputValue: string;
237
+ }>;
238
+
239
+ export { useChat, useChatClient, useChatEvent, useChatState };
@@ -0,0 +1,239 @@
1
+ import * as vue from 'vue';
2
+ import { Ref } from 'vue';
3
+ import * as _lingshuai_chat_core from '@lingshuai/chat-core';
4
+ import { ChatConfig, Message, Conversation, ChatClient, ChatEventType, ChatEventListener, ChatState } from '@lingshuai/chat-core';
5
+ export { ApiClient, ChatClient, ChatConfig, ChatEventListener, ChatEventMap, ChatEventType, ChatState, Conversation, EventEmitter, Message, MessageRole, MessageStatus, SendMessageRequest, SendMessageResponse, StateListener, StateManager, ThemeConfig, WidgetConfig } from '@lingshuai/chat-core';
6
+
7
+ /**
8
+ * useChat Composable - 提供完整的聊天功能
9
+ *
10
+ * @example
11
+ * ```vue
12
+ * <script setup>
13
+ * import { useChat } from '@lingshuai/chat-vue';
14
+ *
15
+ * const {
16
+ * messages,
17
+ * isSending,
18
+ * input,
19
+ * sendMessage,
20
+ * } = useChat({
21
+ * apiKey: 'your-api-key',
22
+ * appId: 'your-app-id',
23
+ * });
24
+ * </script>
25
+ *
26
+ * <template>
27
+ * <div>
28
+ * <div v-for="msg in messages" :key="msg.id">
29
+ * {{ msg.content }}
30
+ * </div>
31
+ * <input v-model="input" @keydown.enter="sendMessage(input)" />
32
+ * <button @click="sendMessage(input)" :disabled="isSending">发送</button>
33
+ * </div>
34
+ * </template>
35
+ * ```
36
+ */
37
+ declare function useChat(config: ChatConfig): {
38
+ messages: Ref<{
39
+ id: string;
40
+ conversationId: string;
41
+ role: _lingshuai_chat_core.MessageRole;
42
+ content: string;
43
+ status: _lingshuai_chat_core.MessageStatus;
44
+ createdAt: Date;
45
+ metadata?: Record<string, unknown> | undefined;
46
+ }[], Message[] | {
47
+ id: string;
48
+ conversationId: string;
49
+ role: _lingshuai_chat_core.MessageRole;
50
+ content: string;
51
+ status: _lingshuai_chat_core.MessageStatus;
52
+ createdAt: Date;
53
+ metadata?: Record<string, unknown> | undefined;
54
+ }[]>;
55
+ conversations: Ref<{
56
+ id: string;
57
+ title?: string | undefined;
58
+ messages: {
59
+ id: string;
60
+ conversationId: string;
61
+ role: _lingshuai_chat_core.MessageRole;
62
+ content: string;
63
+ status: _lingshuai_chat_core.MessageStatus;
64
+ createdAt: Date;
65
+ metadata?: Record<string, unknown> | undefined;
66
+ }[];
67
+ createdAt: Date;
68
+ updatedAt: Date;
69
+ }[], Conversation[] | {
70
+ id: string;
71
+ title?: string | undefined;
72
+ messages: {
73
+ id: string;
74
+ conversationId: string;
75
+ role: _lingshuai_chat_core.MessageRole;
76
+ content: string;
77
+ status: _lingshuai_chat_core.MessageStatus;
78
+ createdAt: Date;
79
+ metadata?: Record<string, unknown> | undefined;
80
+ }[];
81
+ createdAt: Date;
82
+ updatedAt: Date;
83
+ }[]>;
84
+ currentConversation: Ref<{
85
+ id: string;
86
+ title?: string | undefined;
87
+ messages: {
88
+ id: string;
89
+ conversationId: string;
90
+ role: _lingshuai_chat_core.MessageRole;
91
+ content: string;
92
+ status: _lingshuai_chat_core.MessageStatus;
93
+ createdAt: Date;
94
+ metadata?: Record<string, unknown> | undefined;
95
+ }[];
96
+ createdAt: Date;
97
+ updatedAt: Date;
98
+ } | null, Conversation | {
99
+ id: string;
100
+ title?: string | undefined;
101
+ messages: {
102
+ id: string;
103
+ conversationId: string;
104
+ role: _lingshuai_chat_core.MessageRole;
105
+ content: string;
106
+ status: _lingshuai_chat_core.MessageStatus;
107
+ createdAt: Date;
108
+ metadata?: Record<string, unknown> | undefined;
109
+ }[];
110
+ createdAt: Date;
111
+ updatedAt: Date;
112
+ } | null>;
113
+ isSending: Ref<boolean, boolean>;
114
+ isLoading: Ref<boolean, boolean>;
115
+ error: Ref<Error | null, Error | null>;
116
+ input: Ref<string, string>;
117
+ sendMessage: (content: string) => Promise<void>;
118
+ abort: () => void;
119
+ newConversation: () => void;
120
+ switchConversation: (conversationId: string) => Promise<void>;
121
+ deleteConversation: (conversationId: string) => Promise<void>;
122
+ getConversations: () => Promise<never[] | Conversation[]>;
123
+ client: vue.ShallowRef<ChatClient | null, ChatClient | null>;
124
+ };
125
+ /**
126
+ * useChatClient Composable - 创建 ChatClient 实例
127
+ *
128
+ * @example
129
+ * ```vue
130
+ * <script setup>
131
+ * import { useChatClient } from '@lingshuai/chat-vue';
132
+ *
133
+ * const client = useChatClient({
134
+ * apiKey: 'your-api-key',
135
+ * appId: 'your-app-id',
136
+ * });
137
+ *
138
+ * client.on('message:received', ({ message }) => {
139
+ * console.log('收到消息:', message.content);
140
+ * });
141
+ * </script>
142
+ * ```
143
+ */
144
+ declare function useChatClient(config: ChatConfig): Ref<ChatClient | null>;
145
+ /**
146
+ * useChatEvent Composable - 监听聊天事件
147
+ *
148
+ * @example
149
+ * ```vue
150
+ * <script setup>
151
+ * import { useChatClient, useChatEvent } from '@lingshuai/chat-vue';
152
+ *
153
+ * const client = useChatClient({ apiKey: 'xxx', appId: 'xxx' });
154
+ *
155
+ * useChatEvent(client, 'message:stream:chunk', ({ fullContent }) => {
156
+ * console.log('流式内容:', fullContent);
157
+ * });
158
+ * </script>
159
+ * ```
160
+ */
161
+ declare function useChatEvent<T extends ChatEventType>(client: Ref<ChatClient | null>, event: T, listener: ChatEventListener<T>): void;
162
+ /**
163
+ * useChatState Composable - 订阅聊天状态
164
+ */
165
+ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
166
+ currentConversation: {
167
+ id: string;
168
+ title?: string | undefined;
169
+ messages: {
170
+ id: string;
171
+ conversationId: string;
172
+ role: _lingshuai_chat_core.MessageRole;
173
+ content: string;
174
+ status: _lingshuai_chat_core.MessageStatus;
175
+ createdAt: Date;
176
+ metadata?: Record<string, unknown> | undefined;
177
+ }[];
178
+ createdAt: Date;
179
+ updatedAt: Date;
180
+ } | null;
181
+ conversations: {
182
+ id: string;
183
+ title?: string | undefined;
184
+ messages: {
185
+ id: string;
186
+ conversationId: string;
187
+ role: _lingshuai_chat_core.MessageRole;
188
+ content: string;
189
+ status: _lingshuai_chat_core.MessageStatus;
190
+ createdAt: Date;
191
+ metadata?: Record<string, unknown> | undefined;
192
+ }[];
193
+ createdAt: Date;
194
+ updatedAt: Date;
195
+ }[];
196
+ isSending: boolean;
197
+ isLoading: boolean;
198
+ isConnected: boolean;
199
+ error: Error | null;
200
+ inputValue: string;
201
+ }, ChatState | {
202
+ currentConversation: {
203
+ id: string;
204
+ title?: string | undefined;
205
+ messages: {
206
+ id: string;
207
+ conversationId: string;
208
+ role: _lingshuai_chat_core.MessageRole;
209
+ content: string;
210
+ status: _lingshuai_chat_core.MessageStatus;
211
+ createdAt: Date;
212
+ metadata?: Record<string, unknown> | undefined;
213
+ }[];
214
+ createdAt: Date;
215
+ updatedAt: Date;
216
+ } | null;
217
+ conversations: {
218
+ id: string;
219
+ title?: string | undefined;
220
+ messages: {
221
+ id: string;
222
+ conversationId: string;
223
+ role: _lingshuai_chat_core.MessageRole;
224
+ content: string;
225
+ status: _lingshuai_chat_core.MessageStatus;
226
+ createdAt: Date;
227
+ metadata?: Record<string, unknown> | undefined;
228
+ }[];
229
+ createdAt: Date;
230
+ updatedAt: Date;
231
+ }[];
232
+ isSending: boolean;
233
+ isLoading: boolean;
234
+ isConnected: boolean;
235
+ error: Error | null;
236
+ inputValue: string;
237
+ }>;
238
+
239
+ export { useChat, useChatClient, useChatEvent, useChatState };
package/dist/index.js ADDED
@@ -0,0 +1,147 @@
1
+ 'use strict';
2
+
3
+ var vue = require('vue');
4
+ var chatCore = require('@lingshuai/chat-core');
5
+
6
+ // src/composables.ts
7
+ function useChat(config) {
8
+ const client = vue.shallowRef(null);
9
+ const messages = vue.ref([]);
10
+ const conversations = vue.ref([]);
11
+ const currentConversation = vue.ref(null);
12
+ const isSending = vue.ref(false);
13
+ const isLoading = vue.ref(false);
14
+ const error = vue.ref(null);
15
+ const input = vue.ref("");
16
+ vue.onMounted(() => {
17
+ client.value = new chatCore.ChatClient(config);
18
+ client.value.subscribe((state) => {
19
+ messages.value = state.currentConversation?.messages || [];
20
+ conversations.value = state.conversations;
21
+ currentConversation.value = state.currentConversation;
22
+ isSending.value = state.isSending;
23
+ isLoading.value = state.isLoading;
24
+ error.value = state.error;
25
+ });
26
+ });
27
+ vue.onUnmounted(() => {
28
+ client.value?.destroy();
29
+ });
30
+ async function sendMessage(content) {
31
+ if (!client.value || !content.trim()) return;
32
+ await client.value.send(content);
33
+ input.value = "";
34
+ }
35
+ function abort() {
36
+ client.value?.abortAll();
37
+ }
38
+ function newConversation() {
39
+ client.value?.newConversation();
40
+ }
41
+ async function switchConversation(conversationId) {
42
+ await client.value?.switchConversation(conversationId);
43
+ }
44
+ async function deleteConversation(conversationId) {
45
+ await client.value?.deleteConversation(conversationId);
46
+ }
47
+ async function getConversations() {
48
+ return client.value?.getConversations() || [];
49
+ }
50
+ return {
51
+ // 状态(响应式)
52
+ messages,
53
+ conversations,
54
+ currentConversation,
55
+ isSending,
56
+ isLoading,
57
+ error,
58
+ input,
59
+ // 方法
60
+ sendMessage,
61
+ abort,
62
+ newConversation,
63
+ switchConversation,
64
+ deleteConversation,
65
+ getConversations,
66
+ // Client 实例(高级用法)
67
+ client
68
+ };
69
+ }
70
+ function useChatClient(config) {
71
+ const client = vue.shallowRef(null);
72
+ vue.onMounted(() => {
73
+ client.value = new chatCore.ChatClient(config);
74
+ });
75
+ vue.onUnmounted(() => {
76
+ client.value?.destroy();
77
+ });
78
+ return client;
79
+ }
80
+ function useChatEvent(client, event, listener) {
81
+ let unsubscribe = null;
82
+ vue.watch(
83
+ client,
84
+ (newClient) => {
85
+ unsubscribe?.();
86
+ if (newClient) {
87
+ unsubscribe = newClient.on(event, listener);
88
+ }
89
+ },
90
+ { immediate: true }
91
+ );
92
+ vue.onUnmounted(() => {
93
+ unsubscribe?.();
94
+ });
95
+ }
96
+ function useChatState(client) {
97
+ const state = vue.ref({
98
+ currentConversation: null,
99
+ conversations: [],
100
+ isSending: false,
101
+ isLoading: false,
102
+ isConnected: false,
103
+ error: null,
104
+ inputValue: ""
105
+ });
106
+ let unsubscribe = null;
107
+ vue.watch(
108
+ client,
109
+ (newClient) => {
110
+ unsubscribe?.();
111
+ if (newClient) {
112
+ state.value = newClient.getState();
113
+ unsubscribe = newClient.subscribe((newState) => {
114
+ state.value = newState;
115
+ });
116
+ }
117
+ },
118
+ { immediate: true }
119
+ );
120
+ vue.onUnmounted(() => {
121
+ unsubscribe?.();
122
+ });
123
+ return state;
124
+ }
125
+
126
+ Object.defineProperty(exports, "ApiClient", {
127
+ enumerable: true,
128
+ get: function () { return chatCore.ApiClient; }
129
+ });
130
+ Object.defineProperty(exports, "ChatClient", {
131
+ enumerable: true,
132
+ get: function () { return chatCore.ChatClient; }
133
+ });
134
+ Object.defineProperty(exports, "EventEmitter", {
135
+ enumerable: true,
136
+ get: function () { return chatCore.EventEmitter; }
137
+ });
138
+ Object.defineProperty(exports, "StateManager", {
139
+ enumerable: true,
140
+ get: function () { return chatCore.StateManager; }
141
+ });
142
+ exports.useChat = useChat;
143
+ exports.useChatClient = useChatClient;
144
+ exports.useChatEvent = useChatEvent;
145
+ exports.useChatState = useChatState;
146
+ //# sourceMappingURL=index.js.map
147
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/composables.ts"],"names":["shallowRef","ref","onMounted","ChatClient","onUnmounted","watch"],"mappings":"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","file":"index.js","sourcesContent":["import { ref, shallowRef, onMounted, onUnmounted, watch, Ref } from 'vue';\nimport {\n ChatClient,\n ChatConfig,\n ChatState,\n Message,\n Conversation,\n ChatEventType,\n ChatEventListener,\n} from '@lingshuai/chat-core';\n\n/**\n * useChat Composable - 提供完整的聊天功能\n *\n * @example\n * ```vue\n * <script setup>\n * import { useChat } from '@lingshuai/chat-vue';\n *\n * const {\n * messages,\n * isSending,\n * input,\n * sendMessage,\n * } = useChat({\n * apiKey: 'your-api-key',\n * appId: 'your-app-id',\n * });\n * </script>\n *\n * <template>\n * <div>\n * <div v-for=\"msg in messages\" :key=\"msg.id\">\n * {{ msg.content }}\n * </div>\n * <input v-model=\"input\" @keydown.enter=\"sendMessage(input)\" />\n * <button @click=\"sendMessage(input)\" :disabled=\"isSending\">发送</button>\n * </div>\n * </template>\n * ```\n */\nexport function useChat(config: ChatConfig) {\n const client = shallowRef<ChatClient | null>(null);\n const messages = ref<Message[]>([]);\n const conversations = ref<Conversation[]>([]);\n const currentConversation = ref<Conversation | null>(null);\n const isSending = ref(false);\n const isLoading = ref(false);\n const error = ref<Error | null>(null);\n const input = ref('');\n\n // 初始化\n onMounted(() => {\n client.value = new ChatClient(config);\n\n // 订阅状态变更\n client.value.subscribe((state) => {\n messages.value = state.currentConversation?.messages || [];\n conversations.value = state.conversations;\n currentConversation.value = state.currentConversation;\n isSending.value = state.isSending;\n isLoading.value = state.isLoading;\n error.value = state.error;\n });\n });\n\n // 清理\n onUnmounted(() => {\n client.value?.destroy();\n });\n\n // 发送消息\n async function sendMessage(content: string) {\n if (!client.value || !content.trim()) return;\n await client.value.send(content);\n input.value = '';\n }\n\n // 取消发送\n function abort() {\n client.value?.abortAll();\n }\n\n // 新建会话\n function newConversation() {\n client.value?.newConversation();\n }\n\n // 切换会话\n async function switchConversation(conversationId: string) {\n await client.value?.switchConversation(conversationId);\n }\n\n // 删除会话\n async function deleteConversation(conversationId: string) {\n await client.value?.deleteConversation(conversationId);\n }\n\n // 获取会话列表\n async function getConversations() {\n return client.value?.getConversations() || [];\n }\n\n return {\n // 状态(响应式)\n messages,\n conversations,\n currentConversation,\n isSending,\n isLoading,\n error,\n input,\n\n // 方法\n sendMessage,\n abort,\n newConversation,\n switchConversation,\n deleteConversation,\n getConversations,\n\n // Client 实例(高级用法)\n client,\n };\n}\n\n/**\n * useChatClient Composable - 创建 ChatClient 实例\n *\n * @example\n * ```vue\n * <script setup>\n * import { useChatClient } from '@lingshuai/chat-vue';\n *\n * const client = useChatClient({\n * apiKey: 'your-api-key',\n * appId: 'your-app-id',\n * });\n *\n * client.on('message:received', ({ message }) => {\n * console.log('收到消息:', message.content);\n * });\n * </script>\n * ```\n */\nexport function useChatClient(config: ChatConfig): Ref<ChatClient | null> {\n const client = shallowRef<ChatClient | null>(null);\n\n onMounted(() => {\n client.value = new ChatClient(config);\n });\n\n onUnmounted(() => {\n client.value?.destroy();\n });\n\n return client;\n}\n\n/**\n * useChatEvent Composable - 监听聊天事件\n *\n * @example\n * ```vue\n * <script setup>\n * import { useChatClient, useChatEvent } from '@lingshuai/chat-vue';\n *\n * const client = useChatClient({ apiKey: 'xxx', appId: 'xxx' });\n *\n * useChatEvent(client, 'message:stream:chunk', ({ fullContent }) => {\n * console.log('流式内容:', fullContent);\n * });\n * </script>\n * ```\n */\nexport function useChatEvent<T extends ChatEventType>(\n client: Ref<ChatClient | null>,\n event: T,\n listener: ChatEventListener<T>\n) {\n let unsubscribe: (() => void) | null = null;\n\n watch(\n client,\n (newClient) => {\n // 清理旧的订阅\n unsubscribe?.();\n\n // 建立新的订阅\n if (newClient) {\n unsubscribe = newClient.on(event, listener);\n }\n },\n { immediate: true }\n );\n\n onUnmounted(() => {\n unsubscribe?.();\n });\n}\n\n/**\n * useChatState Composable - 订阅聊天状态\n */\nexport function useChatState(client: Ref<ChatClient | null>) {\n const state = ref<ChatState>({\n currentConversation: null,\n conversations: [],\n isSending: false,\n isLoading: false,\n isConnected: false,\n error: null,\n inputValue: '',\n });\n\n let unsubscribe: (() => void) | null = null;\n\n watch(\n client,\n (newClient) => {\n unsubscribe?.();\n\n if (newClient) {\n state.value = newClient.getState();\n unsubscribe = newClient.subscribe((newState) => {\n state.value = newState;\n });\n }\n },\n { immediate: true }\n );\n\n onUnmounted(() => {\n unsubscribe?.();\n });\n\n return state;\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,127 @@
1
+ import { shallowRef, ref, onMounted, onUnmounted, watch } from 'vue';
2
+ import { ChatClient } from '@lingshuai/chat-core';
3
+ export { ApiClient, ChatClient, EventEmitter, StateManager } from '@lingshuai/chat-core';
4
+
5
+ // src/composables.ts
6
+ function useChat(config) {
7
+ const client = shallowRef(null);
8
+ const messages = ref([]);
9
+ const conversations = ref([]);
10
+ const currentConversation = ref(null);
11
+ const isSending = ref(false);
12
+ const isLoading = ref(false);
13
+ const error = ref(null);
14
+ const input = ref("");
15
+ onMounted(() => {
16
+ client.value = new ChatClient(config);
17
+ client.value.subscribe((state) => {
18
+ messages.value = state.currentConversation?.messages || [];
19
+ conversations.value = state.conversations;
20
+ currentConversation.value = state.currentConversation;
21
+ isSending.value = state.isSending;
22
+ isLoading.value = state.isLoading;
23
+ error.value = state.error;
24
+ });
25
+ });
26
+ onUnmounted(() => {
27
+ client.value?.destroy();
28
+ });
29
+ async function sendMessage(content) {
30
+ if (!client.value || !content.trim()) return;
31
+ await client.value.send(content);
32
+ input.value = "";
33
+ }
34
+ function abort() {
35
+ client.value?.abortAll();
36
+ }
37
+ function newConversation() {
38
+ client.value?.newConversation();
39
+ }
40
+ async function switchConversation(conversationId) {
41
+ await client.value?.switchConversation(conversationId);
42
+ }
43
+ async function deleteConversation(conversationId) {
44
+ await client.value?.deleteConversation(conversationId);
45
+ }
46
+ async function getConversations() {
47
+ return client.value?.getConversations() || [];
48
+ }
49
+ return {
50
+ // 状态(响应式)
51
+ messages,
52
+ conversations,
53
+ currentConversation,
54
+ isSending,
55
+ isLoading,
56
+ error,
57
+ input,
58
+ // 方法
59
+ sendMessage,
60
+ abort,
61
+ newConversation,
62
+ switchConversation,
63
+ deleteConversation,
64
+ getConversations,
65
+ // Client 实例(高级用法)
66
+ client
67
+ };
68
+ }
69
+ function useChatClient(config) {
70
+ const client = shallowRef(null);
71
+ onMounted(() => {
72
+ client.value = new ChatClient(config);
73
+ });
74
+ onUnmounted(() => {
75
+ client.value?.destroy();
76
+ });
77
+ return client;
78
+ }
79
+ function useChatEvent(client, event, listener) {
80
+ let unsubscribe = null;
81
+ watch(
82
+ client,
83
+ (newClient) => {
84
+ unsubscribe?.();
85
+ if (newClient) {
86
+ unsubscribe = newClient.on(event, listener);
87
+ }
88
+ },
89
+ { immediate: true }
90
+ );
91
+ onUnmounted(() => {
92
+ unsubscribe?.();
93
+ });
94
+ }
95
+ function useChatState(client) {
96
+ const state = ref({
97
+ currentConversation: null,
98
+ conversations: [],
99
+ isSending: false,
100
+ isLoading: false,
101
+ isConnected: false,
102
+ error: null,
103
+ inputValue: ""
104
+ });
105
+ let unsubscribe = null;
106
+ watch(
107
+ client,
108
+ (newClient) => {
109
+ unsubscribe?.();
110
+ if (newClient) {
111
+ state.value = newClient.getState();
112
+ unsubscribe = newClient.subscribe((newState) => {
113
+ state.value = newState;
114
+ });
115
+ }
116
+ },
117
+ { immediate: true }
118
+ );
119
+ onUnmounted(() => {
120
+ unsubscribe?.();
121
+ });
122
+ return state;
123
+ }
124
+
125
+ export { useChat, useChatClient, useChatEvent, useChatState };
126
+ //# sourceMappingURL=index.mjs.map
127
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/composables.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { ref, shallowRef, onMounted, onUnmounted, watch, Ref } from 'vue';\nimport {\n ChatClient,\n ChatConfig,\n ChatState,\n Message,\n Conversation,\n ChatEventType,\n ChatEventListener,\n} from '@lingshuai/chat-core';\n\n/**\n * useChat Composable - 提供完整的聊天功能\n *\n * @example\n * ```vue\n * <script setup>\n * import { useChat } from '@lingshuai/chat-vue';\n *\n * const {\n * messages,\n * isSending,\n * input,\n * sendMessage,\n * } = useChat({\n * apiKey: 'your-api-key',\n * appId: 'your-app-id',\n * });\n * </script>\n *\n * <template>\n * <div>\n * <div v-for=\"msg in messages\" :key=\"msg.id\">\n * {{ msg.content }}\n * </div>\n * <input v-model=\"input\" @keydown.enter=\"sendMessage(input)\" />\n * <button @click=\"sendMessage(input)\" :disabled=\"isSending\">发送</button>\n * </div>\n * </template>\n * ```\n */\nexport function useChat(config: ChatConfig) {\n const client = shallowRef<ChatClient | null>(null);\n const messages = ref<Message[]>([]);\n const conversations = ref<Conversation[]>([]);\n const currentConversation = ref<Conversation | null>(null);\n const isSending = ref(false);\n const isLoading = ref(false);\n const error = ref<Error | null>(null);\n const input = ref('');\n\n // 初始化\n onMounted(() => {\n client.value = new ChatClient(config);\n\n // 订阅状态变更\n client.value.subscribe((state) => {\n messages.value = state.currentConversation?.messages || [];\n conversations.value = state.conversations;\n currentConversation.value = state.currentConversation;\n isSending.value = state.isSending;\n isLoading.value = state.isLoading;\n error.value = state.error;\n });\n });\n\n // 清理\n onUnmounted(() => {\n client.value?.destroy();\n });\n\n // 发送消息\n async function sendMessage(content: string) {\n if (!client.value || !content.trim()) return;\n await client.value.send(content);\n input.value = '';\n }\n\n // 取消发送\n function abort() {\n client.value?.abortAll();\n }\n\n // 新建会话\n function newConversation() {\n client.value?.newConversation();\n }\n\n // 切换会话\n async function switchConversation(conversationId: string) {\n await client.value?.switchConversation(conversationId);\n }\n\n // 删除会话\n async function deleteConversation(conversationId: string) {\n await client.value?.deleteConversation(conversationId);\n }\n\n // 获取会话列表\n async function getConversations() {\n return client.value?.getConversations() || [];\n }\n\n return {\n // 状态(响应式)\n messages,\n conversations,\n currentConversation,\n isSending,\n isLoading,\n error,\n input,\n\n // 方法\n sendMessage,\n abort,\n newConversation,\n switchConversation,\n deleteConversation,\n getConversations,\n\n // Client 实例(高级用法)\n client,\n };\n}\n\n/**\n * useChatClient Composable - 创建 ChatClient 实例\n *\n * @example\n * ```vue\n * <script setup>\n * import { useChatClient } from '@lingshuai/chat-vue';\n *\n * const client = useChatClient({\n * apiKey: 'your-api-key',\n * appId: 'your-app-id',\n * });\n *\n * client.on('message:received', ({ message }) => {\n * console.log('收到消息:', message.content);\n * });\n * </script>\n * ```\n */\nexport function useChatClient(config: ChatConfig): Ref<ChatClient | null> {\n const client = shallowRef<ChatClient | null>(null);\n\n onMounted(() => {\n client.value = new ChatClient(config);\n });\n\n onUnmounted(() => {\n client.value?.destroy();\n });\n\n return client;\n}\n\n/**\n * useChatEvent Composable - 监听聊天事件\n *\n * @example\n * ```vue\n * <script setup>\n * import { useChatClient, useChatEvent } from '@lingshuai/chat-vue';\n *\n * const client = useChatClient({ apiKey: 'xxx', appId: 'xxx' });\n *\n * useChatEvent(client, 'message:stream:chunk', ({ fullContent }) => {\n * console.log('流式内容:', fullContent);\n * });\n * </script>\n * ```\n */\nexport function useChatEvent<T extends ChatEventType>(\n client: Ref<ChatClient | null>,\n event: T,\n listener: ChatEventListener<T>\n) {\n let unsubscribe: (() => void) | null = null;\n\n watch(\n client,\n (newClient) => {\n // 清理旧的订阅\n unsubscribe?.();\n\n // 建立新的订阅\n if (newClient) {\n unsubscribe = newClient.on(event, listener);\n }\n },\n { immediate: true }\n );\n\n onUnmounted(() => {\n unsubscribe?.();\n });\n}\n\n/**\n * useChatState Composable - 订阅聊天状态\n */\nexport function useChatState(client: Ref<ChatClient | null>) {\n const state = ref<ChatState>({\n currentConversation: null,\n conversations: [],\n isSending: false,\n isLoading: false,\n isConnected: false,\n error: null,\n inputValue: '',\n });\n\n let unsubscribe: (() => void) | null = null;\n\n watch(\n client,\n (newClient) => {\n unsubscribe?.();\n\n if (newClient) {\n state.value = newClient.getState();\n unsubscribe = newClient.subscribe((newState) => {\n state.value = newState;\n });\n }\n },\n { immediate: true }\n );\n\n onUnmounted(() => {\n unsubscribe?.();\n });\n\n return state;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@lingshuai/chat-vue",
3
+ "version": "0.1.0",
4
+ "description": "AI 对话 SDK Vue 组件 - Vue 3 Composables",
5
+ "author": "LingShuAI Team",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/lingshuai/chat-sdk"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "module": "./dist/index.mjs",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.js",
17
+ "types": "./dist/index.d.ts"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "dependencies": {
24
+ "@lingshuai/chat-core": "0.1.0"
25
+ },
26
+ "peerDependencies": {
27
+ "vue": ">=3.3.0"
28
+ },
29
+ "devDependencies": {
30
+ "vue": "^3.4.0",
31
+ "tsup": "^8.0.0",
32
+ "typescript": "^5.3.0",
33
+ "rimraf": "^5.0.0"
34
+ },
35
+ "keywords": [
36
+ "ai",
37
+ "chat",
38
+ "vue",
39
+ "sdk",
40
+ "composables",
41
+ "chatbot"
42
+ ],
43
+ "license": "MIT",
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "scripts": {
48
+ "build": "tsup",
49
+ "dev": "tsup --watch",
50
+ "clean": "rimraf dist",
51
+ "typecheck": "tsc --noEmit"
52
+ }
53
+ }