@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 +99 -1
- package/dist/index.d.ts +99 -1
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +115 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -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":";;;;;AAgDO,SAAS,QAAQ,MAAA,EAAoB;AAC1C,EAAA,MAAM,MAAA,GAAS,WAA8B,IAAI,CAAA;AACjD,EAAA,MAAM,QAAA,GAAW,GAAA,CAAe,EAAE,CAAA;AAClC,EAAA,MAAM,aAAA,GAAgB,GAAA,CAAoB,EAAE,CAAA;AAC5C,EAAA,MAAM,mBAAA,GAAsB,IAAyB,IAAI,CAAA;AACzD,EAAA,MAAM,SAAA,GAAY,IAAI,KAAK,CAAA;AAC3B,EAAA,MAAM,SAAA,GAAY,IAAI,KAAK,CAAA;AAC3B,EAAA,MAAM,WAAA,GAAc,IAAI,KAAK,CAAA;AAC7B,EAAA,MAAM,KAAA,GAAQ,IAAkB,IAAI,CAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,IAAI,EAAE,CAAA;AAGpB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAA,CAAO,KAAA,GAAQ,IAAI,UAAA,CAAW,MAAM,CAAA;AAGpC,IAAA,MAAA,CAAO,KAAA,CAAM,SAAA,CAAU,CAAC,KAAA,KAAU;AAChC,MAAA,QAAA,CAAS,KAAA,GAAQ,KAAA,CAAM,mBAAA,EAAqB,QAAA,IAAY,EAAC;AACzD,MAAA,aAAA,CAAc,QAAQ,KAAA,CAAM,aAAA;AAC5B,MAAA,mBAAA,CAAoB,QAAQ,KAAA,CAAM,mBAAA;AAClC,MAAA,SAAA,CAAU,QAAQ,KAAA,CAAM,SAAA;AACxB,MAAA,SAAA,CAAU,QAAQ,KAAA,CAAM,SAAA;AACxB,MAAA,KAAA,CAAM,QAAQ,KAAA,CAAM,KAAA;AAAA,IACtB,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAGD,EAAA,WAAA,CAAY,MAAM;AAChB,IAAA,MAAA,CAAO,OAAO,OAAA,EAAQ;AAAA,EACxB,CAAC,CAAA;AAGD,EAAA,eAAe,YAAY,OAAA,EAAiB;AAC1C,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,OAAA,CAAQ,MAAK,EAAG;AACtC,IAAA,MAAM,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AAC/B,IAAA,KAAA,CAAM,KAAA,GAAQ,EAAA;AAAA,EAChB;AAGA,EAAA,eAAe,mBAAA,CAAoB,SAAiB,WAAA,EAAgC;AAClF,IAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACnB,IAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,EAAK,IAAK,WAAA,CAAY,WAAW,CAAA,EAAG;AACjD,IAAA,MAAM,MAAA,CAAO,KAAA,CAAM,mBAAA,CAAoB,OAAA,EAAS,WAAW,CAAA;AAC3D,IAAA,KAAA,CAAM,KAAA,GAAQ,EAAA;AAAA,EAChB;AAGA,EAAA,eAAe,UAAA,CAAW,MAAmB,IAAA,EAAoD;AAC/F,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,EAAO,OAAO,MAAA;AAC1B,IAAA,WAAA,CAAY,KAAA,GAAQ,IAAA;AACpB,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,MAAA,CAAO,KAAA,CAAM,UAAA,CAAW,MAAM,IAAI,CAAA;AAAA,IACjD,CAAA,SAAE;AACA,MAAA,WAAA,CAAY,KAAA,GAAQ,KAAA;AAAA,IACtB;AAAA,EACF;AAGA,EAAA,eAAe,SAAA,CAAU,MAAmB,OAAA,EAAkB;AAC5D,IAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACnB,IAAA,WAAA,CAAY,KAAA,GAAQ,IAAA;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,KAAA,CAAM,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AAAA,IAC5C,CAAA,SAAE;AACA,MAAA,WAAA,CAAY,KAAA,GAAQ,KAAA;AAAA,IACtB;AAAA,EACF;AAGA,EAAA,eAAe,SAAA,CAAU,MAAmB,OAAA,EAAkB;AAC5D,IAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACnB,IAAA,WAAA,CAAY,KAAA,GAAQ,IAAA;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,KAAA,CAAM,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AAAA,IAC5C,CAAA,SAAE;AACA,MAAA,WAAA,CAAY,KAAA,GAAQ,KAAA;AAAA,IACtB;AAAA,EACF;AAGA,EAAA,eAAe,SAAA,CAAU,MAAmB,OAAA,EAAkB;AAC5D,IAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACnB,IAAA,WAAA,CAAY,KAAA,GAAQ,IAAA;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,KAAA,CAAM,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AAAA,IAC5C,CAAA,SAAE;AACA,MAAA,WAAA,CAAY,KAAA,GAAQ,KAAA;AAAA,IACtB;AAAA,EACF;AAGA,EAAA,SAAS,KAAA,GAAQ;AACf,IAAA,MAAA,CAAO,OAAO,QAAA,EAAS;AAAA,EACzB;AAGA,EAAA,SAAS,eAAA,GAAkB;AACzB,IAAA,MAAA,CAAO,OAAO,eAAA,EAAgB;AAAA,EAChC;AAGA,EAAA,eAAe,mBAAmB,cAAA,EAAwB;AACxD,IAAA,MAAM,MAAA,CAAO,KAAA,EAAO,kBAAA,CAAmB,cAAc,CAAA;AAAA,EACvD;AAGA,EAAA,eAAe,mBAAmB,cAAA,EAAwB;AACxD,IAAA,MAAM,MAAA,CAAO,KAAA,EAAO,kBAAA,CAAmB,cAAc,CAAA;AAAA,EACvD;AAGA,EAAA,eAAe,gBAAA,GAAmB;AAChC,IAAA,OAAO,MAAA,CAAO,KAAA,EAAO,gBAAA,EAAiB,IAAK,EAAC;AAAA,EAC9C;AAIA,EAAA,MAAM,YAAA,GAAe,IAAkB,MAAM,CAAA;AAC7C,EAAA,MAAM,mBAAA,GAAsB,IAAmB,IAAI,CAAA;AACnD,EAAA,MAAM,WAAA,GAAc,IAAI,KAAK,CAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,IAAI,KAAK,CAAA;AAE1B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,IAAI,MAAA,CAAO,KAAA;AACjB,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,CAAA,CAAE,EAAA,CAAG,WAAA,EAAa,CAAC,EAAE,WAAU,KAAM;AACnC,MAAA,YAAA,CAAa,KAAA,GAAQ,SAAA;AACrB,MAAA,mBAAA,CAAoB,KAAA,GAAQ,SAAA;AAAA,IAC9B,CAAC,CAAA;AACD,IAAA,CAAA,CAAE,EAAA,CAAG,UAAA,EAAY,CAAC,EAAE,WAAU,KAAM;AAClC,MAAA,YAAA,CAAa,KAAA,GAAQ,SAAA;AACrB,MAAA,mBAAA,CAAoB,KAAA,GAAQ,SAAA;AAAA,IAC9B,CAAC,CAAA;AACD,IAAA,CAAA,CAAE,EAAA,CAAG,aAAa,MAAM;AAAE,MAAA,YAAA,CAAa,KAAA,GAAQ,QAAA;AAAA,IAAU,CAAC,CAAA;AAC1D,IAAA,CAAA,CAAE,EAAA,CAAG,YAAY,MAAM;AACrB,MAAA,YAAA,CAAa,KAAA,GAAQ,MAAA;AACrB,MAAA,mBAAA,CAAoB,KAAA,GAAQ,IAAA;AAAA,IAC9B,CAAC,CAAA;AACD,IAAA,CAAA,CAAE,EAAA,CAAG,aAAa,MAAM;AACtB,MAAA,YAAA,CAAa,KAAA,GAAQ,OAAA;AACrB,MAAA,mBAAA,CAAoB,KAAA,GAAQ,IAAA;AAAA,IAC9B,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,eAAe,OAAA,CAAQ,SAAA,EAAmB,IAAA,EAAc,OAAA,EAAsB;AAC5E,IAAA,MAAM,MAAA,CAAO,KAAA,EAAO,OAAA,CAAQ,SAAA,EAAW,MAAM,OAAO,CAAA;AAAA,EACtD;AACA,EAAA,SAAS,QAAA,GAAW;AAAE,IAAA,MAAA,CAAO,OAAO,QAAA,EAAS;AAAA,EAAG;AAChD,EAAA,SAAS,SAAA,GAAY;AAAE,IAAA,MAAA,CAAO,OAAO,SAAA,EAAU;AAAA,EAAG;AAClD,EAAA,SAAS,OAAA,GAAU;AAAE,IAAA,MAAA,CAAO,OAAO,OAAA,EAAQ;AAAA,EAAG;AAE9C,EAAA,SAAS,eAAe,OAAA,EAAkB;AACxC,IAAA,MAAA,CAAO,KAAA,EAAO,eAAe,OAAO,CAAA;AACpC,IAAA,WAAA,CAAY,KAAA,GAAQ,OAAA;AAAA,EACtB;AACA,EAAA,SAAS,YAAY,KAAA,EAAgB;AACnC,IAAA,MAAA,CAAO,KAAA,EAAO,YAAY,KAAK,CAAA;AAC/B,IAAA,QAAA,CAAS,KAAA,GAAQ,KAAA;AAAA,EACnB;AAEA,EAAA,eAAe,WAAA,CAAY,MAAc,OAAA,EAAsD;AAC7F,IAAA,OAAO,MAAA,CAAO,KAAA,EAAO,WAAA,CAAY,IAAA,EAAM,OAAO,CAAA;AAAA,EAChD;AACA,EAAA,eAAe,YAAA,GAA0C;AACvD,IAAA,OAAO,MAAA,CAAO,KAAA,EAAO,YAAA,EAAa,IAAK,EAAC;AAAA,EAC1C;AAEA,EAAA,OAAO;AAAA;AAAA,IAEL,QAAA;AAAA,IACA,aAAA;AAAA,IACA,mBAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA;AAAA,IAGA,WAAA;AAAA,IACA,mBAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,eAAA;AAAA,IACA,kBAAA;AAAA,IACA,kBAAA;AAAA,IACA,gBAAA;AAAA;AAAA,IAGA,YAAA;AAAA,IACA,mBAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,cAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAA;AAAA;AAAA,IAGA;AAAA,GACF;AACF;AAqBO,SAAS,cAAc,MAAA,EAA4C;AACxE,EAAA,MAAM,MAAA,GAAS,WAA8B,IAAI,CAAA;AAEjD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAA,CAAO,KAAA,GAAQ,IAAI,UAAA,CAAW,MAAM,CAAA;AAAA,EACtC,CAAC,CAAA;AAED,EAAA,WAAA,CAAY,MAAM;AAChB,IAAA,MAAA,CAAO,OAAO,OAAA,EAAQ;AAAA,EACxB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAkBO,SAAS,YAAA,CACd,MAAA,EACA,KAAA,EACA,QAAA,EACA;AACA,EAAA,IAAI,WAAA,GAAmC,IAAA;AAEvC,EAAA,KAAA;AAAA,IACE,MAAA;AAAA,IACA,CAAC,SAAA,KAAc;AAEb,MAAA,WAAA,IAAc;AAGd,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,WAAA,GAAc,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,QAAQ,CAAA;AAAA,MAC5C;AAAA,IACF,CAAA;AAAA,IACA,EAAE,WAAW,IAAA;AAAK,GACpB;AAEA,EAAA,WAAA,CAAY,MAAM;AAChB,IAAA,WAAA,IAAc;AAAA,EAChB,CAAC,CAAA;AACH;AAKO,SAAS,aAAa,MAAA,EAAgC;AAC3D,EAAA,MAAM,QAAQ,GAAA,CAAe;AAAA,IAC3B,mBAAA,EAAqB,IAAA;AAAA,IACrB,eAAe,EAAC;AAAA,IAChB,SAAA,EAAW,KAAA;AAAA,IACX,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,KAAA;AAAA,IACb,KAAA,EAAO,IAAA;AAAA,IACP,UAAA,EAAY;AAAA,GACb,CAAA;AAED,EAAA,IAAI,WAAA,GAAmC,IAAA;AAEvC,EAAA,KAAA;AAAA,IACE,MAAA;AAAA,IACA,CAAC,SAAA,KAAc;AACb,MAAA,WAAA,IAAc;AAEd,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,KAAA,CAAM,KAAA,GAAQ,UAAU,QAAA,EAAS;AACjC,QAAA,WAAA,GAAc,SAAA,CAAU,SAAA,CAAU,CAAC,QAAA,KAAa;AAC9C,UAAA,KAAA,CAAM,KAAA,GAAQ,QAAA;AAAA,QAChB,CAAC,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAAA,IACA,EAAE,WAAW,IAAA;AAAK,GACpB;AAEA,EAAA,WAAA,CAAY,MAAM;AAChB,IAAA,WAAA,IAAc;AAAA,EAChB,CAAC,CAAA;AAED,EAAA,OAAO,KAAA;AACT","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.
|
|
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.
|
|
24
|
+
"@lingshuai/chat-core": "0.1.3"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"vue": ">=3.3.0"
|