genesis-ai-cli 14.6.3 → 14.6.4

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.
@@ -9,6 +9,7 @@ import { MessageBus } from './message-bus.js';
9
9
  import { Message, MessageType, ExplorationResult, ExplorationSource } from './types.js';
10
10
  export declare class ExplorerAgent extends BaseAgent {
11
11
  private explorationHistory;
12
+ private mcp;
12
13
  constructor(bus?: MessageBus);
13
14
  protected getMessageTypes(): MessageType[];
14
15
  process(message: Message): Promise<Message | null>;
@@ -16,6 +17,7 @@ export declare class ExplorerAgent extends BaseAgent {
16
17
  private handleCommand;
17
18
  explore(query: string, sources?: ExplorationSource['type'][], depth?: 'shallow' | 'medium' | 'deep'): Promise<ExplorationResult>;
18
19
  private searchSource;
20
+ private computeRelevance;
19
21
  private createFinding;
20
22
  private getDefaultSources;
21
23
  private calculateNovelty;
@@ -10,12 +10,15 @@ exports.ExplorerAgent = void 0;
10
10
  exports.createExplorerAgent = createExplorerAgent;
11
11
  const base_agent_js_1 = require("./base-agent.js");
12
12
  const message_bus_js_1 = require("./message-bus.js");
13
+ const index_js_1 = require("../mcp/index.js");
13
14
  // ============================================================================
14
15
  // Explorer Agent
15
16
  // ============================================================================
16
17
  class ExplorerAgent extends base_agent_js_1.BaseAgent {
17
18
  // Track exploration history for novelty detection
18
19
  explorationHistory = new Set();
20
+ // MCP client for real searches
21
+ mcp = (0, index_js_1.getMCPClient)();
19
22
  constructor(bus = message_bus_js_1.messageBus) {
20
23
  super({ type: 'explorer' }, bus);
21
24
  }
@@ -110,48 +113,137 @@ class ExplorerAgent extends base_agent_js_1.BaseAgent {
110
113
  // Source-Specific Search
111
114
  // ============================================================================
112
115
  async searchSource(source, query) {
113
- // In production, these would call actual MCP servers
114
- // For now, we return simulated results based on source type
115
116
  const findings = [];
116
117
  const metadata = {};
117
- switch (source) {
118
- case 'arxiv':
119
- // Would call: mcp__arxiv__search_arxiv
120
- findings.push(this.createFinding(`[arxiv] Research on "${query}" - Recent papers and preprints`, source, 0.8, true));
121
- metadata.paperCount = 0;
122
- break;
123
- case 'semantic-scholar':
124
- // Would call: mcp__semantic-scholar__search_semantic_scholar
125
- findings.push(this.createFinding(`[semantic-scholar] Academic papers with citations for "${query}"`, source, 0.85, true));
126
- metadata.citationDepth = 2;
127
- break;
128
- case 'brave':
129
- // Would call: mcp__brave-search__brave_web_search
130
- findings.push(this.createFinding(`[brave] Web results and news for "${query}"`, source, 0.7, false));
131
- break;
132
- case 'gemini':
133
- // Would call: mcp__gemini__web_search
134
- findings.push(this.createFinding(`[gemini] AI-synthesized search results for "${query}"`, source, 0.75, false));
135
- break;
136
- case 'exa':
137
- // Would call: mcp__exa__web_search_exa or mcp__exa__get_code_context_exa
138
- findings.push(this.createFinding(`[exa] Code context and examples for "${query}"`, source, 0.8, true));
139
- break;
140
- case 'firecrawl':
141
- // Would call: mcp__firecrawl__firecrawl_search
142
- findings.push(this.createFinding(`[firecrawl] Deep web scraping results for "${query}"`, source, 0.65, false));
143
- break;
144
- case 'context7':
145
- // Would call: mcp__context7__query-docs
146
- findings.push(this.createFinding(`[context7] Library documentation for "${query}"`, source, 0.9, true));
147
- break;
148
- case 'wolfram':
149
- // Would call: mcp__wolfram__wolfram_query
150
- findings.push(this.createFinding(`[wolfram] Computational/mathematical results for "${query}"`, source, 0.95, true));
151
- break;
118
+ try {
119
+ switch (source) {
120
+ case 'arxiv': {
121
+ const result = await this.mcp.call('arxiv', 'search_arxiv', {
122
+ query,
123
+ max_results: 5,
124
+ });
125
+ if (result?.data) {
126
+ const papers = Array.isArray(result.data) ? result.data :
127
+ (result.data.papers || []);
128
+ for (const paper of papers.slice(0, 5)) {
129
+ findings.push(this.createFinding(`[arxiv] ${paper.title || 'Paper'}: ${(paper.summary || paper.abstract || '').slice(0, 200)}...`, source, this.computeRelevance(query, paper.title, paper.summary), true));
130
+ }
131
+ metadata.paperCount = papers.length;
132
+ }
133
+ break;
134
+ }
135
+ case 'semantic-scholar': {
136
+ const result = await this.mcp.call('semantic-scholar', 'search_semantic_scholar', {
137
+ query,
138
+ limit: 5,
139
+ });
140
+ if (result?.data) {
141
+ const papers = Array.isArray(result.data) ? result.data :
142
+ (result.data.papers || []);
143
+ for (const paper of papers.slice(0, 5)) {
144
+ const citations = paper.citationCount || 0;
145
+ findings.push(this.createFinding(`[semantic-scholar] ${paper.title || 'Paper'} (${citations} citations): ${(paper.abstract || '').slice(0, 200)}...`, source, citations > 100 ? 0.9 : citations > 10 ? 0.7 : 0.5, true));
146
+ }
147
+ metadata.citationDepth = 2;
148
+ }
149
+ break;
150
+ }
151
+ case 'brave': {
152
+ const result = await this.mcp.call('brave-search', 'brave_web_search', {
153
+ query,
154
+ count: 5,
155
+ });
156
+ if (result?.data) {
157
+ const results = result.data.web?.results || result.data.results || [];
158
+ for (const item of results.slice(0, 5)) {
159
+ findings.push(this.createFinding(`[brave] ${item.title || 'Result'}: ${(item.description || item.snippet || '').slice(0, 200)}...`, source, 0.7, false));
160
+ }
161
+ }
162
+ break;
163
+ }
164
+ case 'gemini': {
165
+ const result = await this.mcp.call('gemini', 'web_search', {
166
+ query,
167
+ });
168
+ if (result?.data) {
169
+ const content = typeof result.data === 'string' ? result.data :
170
+ JSON.stringify(result.data).slice(0, 500);
171
+ findings.push(this.createFinding(`[gemini] ${content.slice(0, 300)}...`, source, 0.75, false));
172
+ }
173
+ break;
174
+ }
175
+ case 'exa': {
176
+ const result = await this.mcp.call('exa', 'web_search_exa', {
177
+ query,
178
+ numResults: 5,
179
+ });
180
+ if (result?.data) {
181
+ const results = result.data.results || [];
182
+ for (const item of results.slice(0, 5)) {
183
+ findings.push(this.createFinding(`[exa] ${item.title || 'Result'}: ${(item.text || item.snippet || '').slice(0, 200)}...`, source, 0.8, true));
184
+ }
185
+ }
186
+ break;
187
+ }
188
+ case 'firecrawl': {
189
+ const result = await this.mcp.call('firecrawl', 'firecrawl_search', {
190
+ query,
191
+ limit: 5,
192
+ });
193
+ if (result?.data) {
194
+ const results = result.data.results || result.data || [];
195
+ const items = Array.isArray(results) ? results : [results];
196
+ for (const item of items.slice(0, 5)) {
197
+ findings.push(this.createFinding(`[firecrawl] ${item.title || item.url || 'Result'}: ${(item.content || item.description || '').slice(0, 200)}...`, source, 0.65, false));
198
+ }
199
+ }
200
+ break;
201
+ }
202
+ case 'context7': {
203
+ // context7 requires library resolution first
204
+ const libResult = await this.mcp.call('context7', 'resolve-library-id', {
205
+ libraryName: query.split(' ')[0], // Use first word as library name
206
+ });
207
+ if (libResult?.data?.libraryId) {
208
+ const docsResult = await this.mcp.call('context7', 'query-docs', {
209
+ libraryId: libResult.data.libraryId,
210
+ query,
211
+ });
212
+ if (docsResult?.data) {
213
+ findings.push(this.createFinding(`[context7] ${typeof docsResult.data === 'string' ? docsResult.data.slice(0, 300) : JSON.stringify(docsResult.data).slice(0, 300)}...`, source, 0.9, true));
214
+ }
215
+ }
216
+ break;
217
+ }
218
+ case 'wolfram': {
219
+ const result = await this.mcp.call('wolfram', 'wolfram_query', {
220
+ input: query,
221
+ });
222
+ if (result?.data) {
223
+ const content = typeof result.data === 'string' ? result.data :
224
+ JSON.stringify(result.data).slice(0, 500);
225
+ findings.push(this.createFinding(`[wolfram] ${content.slice(0, 300)}...`, source, 0.95, true));
226
+ }
227
+ break;
228
+ }
229
+ }
230
+ }
231
+ catch (error) {
232
+ this.log(`MCP call to ${source} failed: ${error}`);
233
+ // Return empty findings on error - graceful degradation
152
234
  }
153
235
  return { findings, metadata };
154
236
  }
237
+ computeRelevance(query, title, summary) {
238
+ const queryTerms = query.toLowerCase().split(/\s+/);
239
+ const text = `${title || ''} ${summary || ''}`.toLowerCase();
240
+ let matches = 0;
241
+ for (const term of queryTerms) {
242
+ if (text.includes(term))
243
+ matches++;
244
+ }
245
+ return queryTerms.length > 0 ? Math.min(0.95, 0.5 + (matches / queryTerms.length) * 0.45) : 0.5;
246
+ }
155
247
  createFinding(content, sourceType, importance, isNovel) {
156
248
  return {
157
249
  content,
@@ -159,7 +159,9 @@ class PaymentWatcher {
159
159
  try {
160
160
  h(event);
161
161
  }
162
- catch { }
162
+ catch (handlerError) {
163
+ console.error('[PaymentWatcher] Handler error:', handlerError, 'txHash:', event.txHash);
164
+ }
163
165
  }
164
166
  }
165
167
  this.lastBlock = currentBlock;
@@ -79,6 +79,8 @@ export declare class AdvancedRouter {
79
79
  private stats;
80
80
  private metaLearning;
81
81
  private providerHealth;
82
+ private rateLimiters;
83
+ private static readonly TOKEN_REFILL_INTERVAL;
82
84
  constructor(config?: {
83
85
  costOptimize: boolean;
84
86
  speedOptimize: boolean;
@@ -87,6 +89,11 @@ export declare class AdvancedRouter {
87
89
  enableMetaLearning: boolean;
88
90
  });
89
91
  private checkProviderHealth;
92
+ /**
93
+ * Enforce rate limiting using token bucket algorithm.
94
+ * Waits if tokens are exhausted, preventing 429 errors.
95
+ */
96
+ private enforceRateLimit;
90
97
  private getAvailableProviders;
91
98
  route(prompt: string, forceTaskType?: TaskType): Promise<AdvancedRoutingDecision>;
92
99
  private selectCheapest;
@@ -408,6 +408,9 @@ class AdvancedRouter {
408
408
  };
409
409
  metaLearning = [];
410
410
  providerHealth = new Map();
411
+ // Rate limiting with token bucket
412
+ rateLimiters = new Map();
413
+ static TOKEN_REFILL_INTERVAL = 60000; // 1 minute
411
414
  constructor(config = {
412
415
  costOptimize: true,
413
416
  speedOptimize: true,
@@ -458,6 +461,33 @@ class AdvancedRouter {
458
461
  this.providerHealth.set(provider, { available, lastCheck: now });
459
462
  return available;
460
463
  }
464
+ /**
465
+ * Enforce rate limiting using token bucket algorithm.
466
+ * Waits if tokens are exhausted, preventing 429 errors.
467
+ */
468
+ async enforceRateLimit(provider) {
469
+ const config = exports.PROVIDER_REGISTRY[provider];
470
+ const rateLimit = config.rateLimit || 60; // Default 60 RPM
471
+ let bucket = this.rateLimiters.get(provider);
472
+ const now = Date.now();
473
+ if (!bucket) {
474
+ bucket = { tokens: rateLimit, lastRefill: now };
475
+ this.rateLimiters.set(provider, bucket);
476
+ }
477
+ // Refill tokens based on time elapsed
478
+ const elapsed = now - bucket.lastRefill;
479
+ const refillAmount = (elapsed / AdvancedRouter.TOKEN_REFILL_INTERVAL) * rateLimit;
480
+ bucket.tokens = Math.min(rateLimit, bucket.tokens + refillAmount);
481
+ bucket.lastRefill = now;
482
+ // Wait if no tokens available
483
+ if (bucket.tokens < 1) {
484
+ const waitMs = Math.ceil((1 - bucket.tokens) * (AdvancedRouter.TOKEN_REFILL_INTERVAL / rateLimit));
485
+ console.log(`[AdvancedRouter] Rate limit reached for ${provider}, waiting ${waitMs}ms`);
486
+ await new Promise(r => setTimeout(r, waitMs));
487
+ bucket.tokens = 1; // Reset after wait
488
+ }
489
+ bucket.tokens--;
490
+ }
461
491
  async getAvailableProviders() {
462
492
  const checks = await Promise.all(Object.keys(exports.PROVIDER_REGISTRY).map(async (p) => ({
463
493
  provider: p,
@@ -611,6 +641,8 @@ class AdvancedRouter {
611
641
  // Provider Calls
612
642
  // ==========================================================================
613
643
  async callProvider(provider, model, prompt, systemPrompt) {
644
+ // Enforce rate limiting before making the call
645
+ await this.enforceRateLimit(provider);
614
646
  const startTime = Date.now();
615
647
  const config = exports.PROVIDER_REGISTRY[provider];
616
648
  switch (provider) {
@@ -634,6 +634,13 @@ class LLMBridge {
634
634
  }
635
635
  finally {
636
636
  reader.releaseLock();
637
+ // Properly clean up the stream to prevent connection leaks
638
+ try {
639
+ await response.body?.cancel();
640
+ }
641
+ catch {
642
+ // Ignore cancel errors - stream may already be closed
643
+ }
637
644
  }
638
645
  // Add to history
639
646
  this.conversationHistory.push({ role: 'assistant', content: fullContent });
@@ -759,6 +766,13 @@ class LLMBridge {
759
766
  }
760
767
  finally {
761
768
  reader.releaseLock();
769
+ // Properly clean up the stream to prevent connection leaks
770
+ try {
771
+ await response.body?.cancel();
772
+ }
773
+ catch {
774
+ // Ignore cancel errors - stream may already be closed
775
+ }
762
776
  }
763
777
  // Add to history
764
778
  this.conversationHistory.push({ role: 'assistant', content: fullContent });
@@ -842,6 +856,13 @@ class LLMBridge {
842
856
  }
843
857
  finally {
844
858
  reader.releaseLock();
859
+ // Properly clean up the stream to prevent connection leaks
860
+ try {
861
+ await response.body?.cancel();
862
+ }
863
+ catch {
864
+ // Ignore cancel errors - stream may already be closed
865
+ }
845
866
  }
846
867
  // Add to history
847
868
  this.conversationHistory.push({ role: 'assistant', content: fullContent });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis-ai-cli",
3
- "version": "14.6.3",
3
+ "version": "14.6.4",
4
4
  "description": "Fully Autonomous AI System with RSI (Recursive Self-Improvement) - Self-funding, Self-deploying, Production Memory, A2A Protocol & Governance",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",