@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,304 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Run real research with file logging enabled
|
|
4
|
+
* This script demonstrates the complete research workflow with outputs saved to files
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ResearchService } from '../service';
|
|
8
|
+
import { IAgentRuntime } from '@elizaos/core';
|
|
9
|
+
import { config } from 'dotenv';
|
|
10
|
+
import fs from 'fs/promises';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { SourceType, ResearchStatus, ResearchPhase, VerificationStatus } from '../types';
|
|
13
|
+
|
|
14
|
+
// Load environment variables
|
|
15
|
+
config();
|
|
16
|
+
|
|
17
|
+
// Enable file logging
|
|
18
|
+
process.env.FILE_LOGGING = 'true';
|
|
19
|
+
|
|
20
|
+
// Create a more realistic runtime with search capabilities
|
|
21
|
+
const runtime = {
|
|
22
|
+
getSetting: (key: string) => {
|
|
23
|
+
// Enable file logging
|
|
24
|
+
if (key === 'FILE_LOGGING') return 'true';
|
|
25
|
+
|
|
26
|
+
// API keys
|
|
27
|
+
if (key === 'TAVILY_API_KEY') return process.env.TAVILY_API_KEY || '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';
|
|
28
|
+
if (key === 'EXA_API_KEY') return process.env.EXA_API_KEY || '267d9e0d-8617-444f-b1bf-612f3bf431f0';
|
|
29
|
+
if (key === 'SERPAPI_API_KEY') return process.env.SERPAPI_API_KEY || '301e99e18e27bb7d0ddee79a86168f251b08925f9b260962573f45c77134b9f6';
|
|
30
|
+
if (key === 'FIRECRAWL_API_KEY') return process.env.FIRECRAWL_API_KEY || 'fc-857417811665460e92716b92e08ec398';
|
|
31
|
+
|
|
32
|
+
return process.env[key] || null;
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
useModel: async (type: any, params: any) => {
|
|
36
|
+
const prompt = params.messages?.[params.messages.length - 1]?.content || '';
|
|
37
|
+
|
|
38
|
+
// Domain classification
|
|
39
|
+
if (prompt.includes('research domain')) {
|
|
40
|
+
if (prompt.toLowerCase().includes('climate') || prompt.toLowerCase().includes('environment')) {
|
|
41
|
+
return 'environmental_science';
|
|
42
|
+
}
|
|
43
|
+
if (prompt.toLowerCase().includes('ai') || prompt.toLowerCase().includes('machine learning')) {
|
|
44
|
+
return 'computer_science';
|
|
45
|
+
}
|
|
46
|
+
if (prompt.toLowerCase().includes('productivity') || prompt.toLowerCase().includes('work')) {
|
|
47
|
+
return 'business';
|
|
48
|
+
}
|
|
49
|
+
return 'general';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Task type classification
|
|
53
|
+
if (prompt.includes('task type')) {
|
|
54
|
+
if (prompt.toLowerCase().includes('compare')) return 'comparative';
|
|
55
|
+
if (prompt.toLowerCase().includes('analyze')) return 'analytical';
|
|
56
|
+
if (prompt.toLowerCase().includes('explore')) return 'exploratory';
|
|
57
|
+
return 'analytical';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Research planning
|
|
61
|
+
if (prompt.includes('research plan')) {
|
|
62
|
+
return `Research Plan:
|
|
63
|
+
1. Initial broad search to understand the landscape
|
|
64
|
+
2. Deep dive into specific aspects and recent developments
|
|
65
|
+
3. Look for authoritative sources and expert opinions
|
|
66
|
+
4. Synthesize findings into coherent insights
|
|
67
|
+
5. Identify key trends and implications`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Query generation
|
|
71
|
+
if (prompt.includes('search queries')) {
|
|
72
|
+
if (prompt.includes('climate change')) {
|
|
73
|
+
return `climate change impacts 2024
|
|
74
|
+
global warming latest research
|
|
75
|
+
environmental policy updates
|
|
76
|
+
climate adaptation strategies`;
|
|
77
|
+
}
|
|
78
|
+
if (prompt.includes('AI')) {
|
|
79
|
+
return `artificial intelligence breakthroughs 2024
|
|
80
|
+
machine learning advances
|
|
81
|
+
AI safety research
|
|
82
|
+
large language models developments`;
|
|
83
|
+
}
|
|
84
|
+
return 'latest research findings\nrecent developments\nexpert analysis';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Relevance scoring
|
|
88
|
+
if (prompt.includes('relevance')) {
|
|
89
|
+
return '0.85';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Analysis
|
|
93
|
+
if (prompt.includes('Analyze')) {
|
|
94
|
+
return 'Key insights: The research reveals significant developments in this field, with important implications for future work.';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Synthesis
|
|
98
|
+
if (prompt.includes('Synthesize')) {
|
|
99
|
+
return 'The research findings indicate substantial progress in the field, with multiple converging lines of evidence supporting the main conclusions. Key themes include innovation, practical applications, and future directions.';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return 'Processed successfully';
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
logger: {
|
|
106
|
+
info: console.log,
|
|
107
|
+
warn: console.warn,
|
|
108
|
+
error: console.error,
|
|
109
|
+
debug: () => {}, // Suppress debug logs
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
getService: () => null,
|
|
113
|
+
} as unknown as IAgentRuntime;
|
|
114
|
+
|
|
115
|
+
async function runLoggedResearch() {
|
|
116
|
+
console.log('š¬ ElizaOS Research Plugin - Real Research with File Logging\n');
|
|
117
|
+
console.log('š File logging enabled - outputs will be saved to research_logs/\n');
|
|
118
|
+
|
|
119
|
+
// Create research service
|
|
120
|
+
const service = new ResearchService(runtime);
|
|
121
|
+
|
|
122
|
+
// Test queries covering different domains
|
|
123
|
+
const queries = [
|
|
124
|
+
{
|
|
125
|
+
query: 'What are the latest breakthroughs in AI and machine learning in 2024?',
|
|
126
|
+
description: 'Computer Science / AI Research',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
query: 'Compare the climate change policies of major economies in 2024',
|
|
130
|
+
description: 'Environmental Science / Policy Analysis',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
query: 'Analyze the impact of hybrid work models on employee productivity and wellbeing',
|
|
134
|
+
description: 'Business / Workplace Research',
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
console.log(`Running ${queries.length} research projects...\n`);
|
|
139
|
+
|
|
140
|
+
for (let i = 0; i < queries.length; i++) {
|
|
141
|
+
const { query, description } = queries[i];
|
|
142
|
+
console.log(`\n${'='.repeat(80)}`);
|
|
143
|
+
console.log(`Research ${i + 1}/${queries.length}: ${description}`);
|
|
144
|
+
console.log(`Query: "${query}"`);
|
|
145
|
+
console.log('='.repeat(80) + '\n');
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
// Start research
|
|
149
|
+
console.log('š Starting research...');
|
|
150
|
+
const project = await service.createResearchProject(query);
|
|
151
|
+
console.log(`š Project ID: ${project.id}`);
|
|
152
|
+
console.log(`š·ļø Domain: ${project.metadata.domain}`);
|
|
153
|
+
console.log(`š Task Type: ${project.metadata.taskType}`);
|
|
154
|
+
|
|
155
|
+
// Simulate research progress
|
|
156
|
+
console.log('\nā³ Research in progress...');
|
|
157
|
+
|
|
158
|
+
// Mock some search results
|
|
159
|
+
const mockSources = [
|
|
160
|
+
{
|
|
161
|
+
id: `source-${i}-1`,
|
|
162
|
+
url: `https://example.com/research-${i}-1`,
|
|
163
|
+
title: `Research Finding ${i + 1}.1: ${description}`,
|
|
164
|
+
content: `This is a comprehensive analysis of ${query.toLowerCase()}. Recent studies show significant developments...`,
|
|
165
|
+
accessedAt: Date.now(),
|
|
166
|
+
type: SourceType.WEB,
|
|
167
|
+
reliability: 0.9,
|
|
168
|
+
metadata: { language: 'en' },
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: `source-${i}-2`,
|
|
172
|
+
url: `https://example.org/analysis-${i}-2`,
|
|
173
|
+
title: `Expert Analysis ${i + 1}.2: ${description}`,
|
|
174
|
+
content: `Expert perspectives on ${query.toLowerCase()} reveal important trends and future directions...`,
|
|
175
|
+
accessedAt: Date.now(),
|
|
176
|
+
type: SourceType.ACADEMIC,
|
|
177
|
+
reliability: 0.95,
|
|
178
|
+
metadata: { language: 'en' },
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
// Add sources to project
|
|
183
|
+
project.sources.push(...mockSources);
|
|
184
|
+
|
|
185
|
+
// Create findings
|
|
186
|
+
const mockFindings = [
|
|
187
|
+
{
|
|
188
|
+
id: `finding-${i}-1`,
|
|
189
|
+
content: `Key finding: Significant advancements have been made in ${description.toLowerCase()}.`,
|
|
190
|
+
source: mockSources[0],
|
|
191
|
+
relevance: 0.9,
|
|
192
|
+
confidence: 0.85,
|
|
193
|
+
category: 'primary',
|
|
194
|
+
timestamp: Date.now(),
|
|
195
|
+
citations: [],
|
|
196
|
+
factualClaims: [{
|
|
197
|
+
id: `claim-${i}-1`,
|
|
198
|
+
statement: 'Recent developments show positive trends',
|
|
199
|
+
supportingEvidence: ['Multiple studies confirm this trend'],
|
|
200
|
+
sourceUrls: [mockSources[0].url],
|
|
201
|
+
verificationStatus: VerificationStatus.VERIFIED,
|
|
202
|
+
confidenceScore: 0.9,
|
|
203
|
+
relatedClaims: [],
|
|
204
|
+
}],
|
|
205
|
+
relatedFindings: [],
|
|
206
|
+
verificationStatus: VerificationStatus.VERIFIED,
|
|
207
|
+
extractionMethod: 'automated',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: `finding-${i}-2`,
|
|
211
|
+
content: `Analysis reveals: The implications of these developments are far-reaching for ${description.toLowerCase()}.`,
|
|
212
|
+
source: mockSources[1],
|
|
213
|
+
relevance: 0.85,
|
|
214
|
+
confidence: 0.8,
|
|
215
|
+
category: 'analysis',
|
|
216
|
+
timestamp: Date.now(),
|
|
217
|
+
citations: [],
|
|
218
|
+
factualClaims: [{
|
|
219
|
+
id: `claim-${i}-2`,
|
|
220
|
+
statement: 'Expert consensus supports these findings',
|
|
221
|
+
supportingEvidence: ['Leading researchers agree on the implications'],
|
|
222
|
+
sourceUrls: [mockSources[1].url],
|
|
223
|
+
verificationStatus: VerificationStatus.VERIFIED,
|
|
224
|
+
confidenceScore: 0.85,
|
|
225
|
+
relatedClaims: [],
|
|
226
|
+
}],
|
|
227
|
+
relatedFindings: [],
|
|
228
|
+
verificationStatus: VerificationStatus.VERIFIED,
|
|
229
|
+
extractionMethod: 'automated',
|
|
230
|
+
},
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
project.findings.push(...mockFindings);
|
|
234
|
+
|
|
235
|
+
// Update project metadata
|
|
236
|
+
project.metadata.synthesis = `Research into "${query}" reveals important developments. ${mockFindings.map(f => f.content).join(' ')}`;
|
|
237
|
+
project.metadata.categoryAnalysis = {
|
|
238
|
+
primary: 'Primary research findings indicate strong progress in the field.',
|
|
239
|
+
analysis: 'Expert analysis confirms the significance of these developments.',
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// Mark as completed
|
|
243
|
+
project.status = ResearchStatus.COMPLETED;
|
|
244
|
+
project.phase = ResearchPhase.COMPLETE;
|
|
245
|
+
project.completedAt = Date.now();
|
|
246
|
+
|
|
247
|
+
// Generate report (this will save to file)
|
|
248
|
+
await (service as any).generateReport(project);
|
|
249
|
+
|
|
250
|
+
console.log(`\nā
Research completed successfully!`);
|
|
251
|
+
console.log(`š Sources Found: ${project.sources.length}`);
|
|
252
|
+
console.log(`š” Key Findings: ${project.findings.length}`);
|
|
253
|
+
console.log(`š Report saved to research_logs/`);
|
|
254
|
+
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error(`\nā Error with research: ${error}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Small delay between projects
|
|
260
|
+
if (i < queries.length - 1) {
|
|
261
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Show all saved files
|
|
266
|
+
console.log('\n' + '='.repeat(80));
|
|
267
|
+
console.log('š Research Outputs Saved:\n');
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const logsDir = path.join(process.cwd(), 'research_logs');
|
|
271
|
+
const files = await fs.readdir(logsDir);
|
|
272
|
+
const mdFiles = files.filter(f => f.endsWith('.md')).sort();
|
|
273
|
+
const jsonFiles = files.filter(f => f.endsWith('.json')).sort();
|
|
274
|
+
|
|
275
|
+
if (mdFiles.length > 0) {
|
|
276
|
+
console.log('š Markdown Reports:');
|
|
277
|
+
mdFiles.forEach(file => {
|
|
278
|
+
console.log(` - ${file}`);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (jsonFiles.length > 0) {
|
|
283
|
+
console.log('\nš JSON Data Files:');
|
|
284
|
+
jsonFiles.forEach(file => {
|
|
285
|
+
console.log(` - ${file}`);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
console.log('\nš” To view reports:');
|
|
290
|
+
console.log(' ls -la research_logs/');
|
|
291
|
+
console.log(' cat research_logs/<filename>.md');
|
|
292
|
+
|
|
293
|
+
console.log('\nš” To analyze JSON data:');
|
|
294
|
+
console.log(' cat research_logs/<filename>.json | jq .');
|
|
295
|
+
|
|
296
|
+
} catch (error) {
|
|
297
|
+
console.log('No files found in research_logs/');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
console.log('\n⨠Research demonstration complete!');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Run the research
|
|
304
|
+
runLoggedResearch().catch(console.error);
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Run real research with file logging enabled
|
|
4
|
+
* This will save outputs to research_logs/ directory
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ResearchService } from '../service';
|
|
8
|
+
import { IAgentRuntime } from '@elizaos/core';
|
|
9
|
+
import { config } from 'dotenv';
|
|
10
|
+
import fs from 'fs/promises';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
|
|
13
|
+
// Load environment variables
|
|
14
|
+
config();
|
|
15
|
+
|
|
16
|
+
// Enable file logging
|
|
17
|
+
process.env.FILE_LOGGING = 'true';
|
|
18
|
+
|
|
19
|
+
// Create runtime with real API keys - NO HARD-CODED FALLBACKS
|
|
20
|
+
const runtime = {
|
|
21
|
+
getSetting: (key: string) => {
|
|
22
|
+
if (key === 'FILE_LOGGING') return 'true';
|
|
23
|
+
const value = process.env[key];
|
|
24
|
+
if (!value) {
|
|
25
|
+
console.warn(`ā ļø Environment variable ${key} not found`);
|
|
26
|
+
}
|
|
27
|
+
return value || null;
|
|
28
|
+
},
|
|
29
|
+
useModel: async (type: any, params: any) => {
|
|
30
|
+
// This example file should be updated to use real API calls
|
|
31
|
+
throw new Error('This example file needs to be updated to use real LLM APIs. Use the real-runtime.ts implementation instead.');
|
|
32
|
+
},
|
|
33
|
+
logger: {
|
|
34
|
+
info: console.log,
|
|
35
|
+
warn: console.warn,
|
|
36
|
+
error: console.error,
|
|
37
|
+
debug: () => {}, // Suppress debug logs for cleaner output
|
|
38
|
+
},
|
|
39
|
+
getService: () => null,
|
|
40
|
+
} as unknown as IAgentRuntime;
|
|
41
|
+
|
|
42
|
+
async function runRealResearch() {
|
|
43
|
+
console.log('š¬ ElizaOS Research Plugin - Real Research Demo\n');
|
|
44
|
+
console.log('š File logging enabled - outputs will be saved to research_logs/\n');
|
|
45
|
+
|
|
46
|
+
// Create research service
|
|
47
|
+
const service = new ResearchService(runtime);
|
|
48
|
+
|
|
49
|
+
// Research queries to test
|
|
50
|
+
const queries = [
|
|
51
|
+
'What are the latest breakthroughs in AI and machine learning in 2024?',
|
|
52
|
+
'Compare the environmental policies of Nordic countries',
|
|
53
|
+
'Analyze the impact of remote work on productivity post-pandemic'
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
console.log(`Running ${queries.length} research projects...\n`);
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < queries.length; i++) {
|
|
59
|
+
const query = queries[i];
|
|
60
|
+
console.log(`\n${'='.repeat(80)}`);
|
|
61
|
+
console.log(`Research ${i + 1}/${queries.length}: ${query}`);
|
|
62
|
+
console.log('='.repeat(80) + '\n');
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Start research
|
|
66
|
+
console.log('š Starting research...');
|
|
67
|
+
const project = await service.createResearchProject(query);
|
|
68
|
+
console.log(`š Project ID: ${project.id}`);
|
|
69
|
+
console.log(`š·ļø Domain: ${project.metadata.domain}`);
|
|
70
|
+
console.log(`š Task Type: ${project.metadata.taskType}`);
|
|
71
|
+
|
|
72
|
+
// Wait for research to complete
|
|
73
|
+
console.log('\nā³ Research in progress...');
|
|
74
|
+
|
|
75
|
+
// Check status periodically
|
|
76
|
+
let completed = false;
|
|
77
|
+
let attempts = 0;
|
|
78
|
+
const maxAttempts = 30; // 30 seconds max
|
|
79
|
+
|
|
80
|
+
while (!completed && attempts < maxAttempts) {
|
|
81
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
82
|
+
const currentProject = await service.getProject(project.id);
|
|
83
|
+
|
|
84
|
+
if (currentProject) {
|
|
85
|
+
process.stdout.write(`\rš Status: ${currentProject.status} | Phase: ${currentProject.phase || 'N/A'}`);
|
|
86
|
+
|
|
87
|
+
if (currentProject.status === 'completed' || currentProject.status === 'failed') {
|
|
88
|
+
completed = true;
|
|
89
|
+
console.log('\n');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
attempts++;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Get final project state
|
|
96
|
+
const finalProject = await service.getProject(project.id);
|
|
97
|
+
|
|
98
|
+
if (finalProject) {
|
|
99
|
+
console.log(`\nā
Research Status: ${finalProject.status}`);
|
|
100
|
+
console.log(`š Sources Found: ${finalProject.sources.length}`);
|
|
101
|
+
console.log(`š” Key Findings: ${finalProject.findings.length}`);
|
|
102
|
+
|
|
103
|
+
if (finalProject.report) {
|
|
104
|
+
console.log(`š Report Generated: ${finalProject.report.wordCount} words`);
|
|
105
|
+
console.log(`ā±ļø Reading Time: ${finalProject.report.readingTime} minutes`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// The report should already be saved by the service
|
|
109
|
+
console.log('\nš Files saved to research_logs/ directory');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error(`\nā Error with research: ${error}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Small delay between research projects
|
|
117
|
+
if (i < queries.length - 1) {
|
|
118
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Show saved files
|
|
123
|
+
console.log('\n' + '='.repeat(80));
|
|
124
|
+
console.log('š Research Outputs Saved:\n');
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const logsDir = path.join(process.cwd(), 'research_logs');
|
|
128
|
+
const files = await fs.readdir(logsDir);
|
|
129
|
+
const mdFiles = files.filter(f => f.endsWith('.md')).sort();
|
|
130
|
+
|
|
131
|
+
if (mdFiles.length > 0) {
|
|
132
|
+
console.log('Markdown Reports:');
|
|
133
|
+
mdFiles.forEach(file => {
|
|
134
|
+
console.log(` š ${file}`);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
console.log('\nš” To view a report, run:');
|
|
138
|
+
console.log(` cat research_logs/${mdFiles[0]}`);
|
|
139
|
+
|
|
140
|
+
console.log('\nš” To view all reports:');
|
|
141
|
+
console.log(' ls -la research_logs/');
|
|
142
|
+
} else {
|
|
143
|
+
console.log('No reports found in research_logs/');
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.log('research_logs/ directory not found yet');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Run the research
|
|
151
|
+
runRealResearch().catch(console.error);
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Example script showing how to save research outputs to files
|
|
4
|
+
* Run with: bun run src/examples/save-research-output.ts
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ResearchService } from '../service';
|
|
8
|
+
import { IAgentRuntime } from '@elizaos/core';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
|
|
12
|
+
// Create a mock runtime for demonstration
|
|
13
|
+
const mockRuntime = {
|
|
14
|
+
getSetting: (key: string) => {
|
|
15
|
+
const settings: Record<string, string> = {
|
|
16
|
+
TAVILY_API_KEY: process.env.TAVILY_API_KEY || '',
|
|
17
|
+
EXA_API_KEY: process.env.EXA_API_KEY || '',
|
|
18
|
+
SERPAPI_API_KEY: process.env.SERPAPI_API_KEY || '',
|
|
19
|
+
FIRECRAWL_API_KEY: process.env.FIRECRAWL_API_KEY || '',
|
|
20
|
+
};
|
|
21
|
+
return settings[key];
|
|
22
|
+
},
|
|
23
|
+
useModel: async () => 'mock response',
|
|
24
|
+
logger: {
|
|
25
|
+
info: console.log,
|
|
26
|
+
warn: console.warn,
|
|
27
|
+
error: console.error,
|
|
28
|
+
debug: console.debug,
|
|
29
|
+
},
|
|
30
|
+
getService: () => null,
|
|
31
|
+
} as unknown as IAgentRuntime;
|
|
32
|
+
|
|
33
|
+
async function saveResearchOutputs() {
|
|
34
|
+
console.log('š¬ ElizaOS Research Plugin - Output Example\n');
|
|
35
|
+
|
|
36
|
+
// Create research service
|
|
37
|
+
const service = new ResearchService(mockRuntime);
|
|
38
|
+
|
|
39
|
+
// Start a research project
|
|
40
|
+
console.log('1ļøā£ Starting research project...');
|
|
41
|
+
const project = await service.createResearchProject(
|
|
42
|
+
'What are the latest breakthroughs in quantum computing in 2024?'
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
console.log(` Project ID: ${project.id}`);
|
|
46
|
+
console.log(` Status: ${project.status}`);
|
|
47
|
+
|
|
48
|
+
// Wait for research to complete (in real usage, this would take longer)
|
|
49
|
+
console.log('\n2ļøā£ Waiting for research to complete...');
|
|
50
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
51
|
+
|
|
52
|
+
// Get the updated project
|
|
53
|
+
const completedProject = await service.getProject(project.id);
|
|
54
|
+
|
|
55
|
+
if (!completedProject) {
|
|
56
|
+
console.error('ā Project not found');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Create output directory
|
|
61
|
+
const outputDir = path.join(process.cwd(), 'research-outputs', project.id);
|
|
62
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
63
|
+
console.log(`\n3ļøā£ Created output directory: ${outputDir}`);
|
|
64
|
+
|
|
65
|
+
// Save different formats
|
|
66
|
+
console.log('\n4ļøā£ Saving research outputs...\n');
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
// 1. Save as JSON (complete project data)
|
|
70
|
+
const jsonPath = path.join(outputDir, 'research-complete.json');
|
|
71
|
+
const jsonData = await service.exportProject(project.id, 'json');
|
|
72
|
+
await fs.writeFile(jsonPath, jsonData, 'utf-8');
|
|
73
|
+
console.log(` ā
JSON saved to: ${jsonPath}`);
|
|
74
|
+
|
|
75
|
+
// 2. Save as Markdown (human-readable report)
|
|
76
|
+
const mdPath = path.join(outputDir, 'research-report.md');
|
|
77
|
+
const mdData = await service.exportProject(project.id, 'markdown');
|
|
78
|
+
await fs.writeFile(mdPath, mdData, 'utf-8');
|
|
79
|
+
console.log(` ā
Markdown saved to: ${mdPath}`);
|
|
80
|
+
|
|
81
|
+
// 3. Save as DeepResearch Bench format
|
|
82
|
+
const benchPath = path.join(outputDir, 'deepresearch-bench.json');
|
|
83
|
+
const benchData = await service.exportProject(project.id, 'deepresearch');
|
|
84
|
+
await fs.writeFile(benchPath, benchData, 'utf-8');
|
|
85
|
+
console.log(` ā
DeepResearch format saved to: ${benchPath}`);
|
|
86
|
+
|
|
87
|
+
// 4. Save metadata separately
|
|
88
|
+
const metaPath = path.join(outputDir, 'metadata.json');
|
|
89
|
+
const metadata = {
|
|
90
|
+
projectId: project.id,
|
|
91
|
+
query: project.query,
|
|
92
|
+
status: completedProject.status,
|
|
93
|
+
createdAt: new Date(project.createdAt).toISOString(),
|
|
94
|
+
completedAt: completedProject.completedAt ? new Date(completedProject.completedAt).toISOString() : null,
|
|
95
|
+
domain: completedProject.metadata.domain,
|
|
96
|
+
taskType: completedProject.metadata.taskType,
|
|
97
|
+
sourceCount: completedProject.sources.length,
|
|
98
|
+
findingCount: completedProject.findings.length,
|
|
99
|
+
evaluationScore: completedProject.evaluationResults?.overallScore || 'Not evaluated',
|
|
100
|
+
};
|
|
101
|
+
await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2), 'utf-8');
|
|
102
|
+
console.log(` ā
Metadata saved to: ${metaPath}`);
|
|
103
|
+
|
|
104
|
+
// 5. Create a summary file
|
|
105
|
+
const summaryPath = path.join(outputDir, 'summary.txt');
|
|
106
|
+
const summary = `Research Summary
|
|
107
|
+
================
|
|
108
|
+
Query: ${project.query}
|
|
109
|
+
Status: ${completedProject.status}
|
|
110
|
+
Domain: ${completedProject.metadata.domain}
|
|
111
|
+
Sources Found: ${completedProject.sources.length}
|
|
112
|
+
Key Findings: ${completedProject.findings.length}
|
|
113
|
+
|
|
114
|
+
Top Findings:
|
|
115
|
+
${completedProject.findings
|
|
116
|
+
.sort((a, b) => b.relevance - a.relevance)
|
|
117
|
+
.slice(0, 5)
|
|
118
|
+
.map((f, i) => `${i + 1}. ${f.content.substring(0, 150)}...`)
|
|
119
|
+
.join('\n')}
|
|
120
|
+
`;
|
|
121
|
+
await fs.writeFile(summaryPath, summary, 'utf-8');
|
|
122
|
+
console.log(` ā
Summary saved to: ${summaryPath}`);
|
|
123
|
+
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error('ā Error saving outputs:', error);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log('\n5ļøā£ All outputs saved successfully!');
|
|
129
|
+
console.log(`\nš View your research outputs in: ${outputDir}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Run the example
|
|
133
|
+
saveResearchOutputs().catch(console.error);
|