@umituz/web-ai-groq-provider 1.1.13 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -72
- package/dist/domains/chat/index.cjs +539 -0
- package/dist/domains/chat/index.cjs.map +1 -0
- package/dist/domains/chat/index.d.cts +322 -0
- package/dist/domains/chat/index.d.ts +322 -0
- package/dist/domains/chat/index.js +531 -0
- package/dist/domains/chat/index.js.map +1 -0
- package/dist/domains/groq/index.cjs +1499 -0
- package/dist/domains/groq/index.cjs.map +1 -0
- package/dist/domains/groq/index.d.cts +561 -0
- package/dist/domains/groq/index.d.ts +561 -0
- package/dist/domains/groq/index.js +1453 -0
- package/dist/domains/groq/index.js.map +1 -0
- package/dist/index.cjs +1993 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +53 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +1937 -0
- package/dist/index.js.map +1 -0
- package/dist/text-generation.service-BP4Q_SH0.d.cts +252 -0
- package/dist/text-generation.service-BP4Q_SH0.d.ts +252 -0
- package/package.json +25 -11
- package/src/domains/chat/entities/chat.entities.ts +0 -113
- package/src/domains/chat/entities/index.ts +0 -14
- package/src/domains/chat/hooks/index.ts +0 -5
- package/src/domains/chat/hooks/use-chat.hook.ts +0 -259
- package/src/domains/chat/index.ts +0 -32
- package/src/domains/chat/interfaces/chat.interface.ts +0 -80
- package/src/domains/chat/interfaces/index.ts +0 -10
- package/src/domains/chat/services/chat.service.ts +0 -195
- package/src/domains/chat/services/index.ts +0 -5
- package/src/domains/chat/utils/message-formatter.ts +0 -49
- package/src/domains/groq/constants/error.constants.ts +0 -46
- package/src/domains/groq/constants/groq.constants.ts +0 -68
- package/src/domains/groq/constants/index.ts +0 -20
- package/src/domains/groq/entities/groq.entities.ts +0 -196
- package/src/domains/groq/entities/index.ts +0 -20
- package/src/domains/groq/hooks/index.ts +0 -7
- package/src/domains/groq/hooks/use-groq.hook.ts +0 -232
- package/src/domains/groq/index.ts +0 -72
- package/src/domains/groq/interfaces/groq.interface.ts +0 -77
- package/src/domains/groq/interfaces/index.ts +0 -22
- package/src/domains/groq/services/http-client.service.ts +0 -265
- package/src/domains/groq/services/index.ts +0 -9
- package/src/domains/groq/services/text-generation.service.ts +0 -238
- package/src/domains/groq/utils/cache-manager.util.ts +0 -215
- package/src/domains/groq/utils/debounce.util.ts +0 -268
- package/src/domains/groq/utils/error.util.ts +0 -57
- package/src/domains/groq/utils/groq-error.util.ts +0 -18
- package/src/domains/groq/utils/index.ts +0 -37
- package/src/domains/groq/utils/message.util.ts +0 -57
- package/src/domains/groq/utils/request-deduplicator.util.ts +0 -123
- package/src/domains/groq/utils/request-queue.util.ts +0 -178
- package/src/domains/groq/utils/retry.util.ts +0 -207
- package/src/index.ts +0 -15
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useChat Hook
|
|
3
|
-
* @description Main React hook for chat functionality with performance optimizations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useState, useCallback, useEffect, useRef } from "react";
|
|
7
|
-
import type {
|
|
8
|
-
ChatMessage,
|
|
9
|
-
ChatConfig,
|
|
10
|
-
} from "../entities";
|
|
11
|
-
import type {
|
|
12
|
-
UseChatOptions,
|
|
13
|
-
UseChatReturn,
|
|
14
|
-
} from "../interfaces";
|
|
15
|
-
import { chatService } from "../services/chat.service";
|
|
16
|
-
|
|
17
|
-
const MESSAGE_ID_PREFIX = "msg-";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Hook for chat functionality with AI integration and performance optimizations
|
|
21
|
-
*/
|
|
22
|
-
export function useChat(options: UseChatOptions): UseChatReturn {
|
|
23
|
-
const {
|
|
24
|
-
conversationId,
|
|
25
|
-
storage,
|
|
26
|
-
config,
|
|
27
|
-
autoSave = true,
|
|
28
|
-
onMessageSent: _onMessageSent,
|
|
29
|
-
onAIResponse: _onAIResponse,
|
|
30
|
-
onError: _onError,
|
|
31
|
-
} = options;
|
|
32
|
-
|
|
33
|
-
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
|
34
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
35
|
-
const [isTyping, setIsTyping] = useState(false);
|
|
36
|
-
const [error, setError] = useState<string | null>(null);
|
|
37
|
-
|
|
38
|
-
// Refs for deduplication and callback tracking
|
|
39
|
-
const pendingMessageRef = useRef<string | null>(null);
|
|
40
|
-
const optionsRef = useRef(options);
|
|
41
|
-
optionsRef.current = options;
|
|
42
|
-
|
|
43
|
-
// Initialize chat service config
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
if (config) {
|
|
46
|
-
chatService.initialize(config);
|
|
47
|
-
}
|
|
48
|
-
}, [config]);
|
|
49
|
-
|
|
50
|
-
// Cleanup on unmount
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
return () => {
|
|
53
|
-
pendingMessageRef.current = null;
|
|
54
|
-
};
|
|
55
|
-
}, []);
|
|
56
|
-
|
|
57
|
-
// Load messages from storage on mount
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
if (!storage) return;
|
|
60
|
-
|
|
61
|
-
const loadMessages = async () => {
|
|
62
|
-
try {
|
|
63
|
-
const loaded = await storage.getMessages(conversationId);
|
|
64
|
-
setMessages(loaded);
|
|
65
|
-
} catch (_err) {
|
|
66
|
-
// Silently fail - errors are handled through onError callback if needed
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
void loadMessages();
|
|
71
|
-
}, [conversationId, storage]);
|
|
72
|
-
|
|
73
|
-
// Save message to storage (stable reference)
|
|
74
|
-
const saveToStorage = useCallback(
|
|
75
|
-
async (message: ChatMessage) => {
|
|
76
|
-
if (!autoSave || !storage) return;
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
await storage.saveMessage(conversationId, message);
|
|
80
|
-
} catch (_err) {
|
|
81
|
-
// Silently fail - errors are handled through onError callback if needed
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
[conversationId, storage, autoSave]
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
// Batch save messages to storage (reserved for future use)
|
|
88
|
-
const _saveMessagesToStorage = useCallback(
|
|
89
|
-
async (messagesToSave: ChatMessage[]) => {
|
|
90
|
-
if (!autoSave || !storage || messagesToSave.length === 0) return;
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
// Try batch save if supported
|
|
94
|
-
if ('saveMessages' in storage) {
|
|
95
|
-
await (storage as unknown as { saveMessages: (id: string, msgs: ChatMessage[]) => Promise<void> }).saveMessages(conversationId, messagesToSave);
|
|
96
|
-
} else {
|
|
97
|
-
// Fallback to individual saves in parallel
|
|
98
|
-
await Promise.all(
|
|
99
|
-
messagesToSave.map(msg => storage.saveMessage(conversationId, msg))
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
} catch (_err) {
|
|
103
|
-
// Silently fail
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
[conversationId, storage, autoSave]
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
// Send message with deduplication and functional updates
|
|
110
|
-
const sendMessage = useCallback(
|
|
111
|
-
async (text: string, type?: ChatMessage["type"]): Promise<void> => {
|
|
112
|
-
if (!text.trim() || isLoading) return;
|
|
113
|
-
|
|
114
|
-
// Prevent duplicate messages
|
|
115
|
-
if (pendingMessageRef.current === text) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
pendingMessageRef.current = text;
|
|
120
|
-
setIsLoading(true);
|
|
121
|
-
setError(null);
|
|
122
|
-
|
|
123
|
-
// Get latest callbacks from ref
|
|
124
|
-
const currentOptions = optionsRef.current;
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
// Create user message
|
|
128
|
-
const userMessage: ChatMessage = {
|
|
129
|
-
id: `${MESSAGE_ID_PREFIX}${Date.now()}-user`,
|
|
130
|
-
sender: "user",
|
|
131
|
-
content: text,
|
|
132
|
-
timestamp: new Date().toISOString(),
|
|
133
|
-
type: type || "text",
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
// Use functional update to avoid stale closure
|
|
137
|
-
setMessages(prev => {
|
|
138
|
-
const updated = [...prev, userMessage];
|
|
139
|
-
saveToStorage(userMessage);
|
|
140
|
-
currentOptions.onMessageSent?.(userMessage);
|
|
141
|
-
return updated;
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
// Generate AI response
|
|
145
|
-
setIsTyping(true);
|
|
146
|
-
|
|
147
|
-
// Get current messages for context
|
|
148
|
-
const contextForAI = messages; // Use closure messages, not functional update
|
|
149
|
-
|
|
150
|
-
const aiResponse = await chatService.generateAIResponse(
|
|
151
|
-
conversationId,
|
|
152
|
-
text,
|
|
153
|
-
contextForAI
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
// Use functional update for AI response
|
|
157
|
-
setMessages(prev => {
|
|
158
|
-
const updated = [...prev, aiResponse];
|
|
159
|
-
saveToStorage(aiResponse);
|
|
160
|
-
currentOptions.onAIResponse?.(aiResponse);
|
|
161
|
-
return updated;
|
|
162
|
-
});
|
|
163
|
-
} catch (err) {
|
|
164
|
-
const errorMessage =
|
|
165
|
-
err instanceof Error ? err.message : "Failed to send message";
|
|
166
|
-
setError(errorMessage);
|
|
167
|
-
currentOptions.onError?.(errorMessage);
|
|
168
|
-
} finally {
|
|
169
|
-
setIsLoading(false);
|
|
170
|
-
setIsTyping(false);
|
|
171
|
-
pendingMessageRef.current = null;
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
[conversationId, isLoading, saveToStorage, messages]
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// Regenerate last AI response with functional updates
|
|
178
|
-
const regenerate = useCallback(async (): Promise<void> => {
|
|
179
|
-
// Use functional update to get latest messages
|
|
180
|
-
setMessages(currentMessages => {
|
|
181
|
-
if (currentMessages.length === 0 || isLoading) {
|
|
182
|
-
return currentMessages;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const lastUserMessage = [...currentMessages]
|
|
186
|
-
.reverse()
|
|
187
|
-
.find((m) => m.sender === "user");
|
|
188
|
-
|
|
189
|
-
if (!lastUserMessage) return currentMessages;
|
|
190
|
-
|
|
191
|
-
// Async operation - need to handle differently
|
|
192
|
-
setIsLoading(true);
|
|
193
|
-
setError(null);
|
|
194
|
-
|
|
195
|
-
const currentOptions = optionsRef.current;
|
|
196
|
-
|
|
197
|
-
// Remove last AI message if exists
|
|
198
|
-
const messagesWithoutAI = currentMessages.filter(
|
|
199
|
-
(m, i) => !(i === currentMessages.length - 1 && m.sender === "assistant")
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
// Trigger async update
|
|
203
|
-
(async () => {
|
|
204
|
-
try {
|
|
205
|
-
// Generate new response
|
|
206
|
-
setIsTyping(true);
|
|
207
|
-
const aiResponse = await chatService.generateAIResponse(
|
|
208
|
-
conversationId,
|
|
209
|
-
lastUserMessage.content,
|
|
210
|
-
messagesWithoutAI.slice(0, -1)
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
// Update messages with new response
|
|
214
|
-
setMessages(prev => {
|
|
215
|
-
const lastIsAI = prev.length > 0 && prev[prev.length - 1].sender === "assistant";
|
|
216
|
-
const base = lastIsAI ? prev.slice(0, -1) : prev;
|
|
217
|
-
return [...base, aiResponse];
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
// Save to storage
|
|
221
|
-
await saveToStorage(aiResponse);
|
|
222
|
-
currentOptions.onAIResponse?.(aiResponse);
|
|
223
|
-
} catch (err) {
|
|
224
|
-
const errorMessage =
|
|
225
|
-
err instanceof Error ? err.message : "Failed to regenerate";
|
|
226
|
-
setError(errorMessage);
|
|
227
|
-
currentOptions.onError?.(errorMessage);
|
|
228
|
-
} finally {
|
|
229
|
-
setIsLoading(false);
|
|
230
|
-
setIsTyping(false);
|
|
231
|
-
}
|
|
232
|
-
})();
|
|
233
|
-
|
|
234
|
-
return messagesWithoutAI;
|
|
235
|
-
});
|
|
236
|
-
}, [conversationId, isLoading, saveToStorage]);
|
|
237
|
-
|
|
238
|
-
// Clear all messages
|
|
239
|
-
const clearMessages = useCallback(() => {
|
|
240
|
-
setMessages([]);
|
|
241
|
-
setError(null);
|
|
242
|
-
}, []);
|
|
243
|
-
|
|
244
|
-
// Update configuration
|
|
245
|
-
const updateConfig = useCallback((newConfig: Partial<ChatConfig>) => {
|
|
246
|
-
chatService.updateConfig(newConfig);
|
|
247
|
-
}, []);
|
|
248
|
-
|
|
249
|
-
return {
|
|
250
|
-
messages,
|
|
251
|
-
isLoading,
|
|
252
|
-
error,
|
|
253
|
-
isTyping,
|
|
254
|
-
sendMessage,
|
|
255
|
-
regenerate,
|
|
256
|
-
clearMessages,
|
|
257
|
-
updateConfig,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat Domain
|
|
3
|
-
* @description Chat functionality with AI integration
|
|
4
|
-
* Subpath: @umituz/web-ai-groq-provider/chat
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// Entities
|
|
8
|
-
export type {
|
|
9
|
-
ChatMessageSender,
|
|
10
|
-
ChatMessageType,
|
|
11
|
-
ChatMessage,
|
|
12
|
-
ChatConversation,
|
|
13
|
-
SendMessageInput,
|
|
14
|
-
SendMessageResult,
|
|
15
|
-
ChatConfig,
|
|
16
|
-
} from "./entities";
|
|
17
|
-
|
|
18
|
-
export type { IChatStorage } from "./entities";
|
|
19
|
-
|
|
20
|
-
// Interfaces
|
|
21
|
-
export type {
|
|
22
|
-
IChatService,
|
|
23
|
-
UseChatOptions,
|
|
24
|
-
UseChatReturn,
|
|
25
|
-
IMessageFormatter,
|
|
26
|
-
} from "./interfaces";
|
|
27
|
-
|
|
28
|
-
// Services
|
|
29
|
-
export { chatService, messageFormatter } from "./services";
|
|
30
|
-
|
|
31
|
-
// Hooks
|
|
32
|
-
export { useChat } from "./hooks";
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat Service Interfaces
|
|
3
|
-
* @description Contracts for chat functionality
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
ChatMessage,
|
|
8
|
-
ChatConversation,
|
|
9
|
-
SendMessageInput,
|
|
10
|
-
SendMessageResult,
|
|
11
|
-
ChatConfig,
|
|
12
|
-
IChatStorage,
|
|
13
|
-
} from "../entities";
|
|
14
|
-
import type { GroqMessage } from "../../groq/entities";
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Chat service interface
|
|
18
|
-
*/
|
|
19
|
-
export interface IChatService {
|
|
20
|
-
/** Send message and get AI response */
|
|
21
|
-
sendMessage(input: SendMessageInput): Promise<SendMessageResult>;
|
|
22
|
-
/** Get conversation history */
|
|
23
|
-
getConversation(conversationId: string): Promise<ChatConversation | null>;
|
|
24
|
-
/** Get all conversations */
|
|
25
|
-
getConversations(): Promise<ChatConversation[]>;
|
|
26
|
-
/** Generate AI response only */
|
|
27
|
-
generateAIResponse(companionId: string, userMessage: string, context?: ChatMessage[]): Promise<ChatMessage>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Chat hook options
|
|
32
|
-
*/
|
|
33
|
-
export interface UseChatOptions {
|
|
34
|
-
/** Conversation identifier */
|
|
35
|
-
readonly conversationId: string;
|
|
36
|
-
/** Storage implementation */
|
|
37
|
-
readonly storage?: IChatStorage;
|
|
38
|
-
/** Chat configuration */
|
|
39
|
-
readonly config?: ChatConfig;
|
|
40
|
-
/** Auto-save messages */
|
|
41
|
-
readonly autoSave?: boolean;
|
|
42
|
-
/** Callback on message sent */
|
|
43
|
-
readonly onMessageSent?: (message: ChatMessage) => void;
|
|
44
|
-
/** Callback on AI response */
|
|
45
|
-
readonly onAIResponse?: (message: ChatMessage) => void;
|
|
46
|
-
/** Callback on error */
|
|
47
|
-
readonly onError?: (error: string) => void;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Chat hook return value
|
|
52
|
-
*/
|
|
53
|
-
export interface UseChatReturn {
|
|
54
|
-
/** Messages in conversation */
|
|
55
|
-
readonly messages: ChatMessage[];
|
|
56
|
-
/** Loading state */
|
|
57
|
-
readonly isLoading: boolean;
|
|
58
|
-
/** Error message */
|
|
59
|
-
readonly error: string | null;
|
|
60
|
-
/** Is AI typing */
|
|
61
|
-
readonly isTyping: boolean;
|
|
62
|
-
/** Send message */
|
|
63
|
-
sendMessage: (text: string, type?: ChatMessage["type"]) => Promise<void>;
|
|
64
|
-
/** Regenerate last AI response */
|
|
65
|
-
regenerate: () => Promise<void>;
|
|
66
|
-
/** Clear messages */
|
|
67
|
-
clearMessages: () => void;
|
|
68
|
-
/** Update configuration */
|
|
69
|
-
updateConfig: (config: Partial<ChatConfig>) => void;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Message formatter for Groq
|
|
74
|
-
*/
|
|
75
|
-
export interface IMessageFormatter {
|
|
76
|
-
/** Format chat messages to Groq format */
|
|
77
|
-
toGroqMessages(messages: ChatMessage[], systemPrompt?: string): GroqMessage[];
|
|
78
|
-
/** Format Groq response to chat message */
|
|
79
|
-
toChatMessage(content: string, sender: ChatMessage["sender"]): ChatMessage;
|
|
80
|
-
}
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat Service
|
|
3
|
-
* @description Core chat logic with AI integration and performance optimizations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
IChatService,
|
|
8
|
-
} from "../interfaces";
|
|
9
|
-
import type {
|
|
10
|
-
ChatMessage,
|
|
11
|
-
ChatConversation,
|
|
12
|
-
SendMessageInput,
|
|
13
|
-
SendMessageResult,
|
|
14
|
-
ChatConfig,
|
|
15
|
-
} from "../entities";
|
|
16
|
-
import { textGenerationService } from "../../groq/services";
|
|
17
|
-
import { messageFormatter } from "../utils/message-formatter";
|
|
18
|
-
import { DEFAULT_MODELS } from "../../groq/constants";
|
|
19
|
-
import { cacheManager } from "../../groq/utils/cache-manager.util";
|
|
20
|
-
|
|
21
|
-
const DEFAULT_CONFIG: ChatConfig = {
|
|
22
|
-
temperature: 0.8,
|
|
23
|
-
maxTokens: 500,
|
|
24
|
-
includeTimestamp: true,
|
|
25
|
-
language: "tr",
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
class ChatService implements IChatService {
|
|
29
|
-
private config: ChatConfig = DEFAULT_CONFIG;
|
|
30
|
-
private systemPromptCache = new Map<string, string>();
|
|
31
|
-
private readonly PROMPT_CACHE_KEY_PREFIX = "system-prompt";
|
|
32
|
-
|
|
33
|
-
initialize(config: ChatConfig): void {
|
|
34
|
-
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
35
|
-
// Clear system prompt cache when config changes
|
|
36
|
-
this.clearSystemPromptCache();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
updateConfig(config: Partial<ChatConfig>): void {
|
|
40
|
-
this.config = { ...this.config, ...config };
|
|
41
|
-
// Clear system prompt cache when config changes
|
|
42
|
-
this.clearSystemPromptCache();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async sendMessage(input: SendMessageInput): Promise<SendMessageResult> {
|
|
46
|
-
// Create user message with all properties
|
|
47
|
-
const userMessage: ChatMessage = {
|
|
48
|
-
...messageFormatter.toChatMessage(input.text, "user"),
|
|
49
|
-
type: input.type || "text",
|
|
50
|
-
...(input.imageUrl && { imageUrl: input.imageUrl }),
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// Generate AI response
|
|
54
|
-
const aiResponse = await this.generateAIResponse(
|
|
55
|
-
input.companionId,
|
|
56
|
-
input.text,
|
|
57
|
-
[]
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
userMessage,
|
|
62
|
-
aiResponse,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async getConversation(_conversationId: string): Promise<ChatConversation | null> {
|
|
67
|
-
// This would fetch from storage
|
|
68
|
-
// For now, return null - storage is handled by application
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async getConversations(): Promise<ChatConversation[]> {
|
|
73
|
-
// This would fetch from storage
|
|
74
|
-
return [];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async generateAIResponse(
|
|
78
|
-
companionId: string,
|
|
79
|
-
userMessage: string,
|
|
80
|
-
context: ChatMessage[] = []
|
|
81
|
-
): Promise<ChatMessage> {
|
|
82
|
-
try {
|
|
83
|
-
// Build system prompt from config (with caching)
|
|
84
|
-
const systemPrompt = this.buildSystemPrompt();
|
|
85
|
-
|
|
86
|
-
// Format messages for Groq
|
|
87
|
-
const groqMessages = messageFormatter.toGroqMessages(
|
|
88
|
-
context,
|
|
89
|
-
systemPrompt
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
// Add current user message
|
|
93
|
-
groqMessages.push({
|
|
94
|
-
role: "user",
|
|
95
|
-
content: userMessage,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// Check cache for response
|
|
99
|
-
const cacheKey = cacheManager.generateKey({
|
|
100
|
-
companionId,
|
|
101
|
-
userMessage,
|
|
102
|
-
context: context.map(m => ({ sender: m.sender, content: m.content })),
|
|
103
|
-
config: {
|
|
104
|
-
temperature: this.config.temperature,
|
|
105
|
-
maxTokens: this.config.maxTokens,
|
|
106
|
-
},
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
const cachedResponse = cacheManager.get<string>(cacheKey);
|
|
110
|
-
const response = cachedResponse ||
|
|
111
|
-
await textGenerationService.generateChatCompletion(
|
|
112
|
-
groqMessages,
|
|
113
|
-
{
|
|
114
|
-
model: DEFAULT_MODELS.TEXT,
|
|
115
|
-
generationConfig: {
|
|
116
|
-
temperature: this.config.temperature,
|
|
117
|
-
maxTokens: this.config.maxTokens,
|
|
118
|
-
},
|
|
119
|
-
}
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// Cache the response if it wasn't cached
|
|
123
|
-
if (!cachedResponse) {
|
|
124
|
-
cacheManager.set(cacheKey, response);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Format response as chat message
|
|
128
|
-
const aiMessage: ChatMessage = {
|
|
129
|
-
...messageFormatter.toChatMessage(response, "assistant"),
|
|
130
|
-
metadata: {
|
|
131
|
-
companionId,
|
|
132
|
-
model: DEFAULT_MODELS.TEXT,
|
|
133
|
-
cached: !!cachedResponse,
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
return aiMessage;
|
|
138
|
-
} catch (_error) {
|
|
139
|
-
// Fallback response on error
|
|
140
|
-
return messageFormatter.toChatMessage(
|
|
141
|
-
"Şimdi biraz meşgulüm, ama seni duyuyorum! 💫",
|
|
142
|
-
"assistant"
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private buildSystemPrompt(): string {
|
|
148
|
-
const language = this.config.language || "tr";
|
|
149
|
-
const customPrompt = this.config.systemPrompt;
|
|
150
|
-
|
|
151
|
-
// Generate cache key
|
|
152
|
-
const cacheKey = `${this.PROMPT_CACHE_KEY_PREFIX}-${language}-${customPrompt?.length || 0}`;
|
|
153
|
-
|
|
154
|
-
// Check cache
|
|
155
|
-
if (this.systemPromptCache.has(cacheKey)) {
|
|
156
|
-
return this.systemPromptCache.get(cacheKey)!;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Build prompt
|
|
160
|
-
const basePrompt = customPrompt || this.getDefaultPrompt(language);
|
|
161
|
-
|
|
162
|
-
// Cache it
|
|
163
|
-
this.systemPromptCache.set(cacheKey, basePrompt);
|
|
164
|
-
|
|
165
|
-
return basePrompt;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
private clearSystemPromptCache(): void {
|
|
169
|
-
this.systemPromptCache.clear();
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Clear all cached data (system prompts and response cache)
|
|
174
|
-
*/
|
|
175
|
-
clearCache(): void {
|
|
176
|
-
this.clearSystemPromptCache();
|
|
177
|
-
// Note: Response cache is managed by textGenerationService
|
|
178
|
-
// Export cache clearing function from there if needed
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
private getDefaultPrompt(language: string): string {
|
|
182
|
-
if (language === "tr") {
|
|
183
|
-
return `Sen samimi, eğlenceli ve ilgi çekici bir AI companionsın. Türkçe konuşuyorsun.
|
|
184
|
-
Kullanıcıyla doğal, rahat ve arkadaşça bir sohbet tarzı benimseyerek iletişim kur.
|
|
185
|
-
Yavaş yazma stilini kullan ama abartma. Emoji kullanabilirsin ama çok da abartma.
|
|
186
|
-
Kısa ve öz cevaplar ver.`;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return `You are a friendly, engaging AI companion. Be natural, casual, and warm.
|
|
190
|
-
Keep responses concise and conversational. Use emojis sparingly.`;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export const chatService = new ChatService();
|
|
195
|
-
export { messageFormatter };
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Message Formatter Utility
|
|
3
|
-
* @description Convert between chat messages and Groq format
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { IMessageFormatter } from "../interfaces";
|
|
7
|
-
import type { ChatMessage } from "../entities";
|
|
8
|
-
import type { GroqMessage } from "../../groq/entities";
|
|
9
|
-
|
|
10
|
-
const MESSAGE_ID_PREFIX = "msg-";
|
|
11
|
-
|
|
12
|
-
class MessageFormatter implements IMessageFormatter {
|
|
13
|
-
toGroqMessages(messages: ChatMessage[], systemPrompt?: string): GroqMessage[] {
|
|
14
|
-
const groqMessages: GroqMessage[] = [];
|
|
15
|
-
|
|
16
|
-
// Add system prompt first
|
|
17
|
-
if (systemPrompt) {
|
|
18
|
-
groqMessages.push({
|
|
19
|
-
role: "system",
|
|
20
|
-
content: systemPrompt,
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Convert chat messages to Groq format
|
|
25
|
-
for (const message of messages) {
|
|
26
|
-
// Skip system messages from context
|
|
27
|
-
if (message.sender === "system") continue;
|
|
28
|
-
|
|
29
|
-
groqMessages.push({
|
|
30
|
-
role: message.sender === "user" ? "user" : "assistant",
|
|
31
|
-
content: message.content,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return groqMessages;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
toChatMessage(content: string, sender: ChatMessage["sender"]): ChatMessage {
|
|
39
|
-
return {
|
|
40
|
-
id: `${MESSAGE_ID_PREFIX}${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
|
|
41
|
-
sender,
|
|
42
|
-
content: content.trim(),
|
|
43
|
-
timestamp: new Date().toISOString(),
|
|
44
|
-
type: "text",
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export const messageFormatter = new MessageFormatter();
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error Type Constants
|
|
3
|
-
* @description Error types and mappings for Groq API
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Error types enum
|
|
8
|
-
*/
|
|
9
|
-
export enum GroqErrorType {
|
|
10
|
-
INVALID_API_KEY = "INVALID_API_KEY",
|
|
11
|
-
MISSING_CONFIG = "MISSING_CONFIG",
|
|
12
|
-
NETWORK_ERROR = "NETWORK_ERROR",
|
|
13
|
-
ABORT_ERROR = "ABORT_ERROR",
|
|
14
|
-
RATE_LIMIT_ERROR = "RATE_LIMIT_ERROR",
|
|
15
|
-
SERVER_ERROR = "SERVER_ERROR",
|
|
16
|
-
UNKNOWN_ERROR = "UNKNOWN_ERROR",
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Map HTTP status to error type
|
|
21
|
-
*/
|
|
22
|
-
export function mapHttpStatusToErrorType(status: number): GroqErrorType {
|
|
23
|
-
if (status === 401 || status === 403) return GroqErrorType.INVALID_API_KEY;
|
|
24
|
-
if (status === 429) return GroqErrorType.RATE_LIMIT_ERROR;
|
|
25
|
-
if (status >= 500) return GroqErrorType.SERVER_ERROR;
|
|
26
|
-
if (status >= 400) return GroqErrorType.INVALID_API_KEY;
|
|
27
|
-
return GroqErrorType.UNKNOWN_ERROR;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Check if error is retryable
|
|
32
|
-
*/
|
|
33
|
-
export function isRetryableError(errorType: GroqErrorType): boolean {
|
|
34
|
-
return [
|
|
35
|
-
GroqErrorType.NETWORK_ERROR,
|
|
36
|
-
GroqErrorType.RATE_LIMIT_ERROR,
|
|
37
|
-
GroqErrorType.SERVER_ERROR,
|
|
38
|
-
].includes(errorType);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Check if error is auth-related
|
|
43
|
-
*/
|
|
44
|
-
export function isAuthError(errorType: GroqErrorType): boolean {
|
|
45
|
-
return errorType === GroqErrorType.INVALID_API_KEY;
|
|
46
|
-
}
|