@@ -5,50 +5,113 @@ import { printReport } from "./src/output/printer.js";
55import { saveReport , getAllReports } from "./src/output/store.js" ;
66import { config } from "./src/lib/config.js" ;
77import { log } from "./src/lib/logger.js" ;
8+ import type { ResearchReport } from "./src/lib/types.js" ;
89
9- async function researchProtocol ( protocolId : string ) : Promise < void > {
10+ function sleep ( ms : number ) : Promise < void > {
11+ return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
12+ }
13+
14+ async function researchProtocol ( protocolId : string ) : Promise < ResearchReport | null > {
1015 const protocols = getAllProtocols ( ) ;
1116 const protocol = protocols . find ( ( p ) => p . id === protocolId ) ;
12- if ( ! protocol ) { log . warn ( `Protocol not found: ${ protocolId } ` ) ; return ; }
17+ if ( ! protocol ) {
18+ log . warn ( `Protocol not found: ${ protocolId } ` ) ;
19+ return null ;
20+ }
1321
1422 log . info ( `Researching ${ protocol . name } ...` ) ;
1523 const metrics = await fetchProtocolMetrics ( protocol ) . catch ( ( e ) => {
16- log . warn ( `Metrics fetch failed for ${ protocol . name } :` , e . message ) ;
24+ const message = e instanceof Error ? e . message : String ( e ) ;
25+ log . warn ( `Metrics fetch failed for ${ protocol . name } :` , message ) ;
26+ return null ;
27+ } ) ;
28+
29+ const report = await runLoreAgent ( protocol , metrics ) . catch ( ( e ) => {
30+ const message = e instanceof Error ? e . message : String ( e ) ;
31+ log . warn ( `Research generation failed for ${ protocol . name } :` , message ) ;
1732 return null ;
1833 } ) ;
1934
20- const report = await runLoreAgent ( protocol , metrics ) ;
2135 if ( report ) {
2236 saveReport ( report ) ;
2337 printReport ( report ) ;
2438 }
39+
40+ return report ;
2541}
2642
2743async function researchAll ( ) : Promise < void > {
44+ const startedAt = Date . now ( ) ;
2845 const protocols = getAllProtocols ( ) . slice ( 0 , config . MAX_PROTOCOLS_PER_RUN ) ;
2946 log . info ( `Researching ${ protocols . length } protocols...` ) ;
47+ const cycleReports : ResearchReport [ ] = [ ] ;
48+ let skippedProtocols = 0 ;
3049
3150 for ( const protocol of protocols ) {
32- await researchProtocol ( protocol . id ) ;
33- // small delay to avoid rate limits
34- await new Promise ( ( r ) => setTimeout ( r , 1000 ) ) ;
51+ const report = await researchProtocol ( protocol . id ) ;
52+ if ( report ) {
53+ cycleReports . push ( report ) ;
54+ } else {
55+ skippedProtocols ++ ;
56+ }
57+
58+ await sleep ( 1000 ) ;
3559 }
3660
3761 const all = getAllReports ( ) ;
38- log . info ( `Research complete. ${ all . length } reports generated.` ) ;
39- log . info ( `Top protocol: ${ all [ 0 ] ?. protocolName } (${ all [ 0 ] ?. overallScore } ) — ${ all [ 0 ] ?. verdict } ` ) ;
62+ const leader = cycleReports . sort ( ( a , b ) => b . overallScore - a . overallScore ) [ 0 ] ;
63+ const durationMs = Date . now ( ) - startedAt ;
64+
65+ log . info (
66+ `Research complete. ${ cycleReports . length } reports generated this cycle | ${ skippedProtocols } skipped | ${ all . length } stored total` ,
67+ ) ;
68+
69+ if ( leader ) {
70+ log . info ( `Top protocol this cycle: ${ leader . protocolName } (${ leader . overallScore } ) - ${ leader . verdict } ` ) ;
71+ } else {
72+ log . info ( "No protocol reports qualified this cycle" ) ;
73+ }
74+
75+ log . info ( "Lore research cycle complete" , { durationMs } ) ;
4076}
4177
4278async function main ( ) : Promise < void > {
43- log . info ( "Lore v0.1.0 — DeFi protocol research agent" ) ;
79+ log . info ( "Lore v0.1.0 - DeFi protocol research agent" ) ;
4480
4581 const target = process . argv [ 2 ] ;
4682 if ( target ) {
4783 await researchProtocol ( target ) ;
4884 } else {
49- await researchAll ( ) ;
50- setInterval ( ( ) => researchAll ( ) . catch ( ( e ) => log . error ( "Research cycle error:" , e ) ) , config . REFRESH_INTERVAL_MS ) ;
85+ let cycleInFlight = false ;
86+ let skippedCycles = 0 ;
87+
88+ const tick = async ( ) => {
89+ if ( cycleInFlight ) {
90+ skippedCycles ++ ;
91+ log . warn ( "Skipping research cycle because the previous sweep is still running" , {
92+ skippedCycles,
93+ } ) ;
94+ return ;
95+ }
96+
97+ cycleInFlight = true ;
98+ try {
99+ await researchAll ( ) ;
100+ } catch ( e ) {
101+ log . error ( "Research cycle error:" , e ) ;
102+ } finally {
103+ cycleInFlight = false ;
104+ }
105+ } ;
106+
107+ await tick ( ) ;
108+ setInterval ( ( ) => {
109+ void tick ( ) ;
110+ } , config . REFRESH_INTERVAL_MS ) ;
51111 }
52112}
53113
54- main ( ) . catch ( ( e ) => { log . error ( "Fatal:" , e ) ; process . exit ( 1 ) ; } ) ;
114+ main ( ) . catch ( ( e ) => {
115+ log . error ( "Fatal:" , e ) ;
116+ process . exit ( 1 ) ;
117+ } ) ;
0 commit comments