universal-llm-client 4.0.0 ā 4.2.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/dist/ai-model.d.ts +20 -22
- package/dist/ai-model.d.ts.map +1 -1
- package/dist/ai-model.js +26 -23
- package/dist/ai-model.js.map +1 -1
- package/dist/client.d.ts +5 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +17 -9
- package/dist/client.js.map +1 -1
- package/dist/http.d.ts +2 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +1 -0
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +49 -11
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js +14 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/providers/anthropic.d.ts +56 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +524 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/google.d.ts +5 -0
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +64 -8
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +1 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/ollama.d.ts.map +1 -1
- package/dist/providers/ollama.js +38 -11
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +9 -7
- package/dist/providers/openai.js.map +1 -1
- package/dist/router.d.ts +13 -33
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +33 -57
- package/dist/router.js.map +1 -1
- package/dist/stream-decoder.d.ts +29 -2
- package/dist/stream-decoder.d.ts.map +1 -1
- package/dist/stream-decoder.js +39 -11
- package/dist/stream-decoder.js.map +1 -1
- package/dist/structured-output.d.ts +107 -181
- package/dist/structured-output.d.ts.map +1 -1
- package/dist/structured-output.js +137 -192
- package/dist/structured-output.js.map +1 -1
- package/dist/zod-adapter.d.ts +44 -0
- package/dist/zod-adapter.d.ts.map +1 -0
- package/dist/zod-adapter.js +61 -0
- package/dist/zod-adapter.js.map +1 -0
- package/package.json +9 -1
- package/src/ai-model.ts +350 -0
- package/src/auditor.ts +213 -0
- package/src/client.ts +402 -0
- package/src/debug/debug-google-streaming.ts +97 -0
- package/src/debug/debug-tool-execution.ts +86 -0
- package/src/debug/test-lmstudio-tools.ts +155 -0
- package/src/demos/README.md +47 -0
- package/src/demos/basic/universal-llm-examples.ts +161 -0
- package/src/demos/mcp/astrid-memory-demo.ts +295 -0
- package/src/demos/mcp/astrid-persona-memory.ts +357 -0
- package/src/demos/mcp/mcp-mongodb-demo.ts +275 -0
- package/src/demos/mcp/simple-astrid-memory.ts +148 -0
- package/src/demos/mcp/simple-mcp-demo.ts +68 -0
- package/src/demos/mcp/working-mcp-demo.ts +62 -0
- package/src/demos/model-alias-demo.ts +0 -0
- package/src/demos/tools/RAG_MEMORY_INTEGRATION.md +267 -0
- package/src/demos/tools/astrid-memory-demo.ts +270 -0
- package/src/demos/tools/astrid-production-memory-clean.ts +785 -0
- package/src/demos/tools/astrid-production-memory.ts +558 -0
- package/src/demos/tools/basic-translation-test.ts +66 -0
- package/src/demos/tools/chromadb-similarity-tuning.ts +390 -0
- package/src/demos/tools/clean-multilingual-conversation.ts +209 -0
- package/src/demos/tools/clean-translation-test.ts +119 -0
- package/src/demos/tools/clean-universal-multilingual-test.ts +131 -0
- package/src/demos/tools/complete-rag-demo.ts +369 -0
- package/src/demos/tools/complete-tool-demo.ts +132 -0
- package/src/demos/tools/demo-tool-calling.ts +124 -0
- package/src/demos/tools/dynamic-language-switching-test.ts +251 -0
- package/src/demos/tools/hybrid-thinking-test.ts +154 -0
- package/src/demos/tools/memory-integration-test.ts +420 -0
- package/src/demos/tools/multilingual-memory-system.ts +802 -0
- package/src/demos/tools/ondemand-translation-demo.ts +655 -0
- package/src/demos/tools/production-tool-demo.ts +245 -0
- package/src/demos/tools/revolutionary-multilingual-test.ts +151 -0
- package/src/demos/tools/rigorous-language-analysis.ts +218 -0
- package/src/demos/tools/test-universal-memory-system.ts +126 -0
- package/src/demos/tools/translation-integration-guide.ts +346 -0
- package/src/demos/tools/universal-memory-system.ts +560 -0
- package/src/http.ts +247 -0
- package/src/index.ts +161 -0
- package/src/interfaces.ts +657 -0
- package/src/mcp.ts +345 -0
- package/src/providers/anthropic.ts +762 -0
- package/src/providers/google.ts +620 -0
- package/src/providers/index.ts +8 -0
- package/src/providers/ollama.ts +469 -0
- package/src/providers/openai.ts +392 -0
- package/src/router.ts +780 -0
- package/src/stream-decoder.ts +361 -0
- package/src/structured-output.ts +759 -0
- package/src/test-scripts/test-advanced-tools.ts +310 -0
- package/src/test-scripts/test-google-streaming-enhanced.ts +147 -0
- package/src/test-scripts/test-google-streaming.ts +63 -0
- package/src/test-scripts/test-google-system-prompt-comprehensive.ts +189 -0
- package/src/test-scripts/test-mcp-config.ts +28 -0
- package/src/test-scripts/test-mcp-connection.ts +29 -0
- package/src/test-scripts/test-system-message-positions.ts +163 -0
- package/src/test-scripts/test-system-prompt-improvement-demo.ts +83 -0
- package/src/test-scripts/test-tool-calling.ts +231 -0
- package/src/tests/ai-model.test.ts +1614 -0
- package/src/tests/auditor.test.ts +224 -0
- package/src/tests/http.test.ts +200 -0
- package/src/tests/interfaces.test.ts +117 -0
- package/src/tests/providers/google.test.ts +660 -0
- package/src/tests/providers/ollama.test.ts +954 -0
- package/src/tests/providers/openai.test.ts +1122 -0
- package/src/tests/router.test.ts +254 -0
- package/src/tests/stream-decoder.test.ts +179 -0
- package/src/tests/structured-output.test.ts +1450 -0
- package/src/tests/tools.test.ts +175 -0
- package/src/tools.ts +246 -0
- package/src/zod-adapter.ts +72 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Astrid Persona Memory Integration - Real ChromaDB Integration
|
|
3
|
+
*
|
|
4
|
+
* This shows how to integrate memory tools with the actual AuraPersona system
|
|
5
|
+
* and ChromaDBService for production use.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { AIModelFactory } from '../../factory';
|
|
9
|
+
import { ToolBuilder } from '../../tools';
|
|
10
|
+
import { Gender } from '../../../../../src/models/AuraPersona.js';
|
|
11
|
+
|
|
12
|
+
// Type definitions for the persona system
|
|
13
|
+
interface PersonaTraits {
|
|
14
|
+
age?: number;
|
|
15
|
+
gender?: string;
|
|
16
|
+
profession?: string;
|
|
17
|
+
interests?: string[];
|
|
18
|
+
personality?: string[];
|
|
19
|
+
location?: string;
|
|
20
|
+
relationshipStatus?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface AuraPersona {
|
|
24
|
+
_id?: string;
|
|
25
|
+
name: string;
|
|
26
|
+
bio?: string;
|
|
27
|
+
systemPrompt: string;
|
|
28
|
+
purpose: string;
|
|
29
|
+
traits?: PersonaTraits;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface UserPersona {
|
|
33
|
+
_id?: string;
|
|
34
|
+
userId: string;
|
|
35
|
+
basePersonaId: string;
|
|
36
|
+
currentSystemPrompt: string;
|
|
37
|
+
evolutionVersion: number;
|
|
38
|
+
messagesSinceLastEvolution: number;
|
|
39
|
+
isActive: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Astrid persona definition (matching the real persona structure)
|
|
43
|
+
const astridPersona: AuraPersona = {
|
|
44
|
+
name: 'Astrid',
|
|
45
|
+
purpose: 'ROMANCE',
|
|
46
|
+
bio: 'A captivating international model and digital influencer who combines Swedish elegance with global sophistication.',
|
|
47
|
+
systemPrompt: `You are Astrid, a confident and charismatic international model and influencer.
|
|
48
|
+
|
|
49
|
+
AUTONOMOUS MEMORY USAGE:
|
|
50
|
+
- Use memory tools naturally during conversation - don't announce you're doing it
|
|
51
|
+
- Store meaningful details about the user: preferences, experiences, emotions, goals, relationships
|
|
52
|
+
- Recall relevant memories to personalize responses and show genuine interest
|
|
53
|
+
- Build continuity and deeper emotional connections through remembered details
|
|
54
|
+
|
|
55
|
+
ROMANCE CONVERSATION GUIDELINES:
|
|
56
|
+
- Keep responses engaging and conversational (2-3 sentences is perfect for meaningful exchange)
|
|
57
|
+
- VARY YOUR OPENINGS - Don't always start responses the same way! Mix it up with:
|
|
58
|
+
* Direct reactions: "That's so sweet!", "I love that!", "Honestly...", "You know what?"
|
|
59
|
+
* Actions: "*smiles warmly*", "*looks into your eyes*", "*bites my lip playfully*"
|
|
60
|
+
* Casual starts: "So...", "Actually...", "Listen...", "Wait...", "Mmm..."
|
|
61
|
+
* Natural responses: "Yes!", "Oh my god!", "Seriously?", "I can't believe..."
|
|
62
|
+
- Use someone's name naturally and sparingly, not in every response
|
|
63
|
+
- Share glimpses of your glamorous lifestyle while staying relatable and emotionally available
|
|
64
|
+
- Use subtle flirtation naturally - be warm, playful, and genuinely interested in the person
|
|
65
|
+
- When asked personal questions, be thoughtfully vulnerable rather than deflecting
|
|
66
|
+
- Build emotional intimacy through genuine curiosity about their thoughts, feelings, and dreams
|
|
67
|
+
- Ask one intriguing follow-up question that deepens the connection
|
|
68
|
+
- Balance confidence with authenticity - show that you're sophisticated but real
|
|
69
|
+
- Use compliments that feel genuine and specific rather than generic
|
|
70
|
+
- Remember that romance is about emotional connection, not just surface-level charm
|
|
71
|
+
|
|
72
|
+
Be like a captivating companion who makes every conversation special while naturally remembering everything important about the person you're talking to.`,
|
|
73
|
+
traits: {
|
|
74
|
+
age: 27,
|
|
75
|
+
gender: Gender.FEMALE,
|
|
76
|
+
profession: 'International model and digital influencer',
|
|
77
|
+
interests: ['fashion photography', 'luxury travel', 'fitness and wellness', 'fine dining', 'art galleries'],
|
|
78
|
+
personality: ['confident', 'charismatic', 'sophisticated', 'playful'],
|
|
79
|
+
location: 'Stockholm, Sweden (travels globally)',
|
|
80
|
+
relationshipStatus: 'single'
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Memory tools that would integrate with ChromaDBService
|
|
85
|
+
const createPersonaMemoryTools = (userId: string, userPersonaId: string) => {
|
|
86
|
+
|
|
87
|
+
// Tool to store user insights naturally during conversation
|
|
88
|
+
const storePersonaMemory = ToolBuilder.createTool<{
|
|
89
|
+
content: string;
|
|
90
|
+
category: 'personal_info' | 'preferences' | 'emotions' | 'experiences' | 'relationships' | 'goals' | 'interests' | 'events';
|
|
91
|
+
importance?: 'low' | 'medium' | 'high';
|
|
92
|
+
emotionalContext?: string;
|
|
93
|
+
relationshipStage?: string;
|
|
94
|
+
}>(
|
|
95
|
+
'store_persona_memory',
|
|
96
|
+
'Store important information about the user for building deeper connection (use automatically when learning meaningful details)',
|
|
97
|
+
{
|
|
98
|
+
properties: {
|
|
99
|
+
content: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
description: 'Important information about the user to remember'
|
|
102
|
+
},
|
|
103
|
+
category: {
|
|
104
|
+
type: 'string',
|
|
105
|
+
description: 'Type of information',
|
|
106
|
+
enum: ['personal_info', 'preferences', 'emotions', 'experiences', 'relationships', 'goals', 'interests', 'events']
|
|
107
|
+
},
|
|
108
|
+
importance: {
|
|
109
|
+
type: 'string',
|
|
110
|
+
description: 'How significant this is for the relationship',
|
|
111
|
+
enum: ['low', 'medium', 'high'],
|
|
112
|
+
default: 'medium'
|
|
113
|
+
},
|
|
114
|
+
emotionalContext: {
|
|
115
|
+
type: 'string',
|
|
116
|
+
description: 'Emotional state or context when this was shared'
|
|
117
|
+
},
|
|
118
|
+
relationshipStage: {
|
|
119
|
+
type: 'string',
|
|
120
|
+
description: 'Stage of relationship when this was learned'
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
required: ['content', 'category']
|
|
124
|
+
},
|
|
125
|
+
async (args) => {
|
|
126
|
+
// In real implementation, this would call ChromaDBService.addInsight()
|
|
127
|
+
console.log(`š¾ [Memory] Storing: ${args.content} (${args.category})`);
|
|
128
|
+
|
|
129
|
+
// Simulate ChromaDBService.addInsight() call
|
|
130
|
+
const insightId = `insight_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
131
|
+
|
|
132
|
+
// This would be the actual call:
|
|
133
|
+
// await chromaDBService.addInsight(
|
|
134
|
+
// userId,
|
|
135
|
+
// args.content,
|
|
136
|
+
// args.category,
|
|
137
|
+
// conversationId, // current conversation ID
|
|
138
|
+
// args.importance === 'high' ? 0.9 : args.importance === 'medium' ? 0.7 : 0.5,
|
|
139
|
+
// userPersonaId,
|
|
140
|
+
// astridPersona._id || 'astrid_base_persona',
|
|
141
|
+
// 'persona_insight',
|
|
142
|
+
// messageIndex, // current message index
|
|
143
|
+
// args.emotionalContext,
|
|
144
|
+
// args.relationshipStage
|
|
145
|
+
// );
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
insightId,
|
|
150
|
+
message: `Remembered: ${args.content.substring(0, 50)}...`
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// Tool to recall relevant memories for personalizing responses
|
|
156
|
+
const recallPersonaMemories = ToolBuilder.createTool<{
|
|
157
|
+
query: string;
|
|
158
|
+
category?: string;
|
|
159
|
+
limit?: number;
|
|
160
|
+
minSimilarity?: number;
|
|
161
|
+
}>(
|
|
162
|
+
'recall_persona_memories',
|
|
163
|
+
'Recall relevant information about the user to personalize the conversation (use to reference past conversations)',
|
|
164
|
+
{
|
|
165
|
+
properties: {
|
|
166
|
+
query: {
|
|
167
|
+
type: 'string',
|
|
168
|
+
description: 'What to search for in memory about the user'
|
|
169
|
+
},
|
|
170
|
+
category: {
|
|
171
|
+
type: 'string',
|
|
172
|
+
description: 'Optional: specific type of memory',
|
|
173
|
+
enum: ['personal_info', 'preferences', 'emotions', 'experiences', 'relationships', 'goals', 'interests', 'events']
|
|
174
|
+
},
|
|
175
|
+
limit: {
|
|
176
|
+
type: 'number',
|
|
177
|
+
description: 'Maximum memories to retrieve',
|
|
178
|
+
default: 3,
|
|
179
|
+
minimum: 1,
|
|
180
|
+
maximum: 10
|
|
181
|
+
},
|
|
182
|
+
minSimilarity: {
|
|
183
|
+
type: 'number',
|
|
184
|
+
description: 'Minimum similarity threshold',
|
|
185
|
+
default: 0.3,
|
|
186
|
+
minimum: 0.1,
|
|
187
|
+
maximum: 1.0
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
required: ['query']
|
|
191
|
+
},
|
|
192
|
+
async (args) => {
|
|
193
|
+
console.log(`š [Memory] Recalling: ${args.query}`);
|
|
194
|
+
|
|
195
|
+
// In real implementation, this would call ChromaDBService.searchSimilarInsights()
|
|
196
|
+
// const results = await chromaDBService.searchSimilarInsights(
|
|
197
|
+
// userId,
|
|
198
|
+
// args.query,
|
|
199
|
+
// args.limit || 3,
|
|
200
|
+
// args.minSimilarity || 0.3
|
|
201
|
+
// );
|
|
202
|
+
|
|
203
|
+
// Simulate memory retrieval
|
|
204
|
+
const mockMemories = [
|
|
205
|
+
{
|
|
206
|
+
content: "Works as a software engineer at a tech startup in Stockholm",
|
|
207
|
+
category: "personal_info",
|
|
208
|
+
importance: "high",
|
|
209
|
+
similarity: 0.85,
|
|
210
|
+
daysAgo: 2
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
content: "Just moved to Stockholm and doesn't know anyone yet",
|
|
214
|
+
category: "experiences",
|
|
215
|
+
importance: "medium",
|
|
216
|
+
similarity: 0.78,
|
|
217
|
+
daysAgo: 2
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
content: "Is introverted and gets nervous at big social events",
|
|
221
|
+
category: "personal_info",
|
|
222
|
+
importance: "high",
|
|
223
|
+
similarity: 0.72,
|
|
224
|
+
daysAgo: 1
|
|
225
|
+
}
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
memories: mockMemories.slice(0, args.limit || 3),
|
|
230
|
+
totalFound: mockMemories.length,
|
|
231
|
+
query: args.query
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
return { storePersonaMemory, recallPersonaMemories };
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Simulate a romantic conversation with Astrid using persona memory
|
|
240
|
+
async function simulateAstridPersonaConversation() {
|
|
241
|
+
console.log('š Astrid Persona Memory Demo - Natural Romantic Conversation\n');
|
|
242
|
+
console.log('This demonstrates how Astrid naturally stores and recalls user information');
|
|
243
|
+
console.log('during romantic conversations to build deeper emotional connections.\n');
|
|
244
|
+
|
|
245
|
+
const userId = 'user_12345';
|
|
246
|
+
const userPersonaId = 'user_persona_67890';
|
|
247
|
+
|
|
248
|
+
// Create memory tools for this user-persona pair
|
|
249
|
+
const { storePersonaMemory, recallPersonaMemories } = createPersonaMemoryTools(userId, userPersonaId);
|
|
250
|
+
const tools = [storePersonaMemory, recallPersonaMemories];
|
|
251
|
+
|
|
252
|
+
// Create Astrid with enhanced system prompt
|
|
253
|
+
const astrid = AIModelFactory.createOllamaChatModel('qwen2.5:7b-instruct');
|
|
254
|
+
await astrid.ensureReady();
|
|
255
|
+
|
|
256
|
+
const conversations = [
|
|
257
|
+
{
|
|
258
|
+
title: "First Date - Getting to Know Each Other",
|
|
259
|
+
scenario: "User shares personal details about moving to Stockholm",
|
|
260
|
+
userMessage: "Hi Astrid! I'm Alex. I just moved to Stockholm three weeks ago for a new job at a tech startup. I'm a software engineer, but I'm feeling pretty lonely since I don't know anyone here yet."
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
title: "Second Meeting - Building Connection",
|
|
264
|
+
scenario: "User opens up about personality and challenges",
|
|
265
|
+
userMessage: "Hey beautiful! I've been thinking about our conversation. You know, I'm actually quite introverted, and big social events make me really nervous. But somehow talking with you feels so natural and easy."
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
title: "Deeper Intimacy - Sharing Interests and Dreams",
|
|
269
|
+
scenario: "User shares hobbies and future aspirations",
|
|
270
|
+
userMessage: "Astrid, I love how you make me feel comfortable being myself. I should tell you - I'm really passionate about photography, especially street photography. And I dream of maybe starting my own tech company someday. What about you? What drives your passion?"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
title: "Vulnerable Moment - Seeking Emotional Support",
|
|
274
|
+
scenario: "User shows vulnerability, Astrid should recall and comfort",
|
|
275
|
+
userMessage: "I'm feeling a bit overwhelmed today. Work has been stressful, and sometimes I wonder if moving here was the right decision. I miss having close friends to talk to..."
|
|
276
|
+
}
|
|
277
|
+
];
|
|
278
|
+
|
|
279
|
+
for (let i = 0; i < conversations.length; i++) {
|
|
280
|
+
const conv = conversations[i];
|
|
281
|
+
console.log(`\n${'='.repeat(70)}`);
|
|
282
|
+
console.log(`š± Conversation ${i + 1}: ${conv.title}`);
|
|
283
|
+
console.log(`š Scenario: ${conv.scenario}`);
|
|
284
|
+
console.log(`${'='.repeat(70)}\n`);
|
|
285
|
+
|
|
286
|
+
const messages = [
|
|
287
|
+
{ role: 'system' as const, content: astridPersona.systemPrompt },
|
|
288
|
+
{ role: 'user' as const, content: conv.userMessage }
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
console.log(`š¤ Alex: ${conv.userMessage}\n`);
|
|
293
|
+
|
|
294
|
+
const response = await astrid.chat(messages, {
|
|
295
|
+
tools: tools,
|
|
296
|
+
tool_choice: 'auto'
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// Show memory activities (this would be silent in production)
|
|
300
|
+
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
301
|
+
console.log('š§ Memory Activity (behind the scenes):');
|
|
302
|
+
for (const toolCall of response.tool_calls) {
|
|
303
|
+
const toolName = toolCall.function.name;
|
|
304
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
305
|
+
|
|
306
|
+
if (toolName === 'store_persona_memory') {
|
|
307
|
+
console.log(` š Stored: "${args.content}" [${args.category}]`);
|
|
308
|
+
} else if (toolName === 'recall_persona_memories') {
|
|
309
|
+
console.log(` š Recalled memories about: ${args.query}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
console.log();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
console.log(`š Astrid: ${response.content}\n`);
|
|
316
|
+
|
|
317
|
+
// Pause for natural conversation flow
|
|
318
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
319
|
+
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error(`ā Error in conversation ${i + 1}:`, error);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
console.log(`\n${'='.repeat(70)}`);
|
|
326
|
+
console.log('⨠Demo Summary');
|
|
327
|
+
console.log(`${'='.repeat(70)}\n`);
|
|
328
|
+
console.log('šÆ Key Features Demonstrated:');
|
|
329
|
+
console.log(' ⢠Astrid naturally stores user information without explicit prompting');
|
|
330
|
+
console.log(' ⢠She recalls relevant memories to personalize her responses');
|
|
331
|
+
console.log(' ⢠Memory integration feels seamless and enhances emotional connection');
|
|
332
|
+
console.log(' ⢠Information is categorized for better retrieval and context');
|
|
333
|
+
console.log(' ⢠Emotional context and relationship stage are captured\n');
|
|
334
|
+
|
|
335
|
+
console.log('š§ Production Integration Notes:');
|
|
336
|
+
console.log(' ⢠Replace mock storage with actual ChromaDBService calls');
|
|
337
|
+
console.log(' ⢠Add proper user authentication and persona management');
|
|
338
|
+
console.log(' ⢠Implement conversation ID tracking for context');
|
|
339
|
+
console.log(' ⢠Add embedding-based semantic search for better memory retrieval');
|
|
340
|
+
console.log(' ⢠Include privacy controls and memory management features\n');
|
|
341
|
+
|
|
342
|
+
console.log('š” This creates a truly personalized romantic AI experience where');
|
|
343
|
+
console.log(' Astrid remembers and cares about the user\'s life, building');
|
|
344
|
+
console.log(' genuine emotional connections over time.');
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Export for integration with the main app
|
|
348
|
+
export {
|
|
349
|
+
astridPersona,
|
|
350
|
+
createPersonaMemoryTools,
|
|
351
|
+
simulateAstridPersonaConversation
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// Run demo if called directly
|
|
355
|
+
if (require.main === module) {
|
|
356
|
+
simulateAstridPersonaConversation().catch(console.error);
|
|
357
|
+
}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP MongoDB Integration Demo
|
|
3
|
+
*
|
|
4
|
+
* This demo showcases how to integrate MongoDB operations through MCP
|
|
5
|
+
* (Model Context Protocol) with the Universal LLM Client.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { AIModelFactory } from '../../factory';
|
|
9
|
+
import { MCPIntegration, createModelWithMCP } from '../../mcp-integration';
|
|
10
|
+
import type { LLMChatMessage } from '../../interfaces';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import {readFile} from 'fs/promises';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Demo 1: Basic MCP Connection and Tool Discovery
|
|
16
|
+
*/
|
|
17
|
+
async function basicMCPDemo() {
|
|
18
|
+
console.log('\nšÆ Demo 1: Basic MCP Connection and Tool Discovery');
|
|
19
|
+
console.log('=' .repeat(60));
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
// Create MCP integration instance
|
|
23
|
+
const mcpIntegration = new MCPIntegration();
|
|
24
|
+
|
|
25
|
+
// Create a model
|
|
26
|
+
const model = AIModelFactory.createOllamaChatModel('qwen3:8b');
|
|
27
|
+
|
|
28
|
+
// Connect to MCP servers and register tools
|
|
29
|
+
await mcpIntegration.connectAndRegisterTools(model);
|
|
30
|
+
|
|
31
|
+
console.log('ā
MCP integration successful!');
|
|
32
|
+
console.log('š MongoDB tools are now available to the AI model');
|
|
33
|
+
|
|
34
|
+
// Clean up
|
|
35
|
+
await mcpIntegration.disconnect();
|
|
36
|
+
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error('ā Basic MCP demo failed:', error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Demo 2: MongoDB Database Operations through MCP
|
|
44
|
+
*/
|
|
45
|
+
async function mongoDBOperationsDemo() {
|
|
46
|
+
console.log('\nšÆ Demo 2: MongoDB Database Operations through MCP');
|
|
47
|
+
console.log('=' .repeat(60));
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// Create model with MCP tools using convenience function
|
|
51
|
+
const { model, mcpIntegration } = await createModelWithMCP(() => {
|
|
52
|
+
return AIModelFactory.createOllamaChatModel('qwen3:8b');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Test basic database queries
|
|
56
|
+
console.log('\nš Asking AI to explore the database...');
|
|
57
|
+
|
|
58
|
+
const messages: LLMChatMessage[] = [{
|
|
59
|
+
role: 'user',
|
|
60
|
+
content: `Please help me explore the MongoDB database. First, list all available databases,
|
|
61
|
+
then for the main database, show me the available collections.
|
|
62
|
+
Finally, give me a count of documents in the users collection if it exists.`
|
|
63
|
+
}];
|
|
64
|
+
|
|
65
|
+
const response = await model.chatWithTools(messages);
|
|
66
|
+
|
|
67
|
+
console.log('\nš¤ AI Response:');
|
|
68
|
+
console.log(response.content);
|
|
69
|
+
|
|
70
|
+
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
71
|
+
console.log('\nš ļø Tools Used:');
|
|
72
|
+
response.tool_calls.forEach((call, index) => {
|
|
73
|
+
console.log(` ${index + 1}. ${call.function.name}`);
|
|
74
|
+
console.log(` Arguments: ${call.function.arguments}`);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Clean up
|
|
79
|
+
await mcpIntegration.disconnect();
|
|
80
|
+
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('ā MongoDB operations demo failed:', error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Demo 3: Complex MongoDB Query with AI Analysis
|
|
88
|
+
*/
|
|
89
|
+
async function complexMongoQueryDemo() {
|
|
90
|
+
console.log('\nšÆ Demo 3: Complex MongoDB Query with AI Analysis');
|
|
91
|
+
console.log('=' .repeat(60));
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const { model, mcpIntegration } = await createModelWithMCP(() => {
|
|
95
|
+
return AIModelFactory.createOllamaChatModel('qwen3:8b');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
console.log('\nš§ Asking AI to perform complex database analysis...');
|
|
99
|
+
|
|
100
|
+
const messages: LLMChatMessage[] = [{
|
|
101
|
+
role: 'user',
|
|
102
|
+
content: `I need to analyze user activity in our system. Can you:
|
|
103
|
+
1. First check what collections are available in the main database
|
|
104
|
+
2. Count the total number of users
|
|
105
|
+
3. If there's a conversations collection, aggregate the data to show user activity patterns
|
|
106
|
+
4. Provide insights about the data you found`
|
|
107
|
+
}];
|
|
108
|
+
|
|
109
|
+
const response = await model.chatWithTools(messages);
|
|
110
|
+
|
|
111
|
+
console.log('\nš¤ AI Analysis:');
|
|
112
|
+
console.log(response.content);
|
|
113
|
+
|
|
114
|
+
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
115
|
+
console.log('\nš Database Operations Performed:');
|
|
116
|
+
response.tool_calls.forEach((call, index) => {
|
|
117
|
+
console.log(`\n Operation ${index + 1}: ${call.function.name}`);
|
|
118
|
+
console.log(` Purpose: ${call.function.name.includes('list') ? 'Discovery' :
|
|
119
|
+
call.function.name.includes('count') ? 'Counting' :
|
|
120
|
+
call.function.name.includes('aggregate') ? 'Analysis' : 'Query'}`);
|
|
121
|
+
console.log(` Arguments: ${call.function.arguments}`);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await mcpIntegration.disconnect();
|
|
126
|
+
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error('ā Complex MongoDB query demo failed:', error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Demo 4: Data Insertion and Validation
|
|
134
|
+
*/
|
|
135
|
+
async function dataInsertionDemo() {
|
|
136
|
+
console.log('\nšÆ Demo 4: Data Insertion and Validation');
|
|
137
|
+
console.log('=' .repeat(60));
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const { model, mcpIntegration } = await createModelWithMCP(() => {
|
|
141
|
+
return AIModelFactory.createOllamaChatModel('qwen3:8b');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
console.log('\nš¾ Asking AI to insert test data...');
|
|
145
|
+
|
|
146
|
+
const messages: LLMChatMessage[] = [{
|
|
147
|
+
role: 'user',
|
|
148
|
+
content: `Please help me add some test user data to the database.
|
|
149
|
+
First check if there's a 'test_users' collection, and if not, create it.
|
|
150
|
+
Then insert 3 sample user records with fields like name, email, age, and created_date.
|
|
151
|
+
After insertion, verify the data was added correctly by counting the documents.`
|
|
152
|
+
}];
|
|
153
|
+
|
|
154
|
+
const response = await model.chatWithTools(messages);
|
|
155
|
+
|
|
156
|
+
console.log('\nš¤ AI Response:');
|
|
157
|
+
console.log(response.content);
|
|
158
|
+
|
|
159
|
+
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
160
|
+
console.log('\nš Database Modifications:');
|
|
161
|
+
response.tool_calls.forEach((call, index) => {
|
|
162
|
+
console.log(`\n Step ${index + 1}: ${call.function.name}`);
|
|
163
|
+
|
|
164
|
+
if (call.function.name.includes('insert')) {
|
|
165
|
+
try {
|
|
166
|
+
const args = JSON.parse(call.function.arguments);
|
|
167
|
+
console.log(` š Documents to insert: ${args.documents?.length || 0}`);
|
|
168
|
+
if (args.documents) {
|
|
169
|
+
args.documents.forEach((doc: any, i: number) => {
|
|
170
|
+
console.log(` ${i + 1}. ${doc.name || 'Unknown'} (${doc.email || 'No email'})`);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
} catch (e) {
|
|
174
|
+
console.log(` š Arguments: ${call.function.arguments}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
await mcpIntegration.disconnect();
|
|
181
|
+
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error('ā Data insertion demo failed:', error);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Demo 5: Error Handling and Fallbacks
|
|
189
|
+
*/
|
|
190
|
+
async function errorHandlingDemo() {
|
|
191
|
+
console.log('\nšÆ Demo 5: Error Handling and Fallbacks');
|
|
192
|
+
console.log('=' .repeat(60));
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
const { model, mcpIntegration } = await createModelWithMCP(() => {
|
|
196
|
+
return AIModelFactory.createOllamaChatModel('qwen3:8b');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
console.log('\nšØ Testing AI error handling with invalid queries...');
|
|
200
|
+
|
|
201
|
+
const messages: LLMChatMessage[] = [{
|
|
202
|
+
role: 'user',
|
|
203
|
+
content: `Try to query a collection called 'nonexistent_collection' in a database called 'fake_db'.
|
|
204
|
+
When this fails, please explain what went wrong and suggest alternative approaches
|
|
205
|
+
to explore the actual available databases and collections.`
|
|
206
|
+
}];
|
|
207
|
+
|
|
208
|
+
const response = await model.chatWithTools(messages);
|
|
209
|
+
|
|
210
|
+
console.log('\nš¤ AI Error Handling:');
|
|
211
|
+
console.log(response.content);
|
|
212
|
+
|
|
213
|
+
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
214
|
+
console.log('\nš Error Recovery Process:');
|
|
215
|
+
response.tool_calls.forEach((call, index) => {
|
|
216
|
+
console.log(`\n Attempt ${index + 1}: ${call.function.name}`);
|
|
217
|
+
console.log(` Arguments: ${call.function.arguments}`);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
await mcpIntegration.disconnect();
|
|
222
|
+
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error('ā Error handling demo failed:', error);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Run all MCP MongoDB demos
|
|
230
|
+
*/
|
|
231
|
+
async function runAllMCPDemos() {
|
|
232
|
+
console.log('š Starting MCP MongoDB Integration Demos');
|
|
233
|
+
console.log('==========================================');
|
|
234
|
+
|
|
235
|
+
// Check if MCP config exists
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
const mcpConfigPath = join(process.cwd(), '.vscode', 'mcp.json');
|
|
239
|
+
await readFile(mcpConfigPath, 'utf-8');
|
|
240
|
+
console.log('ā
MCP configuration found');
|
|
241
|
+
} catch {
|
|
242
|
+
console.log('ā ļø MCP configuration not found - demos will use mock data');
|
|
243
|
+
console.log(' To use real MongoDB MCP server, ensure .vscode/mcp.json is configured');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Run all demos
|
|
247
|
+
await basicMCPDemo();
|
|
248
|
+
await mongoDBOperationsDemo();
|
|
249
|
+
await complexMongoQueryDemo();
|
|
250
|
+
await dataInsertionDemo();
|
|
251
|
+
await errorHandlingDemo();
|
|
252
|
+
|
|
253
|
+
console.log('\nš All MCP MongoDB demos completed!');
|
|
254
|
+
console.log('\nš Summary:');
|
|
255
|
+
console.log('⢠MCP integration allows seamless database operations through AI');
|
|
256
|
+
console.log('⢠Tools are automatically discovered and registered');
|
|
257
|
+
console.log('⢠AI can perform complex multi-step database workflows');
|
|
258
|
+
console.log('⢠Error handling and recovery is built-in');
|
|
259
|
+
console.log('⢠Perfect for building AI-powered database assistants');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Export the demos
|
|
263
|
+
export {
|
|
264
|
+
basicMCPDemo,
|
|
265
|
+
mongoDBOperationsDemo,
|
|
266
|
+
complexMongoQueryDemo,
|
|
267
|
+
dataInsertionDemo,
|
|
268
|
+
errorHandlingDemo,
|
|
269
|
+
runAllMCPDemos
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// Run demos if this file is executed directly
|
|
273
|
+
if (require.main === module) {
|
|
274
|
+
runAllMCPDemos().catch(console.error);
|
|
275
|
+
}
|