@elizaos/plugin-research 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +400 -0
- package/dist/index.cjs +9366 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +9284 -0
- package/dist/index.js.map +1 -0
- package/package.json +80 -0
- package/src/__tests__/action-chaining.test.ts +532 -0
- package/src/__tests__/actions.test.ts +118 -0
- package/src/__tests__/cache-rate-limiter.test.ts +303 -0
- package/src/__tests__/content-extractors.test.ts +26 -0
- package/src/__tests__/deepresearch-bench-integration.test.ts +520 -0
- package/src/__tests__/deepresearch-bench-simplified.e2e.test.ts +290 -0
- package/src/__tests__/deepresearch-bench.e2e.test.ts +376 -0
- package/src/__tests__/e2e.test.ts +1870 -0
- package/src/__tests__/multi-benchmark-runner.ts +427 -0
- package/src/__tests__/providers.test.ts +156 -0
- package/src/__tests__/real-world.e2e.test.ts +788 -0
- package/src/__tests__/research-scenarios.test.ts +755 -0
- package/src/__tests__/research.e2e.test.ts +704 -0
- package/src/__tests__/research.test.ts +174 -0
- package/src/__tests__/search-providers.test.ts +174 -0
- package/src/__tests__/single-benchmark-runner.ts +735 -0
- package/src/__tests__/test-search-providers.ts +171 -0
- package/src/__tests__/verify-apis.test.ts +82 -0
- package/src/actions.ts +1677 -0
- package/src/benchmark/deepresearch-benchmark.ts +369 -0
- package/src/evaluation/research-evaluator.ts +444 -0
- package/src/examples/api-integration.md +498 -0
- package/src/examples/browserbase-integration.md +132 -0
- package/src/examples/debug-research-query.ts +162 -0
- package/src/examples/defi-code-scenarios.md +536 -0
- package/src/examples/defi-implementation-guide.md +454 -0
- package/src/examples/eliza-research-example.ts +142 -0
- package/src/examples/fix-renewable-energy-research.ts +209 -0
- package/src/examples/research-scenarios.md +408 -0
- package/src/examples/run-complete-renewable-research.ts +303 -0
- package/src/examples/run-deep-research.ts +352 -0
- package/src/examples/run-logged-research.ts +304 -0
- package/src/examples/run-real-research.ts +151 -0
- package/src/examples/save-research-output.ts +133 -0
- package/src/examples/test-file-logging.ts +199 -0
- package/src/examples/test-real-research.ts +67 -0
- package/src/examples/test-renewable-energy-research.ts +229 -0
- package/src/index.ts +28 -0
- package/src/integrations/cache.ts +128 -0
- package/src/integrations/content-extractors/firecrawl.ts +314 -0
- package/src/integrations/content-extractors/pdf-extractor.ts +350 -0
- package/src/integrations/content-extractors/playwright.ts +420 -0
- package/src/integrations/factory.ts +419 -0
- package/src/integrations/index.ts +18 -0
- package/src/integrations/rate-limiter.ts +181 -0
- package/src/integrations/search-providers/academic.ts +290 -0
- package/src/integrations/search-providers/exa.ts +205 -0
- package/src/integrations/search-providers/npm.ts +330 -0
- package/src/integrations/search-providers/pypi.ts +211 -0
- package/src/integrations/search-providers/serpapi.ts +277 -0
- package/src/integrations/search-providers/serper.ts +358 -0
- package/src/integrations/search-providers/stagehand-google.ts +87 -0
- package/src/integrations/search-providers/tavily.ts +187 -0
- package/src/processing/relevance-analyzer.ts +353 -0
- package/src/processing/research-logger.ts +450 -0
- package/src/processing/result-processor.ts +372 -0
- package/src/prompts/research-prompts.ts +419 -0
- package/src/providers/cacheProvider.ts +164 -0
- package/src/providers.ts +173 -0
- package/src/service.ts +2588 -0
- package/src/services/swe-bench.ts +286 -0
- package/src/strategies/research-strategies.ts +790 -0
- package/src/types/pdf-parse.d.ts +34 -0
- package/src/types.ts +551 -0
- package/src/verification/claim-verifier.ts +443 -0
|
@@ -0,0 +1,1870 @@
|
|
|
1
|
+
import { IAgentRuntime, Memory, elizaLogger } from '@elizaos/core';
|
|
2
|
+
import { ResearchService } from '../service';
|
|
3
|
+
import { ResearchProject, ResearchStatus, ResearchPhase } from '../types';
|
|
4
|
+
|
|
5
|
+
// #region: Test Helpers
|
|
6
|
+
|
|
7
|
+
// Helper to create a realistic test memory object
|
|
8
|
+
function createTestMemory(text: string): Memory {
|
|
9
|
+
return {
|
|
10
|
+
id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}` as `${string}-${string}-${string}-${string}-${string}`,
|
|
11
|
+
entityId: '00000000-0000-0000-0000-000000000001' as `${string}-${string}-${string}-${string}-${string}`,
|
|
12
|
+
roomId: '00000000-0000-0000-0000-000000000002' as `${string}-${string}-${string}-${string}-${string}`,
|
|
13
|
+
content: { text },
|
|
14
|
+
createdAt: Date.now(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Helper to wait and monitor research progress
|
|
19
|
+
async function monitorResearch(
|
|
20
|
+
service: ResearchService,
|
|
21
|
+
projectId: string,
|
|
22
|
+
options: {
|
|
23
|
+
timeout?: number;
|
|
24
|
+
checkInterval?: number;
|
|
25
|
+
onProgress?: (project: ResearchProject) => void;
|
|
26
|
+
} = {}
|
|
27
|
+
): Promise<ResearchProject | null> {
|
|
28
|
+
const {
|
|
29
|
+
timeout = 180000, // 3 minutes default
|
|
30
|
+
checkInterval = 5000,
|
|
31
|
+
onProgress,
|
|
32
|
+
} = options;
|
|
33
|
+
|
|
34
|
+
const startTime = Date.now();
|
|
35
|
+
let lastPhase: ResearchPhase | null = null;
|
|
36
|
+
|
|
37
|
+
while (Date.now() - startTime < timeout) {
|
|
38
|
+
const project = await service.getProject(projectId);
|
|
39
|
+
if (!project) return null;
|
|
40
|
+
|
|
41
|
+
// Log phase changes
|
|
42
|
+
if (project.phase !== lastPhase) {
|
|
43
|
+
elizaLogger.info(`Research phase: ${lastPhase || 'START'} → ${project.phase}`);
|
|
44
|
+
lastPhase = project.phase;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Call progress callback
|
|
48
|
+
if (onProgress) {
|
|
49
|
+
onProgress(project);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check completion
|
|
53
|
+
if (
|
|
54
|
+
project.status === ResearchStatus.COMPLETED ||
|
|
55
|
+
project.status === ResearchStatus.FAILED
|
|
56
|
+
) {
|
|
57
|
+
return project;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Return whatever we have after timeout
|
|
64
|
+
const finalProject = await service.getProject(projectId);
|
|
65
|
+
return finalProject || null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Test helper to wait for research completion with longer timeout for real operations
|
|
69
|
+
async function waitForResearchCompletion(
|
|
70
|
+
service: ResearchService,
|
|
71
|
+
projectId: string,
|
|
72
|
+
maxWaitTime: number = 300000 // 5 minutes for real web operations
|
|
73
|
+
): Promise<boolean> {
|
|
74
|
+
const startTime = Date.now();
|
|
75
|
+
|
|
76
|
+
while (Date.now() - startTime < maxWaitTime) {
|
|
77
|
+
const project = await service.getProject(projectId);
|
|
78
|
+
if (!project) return false;
|
|
79
|
+
|
|
80
|
+
if (
|
|
81
|
+
project.status === ResearchStatus.COMPLETED ||
|
|
82
|
+
project.status === ResearchStatus.FAILED
|
|
83
|
+
) {
|
|
84
|
+
return project.status === ResearchStatus.COMPLETED;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Wait 5 seconds before checking again (longer for real operations)
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Helper to validate research quality
|
|
95
|
+
function validateResearchQuality(project: ResearchProject): {
|
|
96
|
+
isValid: boolean;
|
|
97
|
+
issues: string[];
|
|
98
|
+
} {
|
|
99
|
+
const issues: string[] = [];
|
|
100
|
+
|
|
101
|
+
if (project.sources.length === 0) {
|
|
102
|
+
issues.push('No sources found');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (project.findings.length === 0) {
|
|
106
|
+
issues.push('No findings collected');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check for diverse sources
|
|
110
|
+
const uniqueDomains = new Set(
|
|
111
|
+
project.sources.map((s) => {
|
|
112
|
+
try {
|
|
113
|
+
return new URL(s.url).hostname;
|
|
114
|
+
} catch {
|
|
115
|
+
return 'unknown';
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (uniqueDomains.size < 2 && project.sources.length > 2) {
|
|
121
|
+
issues.push('Sources lack diversity (all from same domain)');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Check findings have reasonable content
|
|
125
|
+
const avgFindingLength =
|
|
126
|
+
project.findings.reduce((sum, f) => sum + f.content.length, 0) /
|
|
127
|
+
(project.findings.length || 1);
|
|
128
|
+
if (avgFindingLength < 100) {
|
|
129
|
+
issues.push('Findings are too short (average < 100 chars)');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Check relevance scores
|
|
133
|
+
const avgRelevance =
|
|
134
|
+
project.findings.reduce((sum, f) => sum + f.relevance, 0) /
|
|
135
|
+
(project.findings.length || 1);
|
|
136
|
+
if (avgRelevance < 0.3) {
|
|
137
|
+
issues.push('Low average relevance score');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
isValid: issues.length === 0,
|
|
142
|
+
issues,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// #endregion
|
|
147
|
+
|
|
148
|
+
// #region: Real-World Persona Scenarios
|
|
149
|
+
|
|
150
|
+
// Test 1: Research for Building a New Feature (Real Developer Workflow)
|
|
151
|
+
export async function testFeatureDevelopmentResearch(
|
|
152
|
+
runtime: IAgentRuntime
|
|
153
|
+
): Promise<void> {
|
|
154
|
+
elizaLogger.info('🔨 Starting Real-World Test: Feature Development Research');
|
|
155
|
+
|
|
156
|
+
const service = runtime.getService<ResearchService>('research');
|
|
157
|
+
if (!service) throw new Error('Research service not available');
|
|
158
|
+
|
|
159
|
+
// Scenario: Developer needs to implement WebSocket real-time features
|
|
160
|
+
const queries = [
|
|
161
|
+
'WebSocket implementation Node.js TypeScript scaling best practices 2024',
|
|
162
|
+
'Socket.io vs native WebSocket performance comparison production',
|
|
163
|
+
'WebSocket authentication JWT security implementation examples',
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
elizaLogger.info(
|
|
167
|
+
'Researching WebSocket implementation across multiple aspects...'
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const projects = await Promise.all(
|
|
171
|
+
queries.map((query, index) =>
|
|
172
|
+
service.createResearchProject(query, {
|
|
173
|
+
maxSearchResults: 3,
|
|
174
|
+
metadata: {
|
|
175
|
+
aspect: ['implementation', 'comparison', 'security'][index],
|
|
176
|
+
featureType: 'websocket',
|
|
177
|
+
},
|
|
178
|
+
})
|
|
179
|
+
)
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
// Monitor all projects
|
|
183
|
+
const results = await Promise.all(
|
|
184
|
+
projects.map((project) =>
|
|
185
|
+
monitorResearch(service, project.id, {
|
|
186
|
+
timeout: 120000,
|
|
187
|
+
onProgress: (p) => {
|
|
188
|
+
if (p.findings.length > 0 && p.findings.length % 3 === 0) {
|
|
189
|
+
elizaLogger.info(
|
|
190
|
+
`Project ${project.query.substring(
|
|
191
|
+
0,
|
|
192
|
+
30
|
|
193
|
+
)}... has ${p.findings.length} findings`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
)
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Analyze combined results
|
|
202
|
+
const allFindings = results.flatMap((r) => r?.findings || []);
|
|
203
|
+
const allSources = results.flatMap((r) => r?.sources || []);
|
|
204
|
+
|
|
205
|
+
// Check for implementation details
|
|
206
|
+
const hasImplementationDetails = allFindings.some((f) => {
|
|
207
|
+
const content = f.content.toLowerCase();
|
|
208
|
+
return (
|
|
209
|
+
content.includes('const') ||
|
|
210
|
+
content.includes('server') ||
|
|
211
|
+
content.includes('client') ||
|
|
212
|
+
content.includes('connection')
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Check for security considerations
|
|
217
|
+
const hasSecurityInfo = allFindings.some((f) => {
|
|
218
|
+
const content = f.content.toLowerCase();
|
|
219
|
+
return (
|
|
220
|
+
content.includes('auth') ||
|
|
221
|
+
content.includes('security') ||
|
|
222
|
+
content.includes('jwt') ||
|
|
223
|
+
content.includes('cors')
|
|
224
|
+
);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// Check for performance insights
|
|
228
|
+
const hasPerformanceInfo = allFindings.some((f) => {
|
|
229
|
+
const content = f.content.toLowerCase();
|
|
230
|
+
return (
|
|
231
|
+
content.includes('performance') ||
|
|
232
|
+
content.includes('scaling') ||
|
|
233
|
+
content.includes('benchmark') ||
|
|
234
|
+
content.includes('latency')
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Find Stack Overflow or GitHub sources (developer favorites)
|
|
239
|
+
const devSources = allSources.filter(
|
|
240
|
+
(s) =>
|
|
241
|
+
s.url.includes('stackoverflow.com') ||
|
|
242
|
+
s.url.includes('github.com') ||
|
|
243
|
+
s.url.includes('dev.to') ||
|
|
244
|
+
s.url.includes('medium.com')
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
elizaLogger.info('📊 Feature Development Research Results:');
|
|
248
|
+
elizaLogger.info(`- Total findings across aspects: ${allFindings.length}`);
|
|
249
|
+
elizaLogger.info(
|
|
250
|
+
`- Implementation details found: ${hasImplementationDetails}`
|
|
251
|
+
);
|
|
252
|
+
elizaLogger.info(`- Security considerations found: ${hasSecurityInfo}`);
|
|
253
|
+
elizaLogger.info(`- Performance insights found: ${hasPerformanceInfo}`);
|
|
254
|
+
elizaLogger.info(
|
|
255
|
+
`- Developer-focused sources: ${devSources.length}/${allSources.length}`
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
if (devSources.length > 0) {
|
|
259
|
+
elizaLogger.info(`- Sample dev source: ${devSources[0].title}`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Simulate decision-making based on research
|
|
263
|
+
if (hasImplementationDetails && hasSecurityInfo && hasPerformanceInfo) {
|
|
264
|
+
elizaLogger.success(
|
|
265
|
+
'✅ Research provides comprehensive information for feature implementation'
|
|
266
|
+
);
|
|
267
|
+
} else {
|
|
268
|
+
elizaLogger.warn('⚠️ Some aspects missing - may need additional research');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
elizaLogger.success(
|
|
272
|
+
'✅ Real-World Test Passed: Feature Development Research'
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Test 2: Research a Person for Hiring/Partnership (Real HR/Business Workflow)
|
|
277
|
+
export async function testPersonBackgroundResearch(
|
|
278
|
+
runtime: IAgentRuntime
|
|
279
|
+
): Promise<void> {
|
|
280
|
+
elizaLogger.info('👤 Starting Real-World Test: Person Background Research');
|
|
281
|
+
|
|
282
|
+
const service = runtime.getService<ResearchService>('research');
|
|
283
|
+
if (!service) throw new Error('Research service not available');
|
|
284
|
+
|
|
285
|
+
// Scenario: Researching a potential technical advisor or hire
|
|
286
|
+
const personQuery =
|
|
287
|
+
'Andrej Karpathy AI research contributions Tesla OpenAI recent projects 2024';
|
|
288
|
+
|
|
289
|
+
const project = await service.createResearchProject(personQuery, {
|
|
290
|
+
maxSearchResults: 5,
|
|
291
|
+
metadata: {
|
|
292
|
+
researchType: 'person_background',
|
|
293
|
+
purpose: 'professional_evaluation',
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
elizaLogger.info('Researching professional background...');
|
|
298
|
+
|
|
299
|
+
const result = await monitorResearch(service, project.id, {
|
|
300
|
+
timeout: 150000,
|
|
301
|
+
onProgress: (p) => {
|
|
302
|
+
// Track what types of sources we're finding
|
|
303
|
+
const sources = p.sources.map((s) => new URL(s.url).hostname);
|
|
304
|
+
const hasLinkedIn = sources.some((s) => s.includes('linkedin'));
|
|
305
|
+
const hasTwitter = sources.some(
|
|
306
|
+
(s) => s.includes('twitter') || s.includes('x.com')
|
|
307
|
+
);
|
|
308
|
+
const hasGitHub = sources.some((s) => s.includes('github'));
|
|
309
|
+
|
|
310
|
+
if (
|
|
311
|
+
(hasLinkedIn || hasTwitter || hasGitHub) &&
|
|
312
|
+
p.phase === ResearchPhase.SEARCHING
|
|
313
|
+
) {
|
|
314
|
+
elizaLogger.info(
|
|
315
|
+
`Found professional profiles: LinkedIn=${hasLinkedIn}, Twitter=${hasTwitter}, GitHub=${hasGitHub}`
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
if (!result) throw new Error('Person research failed to complete');
|
|
322
|
+
|
|
323
|
+
// Analyze findings for key information
|
|
324
|
+
const findings = result.findings;
|
|
325
|
+
|
|
326
|
+
// Professional history
|
|
327
|
+
const hasTeslaInfo = findings.some((f) =>
|
|
328
|
+
f.content.toLowerCase().includes('tesla')
|
|
329
|
+
);
|
|
330
|
+
const hasOpenAIInfo = findings.some((f) =>
|
|
331
|
+
f.content.toLowerCase().includes('openai')
|
|
332
|
+
);
|
|
333
|
+
const hasEducation = findings.some(
|
|
334
|
+
(f) =>
|
|
335
|
+
f.content.toLowerCase().includes('stanford') ||
|
|
336
|
+
f.content.toLowerCase().includes('phd') ||
|
|
337
|
+
f.content.toLowerCase().includes('university')
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
// Recent activities
|
|
341
|
+
const hasRecentActivity = findings.some((f) => {
|
|
342
|
+
const content = f.content;
|
|
343
|
+
return (
|
|
344
|
+
content.includes('2024') ||
|
|
345
|
+
content.includes('2023') ||
|
|
346
|
+
content.toLowerCase().includes('recent') ||
|
|
347
|
+
content.toLowerCase().includes('latest')
|
|
348
|
+
);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// Technical contributions
|
|
352
|
+
const hasTechnicalWork = findings.some((f) => {
|
|
353
|
+
const content = f.content.toLowerCase();
|
|
354
|
+
return (
|
|
355
|
+
content.includes('paper') ||
|
|
356
|
+
content.includes('research') ||
|
|
357
|
+
content.includes('model') ||
|
|
358
|
+
content.includes('algorithm') ||
|
|
359
|
+
content.includes('course')
|
|
360
|
+
);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// Extract key achievements
|
|
364
|
+
const achievements = findings.filter((f) => {
|
|
365
|
+
const content = f.content.toLowerCase();
|
|
366
|
+
return (
|
|
367
|
+
content.includes('founded') ||
|
|
368
|
+
content.includes('created') ||
|
|
369
|
+
content.includes('developed') ||
|
|
370
|
+
content.includes('led') ||
|
|
371
|
+
content.includes('published')
|
|
372
|
+
);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
elizaLogger.info('📋 Person Background Research Results:');
|
|
376
|
+
elizaLogger.info(
|
|
377
|
+
`- Professional history coverage: Tesla=${hasTeslaInfo}, OpenAI=${hasOpenAIInfo}`
|
|
378
|
+
);
|
|
379
|
+
elizaLogger.info(`- Education info found: ${hasEducation}`);
|
|
380
|
+
elizaLogger.info(`- Recent activity (2023-2024): ${hasRecentActivity}`);
|
|
381
|
+
elizaLogger.info(`- Technical contributions: ${hasTechnicalWork}`);
|
|
382
|
+
elizaLogger.info(`- Key achievements identified: ${achievements.length}`);
|
|
383
|
+
|
|
384
|
+
if (achievements.length > 0) {
|
|
385
|
+
const sample = achievements[0].content.substring(0, 150);
|
|
386
|
+
elizaLogger.info(`- Sample achievement: "${sample}..."`);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Professional assessment
|
|
390
|
+
const professionalScore = [
|
|
391
|
+
hasTeslaInfo,
|
|
392
|
+
hasOpenAIInfo,
|
|
393
|
+
hasEducation,
|
|
394
|
+
hasRecentActivity,
|
|
395
|
+
hasTechnicalWork,
|
|
396
|
+
].filter(Boolean).length;
|
|
397
|
+
|
|
398
|
+
if (professionalScore >= 4) {
|
|
399
|
+
elizaLogger.success('✅ Comprehensive professional profile assembled');
|
|
400
|
+
} else if (professionalScore >= 2) {
|
|
401
|
+
elizaLogger.info(
|
|
402
|
+
'ℹ️ Partial professional profile - may need additional sources'
|
|
403
|
+
);
|
|
404
|
+
} else {
|
|
405
|
+
elizaLogger.warn('⚠️ Limited professional information found');
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
elizaLogger.success('✅ Real-World Test Passed: Person Background Research');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Test 3: Breaking News Research (Real Journalist/Analyst Workflow)
|
|
412
|
+
export async function testBreakingNewsResearch(
|
|
413
|
+
runtime: IAgentRuntime
|
|
414
|
+
): Promise<void> {
|
|
415
|
+
elizaLogger.info('📰 Starting Real-World Test: Breaking News Research');
|
|
416
|
+
|
|
417
|
+
const service = runtime.getService<ResearchService>('research');
|
|
418
|
+
if (!service) throw new Error('Research service not available');
|
|
419
|
+
|
|
420
|
+
// Scenario: Researching breaking AI news
|
|
421
|
+
const newsQuery =
|
|
422
|
+
'AI artificial intelligence news today latest announcements breakthroughs December 2024';
|
|
423
|
+
|
|
424
|
+
const project = await service.createResearchProject(newsQuery, {
|
|
425
|
+
maxSearchResults: 6,
|
|
426
|
+
metadata: {
|
|
427
|
+
researchType: 'breaking_news',
|
|
428
|
+
timeframe: 'current',
|
|
429
|
+
industry: 'AI/ML',
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
elizaLogger.info('Scanning for breaking AI news...');
|
|
434
|
+
|
|
435
|
+
const result = await monitorResearch(service, project.id, {
|
|
436
|
+
timeout: 150000,
|
|
437
|
+
checkInterval: 3000,
|
|
438
|
+
onProgress: (p) => {
|
|
439
|
+
// Track news sources as they're found
|
|
440
|
+
if (p.phase === ResearchPhase.SEARCHING && p.sources.length > 0) {
|
|
441
|
+
const newsSources = p.sources.filter((s) => {
|
|
442
|
+
const url = s.url.toLowerCase();
|
|
443
|
+
return (
|
|
444
|
+
url.includes('news') ||
|
|
445
|
+
url.includes('article') ||
|
|
446
|
+
url.includes('press') ||
|
|
447
|
+
url.includes('announcement')
|
|
448
|
+
);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
if (newsSources.length > 0) {
|
|
452
|
+
elizaLogger.info(`Found ${newsSources.length} news sources`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
if (!result) throw new Error('News research failed to complete');
|
|
459
|
+
|
|
460
|
+
// Analyze news findings
|
|
461
|
+
const findings = result.findings;
|
|
462
|
+
const sources = result.sources;
|
|
463
|
+
|
|
464
|
+
// Identify news sources by domain
|
|
465
|
+
const newsSourceTypes = {
|
|
466
|
+
mainstream: sources.filter(
|
|
467
|
+
(s) =>
|
|
468
|
+
s.url.includes('reuters.com') ||
|
|
469
|
+
s.url.includes('bloomberg.com') ||
|
|
470
|
+
s.url.includes('wsj.com') ||
|
|
471
|
+
s.url.includes('nytimes.com')
|
|
472
|
+
),
|
|
473
|
+
tech: sources.filter(
|
|
474
|
+
(s) =>
|
|
475
|
+
s.url.includes('techcrunch.com') ||
|
|
476
|
+
s.url.includes('theverge.com') ||
|
|
477
|
+
s.url.includes('arstechnica.com') ||
|
|
478
|
+
s.url.includes('wired.com')
|
|
479
|
+
),
|
|
480
|
+
ai_specific: sources.filter(
|
|
481
|
+
(s) =>
|
|
482
|
+
s.url.includes('openai.com') ||
|
|
483
|
+
s.url.includes('anthropic.com') ||
|
|
484
|
+
s.url.includes('deepmind.com') ||
|
|
485
|
+
s.url.includes('ai.')
|
|
486
|
+
),
|
|
487
|
+
social: sources.filter(
|
|
488
|
+
(s) =>
|
|
489
|
+
s.url.includes('twitter.com') ||
|
|
490
|
+
s.url.includes('x.com') ||
|
|
491
|
+
s.url.includes('reddit.com')
|
|
492
|
+
),
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
// Check for time-sensitive content
|
|
496
|
+
const currentMonth = new Date().toLocaleDateString('en-US', {
|
|
497
|
+
month: 'long',
|
|
498
|
+
});
|
|
499
|
+
const currentYear = new Date().getFullYear();
|
|
500
|
+
|
|
501
|
+
const hasCurrentMonth = findings.some((f) => f.content.includes(currentMonth));
|
|
502
|
+
const hasCurrentYear = findings.some((f) =>
|
|
503
|
+
f.content.includes(currentYear.toString())
|
|
504
|
+
);
|
|
505
|
+
const hasTimeWords = findings.some((f) => {
|
|
506
|
+
const content = f.content.toLowerCase();
|
|
507
|
+
return (
|
|
508
|
+
content.includes('today') ||
|
|
509
|
+
content.includes('yesterday') ||
|
|
510
|
+
content.includes('this week') ||
|
|
511
|
+
content.includes('announced') ||
|
|
512
|
+
content.includes('just')
|
|
513
|
+
);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
// Identify major announcements
|
|
517
|
+
const announcements = findings.filter((f) => {
|
|
518
|
+
const content = f.content.toLowerCase();
|
|
519
|
+
return (
|
|
520
|
+
content.includes('announc') ||
|
|
521
|
+
content.includes('launch') ||
|
|
522
|
+
content.includes('releas') ||
|
|
523
|
+
content.includes('unveil') ||
|
|
524
|
+
content.includes('introduc')
|
|
525
|
+
);
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Extract companies/organizations mentioned
|
|
529
|
+
const companies = [
|
|
530
|
+
'OpenAI',
|
|
531
|
+
'Google',
|
|
532
|
+
'Microsoft',
|
|
533
|
+
'Anthropic',
|
|
534
|
+
'Meta',
|
|
535
|
+
'Amazon',
|
|
536
|
+
'Apple',
|
|
537
|
+
];
|
|
538
|
+
const companyMentions: Record<string, number> = {};
|
|
539
|
+
|
|
540
|
+
companies.forEach((company) => {
|
|
541
|
+
companyMentions[company] = findings.filter((f) =>
|
|
542
|
+
f.content.includes(company)
|
|
543
|
+
).length;
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
elizaLogger.info('📊 Breaking News Research Results:');
|
|
547
|
+
elizaLogger.info(`- Source distribution:`);
|
|
548
|
+
elizaLogger.info(
|
|
549
|
+
` * Mainstream media: ${newsSourceTypes.mainstream.length}`
|
|
550
|
+
);
|
|
551
|
+
elizaLogger.info(` * Tech media: ${newsSourceTypes.tech.length}`);
|
|
552
|
+
elizaLogger.info(` * AI companies: ${newsSourceTypes.ai_specific.length}`);
|
|
553
|
+
elizaLogger.info(` * Social media: ${newsSourceTypes.social.length}`);
|
|
554
|
+
elizaLogger.info(`- Timeliness indicators:`);
|
|
555
|
+
elizaLogger.info(` * Current month mentioned: ${hasCurrentMonth}`);
|
|
556
|
+
elizaLogger.info(` * Current year mentioned: ${hasCurrentYear}`);
|
|
557
|
+
elizaLogger.info(` * Time-sensitive words: ${hasTimeWords}`);
|
|
558
|
+
elizaLogger.info(`- Announcements found: ${announcements.length}`);
|
|
559
|
+
elizaLogger.info(
|
|
560
|
+
`- Company mentions: ${Object.entries(companyMentions)
|
|
561
|
+
.filter(([_, count]) => count > 0)
|
|
562
|
+
.map(([company, count]) => `${company}=${count}`)
|
|
563
|
+
.join(', ')}`
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
if (announcements.length > 0) {
|
|
567
|
+
const latestAnnouncement = announcements[0].content.substring(0, 200);
|
|
568
|
+
elizaLogger.info(`- Latest announcement: "${latestAnnouncement}..."`);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// News quality assessment
|
|
572
|
+
const hasRecentNews = hasCurrentMonth || hasTimeWords;
|
|
573
|
+
const hasDiverseSources =
|
|
574
|
+
Object.values(newsSourceTypes).filter((arr) => arr.length > 0).length >= 2;
|
|
575
|
+
const hasAnnouncements = announcements.length > 0;
|
|
576
|
+
|
|
577
|
+
if (hasRecentNews && hasDiverseSources && hasAnnouncements) {
|
|
578
|
+
elizaLogger.success('✅ High-quality breaking news coverage achieved');
|
|
579
|
+
} else {
|
|
580
|
+
elizaLogger.info(
|
|
581
|
+
`ℹ️ News coverage: Recent=${hasRecentNews}, Diverse=${hasDiverseSources}, Announcements=${hasAnnouncements}`
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
elizaLogger.success('✅ Real-World Test Passed: Breaking News Research');
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Test 4: Market/Competitive Intelligence (Real Business Strategy Workflow)
|
|
589
|
+
export async function testMarketIntelligenceResearch(
|
|
590
|
+
runtime: IAgentRuntime
|
|
591
|
+
): Promise<void> {
|
|
592
|
+
elizaLogger.info('📈 Starting Real-World Test: Market Intelligence Research');
|
|
593
|
+
|
|
594
|
+
const service = runtime.getService<ResearchService>('research');
|
|
595
|
+
if (!service) throw new Error('Research service not available');
|
|
596
|
+
|
|
597
|
+
// Scenario: Analyzing the AI agent framework market
|
|
598
|
+
const marketQuery =
|
|
599
|
+
'AI agent frameworks market analysis 2024 LangChain AutoGPT CrewAI pricing features comparison adoption';
|
|
600
|
+
|
|
601
|
+
const project = await service.createResearchProject(marketQuery, {
|
|
602
|
+
maxSearchResults: 5,
|
|
603
|
+
metadata: {
|
|
604
|
+
researchType: 'market_intelligence',
|
|
605
|
+
competitors: ['LangChain', 'AutoGPT', 'CrewAI'],
|
|
606
|
+
analysisType: 'competitive',
|
|
607
|
+
},
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
elizaLogger.info('Conducting market intelligence analysis...');
|
|
611
|
+
|
|
612
|
+
const result = await monitorResearch(service, project.id, {
|
|
613
|
+
timeout: 180000,
|
|
614
|
+
onProgress: (p) => {
|
|
615
|
+
if (p.phase === ResearchPhase.ANALYZING && p.findings.length > 5) {
|
|
616
|
+
elizaLogger.info(
|
|
617
|
+
`Analyzing ${p.findings.length} market data points...`
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
},
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
if (!result) throw new Error('Market research failed to complete');
|
|
624
|
+
|
|
625
|
+
// Market analysis
|
|
626
|
+
const findings = result.findings;
|
|
627
|
+
const competitors = ['LangChain', 'AutoGPT', 'CrewAI', 'BabyAGI', 'AgentGPT'];
|
|
628
|
+
|
|
629
|
+
// Competitor analysis
|
|
630
|
+
const competitorData: Record<
|
|
631
|
+
string,
|
|
632
|
+
{
|
|
633
|
+
mentions: number;
|
|
634
|
+
features: string[];
|
|
635
|
+
pricing: boolean;
|
|
636
|
+
adoption: boolean;
|
|
637
|
+
}
|
|
638
|
+
> = {};
|
|
639
|
+
|
|
640
|
+
competitors.forEach((competitor) => {
|
|
641
|
+
const competitorFindings = findings.filter((f) =>
|
|
642
|
+
f.content.toLowerCase().includes(competitor.toLowerCase())
|
|
643
|
+
);
|
|
644
|
+
|
|
645
|
+
const features: string[] = [];
|
|
646
|
+
let hasPricing = false;
|
|
647
|
+
let hasAdoption = false;
|
|
648
|
+
|
|
649
|
+
competitorFindings.forEach((f) => {
|
|
650
|
+
const content = f.content.toLowerCase();
|
|
651
|
+
|
|
652
|
+
// Extract features
|
|
653
|
+
if (content.includes('feature') || content.includes('capability')) {
|
|
654
|
+
if (content.includes('memory')) features.push('memory');
|
|
655
|
+
if (content.includes('tool') || content.includes('function'))
|
|
656
|
+
features.push('tools');
|
|
657
|
+
if (content.includes('chain') || content.includes('workflow'))
|
|
658
|
+
features.push('workflow');
|
|
659
|
+
if (content.includes('llm') || content.includes('model'))
|
|
660
|
+
features.push('multi-llm');
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Check for pricing info
|
|
664
|
+
if (
|
|
665
|
+
content.includes('price') ||
|
|
666
|
+
content.includes('cost') ||
|
|
667
|
+
content.includes('free') ||
|
|
668
|
+
content.includes('$')
|
|
669
|
+
) {
|
|
670
|
+
hasPricing = true;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Check for adoption metrics
|
|
674
|
+
if (
|
|
675
|
+
content.includes('user') ||
|
|
676
|
+
content.includes('download') ||
|
|
677
|
+
content.includes('star') ||
|
|
678
|
+
content.includes('popular')
|
|
679
|
+
) {
|
|
680
|
+
hasAdoption = true;
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
competitorData[competitor] = {
|
|
685
|
+
mentions: competitorFindings.length,
|
|
686
|
+
features: [...new Set(features)],
|
|
687
|
+
pricing: hasPricing,
|
|
688
|
+
adoption: hasAdoption,
|
|
689
|
+
};
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
// Market trends
|
|
693
|
+
const trendKeywords = [
|
|
694
|
+
'growth',
|
|
695
|
+
'trend',
|
|
696
|
+
'future',
|
|
697
|
+
'emerging',
|
|
698
|
+
'adoption',
|
|
699
|
+
'market size',
|
|
700
|
+
];
|
|
701
|
+
const trendsFound = trendKeywords.filter((keyword) =>
|
|
702
|
+
findings.some((f) => f.content.toLowerCase().includes(keyword))
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
// Technical comparisons
|
|
706
|
+
const hasComparisons = findings.some((f) => {
|
|
707
|
+
const content = f.content.toLowerCase();
|
|
708
|
+
return (
|
|
709
|
+
content.includes('compar') ||
|
|
710
|
+
content.includes('versus') ||
|
|
711
|
+
content.includes('vs') ||
|
|
712
|
+
content.includes('better') ||
|
|
713
|
+
content.includes('advantage')
|
|
714
|
+
);
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
// Use cases and applications
|
|
718
|
+
const useCases = findings.filter((f) => {
|
|
719
|
+
const content = f.content.toLowerCase();
|
|
720
|
+
return (
|
|
721
|
+
content.includes('use case') ||
|
|
722
|
+
content.includes('application') ||
|
|
723
|
+
content.includes('example') ||
|
|
724
|
+
content.includes('implementation')
|
|
725
|
+
);
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
elizaLogger.info('📊 Market Intelligence Results:');
|
|
729
|
+
elizaLogger.info('- Competitor Analysis:');
|
|
730
|
+
Object.entries(competitorData).forEach(([competitor, data]) => {
|
|
731
|
+
if (data.mentions > 0) {
|
|
732
|
+
elizaLogger.info(
|
|
733
|
+
` * ${competitor}: ${
|
|
734
|
+
data.mentions
|
|
735
|
+
} mentions, features=[${data.features.join(
|
|
736
|
+
','
|
|
737
|
+
)}], pricing=${data.pricing}, adoption=${data.adoption}`
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
elizaLogger.info(`- Market trends identified: ${trendsFound.join(', ')}`);
|
|
742
|
+
elizaLogger.info(`- Comparative analysis found: ${hasComparisons}`);
|
|
743
|
+
elizaLogger.info(`- Use cases documented: ${useCases.length}`);
|
|
744
|
+
|
|
745
|
+
// Strategic insights
|
|
746
|
+
const wellCoveredCompetitors = Object.entries(competitorData)
|
|
747
|
+
.filter(([_, data]) => data.mentions >= 2)
|
|
748
|
+
.map(([name, _]) => name);
|
|
749
|
+
|
|
750
|
+
const hasComprehensiveData =
|
|
751
|
+
wellCoveredCompetitors.length >= 2 && hasComparisons && useCases.length > 0;
|
|
752
|
+
|
|
753
|
+
if (hasComprehensiveData) {
|
|
754
|
+
elizaLogger.success('✅ Comprehensive market intelligence gathered');
|
|
755
|
+
elizaLogger.info(
|
|
756
|
+
`Key competitors analyzed: ${wellCoveredCompetitors.join(', ')}`
|
|
757
|
+
);
|
|
758
|
+
} else {
|
|
759
|
+
elizaLogger.info(
|
|
760
|
+
'ℹ️ Partial market intelligence - consider additional research'
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
elizaLogger.success('✅ Real-World Test Passed: Market Intelligence Research');
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Test 5: Technical Problem Solving Research (Real Developer Debug Workflow)
|
|
768
|
+
export async function testProblemSolvingResearch(
|
|
769
|
+
runtime: IAgentRuntime
|
|
770
|
+
): Promise<void> {
|
|
771
|
+
elizaLogger.info(
|
|
772
|
+
'🔧 Starting Real-World Test: Technical Problem Solving Research'
|
|
773
|
+
);
|
|
774
|
+
|
|
775
|
+
const service = runtime.getService<ResearchService>('research');
|
|
776
|
+
if (!service) throw new Error('Research service not available');
|
|
777
|
+
|
|
778
|
+
// Scenario: Debugging a complex technical issue
|
|
779
|
+
const problemQuery =
|
|
780
|
+
'TypeError cannot read property undefined JavaScript async await Promise debugging stack trace fix';
|
|
781
|
+
|
|
782
|
+
const project = await service.createResearchProject(problemQuery, {
|
|
783
|
+
maxSearchResults: 4,
|
|
784
|
+
metadata: {
|
|
785
|
+
researchType: 'debugging',
|
|
786
|
+
problemType: 'runtime_error',
|
|
787
|
+
technology: 'JavaScript',
|
|
788
|
+
},
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
elizaLogger.info('Researching technical problem solutions...');
|
|
792
|
+
|
|
793
|
+
const result = await monitorResearch(service, project.id, {
|
|
794
|
+
timeout: 120000,
|
|
795
|
+
onProgress: (p) => {
|
|
796
|
+
// Look for Stack Overflow as it appears
|
|
797
|
+
const hasStackOverflow = p.sources.some((s) =>
|
|
798
|
+
s.url.includes('stackoverflow.com')
|
|
799
|
+
);
|
|
800
|
+
if (hasStackOverflow && p.sources.length === 1) {
|
|
801
|
+
elizaLogger.info('Found Stack Overflow - good sign for debugging!');
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
if (!result) throw new Error('Problem solving research failed to complete');
|
|
807
|
+
|
|
808
|
+
// Analyze debugging findings
|
|
809
|
+
const findings = result.findings;
|
|
810
|
+
const sources = result.sources;
|
|
811
|
+
|
|
812
|
+
// Categorize sources
|
|
813
|
+
const debuggingSources = {
|
|
814
|
+
stackoverflow: sources.filter((s) => s.url.includes('stackoverflow.com')),
|
|
815
|
+
github: sources.filter((s) => s.url.includes('github.com')),
|
|
816
|
+
documentation: sources.filter(
|
|
817
|
+
(s) =>
|
|
818
|
+
s.url.includes('developer.mozilla.org') ||
|
|
819
|
+
s.url.includes('javascript.info') ||
|
|
820
|
+
s.url.includes('docs.')
|
|
821
|
+
),
|
|
822
|
+
blogs: sources.filter(
|
|
823
|
+
(s) =>
|
|
824
|
+
s.url.includes('blog') ||
|
|
825
|
+
s.url.includes('medium.com') ||
|
|
826
|
+
s.url.includes('dev.to')
|
|
827
|
+
),
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
// Look for solutions
|
|
831
|
+
const hasSolutions = findings.filter((f) => {
|
|
832
|
+
const content = f.content.toLowerCase();
|
|
833
|
+
return (
|
|
834
|
+
content.includes('solution') ||
|
|
835
|
+
content.includes('fix') ||
|
|
836
|
+
content.includes('resolve') ||
|
|
837
|
+
content.includes('solved') ||
|
|
838
|
+
content.includes('work')
|
|
839
|
+
);
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
// Look for code examples
|
|
843
|
+
const hasCodeExamples = findings.filter((f) => {
|
|
844
|
+
const content = f.content;
|
|
845
|
+
return (
|
|
846
|
+
content.includes('```') ||
|
|
847
|
+
content.includes('const ') ||
|
|
848
|
+
content.includes('let ') ||
|
|
849
|
+
content.includes('function') ||
|
|
850
|
+
content.includes('async ') ||
|
|
851
|
+
content.includes('await ') ||
|
|
852
|
+
content.includes('try') ||
|
|
853
|
+
content.includes('catch')
|
|
854
|
+
);
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
// Look for explanations
|
|
858
|
+
const hasExplanations = findings.filter((f) => {
|
|
859
|
+
const content = f.content.toLowerCase();
|
|
860
|
+
return (
|
|
861
|
+
content.includes('because') ||
|
|
862
|
+
content.includes('reason') ||
|
|
863
|
+
content.includes('cause') ||
|
|
864
|
+
content.includes('happen') ||
|
|
865
|
+
content.includes('occur')
|
|
866
|
+
);
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
// Check for similar issues
|
|
870
|
+
const similarIssues = findings.filter((f) => {
|
|
871
|
+
const content = f.content.toLowerCase();
|
|
872
|
+
return (
|
|
873
|
+
content.includes('similar') ||
|
|
874
|
+
content.includes('same error') ||
|
|
875
|
+
content.includes('same issue') ||
|
|
876
|
+
content.includes('also')
|
|
877
|
+
);
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
elizaLogger.info('🔍 Problem Solving Research Results:');
|
|
881
|
+
elizaLogger.info('- Source distribution:');
|
|
882
|
+
elizaLogger.info(
|
|
883
|
+
` * Stack Overflow: ${debuggingSources.stackoverflow.length}`
|
|
884
|
+
);
|
|
885
|
+
elizaLogger.info(` * GitHub Issues: ${debuggingSources.github.length}`);
|
|
886
|
+
elizaLogger.info(
|
|
887
|
+
` * Documentation: ${debuggingSources.documentation.length}`
|
|
888
|
+
);
|
|
889
|
+
elizaLogger.info(` * Technical Blogs: ${debuggingSources.blogs.length}`);
|
|
890
|
+
elizaLogger.info(`- Solutions found: ${hasSolutions.length}`);
|
|
891
|
+
elizaLogger.info(`- Code examples: ${hasCodeExamples.length}`);
|
|
892
|
+
elizaLogger.info(`- Explanations: ${hasExplanations.length}`);
|
|
893
|
+
elizaLogger.info(`- Similar issues: ${similarIssues.length}`);
|
|
894
|
+
|
|
895
|
+
// Extract a solution if found
|
|
896
|
+
if (hasSolutions.length > 0 && hasCodeExamples.length > 0) {
|
|
897
|
+
elizaLogger.success('✅ Found solutions with code examples!');
|
|
898
|
+
|
|
899
|
+
// Find the most relevant solution
|
|
900
|
+
const bestSolution = hasSolutions.sort((a, b) => b.relevance - a.relevance)[0];
|
|
901
|
+
const preview = bestSolution.content.substring(0, 250);
|
|
902
|
+
elizaLogger.info(`Top solution preview: "${preview}..."`);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Problem solving quality
|
|
906
|
+
const hasGoodSources =
|
|
907
|
+
debuggingSources.stackoverflow.length > 0 ||
|
|
908
|
+
debuggingSources.documentation.length > 0;
|
|
909
|
+
const hasGoodContent =
|
|
910
|
+
hasSolutions.length > 0 && hasCodeExamples.length > 0;
|
|
911
|
+
const hasContext = hasExplanations.length > 0;
|
|
912
|
+
|
|
913
|
+
if (hasGoodSources && hasGoodContent && hasContext) {
|
|
914
|
+
elizaLogger.success('✅ Comprehensive debugging information found');
|
|
915
|
+
} else {
|
|
916
|
+
elizaLogger.info(
|
|
917
|
+
`ℹ️ Debugging info: Sources=${hasGoodSources}, Solutions=${hasGoodContent}, Context=${hasContext}`
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
elizaLogger.success(
|
|
922
|
+
'✅ Real-World Test Passed: Technical Problem Solving Research'
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// Test 6: Academic/Learning Research (Real Student/Researcher Workflow)
|
|
927
|
+
export async function testAcademicResearch(runtime: IAgentRuntime): Promise<void> {
|
|
928
|
+
elizaLogger.info('🎓 Starting Real-World Test: Academic/Learning Research');
|
|
929
|
+
|
|
930
|
+
const service = runtime.getService<ResearchService>('research');
|
|
931
|
+
if (!service) throw new Error('Research service not available');
|
|
932
|
+
|
|
933
|
+
// Scenario: Researching for learning/academic purposes
|
|
934
|
+
const academicQuery =
|
|
935
|
+
'transformer architecture attention mechanism self-attention tutorial papers implementation from scratch';
|
|
936
|
+
|
|
937
|
+
const project = await service.createResearchProject(academicQuery, {
|
|
938
|
+
maxSearchResults: 5,
|
|
939
|
+
metadata: {
|
|
940
|
+
researchType: 'academic',
|
|
941
|
+
subject: 'machine_learning',
|
|
942
|
+
level: 'advanced',
|
|
943
|
+
},
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
elizaLogger.info(
|
|
947
|
+
'Conducting academic research on transformer architecture...'
|
|
948
|
+
);
|
|
949
|
+
|
|
950
|
+
const result = await monitorResearch(service, project.id, {
|
|
951
|
+
timeout: 150000,
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
if (!result) throw new Error('Academic research failed to complete');
|
|
955
|
+
|
|
956
|
+
// Analyze academic findings
|
|
957
|
+
const findings = result.findings;
|
|
958
|
+
const sources = result.sources;
|
|
959
|
+
|
|
960
|
+
// Categorize academic sources
|
|
961
|
+
const academicSources = {
|
|
962
|
+
papers: sources.filter(
|
|
963
|
+
(s) =>
|
|
964
|
+
s.url.includes('arxiv.org') ||
|
|
965
|
+
s.url.includes('paper') ||
|
|
966
|
+
s.url.includes('pdf') ||
|
|
967
|
+
s.title.toLowerCase().includes('paper')
|
|
968
|
+
),
|
|
969
|
+
tutorials: sources.filter(
|
|
970
|
+
(s) =>
|
|
971
|
+
s.url.includes('tutorial') ||
|
|
972
|
+
s.url.includes('guide') ||
|
|
973
|
+
s.url.includes('explained') ||
|
|
974
|
+
s.title.toLowerCase().includes('tutorial')
|
|
975
|
+
),
|
|
976
|
+
educational: sources.filter(
|
|
977
|
+
(s) =>
|
|
978
|
+
s.url.includes('edu') ||
|
|
979
|
+
s.url.includes('course') ||
|
|
980
|
+
s.url.includes('stanford') ||
|
|
981
|
+
s.url.includes('mit')
|
|
982
|
+
),
|
|
983
|
+
implementation: sources.filter(
|
|
984
|
+
(s) =>
|
|
985
|
+
s.url.includes('github.com') ||
|
|
986
|
+
s.url.includes('colab') ||
|
|
987
|
+
s.url.includes('kaggle')
|
|
988
|
+
),
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
// Look for key concepts
|
|
992
|
+
const concepts = [
|
|
993
|
+
'attention',
|
|
994
|
+
'self-attention',
|
|
995
|
+
'multi-head',
|
|
996
|
+
'query',
|
|
997
|
+
'key',
|
|
998
|
+
'value',
|
|
999
|
+
'transformer',
|
|
1000
|
+
];
|
|
1001
|
+
const conceptCoverage: Record<string, number> = {};
|
|
1002
|
+
|
|
1003
|
+
concepts.forEach((concept) => {
|
|
1004
|
+
conceptCoverage[concept] = findings.filter((f) =>
|
|
1005
|
+
f.content.toLowerCase().includes(concept)
|
|
1006
|
+
).length;
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
// Check for mathematical content
|
|
1010
|
+
const hasMath = findings.some((f) => {
|
|
1011
|
+
const content = f.content;
|
|
1012
|
+
return (
|
|
1013
|
+
content.includes('equation') ||
|
|
1014
|
+
content.includes('formula') ||
|
|
1015
|
+
content.includes('Σ') ||
|
|
1016
|
+
content.includes('matrix') ||
|
|
1017
|
+
content.includes('dimension')
|
|
1018
|
+
);
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
// Check for visual explanations
|
|
1022
|
+
const hasVisuals = findings.some((f) => {
|
|
1023
|
+
const content = f.content.toLowerCase();
|
|
1024
|
+
return (
|
|
1025
|
+
content.includes('diagram') ||
|
|
1026
|
+
content.includes('figure') ||
|
|
1027
|
+
content.includes('image') ||
|
|
1028
|
+
content.includes('illustration') ||
|
|
1029
|
+
content.includes('visualization')
|
|
1030
|
+
);
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
// Check for code implementations
|
|
1034
|
+
const hasImplementations = findings.filter((f) => {
|
|
1035
|
+
const content = f.content;
|
|
1036
|
+
return (
|
|
1037
|
+
content.includes('class Transformer') ||
|
|
1038
|
+
content.includes('class Attention') ||
|
|
1039
|
+
content.includes('def attention') ||
|
|
1040
|
+
content.includes('import torch') ||
|
|
1041
|
+
content.includes('import tensorflow')
|
|
1042
|
+
);
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
elizaLogger.info('📚 Academic Research Results:');
|
|
1046
|
+
elizaLogger.info('- Source types:');
|
|
1047
|
+
elizaLogger.info(` * Academic papers: ${academicSources.papers.length}`);
|
|
1048
|
+
elizaLogger.info(
|
|
1049
|
+
` * Tutorials/Guides: ${academicSources.tutorials.length}`
|
|
1050
|
+
);
|
|
1051
|
+
elizaLogger.info(
|
|
1052
|
+
` * Educational institutions: ${academicSources.educational.length}`
|
|
1053
|
+
);
|
|
1054
|
+
elizaLogger.info(
|
|
1055
|
+
` * Code implementations: ${academicSources.implementation.length}`
|
|
1056
|
+
);
|
|
1057
|
+
elizaLogger.info('- Concept coverage:');
|
|
1058
|
+
Object.entries(conceptCoverage).forEach(([concept, count]) => {
|
|
1059
|
+
if (count > 0) elizaLogger.info(` * ${concept}: ${count} mentions`);
|
|
1060
|
+
});
|
|
1061
|
+
elizaLogger.info(`- Mathematical content: ${hasMath}`);
|
|
1062
|
+
elizaLogger.info(`- Visual explanations: ${hasVisuals}`);
|
|
1063
|
+
elizaLogger.info(
|
|
1064
|
+
`- Code implementations found: ${hasImplementations.length}`
|
|
1065
|
+
);
|
|
1066
|
+
|
|
1067
|
+
// Learning quality assessment
|
|
1068
|
+
const hasTheory =
|
|
1069
|
+
academicSources.papers.length > 0 ||
|
|
1070
|
+
Object.values(conceptCoverage).some((c) => c > 2);
|
|
1071
|
+
const hasPractice =
|
|
1072
|
+
academicSources.tutorials.length > 0 || hasImplementations.length > 0;
|
|
1073
|
+
const conceptsCovered = Object.values(conceptCoverage).filter(
|
|
1074
|
+
(c) => c > 0
|
|
1075
|
+
).length;
|
|
1076
|
+
|
|
1077
|
+
if (hasTheory && hasPractice && conceptsCovered >= 4) {
|
|
1078
|
+
elizaLogger.success(
|
|
1079
|
+
'✅ Excellent academic research - covers theory and practice'
|
|
1080
|
+
);
|
|
1081
|
+
} else {
|
|
1082
|
+
elizaLogger.info(
|
|
1083
|
+
`ℹ️ Academic coverage: Theory=${hasTheory}, Practice=${hasPractice}, Concepts=${conceptsCovered}/7`
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
elizaLogger.success('✅ Real-World Test Passed: Academic/Learning Research');
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// #endregion
|
|
1091
|
+
|
|
1092
|
+
// #region: Core Functionality Scenarios
|
|
1093
|
+
|
|
1094
|
+
// Test 1: Code/Feature Research - Simulating research before building a feature
|
|
1095
|
+
export async function testCodeFeatureResearch(
|
|
1096
|
+
runtime: IAgentRuntime
|
|
1097
|
+
): Promise<void> {
|
|
1098
|
+
elizaLogger.info('Starting E2E Test: Code/Feature Research');
|
|
1099
|
+
|
|
1100
|
+
const service = runtime.getService<ResearchService>('research');
|
|
1101
|
+
if (!service) {
|
|
1102
|
+
throw new Error('Research service not available');
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// Research query that a developer would make before implementing a feature
|
|
1106
|
+
const featureQuery =
|
|
1107
|
+
'How to implement OAuth2 authentication in Node.js with TypeScript best practices security 2024';
|
|
1108
|
+
|
|
1109
|
+
const project = await service.createResearchProject(featureQuery, {
|
|
1110
|
+
maxSearchResults: 5,
|
|
1111
|
+
language: 'en',
|
|
1112
|
+
metadata: {
|
|
1113
|
+
researchType: 'technical',
|
|
1114
|
+
purpose: 'feature_implementation',
|
|
1115
|
+
},
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
elizaLogger.info(`Created code research project: ${project.id}`);
|
|
1119
|
+
|
|
1120
|
+
// Monitor progress
|
|
1121
|
+
let lastUpdate = Date.now();
|
|
1122
|
+
let phaseProgress: Record<string, number> = {};
|
|
1123
|
+
|
|
1124
|
+
const checkProgress = setInterval(async () => {
|
|
1125
|
+
const current = await service.getProject(project.id);
|
|
1126
|
+
if (!current) return;
|
|
1127
|
+
|
|
1128
|
+
if (!phaseProgress[current.phase]) {
|
|
1129
|
+
phaseProgress[current.phase] = Date.now() - lastUpdate;
|
|
1130
|
+
elizaLogger.info(
|
|
1131
|
+
`Phase ${current.phase} started after ${phaseProgress[current.phase]}ms`
|
|
1132
|
+
);
|
|
1133
|
+
lastUpdate = Date.now();
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
if (
|
|
1137
|
+
current.status === ResearchStatus.COMPLETED ||
|
|
1138
|
+
current.status === ResearchStatus.FAILED
|
|
1139
|
+
) {
|
|
1140
|
+
clearInterval(checkProgress);
|
|
1141
|
+
}
|
|
1142
|
+
}, 3000);
|
|
1143
|
+
|
|
1144
|
+
// Wait for completion
|
|
1145
|
+
const completed = await waitForResearchCompletion(service, project.id, 180000);
|
|
1146
|
+
clearInterval(checkProgress);
|
|
1147
|
+
|
|
1148
|
+
if (!completed) {
|
|
1149
|
+
throw new Error('Code research did not complete within timeout');
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
const finalProject = await service.getProject(project.id);
|
|
1153
|
+
if (!finalProject) {
|
|
1154
|
+
throw new Error('Could not retrieve completed project');
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// Validate research quality
|
|
1158
|
+
const quality = validateResearchQuality(finalProject);
|
|
1159
|
+
if (!quality.isValid) {
|
|
1160
|
+
elizaLogger.warn(`Research quality issues: ${quality.issues.join(', ')}`);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
// Verify we found technical content
|
|
1164
|
+
const hasCodeExamples = finalProject.findings.some(
|
|
1165
|
+
(f) =>
|
|
1166
|
+
f.content.includes('npm') ||
|
|
1167
|
+
f.content.includes('const') ||
|
|
1168
|
+
f.content.includes('import') ||
|
|
1169
|
+
f.content.includes('OAuth')
|
|
1170
|
+
);
|
|
1171
|
+
|
|
1172
|
+
if (!hasCodeExamples) {
|
|
1173
|
+
elizaLogger.warn('No code examples found in technical research');
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
// Check for security considerations (important for auth research)
|
|
1177
|
+
const hasSecurityInfo = finalProject.findings.some(
|
|
1178
|
+
(f) =>
|
|
1179
|
+
f.content.toLowerCase().includes('security') ||
|
|
1180
|
+
f.content.toLowerCase().includes('csrf') ||
|
|
1181
|
+
f.content.toLowerCase().includes('token')
|
|
1182
|
+
);
|
|
1183
|
+
|
|
1184
|
+
if (!hasSecurityInfo) {
|
|
1185
|
+
elizaLogger.warn('No security information found in OAuth research');
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
elizaLogger.info(
|
|
1189
|
+
`Code research completed with ${finalProject.sources.length} sources and ${finalProject.findings.length} findings`
|
|
1190
|
+
);
|
|
1191
|
+
elizaLogger.info(
|
|
1192
|
+
`Found code examples: ${hasCodeExamples}, Security info: ${hasSecurityInfo}`
|
|
1193
|
+
);
|
|
1194
|
+
|
|
1195
|
+
if (finalProject.report) {
|
|
1196
|
+
elizaLogger.info(
|
|
1197
|
+
`Report generated with ${finalProject.report.sections.length} sections`
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
elizaLogger.success('E2E Test Passed: Code/Feature Research');
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// Test 2: Person Research - Researching a public figure
|
|
1205
|
+
export async function testPersonResearch(runtime: IAgentRuntime): Promise<void> {
|
|
1206
|
+
elizaLogger.info('Starting E2E Test: Person Research');
|
|
1207
|
+
|
|
1208
|
+
const service = runtime.getService<ResearchService>('research');
|
|
1209
|
+
if (!service) {
|
|
1210
|
+
throw new Error('Research service not available');
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// Research a well-known tech figure
|
|
1214
|
+
const personQuery =
|
|
1215
|
+
'Vitalik Buterin Ethereum founder recent projects writings 2024';
|
|
1216
|
+
|
|
1217
|
+
const project = await service.createResearchProject(personQuery, {
|
|
1218
|
+
maxSearchResults: 4,
|
|
1219
|
+
metadata: {
|
|
1220
|
+
researchType: 'person',
|
|
1221
|
+
purpose: 'background_research',
|
|
1222
|
+
},
|
|
1223
|
+
});
|
|
1224
|
+
|
|
1225
|
+
elizaLogger.info(`Created person research project: ${project.id}`);
|
|
1226
|
+
|
|
1227
|
+
// Wait for completion
|
|
1228
|
+
const completed = await waitForResearchCompletion(service, project.id, 150000);
|
|
1229
|
+
|
|
1230
|
+
if (!completed) {
|
|
1231
|
+
const partial = await service.getProject(project.id);
|
|
1232
|
+
if (partial && partial.findings.length > 0) {
|
|
1233
|
+
elizaLogger.warn(
|
|
1234
|
+
`Person research incomplete but found ${partial.findings.length} findings`
|
|
1235
|
+
);
|
|
1236
|
+
} else {
|
|
1237
|
+
throw new Error('Person research did not complete and no findings collected');
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
const finalProject = await service.getProject(project.id);
|
|
1242
|
+
if (!finalProject) {
|
|
1243
|
+
throw new Error('Could not retrieve completed project');
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// Validate we found relevant information about the person
|
|
1247
|
+
const relevantFindings = finalProject.findings.filter(
|
|
1248
|
+
(f) =>
|
|
1249
|
+
f.content.toLowerCase().includes('vitalik') ||
|
|
1250
|
+
f.content.toLowerCase().includes('ethereum') ||
|
|
1251
|
+
f.content.toLowerCase().includes('buterin')
|
|
1252
|
+
);
|
|
1253
|
+
|
|
1254
|
+
if (relevantFindings.length === 0) {
|
|
1255
|
+
throw new Error('No relevant findings about the person');
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
// Check for recent information
|
|
1259
|
+
const hasRecentInfo = finalProject.findings.some(
|
|
1260
|
+
(f) =>
|
|
1261
|
+
f.content.includes('2024') ||
|
|
1262
|
+
f.content.includes('2023') ||
|
|
1263
|
+
f.content.toLowerCase().includes('recent')
|
|
1264
|
+
);
|
|
1265
|
+
|
|
1266
|
+
elizaLogger.info(
|
|
1267
|
+
`Person research completed: ${relevantFindings.length}/${finalProject.findings.length} relevant findings`
|
|
1268
|
+
);
|
|
1269
|
+
elizaLogger.info(`Found recent information: ${hasRecentInfo}`);
|
|
1270
|
+
|
|
1271
|
+
// Sample a finding
|
|
1272
|
+
if (relevantFindings.length > 0) {
|
|
1273
|
+
const sample = relevantFindings[0].content.substring(0, 200);
|
|
1274
|
+
elizaLogger.info(`Sample finding: "${sample}..."`);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
elizaLogger.success('E2E Test Passed: Person Research');
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
// Test 3: News/Current Events Research
|
|
1281
|
+
export async function testNewsResearch(runtime: IAgentRuntime): Promise<void> {
|
|
1282
|
+
elizaLogger.info('Starting E2E Test: News/Current Events Research');
|
|
1283
|
+
|
|
1284
|
+
const service = runtime.getService<ResearchService>('research');
|
|
1285
|
+
if (!service) {
|
|
1286
|
+
throw new Error('Research service not available');
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
// Research current AI developments
|
|
1290
|
+
const newsQuery =
|
|
1291
|
+
'latest artificial intelligence breakthroughs news December 2024 ChatGPT Claude Gemini';
|
|
1292
|
+
|
|
1293
|
+
const project = await service.createResearchProject(newsQuery, {
|
|
1294
|
+
maxSearchResults: 5,
|
|
1295
|
+
metadata: {
|
|
1296
|
+
researchType: 'news',
|
|
1297
|
+
timeframe: 'current',
|
|
1298
|
+
purpose: 'market_intelligence',
|
|
1299
|
+
},
|
|
1300
|
+
});
|
|
1301
|
+
|
|
1302
|
+
elizaLogger.info(`Created news research project: ${project.id}`);
|
|
1303
|
+
|
|
1304
|
+
// Monitor for news-specific content
|
|
1305
|
+
let checkCount = 0;
|
|
1306
|
+
const newsCheckInterval = setInterval(async () => {
|
|
1307
|
+
checkCount++;
|
|
1308
|
+
const current = await service.getProject(project.id);
|
|
1309
|
+
if (!current) return;
|
|
1310
|
+
|
|
1311
|
+
// Check if we're finding news sources
|
|
1312
|
+
const newsSource = current.sources.find(
|
|
1313
|
+
(s) =>
|
|
1314
|
+
s.url.includes('news') ||
|
|
1315
|
+
s.url.includes('article') ||
|
|
1316
|
+
s.url.includes('blog') ||
|
|
1317
|
+
s.title.toLowerCase().includes('2024')
|
|
1318
|
+
);
|
|
1319
|
+
|
|
1320
|
+
if (newsSource && checkCount === 1) {
|
|
1321
|
+
elizaLogger.info(`Found news source: ${newsSource.title}`);
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
if (
|
|
1325
|
+
current.status === ResearchStatus.COMPLETED ||
|
|
1326
|
+
current.status === ResearchStatus.FAILED ||
|
|
1327
|
+
checkCount > 30
|
|
1328
|
+
) {
|
|
1329
|
+
clearInterval(newsCheckInterval);
|
|
1330
|
+
}
|
|
1331
|
+
}, 5000);
|
|
1332
|
+
|
|
1333
|
+
// Wait for completion
|
|
1334
|
+
const completed = await waitForResearchCompletion(service, project.id, 180000);
|
|
1335
|
+
clearInterval(newsCheckInterval);
|
|
1336
|
+
|
|
1337
|
+
const finalProject = await service.getProject(project.id);
|
|
1338
|
+
if (!finalProject) {
|
|
1339
|
+
throw new Error('Could not retrieve completed project');
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
// Validate news research quality
|
|
1343
|
+
const quality = validateResearchQuality(finalProject);
|
|
1344
|
+
|
|
1345
|
+
// Check for AI-related content
|
|
1346
|
+
const aiFindings = finalProject.findings.filter((f) => {
|
|
1347
|
+
const content = f.content.toLowerCase();
|
|
1348
|
+
return (
|
|
1349
|
+
content.includes('ai') ||
|
|
1350
|
+
content.includes('artificial intelligence') ||
|
|
1351
|
+
content.includes('chatgpt') ||
|
|
1352
|
+
content.includes('claude') ||
|
|
1353
|
+
content.includes('gemini') ||
|
|
1354
|
+
content.includes('machine learning')
|
|
1355
|
+
);
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1358
|
+
if (aiFindings.length === 0) {
|
|
1359
|
+
elizaLogger.warn('No AI-related findings in news research');
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
// Check for recent dates
|
|
1363
|
+
const hasRecentDates = finalProject.findings.some((f) => {
|
|
1364
|
+
const content = f.content;
|
|
1365
|
+
return (
|
|
1366
|
+
content.includes('2024') ||
|
|
1367
|
+
content.includes('December') ||
|
|
1368
|
+
content.includes('November') ||
|
|
1369
|
+
content.includes('recent')
|
|
1370
|
+
);
|
|
1371
|
+
});
|
|
1372
|
+
|
|
1373
|
+
elizaLogger.info(
|
|
1374
|
+
`News research completed: ${aiFindings.length} AI-related findings out of ${finalProject.findings.length} total`
|
|
1375
|
+
);
|
|
1376
|
+
elizaLogger.info(`Contains recent dates: ${hasRecentDates}`);
|
|
1377
|
+
elizaLogger.info(
|
|
1378
|
+
`Research quality: ${
|
|
1379
|
+
quality.isValid ? 'Good' : 'Issues: ' + quality.issues.join(', ')
|
|
1380
|
+
}`
|
|
1381
|
+
);
|
|
1382
|
+
|
|
1383
|
+
elizaLogger.success('E2E Test Passed: News/Current Events Research');
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
// Test 4: Technical Documentation Research
|
|
1387
|
+
export async function testDocumentationResearch(
|
|
1388
|
+
runtime: IAgentRuntime
|
|
1389
|
+
): Promise<void> {
|
|
1390
|
+
elizaLogger.info('Starting E2E Test: Technical Documentation Research');
|
|
1391
|
+
|
|
1392
|
+
const service = runtime.getService<ResearchService>('research');
|
|
1393
|
+
if (!service) {
|
|
1394
|
+
throw new Error('Research service not available');
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
// Research technical documentation
|
|
1398
|
+
const docQuery =
|
|
1399
|
+
'React Server Components documentation examples best practices performance optimization';
|
|
1400
|
+
|
|
1401
|
+
const project = await service.createResearchProject(docQuery, {
|
|
1402
|
+
maxSearchResults: 4,
|
|
1403
|
+
metadata: {
|
|
1404
|
+
researchType: 'documentation',
|
|
1405
|
+
purpose: 'learning',
|
|
1406
|
+
},
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1409
|
+
elizaLogger.info(`Created documentation research project: ${project.id}`);
|
|
1410
|
+
|
|
1411
|
+
// Wait for completion
|
|
1412
|
+
const completed = await waitForResearchCompletion(service, project.id, 150000);
|
|
1413
|
+
|
|
1414
|
+
const finalProject = await service.getProject(project.id);
|
|
1415
|
+
if (!finalProject) {
|
|
1416
|
+
throw new Error('Could not retrieve completed project');
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
// Check for documentation-specific content
|
|
1420
|
+
const hasDocSources = finalProject.sources.some(
|
|
1421
|
+
(s) =>
|
|
1422
|
+
s.url.includes('react.dev') ||
|
|
1423
|
+
s.url.includes('docs') ||
|
|
1424
|
+
s.url.includes('documentation') ||
|
|
1425
|
+
s.url.includes('github.com')
|
|
1426
|
+
);
|
|
1427
|
+
|
|
1428
|
+
const hasCodeExamples = finalProject.findings.some(
|
|
1429
|
+
(f) =>
|
|
1430
|
+
f.content.includes('```') ||
|
|
1431
|
+
f.content.includes('<') ||
|
|
1432
|
+
f.content.includes('/>') ||
|
|
1433
|
+
f.content.includes('function') ||
|
|
1434
|
+
f.content.includes('const')
|
|
1435
|
+
);
|
|
1436
|
+
|
|
1437
|
+
const hasBestPractices = finalProject.findings.some(
|
|
1438
|
+
(f) =>
|
|
1439
|
+
f.content.toLowerCase().includes('best practice') ||
|
|
1440
|
+
f.content.toLowerCase().includes('recommendation') ||
|
|
1441
|
+
f.content.toLowerCase().includes('should') ||
|
|
1442
|
+
f.content.toLowerCase().includes('avoid')
|
|
1443
|
+
);
|
|
1444
|
+
|
|
1445
|
+
elizaLogger.info(`Documentation research completed:`);
|
|
1446
|
+
elizaLogger.info(`- Found documentation sources: ${hasDocSources}`);
|
|
1447
|
+
elizaLogger.info(`- Contains code examples: ${hasCodeExamples}`);
|
|
1448
|
+
elizaLogger.info(`- Includes best practices: ${hasBestPractices}`);
|
|
1449
|
+
elizaLogger.info(`- Total findings: ${finalProject.findings.length}`);
|
|
1450
|
+
|
|
1451
|
+
elizaLogger.success('E2E Test Passed: Technical Documentation Research');
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// Test 5: Competitive Analysis Research
|
|
1455
|
+
export async function testCompetitiveAnalysis(
|
|
1456
|
+
runtime: IAgentRuntime
|
|
1457
|
+
): Promise<void> {
|
|
1458
|
+
elizaLogger.info('Starting E2E Test: Competitive Analysis Research');
|
|
1459
|
+
|
|
1460
|
+
const service = runtime.getService<ResearchService>('research');
|
|
1461
|
+
if (!service) {
|
|
1462
|
+
throw new Error('Research service not available');
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
// Research competitors in the AI agent space
|
|
1466
|
+
const competitorQuery =
|
|
1467
|
+
'AI agent frameworks comparison AutoGPT BabyAGI LangChain CrewAI features pricing';
|
|
1468
|
+
|
|
1469
|
+
const project = await service.createResearchProject(competitorQuery, {
|
|
1470
|
+
maxSearchResults: 5,
|
|
1471
|
+
metadata: {
|
|
1472
|
+
researchType: 'competitive_analysis',
|
|
1473
|
+
purpose: 'market_research',
|
|
1474
|
+
},
|
|
1475
|
+
});
|
|
1476
|
+
|
|
1477
|
+
elizaLogger.info(`Created competitive analysis project: ${project.id}`);
|
|
1478
|
+
|
|
1479
|
+
// Wait for completion
|
|
1480
|
+
const completed = await waitForResearchCompletion(service, project.id, 180000);
|
|
1481
|
+
|
|
1482
|
+
const finalProject = await service.getProject(project.id);
|
|
1483
|
+
if (!finalProject) {
|
|
1484
|
+
throw new Error('Could not retrieve completed project');
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
// Check for competitor mentions
|
|
1488
|
+
const competitors = ['AutoGPT', 'BabyAGI', 'LangChain', 'CrewAI'];
|
|
1489
|
+
const competitorMentions: Record<string, number> = {};
|
|
1490
|
+
|
|
1491
|
+
competitors.forEach((competitor) => {
|
|
1492
|
+
competitorMentions[competitor] = finalProject.findings.filter((f) =>
|
|
1493
|
+
f.content.toLowerCase().includes(competitor.toLowerCase())
|
|
1494
|
+
).length;
|
|
1495
|
+
});
|
|
1496
|
+
|
|
1497
|
+
const totalMentions = Object.values(competitorMentions).reduce(
|
|
1498
|
+
(a, b) => a + b,
|
|
1499
|
+
0
|
|
1500
|
+
);
|
|
1501
|
+
|
|
1502
|
+
// Check for comparison content
|
|
1503
|
+
const hasComparison = finalProject.findings.some((f) => {
|
|
1504
|
+
const content = f.content.toLowerCase();
|
|
1505
|
+
return (
|
|
1506
|
+
content.includes('compar') ||
|
|
1507
|
+
content.includes('versus') ||
|
|
1508
|
+
content.includes('vs') ||
|
|
1509
|
+
content.includes('better') ||
|
|
1510
|
+
content.includes('advantage')
|
|
1511
|
+
);
|
|
1512
|
+
});
|
|
1513
|
+
|
|
1514
|
+
// Check for feature analysis
|
|
1515
|
+
const hasFeatures = finalProject.findings.some((f) => {
|
|
1516
|
+
const content = f.content.toLowerCase();
|
|
1517
|
+
return (
|
|
1518
|
+
content.includes('feature') ||
|
|
1519
|
+
content.includes('capability') ||
|
|
1520
|
+
content.includes('functionality') ||
|
|
1521
|
+
content.includes('support')
|
|
1522
|
+
);
|
|
1523
|
+
});
|
|
1524
|
+
|
|
1525
|
+
elizaLogger.info(`Competitive analysis completed:`);
|
|
1526
|
+
elizaLogger.info(
|
|
1527
|
+
`- Competitor mentions: ${JSON.stringify(competitorMentions)}`
|
|
1528
|
+
);
|
|
1529
|
+
elizaLogger.info(`- Total competitor mentions: ${totalMentions}`);
|
|
1530
|
+
elizaLogger.info(`- Contains comparisons: ${hasComparison}`);
|
|
1531
|
+
elizaLogger.info(`- Analyzes features: ${hasFeatures}`);
|
|
1532
|
+
|
|
1533
|
+
if (totalMentions < 2) {
|
|
1534
|
+
elizaLogger.warn('Limited competitor information found');
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
elizaLogger.success('E2E Test Passed: Competitive Analysis Research');
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
// Test 6: DeFi Research Integration
|
|
1541
|
+
export async function testDeFiResearch(runtime: IAgentRuntime): Promise<void> {
|
|
1542
|
+
elizaLogger.info('Starting E2E Test: DeFi Research Integration');
|
|
1543
|
+
|
|
1544
|
+
const service = runtime.getService<ResearchService>('research');
|
|
1545
|
+
if (!service) {
|
|
1546
|
+
throw new Error('Research service not available');
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
// Import DeFi action to test
|
|
1550
|
+
const { defiSecurityResearchAction } = await import(
|
|
1551
|
+
'../actions/defi-actions'
|
|
1552
|
+
);
|
|
1553
|
+
|
|
1554
|
+
// Create a mock message for DeFi research
|
|
1555
|
+
const mockMessage: Memory = {
|
|
1556
|
+
id: '00000000-0000-0000-0000-000000000001' as `${string}-${string}-${string}-${string}-${string}`,
|
|
1557
|
+
entityId: '00000000-0000-0000-0000-000000000002' as `${string}-${string}-${string}-${string}-${string}`,
|
|
1558
|
+
roomId: '00000000-0000-0000-0000-000000000003' as `${string}-${string}-${string}-${string}-${string}`,
|
|
1559
|
+
content: {
|
|
1560
|
+
text: 'Research smart contract security vulnerabilities and audit best practices for DeFi protocols',
|
|
1561
|
+
},
|
|
1562
|
+
createdAt: Date.now(),
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1565
|
+
// Execute DeFi security research
|
|
1566
|
+
const result = await defiSecurityResearchAction.handler(
|
|
1567
|
+
runtime,
|
|
1568
|
+
mockMessage,
|
|
1569
|
+
undefined,
|
|
1570
|
+
{}
|
|
1571
|
+
);
|
|
1572
|
+
|
|
1573
|
+
if (!result || typeof result !== 'object') {
|
|
1574
|
+
throw new Error('DeFi research action returned invalid result');
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
// Extract project ID from response
|
|
1578
|
+
const responseText = (result as any).text || '';
|
|
1579
|
+
const projectIdMatch = responseText.match(/([a-f0-9-]{36})/);
|
|
1580
|
+
|
|
1581
|
+
if (!projectIdMatch) {
|
|
1582
|
+
throw new Error('Could not extract project ID from DeFi research response');
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
const projectId = projectIdMatch[1];
|
|
1586
|
+
elizaLogger.info(`DeFi research started with project ID: ${projectId}`);
|
|
1587
|
+
|
|
1588
|
+
// Monitor DeFi-specific findings
|
|
1589
|
+
let defiCheckCount = 0;
|
|
1590
|
+
const defiCheckInterval = setInterval(async () => {
|
|
1591
|
+
defiCheckCount++;
|
|
1592
|
+
const current = await service.getProject(projectId);
|
|
1593
|
+
if (!current) return;
|
|
1594
|
+
|
|
1595
|
+
// Check for DeFi-specific content
|
|
1596
|
+
const defiFindings = current.findings.filter((f) => {
|
|
1597
|
+
const content = f.content.toLowerCase();
|
|
1598
|
+
return (
|
|
1599
|
+
content.includes('smart contract') ||
|
|
1600
|
+
content.includes('defi') ||
|
|
1601
|
+
content.includes('audit') ||
|
|
1602
|
+
content.includes('vulnerability') ||
|
|
1603
|
+
content.includes('security')
|
|
1604
|
+
);
|
|
1605
|
+
});
|
|
1606
|
+
|
|
1607
|
+
if (defiFindings.length > 0 && defiCheckCount === 1) {
|
|
1608
|
+
elizaLogger.info(
|
|
1609
|
+
`Found ${defiFindings.length} DeFi-specific findings`
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
if (
|
|
1614
|
+
current.status === ResearchStatus.COMPLETED ||
|
|
1615
|
+
current.status === ResearchStatus.FAILED ||
|
|
1616
|
+
defiCheckCount > 20
|
|
1617
|
+
) {
|
|
1618
|
+
clearInterval(defiCheckInterval);
|
|
1619
|
+
}
|
|
1620
|
+
}, 5000);
|
|
1621
|
+
|
|
1622
|
+
// Wait for completion
|
|
1623
|
+
const completed = await waitForResearchCompletion(service, projectId, 120000);
|
|
1624
|
+
clearInterval(defiCheckInterval);
|
|
1625
|
+
|
|
1626
|
+
const finalProject = await service.getProject(projectId);
|
|
1627
|
+
if (!finalProject) {
|
|
1628
|
+
throw new Error('Could not retrieve DeFi research project');
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
// Validate DeFi research quality
|
|
1632
|
+
const hasSecurityContent = finalProject.findings.some(
|
|
1633
|
+
(f) =>
|
|
1634
|
+
f.content.toLowerCase().includes('security') ||
|
|
1635
|
+
f.content.toLowerCase().includes('vulnerability') ||
|
|
1636
|
+
f.content.toLowerCase().includes('exploit')
|
|
1637
|
+
);
|
|
1638
|
+
|
|
1639
|
+
const hasAuditContent = finalProject.findings.some(
|
|
1640
|
+
(f) =>
|
|
1641
|
+
f.content.toLowerCase().includes('audit') ||
|
|
1642
|
+
f.content.toLowerCase().includes('review') ||
|
|
1643
|
+
f.content.toLowerCase().includes('verification')
|
|
1644
|
+
);
|
|
1645
|
+
|
|
1646
|
+
const hasCodeExamples = finalProject.findings.some(
|
|
1647
|
+
(f) =>
|
|
1648
|
+
f.content.includes('solidity') ||
|
|
1649
|
+
f.content.includes('contract') ||
|
|
1650
|
+
f.content.includes('function') ||
|
|
1651
|
+
f.content.includes('require')
|
|
1652
|
+
);
|
|
1653
|
+
|
|
1654
|
+
elizaLogger.info(`DeFi research completed:`);
|
|
1655
|
+
elizaLogger.info(`- Security content found: ${hasSecurityContent}`);
|
|
1656
|
+
elizaLogger.info(`- Audit content found: ${hasAuditContent}`);
|
|
1657
|
+
elizaLogger.info(`- Code examples found: ${hasCodeExamples}`);
|
|
1658
|
+
elizaLogger.info(`- Total findings: ${finalProject.findings.length}`);
|
|
1659
|
+
|
|
1660
|
+
elizaLogger.success('E2E Test Passed: DeFi Research Integration');
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
// Test 7: Research Quality and Relevance
|
|
1664
|
+
export async function testResearchQualityAssurance(
|
|
1665
|
+
runtime: IAgentRuntime
|
|
1666
|
+
): Promise<void> {
|
|
1667
|
+
elizaLogger.info('Starting E2E Test: Research Quality Assurance');
|
|
1668
|
+
|
|
1669
|
+
const service = runtime.getService<ResearchService>('research');
|
|
1670
|
+
if (!service) {
|
|
1671
|
+
throw new Error('Research service not available');
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
// Create a very specific research query
|
|
1675
|
+
const specificQuery =
|
|
1676
|
+
'ElizaOS plugin development tutorial TypeScript examples 2024';
|
|
1677
|
+
|
|
1678
|
+
const project = await service.createResearchProject(specificQuery, {
|
|
1679
|
+
maxSearchResults: 3,
|
|
1680
|
+
metadata: {
|
|
1681
|
+
researchType: 'tutorial',
|
|
1682
|
+
expectedKeywords: ['ElizaOS', 'plugin', 'TypeScript', 'development'],
|
|
1683
|
+
},
|
|
1684
|
+
});
|
|
1685
|
+
|
|
1686
|
+
elizaLogger.info(`Created quality assurance research project: ${project.id}`);
|
|
1687
|
+
|
|
1688
|
+
// Wait for completion
|
|
1689
|
+
const completed = await waitForResearchCompletion(service, project.id, 120000);
|
|
1690
|
+
|
|
1691
|
+
const finalProject = await service.getProject(project.id);
|
|
1692
|
+
if (!finalProject) {
|
|
1693
|
+
throw new Error('Could not retrieve completed project');
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
// Detailed quality checks
|
|
1697
|
+
const expectedKeywords = [
|
|
1698
|
+
'ElizaOS',
|
|
1699
|
+
'plugin',
|
|
1700
|
+
'TypeScript',
|
|
1701
|
+
'development',
|
|
1702
|
+
'tutorial',
|
|
1703
|
+
];
|
|
1704
|
+
const keywordCoverage: Record<string, number> = {};
|
|
1705
|
+
|
|
1706
|
+
expectedKeywords.forEach((keyword) => {
|
|
1707
|
+
keywordCoverage[keyword] = finalProject.findings.filter((f) =>
|
|
1708
|
+
f.content.toLowerCase().includes(keyword.toLowerCase())
|
|
1709
|
+
).length;
|
|
1710
|
+
});
|
|
1711
|
+
|
|
1712
|
+
// Calculate relevance metrics
|
|
1713
|
+
const totalFindings = finalProject.findings.length;
|
|
1714
|
+
const highRelevanceFindings = finalProject.findings.filter(
|
|
1715
|
+
(f) => f.relevance > 0.7
|
|
1716
|
+
).length;
|
|
1717
|
+
const mediumRelevanceFindings = finalProject.findings.filter(
|
|
1718
|
+
(f) => f.relevance > 0.4 && f.relevance <= 0.7
|
|
1719
|
+
).length;
|
|
1720
|
+
const lowRelevanceFindings = finalProject.findings.filter(
|
|
1721
|
+
(f) => f.relevance <= 0.4
|
|
1722
|
+
).length;
|
|
1723
|
+
|
|
1724
|
+
// Check source diversity
|
|
1725
|
+
const sourceDomains = new Set(
|
|
1726
|
+
finalProject.sources.map((s) => {
|
|
1727
|
+
try {
|
|
1728
|
+
return new URL(s.url).hostname;
|
|
1729
|
+
} catch {
|
|
1730
|
+
return 'unknown';
|
|
1731
|
+
}
|
|
1732
|
+
})
|
|
1733
|
+
);
|
|
1734
|
+
|
|
1735
|
+
// Quality report
|
|
1736
|
+
elizaLogger.info(`Research Quality Analysis:`);
|
|
1737
|
+
elizaLogger.info(`- Keyword coverage: ${JSON.stringify(keywordCoverage)}`);
|
|
1738
|
+
elizaLogger.info(`- Relevance distribution:`);
|
|
1739
|
+
elizaLogger.info(
|
|
1740
|
+
` * High (>0.7): ${highRelevanceFindings}/${totalFindings}`
|
|
1741
|
+
);
|
|
1742
|
+
elizaLogger.info(
|
|
1743
|
+
` * Medium (0.4-0.7): ${mediumRelevanceFindings}/${totalFindings}`
|
|
1744
|
+
);
|
|
1745
|
+
elizaLogger.info(` * Low (<0.4): ${lowRelevanceFindings}/${totalFindings}`);
|
|
1746
|
+
elizaLogger.info(`- Source diversity: ${sourceDomains.size} unique domains`);
|
|
1747
|
+
elizaLogger.info(
|
|
1748
|
+
`- Average finding length: ${Math.round(
|
|
1749
|
+
finalProject.findings.reduce((sum, f) => sum + f.content.length, 0) /
|
|
1750
|
+
totalFindings
|
|
1751
|
+
)} chars`
|
|
1752
|
+
);
|
|
1753
|
+
|
|
1754
|
+
// Validate minimum quality standards
|
|
1755
|
+
const keywordsCovered = Object.values(keywordCoverage).filter(
|
|
1756
|
+
(count) => count > 0
|
|
1757
|
+
).length;
|
|
1758
|
+
if (keywordsCovered < 2) {
|
|
1759
|
+
elizaLogger.warn(
|
|
1760
|
+
`Low keyword coverage: only ${keywordsCovered}/${expectedKeywords.length} keywords found`
|
|
1761
|
+
);
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
if (highRelevanceFindings < totalFindings * 0.3) {
|
|
1765
|
+
elizaLogger.warn(
|
|
1766
|
+
`Low proportion of high-relevance findings: ${highRelevanceFindings}/${totalFindings}`
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
elizaLogger.success('E2E Test Passed: Research Quality Assurance');
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
// #endregion
|
|
1774
|
+
|
|
1775
|
+
// #region: Test Suite Export
|
|
1776
|
+
|
|
1777
|
+
// Export all tests as a TestSuite for the ElizaOS test runner
|
|
1778
|
+
const realWorldE2ETests = [
|
|
1779
|
+
{
|
|
1780
|
+
name: 'Real-World Research Scenarios',
|
|
1781
|
+
description: 'Comprehensive tests simulating actual research workflows',
|
|
1782
|
+
tests: [
|
|
1783
|
+
{
|
|
1784
|
+
name: 'Feature Development Research',
|
|
1785
|
+
description:
|
|
1786
|
+
'Simulates a developer researching how to implement a new feature',
|
|
1787
|
+
fn: testFeatureDevelopmentResearch,
|
|
1788
|
+
},
|
|
1789
|
+
{
|
|
1790
|
+
name: 'Person Background Research',
|
|
1791
|
+
description:
|
|
1792
|
+
'Simulates researching a person for hiring or partnership evaluation',
|
|
1793
|
+
fn: testPersonBackgroundResearch,
|
|
1794
|
+
},
|
|
1795
|
+
{
|
|
1796
|
+
name: 'Breaking News Research',
|
|
1797
|
+
description:
|
|
1798
|
+
'Simulates a journalist or analyst researching breaking news',
|
|
1799
|
+
fn: testBreakingNewsResearch,
|
|
1800
|
+
},
|
|
1801
|
+
{
|
|
1802
|
+
name: 'Market Intelligence Research',
|
|
1803
|
+
description: 'Simulates competitive analysis and market research',
|
|
1804
|
+
fn: testMarketIntelligenceResearch,
|
|
1805
|
+
},
|
|
1806
|
+
{
|
|
1807
|
+
name: 'Technical Problem Solving',
|
|
1808
|
+
description: 'Simulates debugging and problem-solving research',
|
|
1809
|
+
fn: testProblemSolvingResearch,
|
|
1810
|
+
},
|
|
1811
|
+
{
|
|
1812
|
+
name: 'Academic/Learning Research',
|
|
1813
|
+
description: 'Simulates research for learning and academic purposes',
|
|
1814
|
+
fn: testAcademicResearch,
|
|
1815
|
+
},
|
|
1816
|
+
],
|
|
1817
|
+
},
|
|
1818
|
+
];
|
|
1819
|
+
|
|
1820
|
+
const researchE2ETests = [
|
|
1821
|
+
{
|
|
1822
|
+
name: 'Research Plugin E2E Tests - Core Scenarios',
|
|
1823
|
+
description:
|
|
1824
|
+
'Comprehensive end-to-end tests simulating real-world research use cases',
|
|
1825
|
+
tests: [
|
|
1826
|
+
{
|
|
1827
|
+
name: 'Code/Feature Research',
|
|
1828
|
+
description:
|
|
1829
|
+
'Simulates researching technical implementation details before building a feature',
|
|
1830
|
+
fn: testCodeFeatureResearch,
|
|
1831
|
+
},
|
|
1832
|
+
{
|
|
1833
|
+
name: 'Person Research',
|
|
1834
|
+
description: 'Tests researching information about a public figure',
|
|
1835
|
+
fn: testPersonResearch,
|
|
1836
|
+
},
|
|
1837
|
+
{
|
|
1838
|
+
name: 'News/Current Events Research',
|
|
1839
|
+
description: 'Tests researching latest news and current developments',
|
|
1840
|
+
fn: testNewsResearch,
|
|
1841
|
+
},
|
|
1842
|
+
{
|
|
1843
|
+
name: 'Technical Documentation Research',
|
|
1844
|
+
description:
|
|
1845
|
+
'Tests researching technical documentation and best practices',
|
|
1846
|
+
fn: testDocumentationResearch,
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
name: 'Competitive Analysis',
|
|
1850
|
+
description: 'Tests researching competitors and market analysis',
|
|
1851
|
+
fn: testCompetitiveAnalysis,
|
|
1852
|
+
},
|
|
1853
|
+
{
|
|
1854
|
+
name: 'DeFi Research Integration',
|
|
1855
|
+
description: 'Tests DeFi-specific research scenarios',
|
|
1856
|
+
fn: testDeFiResearch,
|
|
1857
|
+
},
|
|
1858
|
+
{
|
|
1859
|
+
name: 'Research Quality Assurance',
|
|
1860
|
+
description:
|
|
1861
|
+
'Tests research quality, relevance, and comprehensive coverage',
|
|
1862
|
+
fn: testResearchQualityAssurance,
|
|
1863
|
+
},
|
|
1864
|
+
],
|
|
1865
|
+
},
|
|
1866
|
+
];
|
|
1867
|
+
|
|
1868
|
+
export const e2eTests = [...realWorldE2ETests, ...researchE2ETests];
|
|
1869
|
+
|
|
1870
|
+
// #endregion
|