@lingshuai/chat-vue 0.1.2 → 0.1.3

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/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as vue from 'vue';
2
2
  import { Ref } from 'vue';
3
3
  import * as _lingshuai_chat_core from '@lingshuai/chat-core';
4
- import { ChatConfig, Message, Conversation, ChatClient, ChatEventType, ChatEventListener, ChatState } from '@lingshuai/chat-core';
4
+ import { ChatConfig, MediaType, Message, Conversation, MediaAttachment, UploadResult, TtsPlayState, TtsOptions, TtsResult, TtsVoiceOption, ChatClient, ChatEventType, ChatEventListener, ChatState } from '@lingshuai/chat-core';
5
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
6
 
7
7
  /**
@@ -42,6 +42,14 @@ declare function useChat(config: ChatConfig): {
42
42
  content: string;
43
43
  status: _lingshuai_chat_core.MessageStatus;
44
44
  createdAt: Date;
45
+ attachments?: {
46
+ type: MediaType;
47
+ url: string;
48
+ mimeType?: string | undefined;
49
+ name?: string | undefined;
50
+ size?: number | undefined;
51
+ duration?: number | undefined;
52
+ }[] | undefined;
45
53
  metadata?: Record<string, unknown> | undefined;
46
54
  }[], Message[] | {
47
55
  id: string;
@@ -50,6 +58,14 @@ declare function useChat(config: ChatConfig): {
50
58
  content: string;
51
59
  status: _lingshuai_chat_core.MessageStatus;
52
60
  createdAt: Date;
61
+ attachments?: {
62
+ type: MediaType;
63
+ url: string;
64
+ mimeType?: string | undefined;
65
+ name?: string | undefined;
66
+ size?: number | undefined;
67
+ duration?: number | undefined;
68
+ }[] | undefined;
53
69
  metadata?: Record<string, unknown> | undefined;
54
70
  }[]>;
55
71
  conversations: Ref<{
@@ -62,6 +78,14 @@ declare function useChat(config: ChatConfig): {
62
78
  content: string;
63
79
  status: _lingshuai_chat_core.MessageStatus;
64
80
  createdAt: Date;
81
+ attachments?: {
82
+ type: MediaType;
83
+ url: string;
84
+ mimeType?: string | undefined;
85
+ name?: string | undefined;
86
+ size?: number | undefined;
87
+ duration?: number | undefined;
88
+ }[] | undefined;
65
89
  metadata?: Record<string, unknown> | undefined;
66
90
  }[];
67
91
  createdAt: Date;
@@ -76,6 +100,14 @@ declare function useChat(config: ChatConfig): {
76
100
  content: string;
77
101
  status: _lingshuai_chat_core.MessageStatus;
78
102
  createdAt: Date;
103
+ attachments?: {
104
+ type: MediaType;
105
+ url: string;
106
+ mimeType?: string | undefined;
107
+ name?: string | undefined;
108
+ size?: number | undefined;
109
+ duration?: number | undefined;
110
+ }[] | undefined;
79
111
  metadata?: Record<string, unknown> | undefined;
80
112
  }[];
81
113
  createdAt: Date;
@@ -91,6 +123,14 @@ declare function useChat(config: ChatConfig): {
91
123
  content: string;
92
124
  status: _lingshuai_chat_core.MessageStatus;
93
125
  createdAt: Date;
126
+ attachments?: {
127
+ type: MediaType;
128
+ url: string;
129
+ mimeType?: string | undefined;
130
+ name?: string | undefined;
131
+ size?: number | undefined;
132
+ duration?: number | undefined;
133
+ }[] | undefined;
94
134
  metadata?: Record<string, unknown> | undefined;
95
135
  }[];
96
136
  createdAt: Date;
@@ -105,6 +145,14 @@ declare function useChat(config: ChatConfig): {
105
145
  content: string;
106
146
  status: _lingshuai_chat_core.MessageStatus;
107
147
  createdAt: Date;
148
+ attachments?: {
149
+ type: MediaType;
150
+ url: string;
151
+ mimeType?: string | undefined;
152
+ name?: string | undefined;
153
+ size?: number | undefined;
154
+ duration?: number | undefined;
155
+ }[] | undefined;
108
156
  metadata?: Record<string, unknown> | undefined;
109
157
  }[];
110
158
  createdAt: Date;
@@ -112,14 +160,32 @@ declare function useChat(config: ChatConfig): {
112
160
  } | null>;
113
161
  isSending: Ref<boolean, boolean>;
114
162
  isLoading: Ref<boolean, boolean>;
163
+ isUploading: Ref<boolean, boolean>;
115
164
  error: Ref<Error | null, Error | null>;
116
165
  input: Ref<string, string>;
117
166
  sendMessage: (content: string) => Promise<void>;
167
+ sendWithAttachments: (content: string, attachments: MediaAttachment[]) => Promise<void>;
168
+ uploadFile: (file: File | Blob, type: MediaType) => Promise<UploadResult | undefined>;
169
+ sendImage: (file: File | Blob, content?: string) => Promise<void>;
170
+ sendVoice: (file: File | Blob, content?: string) => Promise<void>;
171
+ sendVideo: (file: File | Blob, content?: string) => Promise<void>;
118
172
  abort: () => void;
119
173
  newConversation: () => void;
120
174
  switchConversation: (conversationId: string) => Promise<void>;
121
175
  deleteConversation: (conversationId: string) => Promise<void>;
122
176
  getConversations: () => Promise<never[] | Conversation[]>;
177
+ ttsPlayState: Ref<TtsPlayState, TtsPlayState>;
178
+ ttsPlayingMessageId: Ref<string | null, string | null>;
179
+ ttsAutoPlay: Ref<boolean, boolean>;
180
+ ttsMuted: Ref<boolean, boolean>;
181
+ playTts: (messageId: string, text: string, options?: TtsOptions) => Promise<void>;
182
+ pauseTts: () => void;
183
+ resumeTts: () => void;
184
+ stopTts: () => void;
185
+ setTtsAutoPlay: (enabled: boolean) => void;
186
+ setTtsMuted: (muted: boolean) => void;
187
+ generateTts: (text: string, options?: TtsOptions) => Promise<TtsResult | undefined>;
188
+ getTtsVoices: () => Promise<TtsVoiceOption[]>;
123
189
  client: vue.ShallowRef<ChatClient | null, ChatClient | null>;
124
190
  };
125
191
  /**
@@ -173,6 +239,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
173
239
  content: string;
174
240
  status: _lingshuai_chat_core.MessageStatus;
175
241
  createdAt: Date;
242
+ attachments?: {
243
+ type: MediaType;
244
+ url: string;
245
+ mimeType?: string | undefined;
246
+ name?: string | undefined;
247
+ size?: number | undefined;
248
+ duration?: number | undefined;
249
+ }[] | undefined;
176
250
  metadata?: Record<string, unknown> | undefined;
177
251
  }[];
178
252
  createdAt: Date;
@@ -188,6 +262,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
188
262
  content: string;
189
263
  status: _lingshuai_chat_core.MessageStatus;
190
264
  createdAt: Date;
265
+ attachments?: {
266
+ type: MediaType;
267
+ url: string;
268
+ mimeType?: string | undefined;
269
+ name?: string | undefined;
270
+ size?: number | undefined;
271
+ duration?: number | undefined;
272
+ }[] | undefined;
191
273
  metadata?: Record<string, unknown> | undefined;
192
274
  }[];
193
275
  createdAt: Date;
@@ -209,6 +291,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
209
291
  content: string;
210
292
  status: _lingshuai_chat_core.MessageStatus;
211
293
  createdAt: Date;
294
+ attachments?: {
295
+ type: MediaType;
296
+ url: string;
297
+ mimeType?: string | undefined;
298
+ name?: string | undefined;
299
+ size?: number | undefined;
300
+ duration?: number | undefined;
301
+ }[] | undefined;
212
302
  metadata?: Record<string, unknown> | undefined;
213
303
  }[];
214
304
  createdAt: Date;
@@ -224,6 +314,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
224
314
  content: string;
225
315
  status: _lingshuai_chat_core.MessageStatus;
226
316
  createdAt: Date;
317
+ attachments?: {
318
+ type: MediaType;
319
+ url: string;
320
+ mimeType?: string | undefined;
321
+ name?: string | undefined;
322
+ size?: number | undefined;
323
+ duration?: number | undefined;
324
+ }[] | undefined;
227
325
  metadata?: Record<string, unknown> | undefined;
228
326
  }[];
229
327
  createdAt: Date;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as vue from 'vue';
2
2
  import { Ref } from 'vue';
3
3
  import * as _lingshuai_chat_core from '@lingshuai/chat-core';
4
- import { ChatConfig, Message, Conversation, ChatClient, ChatEventType, ChatEventListener, ChatState } from '@lingshuai/chat-core';
4
+ import { ChatConfig, MediaType, Message, Conversation, MediaAttachment, UploadResult, TtsPlayState, TtsOptions, TtsResult, TtsVoiceOption, ChatClient, ChatEventType, ChatEventListener, ChatState } from '@lingshuai/chat-core';
5
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
6
 
7
7
  /**
@@ -42,6 +42,14 @@ declare function useChat(config: ChatConfig): {
42
42
  content: string;
43
43
  status: _lingshuai_chat_core.MessageStatus;
44
44
  createdAt: Date;
45
+ attachments?: {
46
+ type: MediaType;
47
+ url: string;
48
+ mimeType?: string | undefined;
49
+ name?: string | undefined;
50
+ size?: number | undefined;
51
+ duration?: number | undefined;
52
+ }[] | undefined;
45
53
  metadata?: Record<string, unknown> | undefined;
46
54
  }[], Message[] | {
47
55
  id: string;
@@ -50,6 +58,14 @@ declare function useChat(config: ChatConfig): {
50
58
  content: string;
51
59
  status: _lingshuai_chat_core.MessageStatus;
52
60
  createdAt: Date;
61
+ attachments?: {
62
+ type: MediaType;
63
+ url: string;
64
+ mimeType?: string | undefined;
65
+ name?: string | undefined;
66
+ size?: number | undefined;
67
+ duration?: number | undefined;
68
+ }[] | undefined;
53
69
  metadata?: Record<string, unknown> | undefined;
54
70
  }[]>;
55
71
  conversations: Ref<{
@@ -62,6 +78,14 @@ declare function useChat(config: ChatConfig): {
62
78
  content: string;
63
79
  status: _lingshuai_chat_core.MessageStatus;
64
80
  createdAt: Date;
81
+ attachments?: {
82
+ type: MediaType;
83
+ url: string;
84
+ mimeType?: string | undefined;
85
+ name?: string | undefined;
86
+ size?: number | undefined;
87
+ duration?: number | undefined;
88
+ }[] | undefined;
65
89
  metadata?: Record<string, unknown> | undefined;
66
90
  }[];
67
91
  createdAt: Date;
@@ -76,6 +100,14 @@ declare function useChat(config: ChatConfig): {
76
100
  content: string;
77
101
  status: _lingshuai_chat_core.MessageStatus;
78
102
  createdAt: Date;
103
+ attachments?: {
104
+ type: MediaType;
105
+ url: string;
106
+ mimeType?: string | undefined;
107
+ name?: string | undefined;
108
+ size?: number | undefined;
109
+ duration?: number | undefined;
110
+ }[] | undefined;
79
111
  metadata?: Record<string, unknown> | undefined;
80
112
  }[];
81
113
  createdAt: Date;
@@ -91,6 +123,14 @@ declare function useChat(config: ChatConfig): {
91
123
  content: string;
92
124
  status: _lingshuai_chat_core.MessageStatus;
93
125
  createdAt: Date;
126
+ attachments?: {
127
+ type: MediaType;
128
+ url: string;
129
+ mimeType?: string | undefined;
130
+ name?: string | undefined;
131
+ size?: number | undefined;
132
+ duration?: number | undefined;
133
+ }[] | undefined;
94
134
  metadata?: Record<string, unknown> | undefined;
95
135
  }[];
96
136
  createdAt: Date;
@@ -105,6 +145,14 @@ declare function useChat(config: ChatConfig): {
105
145
  content: string;
106
146
  status: _lingshuai_chat_core.MessageStatus;
107
147
  createdAt: Date;
148
+ attachments?: {
149
+ type: MediaType;
150
+ url: string;
151
+ mimeType?: string | undefined;
152
+ name?: string | undefined;
153
+ size?: number | undefined;
154
+ duration?: number | undefined;
155
+ }[] | undefined;
108
156
  metadata?: Record<string, unknown> | undefined;
109
157
  }[];
110
158
  createdAt: Date;
@@ -112,14 +160,32 @@ declare function useChat(config: ChatConfig): {
112
160
  } | null>;
113
161
  isSending: Ref<boolean, boolean>;
114
162
  isLoading: Ref<boolean, boolean>;
163
+ isUploading: Ref<boolean, boolean>;
115
164
  error: Ref<Error | null, Error | null>;
116
165
  input: Ref<string, string>;
117
166
  sendMessage: (content: string) => Promise<void>;
167
+ sendWithAttachments: (content: string, attachments: MediaAttachment[]) => Promise<void>;
168
+ uploadFile: (file: File | Blob, type: MediaType) => Promise<UploadResult | undefined>;
169
+ sendImage: (file: File | Blob, content?: string) => Promise<void>;
170
+ sendVoice: (file: File | Blob, content?: string) => Promise<void>;
171
+ sendVideo: (file: File | Blob, content?: string) => Promise<void>;
118
172
  abort: () => void;
119
173
  newConversation: () => void;
120
174
  switchConversation: (conversationId: string) => Promise<void>;
121
175
  deleteConversation: (conversationId: string) => Promise<void>;
122
176
  getConversations: () => Promise<never[] | Conversation[]>;
177
+ ttsPlayState: Ref<TtsPlayState, TtsPlayState>;
178
+ ttsPlayingMessageId: Ref<string | null, string | null>;
179
+ ttsAutoPlay: Ref<boolean, boolean>;
180
+ ttsMuted: Ref<boolean, boolean>;
181
+ playTts: (messageId: string, text: string, options?: TtsOptions) => Promise<void>;
182
+ pauseTts: () => void;
183
+ resumeTts: () => void;
184
+ stopTts: () => void;
185
+ setTtsAutoPlay: (enabled: boolean) => void;
186
+ setTtsMuted: (muted: boolean) => void;
187
+ generateTts: (text: string, options?: TtsOptions) => Promise<TtsResult | undefined>;
188
+ getTtsVoices: () => Promise<TtsVoiceOption[]>;
123
189
  client: vue.ShallowRef<ChatClient | null, ChatClient | null>;
124
190
  };
125
191
  /**
@@ -173,6 +239,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
173
239
  content: string;
174
240
  status: _lingshuai_chat_core.MessageStatus;
175
241
  createdAt: Date;
242
+ attachments?: {
243
+ type: MediaType;
244
+ url: string;
245
+ mimeType?: string | undefined;
246
+ name?: string | undefined;
247
+ size?: number | undefined;
248
+ duration?: number | undefined;
249
+ }[] | undefined;
176
250
  metadata?: Record<string, unknown> | undefined;
177
251
  }[];
178
252
  createdAt: Date;
@@ -188,6 +262,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
188
262
  content: string;
189
263
  status: _lingshuai_chat_core.MessageStatus;
190
264
  createdAt: Date;
265
+ attachments?: {
266
+ type: MediaType;
267
+ url: string;
268
+ mimeType?: string | undefined;
269
+ name?: string | undefined;
270
+ size?: number | undefined;
271
+ duration?: number | undefined;
272
+ }[] | undefined;
191
273
  metadata?: Record<string, unknown> | undefined;
192
274
  }[];
193
275
  createdAt: Date;
@@ -209,6 +291,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
209
291
  content: string;
210
292
  status: _lingshuai_chat_core.MessageStatus;
211
293
  createdAt: Date;
294
+ attachments?: {
295
+ type: MediaType;
296
+ url: string;
297
+ mimeType?: string | undefined;
298
+ name?: string | undefined;
299
+ size?: number | undefined;
300
+ duration?: number | undefined;
301
+ }[] | undefined;
212
302
  metadata?: Record<string, unknown> | undefined;
213
303
  }[];
214
304
  createdAt: Date;
@@ -224,6 +314,14 @@ declare function useChatState(client: Ref<ChatClient | null>): Ref<{
224
314
  content: string;
225
315
  status: _lingshuai_chat_core.MessageStatus;
226
316
  createdAt: Date;
317
+ attachments?: {
318
+ type: MediaType;
319
+ url: string;
320
+ mimeType?: string | undefined;
321
+ name?: string | undefined;
322
+ size?: number | undefined;
323
+ duration?: number | undefined;
324
+ }[] | undefined;
227
325
  metadata?: Record<string, unknown> | undefined;
228
326
  }[];
229
327
  createdAt: Date;
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ function useChat(config) {
11
11
  const currentConversation = vue.ref(null);
12
12
  const isSending = vue.ref(false);
13
13
  const isLoading = vue.ref(false);
14
+ const isUploading = vue.ref(false);
14
15
  const error = vue.ref(null);
15
16
  const input = vue.ref("");
16
17
  vue.onMounted(() => {
@@ -32,6 +33,48 @@ function useChat(config) {
32
33
  await client.value.send(content);
33
34
  input.value = "";
34
35
  }
36
+ async function sendWithAttachments(content, attachments) {
37
+ if (!client.value) return;
38
+ if (!content.trim() && attachments.length === 0) return;
39
+ await client.value.sendWithAttachments(content, attachments);
40
+ input.value = "";
41
+ }
42
+ async function uploadFile(file, type) {
43
+ if (!client.value) return void 0;
44
+ isUploading.value = true;
45
+ try {
46
+ return await client.value.uploadFile(file, type);
47
+ } finally {
48
+ isUploading.value = false;
49
+ }
50
+ }
51
+ async function sendImage(file, content) {
52
+ if (!client.value) return;
53
+ isUploading.value = true;
54
+ try {
55
+ await client.value.sendImage(file, content);
56
+ } finally {
57
+ isUploading.value = false;
58
+ }
59
+ }
60
+ async function sendVoice(file, content) {
61
+ if (!client.value) return;
62
+ isUploading.value = true;
63
+ try {
64
+ await client.value.sendVoice(file, content);
65
+ } finally {
66
+ isUploading.value = false;
67
+ }
68
+ }
69
+ async function sendVideo(file, content) {
70
+ if (!client.value) return;
71
+ isUploading.value = true;
72
+ try {
73
+ await client.value.sendVideo(file, content);
74
+ } finally {
75
+ isUploading.value = false;
76
+ }
77
+ }
35
78
  function abort() {
36
79
  client.value?.abortAll();
37
80
  }
@@ -47,6 +90,59 @@ function useChat(config) {
47
90
  async function getConversations() {
48
91
  return client.value?.getConversations() || [];
49
92
  }
93
+ const ttsPlayState = vue.ref("idle");
94
+ const ttsPlayingMessageId = vue.ref(null);
95
+ const ttsAutoPlay = vue.ref(false);
96
+ const ttsMuted = vue.ref(false);
97
+ vue.onMounted(() => {
98
+ const c = client.value;
99
+ if (!c) return;
100
+ c.on("tts:start", ({ messageId }) => {
101
+ ttsPlayState.value = "loading";
102
+ ttsPlayingMessageId.value = messageId;
103
+ });
104
+ c.on("tts:play", ({ messageId }) => {
105
+ ttsPlayState.value = "playing";
106
+ ttsPlayingMessageId.value = messageId;
107
+ });
108
+ c.on("tts:pause", () => {
109
+ ttsPlayState.value = "paused";
110
+ });
111
+ c.on("tts:stop", () => {
112
+ ttsPlayState.value = "idle";
113
+ ttsPlayingMessageId.value = null;
114
+ });
115
+ c.on("tts:error", () => {
116
+ ttsPlayState.value = "error";
117
+ ttsPlayingMessageId.value = null;
118
+ });
119
+ });
120
+ async function playTts(messageId, text, options) {
121
+ await client.value?.playTts(messageId, text, options);
122
+ }
123
+ function pauseTts() {
124
+ client.value?.pauseTts();
125
+ }
126
+ function resumeTts() {
127
+ client.value?.resumeTts();
128
+ }
129
+ function stopTts() {
130
+ client.value?.stopTts();
131
+ }
132
+ function setTtsAutoPlay(enabled) {
133
+ client.value?.setTtsAutoPlay(enabled);
134
+ ttsAutoPlay.value = enabled;
135
+ }
136
+ function setTtsMuted(muted) {
137
+ client.value?.setTtsMuted(muted);
138
+ ttsMuted.value = muted;
139
+ }
140
+ async function generateTts(text, options) {
141
+ return client.value?.generateTts(text, options);
142
+ }
143
+ async function getTtsVoices() {
144
+ return client.value?.getTtsVoices() || [];
145
+ }
50
146
  return {
51
147
  // 状态(响应式)
52
148
  messages,
@@ -54,15 +150,34 @@ function useChat(config) {
54
150
  currentConversation,
55
151
  isSending,
56
152
  isLoading,
153
+ isUploading,
57
154
  error,
58
155
  input,
59
156
  // 方法
60
157
  sendMessage,
158
+ sendWithAttachments,
159
+ uploadFile,
160
+ sendImage,
161
+ sendVoice,
162
+ sendVideo,
61
163
  abort,
62
164
  newConversation,
63
165
  switchConversation,
64
166
  deleteConversation,
65
167
  getConversations,
168
+ // TTS 语音播报
169
+ ttsPlayState,
170
+ ttsPlayingMessageId,
171
+ ttsAutoPlay,
172
+ ttsMuted,
173
+ playTts,
174
+ pauseTts,
175
+ resumeTts,
176
+ stopTts,
177
+ setTtsAutoPlay,
178
+ setTtsMuted,
179
+ generateTts,
180
+ getTtsVoices,
66
181
  // Client 实例(高级用法)
67
182
  client
68
183
  };
package/dist/index.js.map CHANGED
@@ -1 +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"]}
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 MediaAttachment,\n MediaType,\n UploadResult,\n TtsOptions,\n TtsResult,\n TtsVoiceOption,\n TtsPlayState,\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 isUploading = 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 async function sendWithAttachments(content: string, attachments: MediaAttachment[]) {\n if (!client.value) return;\n if (!content.trim() && attachments.length === 0) return;\n await client.value.sendWithAttachments(content, attachments);\n input.value = '';\n }\n\n // 上传文件\n async function uploadFile(file: File | Blob, type: MediaType): Promise<UploadResult | undefined> {\n if (!client.value) return undefined;\n isUploading.value = true;\n try {\n return await client.value.uploadFile(file, type);\n } finally {\n isUploading.value = false;\n }\n }\n\n // 上传并发送图片\n async function sendImage(file: File | Blob, content?: string) {\n if (!client.value) return;\n isUploading.value = true;\n try {\n await client.value.sendImage(file, content);\n } finally {\n isUploading.value = false;\n }\n }\n\n // 上传并发送语音\n async function sendVoice(file: File | Blob, content?: string) {\n if (!client.value) return;\n isUploading.value = true;\n try {\n await client.value.sendVoice(file, content);\n } finally {\n isUploading.value = false;\n }\n }\n\n // 上传并发送视频\n async function sendVideo(file: File | Blob, content?: string) {\n if (!client.value) return;\n isUploading.value = true;\n try {\n await client.value.sendVideo(file, content);\n } finally {\n isUploading.value = false;\n }\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 // ========== TTS 语音播报 ==========\n\n const ttsPlayState = ref<TtsPlayState>('idle');\n const ttsPlayingMessageId = ref<string | null>(null);\n const ttsAutoPlay = ref(false);\n const ttsMuted = ref(false);\n\n onMounted(() => {\n const c = client.value;\n if (!c) return;\n c.on('tts:start', ({ messageId }) => {\n ttsPlayState.value = 'loading';\n ttsPlayingMessageId.value = messageId;\n });\n c.on('tts:play', ({ messageId }) => {\n ttsPlayState.value = 'playing';\n ttsPlayingMessageId.value = messageId;\n });\n c.on('tts:pause', () => { ttsPlayState.value = 'paused'; });\n c.on('tts:stop', () => {\n ttsPlayState.value = 'idle';\n ttsPlayingMessageId.value = null;\n });\n c.on('tts:error', () => {\n ttsPlayState.value = 'error';\n ttsPlayingMessageId.value = null;\n });\n });\n\n async function playTts(messageId: string, text: string, options?: TtsOptions) {\n await client.value?.playTts(messageId, text, options);\n }\n function pauseTts() { client.value?.pauseTts(); }\n function resumeTts() { client.value?.resumeTts(); }\n function stopTts() { client.value?.stopTts(); }\n\n function setTtsAutoPlay(enabled: boolean) {\n client.value?.setTtsAutoPlay(enabled);\n ttsAutoPlay.value = enabled;\n }\n function setTtsMuted(muted: boolean) {\n client.value?.setTtsMuted(muted);\n ttsMuted.value = muted;\n }\n\n async function generateTts(text: string, options?: TtsOptions): Promise<TtsResult | undefined> {\n return client.value?.generateTts(text, options);\n }\n async function getTtsVoices(): Promise<TtsVoiceOption[]> {\n return client.value?.getTtsVoices() || [];\n }\n\n return {\n // 状态(响应式)\n messages,\n conversations,\n currentConversation,\n isSending,\n isLoading,\n isUploading,\n error,\n input,\n\n // 方法\n sendMessage,\n sendWithAttachments,\n uploadFile,\n sendImage,\n sendVoice,\n sendVideo,\n abort,\n newConversation,\n switchConversation,\n deleteConversation,\n getConversations,\n\n // TTS 语音播报\n ttsPlayState,\n ttsPlayingMessageId,\n ttsAutoPlay,\n ttsMuted,\n playTts,\n pauseTts,\n resumeTts,\n stopTts,\n setTtsAutoPlay,\n setTtsMuted,\n generateTts,\n getTtsVoices,\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 CHANGED
@@ -10,6 +10,7 @@ function useChat(config) {
10
10
  const currentConversation = ref(null);
11
11
  const isSending = ref(false);
12
12
  const isLoading = ref(false);
13
+ const isUploading = ref(false);
13
14
  const error = ref(null);
14
15
  const input = ref("");
15
16
  onMounted(() => {
@@ -31,6 +32,48 @@ function useChat(config) {
31
32
  await client.value.send(content);
32
33
  input.value = "";
33
34
  }
35
+ async function sendWithAttachments(content, attachments) {
36
+ if (!client.value) return;
37
+ if (!content.trim() && attachments.length === 0) return;
38
+ await client.value.sendWithAttachments(content, attachments);
39
+ input.value = "";
40
+ }
41
+ async function uploadFile(file, type) {
42
+ if (!client.value) return void 0;
43
+ isUploading.value = true;
44
+ try {
45
+ return await client.value.uploadFile(file, type);
46
+ } finally {
47
+ isUploading.value = false;
48
+ }
49
+ }
50
+ async function sendImage(file, content) {
51
+ if (!client.value) return;
52
+ isUploading.value = true;
53
+ try {
54
+ await client.value.sendImage(file, content);
55
+ } finally {
56
+ isUploading.value = false;
57
+ }
58
+ }
59
+ async function sendVoice(file, content) {
60
+ if (!client.value) return;
61
+ isUploading.value = true;
62
+ try {
63
+ await client.value.sendVoice(file, content);
64
+ } finally {
65
+ isUploading.value = false;
66
+ }
67
+ }
68
+ async function sendVideo(file, content) {
69
+ if (!client.value) return;
70
+ isUploading.value = true;
71
+ try {
72
+ await client.value.sendVideo(file, content);
73
+ } finally {
74
+ isUploading.value = false;
75
+ }
76
+ }
34
77
  function abort() {
35
78
  client.value?.abortAll();
36
79
  }
@@ -46,6 +89,59 @@ function useChat(config) {
46
89
  async function getConversations() {
47
90
  return client.value?.getConversations() || [];
48
91
  }
92
+ const ttsPlayState = ref("idle");
93
+ const ttsPlayingMessageId = ref(null);
94
+ const ttsAutoPlay = ref(false);
95
+ const ttsMuted = ref(false);
96
+ onMounted(() => {
97
+ const c = client.value;
98
+ if (!c) return;
99
+ c.on("tts:start", ({ messageId }) => {
100
+ ttsPlayState.value = "loading";
101
+ ttsPlayingMessageId.value = messageId;
102
+ });
103
+ c.on("tts:play", ({ messageId }) => {
104
+ ttsPlayState.value = "playing";
105
+ ttsPlayingMessageId.value = messageId;
106
+ });
107
+ c.on("tts:pause", () => {
108
+ ttsPlayState.value = "paused";
109
+ });
110
+ c.on("tts:stop", () => {
111
+ ttsPlayState.value = "idle";
112
+ ttsPlayingMessageId.value = null;
113
+ });
114
+ c.on("tts:error", () => {
115
+ ttsPlayState.value = "error";
116
+ ttsPlayingMessageId.value = null;
117
+ });
118
+ });
119
+ async function playTts(messageId, text, options) {
120
+ await client.value?.playTts(messageId, text, options);
121
+ }
122
+ function pauseTts() {
123
+ client.value?.pauseTts();
124
+ }
125
+ function resumeTts() {
126
+ client.value?.resumeTts();
127
+ }
128
+ function stopTts() {
129
+ client.value?.stopTts();
130
+ }
131
+ function setTtsAutoPlay(enabled) {
132
+ client.value?.setTtsAutoPlay(enabled);
133
+ ttsAutoPlay.value = enabled;
134
+ }
135
+ function setTtsMuted(muted) {
136
+ client.value?.setTtsMuted(muted);
137
+ ttsMuted.value = muted;
138
+ }
139
+ async function generateTts(text, options) {
140
+ return client.value?.generateTts(text, options);
141
+ }
142
+ async function getTtsVoices() {
143
+ return client.value?.getTtsVoices() || [];
144
+ }
49
145
  return {
50
146
  // 状态(响应式)
51
147
  messages,
@@ -53,15 +149,34 @@ function useChat(config) {
53
149
  currentConversation,
54
150
  isSending,
55
151
  isLoading,
152
+ isUploading,
56
153
  error,
57
154
  input,
58
155
  // 方法
59
156
  sendMessage,
157
+ sendWithAttachments,
158
+ uploadFile,
159
+ sendImage,
160
+ sendVoice,
161
+ sendVideo,
60
162
  abort,
61
163
  newConversation,
62
164
  switchConversation,
63
165
  deleteConversation,
64
166
  getConversations,
167
+ // TTS 语音播报
168
+ ttsPlayState,
169
+ ttsPlayingMessageId,
170
+ ttsAutoPlay,
171
+ ttsMuted,
172
+ playTts,
173
+ pauseTts,
174
+ resumeTts,
175
+ stopTts,
176
+ setTtsAutoPlay,
177
+ setTtsMuted,
178
+ generateTts,
179
+ getTtsVoices,
65
180
  // Client 实例(高级用法)
66
181
  client
67
182
  };
@@ -1 +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"]}
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 MediaAttachment,\n MediaType,\n UploadResult,\n TtsOptions,\n TtsResult,\n TtsVoiceOption,\n TtsPlayState,\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 isUploading = 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 async function sendWithAttachments(content: string, attachments: MediaAttachment[]) {\n if (!client.value) return;\n if (!content.trim() && attachments.length === 0) return;\n await client.value.sendWithAttachments(content, attachments);\n input.value = '';\n }\n\n // 上传文件\n async function uploadFile(file: File | Blob, type: MediaType): Promise<UploadResult | undefined> {\n if (!client.value) return undefined;\n isUploading.value = true;\n try {\n return await client.value.uploadFile(file, type);\n } finally {\n isUploading.value = false;\n }\n }\n\n // 上传并发送图片\n async function sendImage(file: File | Blob, content?: string) {\n if (!client.value) return;\n isUploading.value = true;\n try {\n await client.value.sendImage(file, content);\n } finally {\n isUploading.value = false;\n }\n }\n\n // 上传并发送语音\n async function sendVoice(file: File | Blob, content?: string) {\n if (!client.value) return;\n isUploading.value = true;\n try {\n await client.value.sendVoice(file, content);\n } finally {\n isUploading.value = false;\n }\n }\n\n // 上传并发送视频\n async function sendVideo(file: File | Blob, content?: string) {\n if (!client.value) return;\n isUploading.value = true;\n try {\n await client.value.sendVideo(file, content);\n } finally {\n isUploading.value = false;\n }\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 // ========== TTS 语音播报 ==========\n\n const ttsPlayState = ref<TtsPlayState>('idle');\n const ttsPlayingMessageId = ref<string | null>(null);\n const ttsAutoPlay = ref(false);\n const ttsMuted = ref(false);\n\n onMounted(() => {\n const c = client.value;\n if (!c) return;\n c.on('tts:start', ({ messageId }) => {\n ttsPlayState.value = 'loading';\n ttsPlayingMessageId.value = messageId;\n });\n c.on('tts:play', ({ messageId }) => {\n ttsPlayState.value = 'playing';\n ttsPlayingMessageId.value = messageId;\n });\n c.on('tts:pause', () => { ttsPlayState.value = 'paused'; });\n c.on('tts:stop', () => {\n ttsPlayState.value = 'idle';\n ttsPlayingMessageId.value = null;\n });\n c.on('tts:error', () => {\n ttsPlayState.value = 'error';\n ttsPlayingMessageId.value = null;\n });\n });\n\n async function playTts(messageId: string, text: string, options?: TtsOptions) {\n await client.value?.playTts(messageId, text, options);\n }\n function pauseTts() { client.value?.pauseTts(); }\n function resumeTts() { client.value?.resumeTts(); }\n function stopTts() { client.value?.stopTts(); }\n\n function setTtsAutoPlay(enabled: boolean) {\n client.value?.setTtsAutoPlay(enabled);\n ttsAutoPlay.value = enabled;\n }\n function setTtsMuted(muted: boolean) {\n client.value?.setTtsMuted(muted);\n ttsMuted.value = muted;\n }\n\n async function generateTts(text: string, options?: TtsOptions): Promise<TtsResult | undefined> {\n return client.value?.generateTts(text, options);\n }\n async function getTtsVoices(): Promise<TtsVoiceOption[]> {\n return client.value?.getTtsVoices() || [];\n }\n\n return {\n // 状态(响应式)\n messages,\n conversations,\n currentConversation,\n isSending,\n isLoading,\n isUploading,\n error,\n input,\n\n // 方法\n sendMessage,\n sendWithAttachments,\n uploadFile,\n sendImage,\n sendVoice,\n sendVideo,\n abort,\n newConversation,\n switchConversation,\n deleteConversation,\n getConversations,\n\n // TTS 语音播报\n ttsPlayState,\n ttsPlayingMessageId,\n ttsAutoPlay,\n ttsMuted,\n playTts,\n pauseTts,\n resumeTts,\n stopTts,\n setTtsAutoPlay,\n setTtsMuted,\n generateTts,\n getTtsVoices,\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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingshuai/chat-vue",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "AI 对话 SDK Vue 组件 - Vue 3 Composables",
5
5
  "author": "LingShuAI Team",
6
6
  "repository": {
@@ -21,7 +21,7 @@
21
21
  "dist"
22
22
  ],
23
23
  "dependencies": {
24
- "@lingshuai/chat-core": "0.1.2"
24
+ "@lingshuai/chat-core": "0.1.3"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "vue": ">=3.3.0"