genesis-ai-cli 7.4.8 → 7.5.1

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.
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Genesis MCP Intelligent Cache
3
+ *
4
+ * Smart caching with per-server TTL, semantic deduplication,
5
+ * and LRU eviction.
6
+ *
7
+ * Features:
8
+ * - Per-server TTL configuration
9
+ * - Semantic key hashing (similar queries hit same cache)
10
+ * - LRU eviction with configurable max size
11
+ * - Cache statistics and monitoring
12
+ * - Invalidation patterns
13
+ * - Persistent cache option (filesystem)
14
+ */
15
+ import { MCPServerName } from '../types.js';
16
+ import { MCPCallResult } from './index.js';
17
+ export interface CacheEntry<T = any> {
18
+ key: string;
19
+ data: T;
20
+ server: MCPServerName;
21
+ tool: string;
22
+ createdAt: number;
23
+ expiresAt: number;
24
+ hits: number;
25
+ size: number;
26
+ }
27
+ export interface CacheStats {
28
+ hits: number;
29
+ misses: number;
30
+ entries: number;
31
+ totalSize: number;
32
+ hitRate: number;
33
+ byServer: Record<MCPServerName, {
34
+ hits: number;
35
+ misses: number;
36
+ entries: number;
37
+ }>;
38
+ }
39
+ export interface CacheConfig {
40
+ maxEntries?: number;
41
+ maxSize?: number;
42
+ defaultTTL?: number;
43
+ serverTTL?: Partial<Record<MCPServerName, number>>;
44
+ persistent?: boolean;
45
+ persistPath?: string;
46
+ semanticKeys?: boolean;
47
+ }
48
+ export declare class MCPCache {
49
+ private cache;
50
+ private accessOrder;
51
+ private stats;
52
+ private config;
53
+ constructor(config?: CacheConfig);
54
+ /**
55
+ * Get cached result
56
+ */
57
+ get<T = any>(server: MCPServerName, tool: string, params: Record<string, any>): CacheEntry<T> | null;
58
+ /**
59
+ * Cache a result
60
+ */
61
+ set<T = any>(server: MCPServerName, tool: string, params: Record<string, any>, data: T): void;
62
+ /**
63
+ * Wrap an MCP call with caching
64
+ */
65
+ wrap<T = any>(server: MCPServerName, tool: string, params: Record<string, any>, fetcher: () => Promise<MCPCallResult<T>>): Promise<MCPCallResult<T>>;
66
+ /**
67
+ * Invalidate cache entries
68
+ */
69
+ invalidate(pattern: {
70
+ server?: MCPServerName;
71
+ tool?: string;
72
+ olderThan?: number;
73
+ }): number;
74
+ /**
75
+ * Clear entire cache
76
+ */
77
+ clear(): void;
78
+ /**
79
+ * Get cache statistics
80
+ */
81
+ getStats(): CacheStats;
82
+ /**
83
+ * Get cache entries for debugging
84
+ */
85
+ getEntries(): CacheEntry[];
86
+ private generateKey;
87
+ private normalizeParams;
88
+ private getTTL;
89
+ private estimateSize;
90
+ private updateAccessOrder;
91
+ private evictIfNeeded;
92
+ private delete;
93
+ private updateHitRate;
94
+ private loadFromDisk;
95
+ private persistEntry;
96
+ private clearDisk;
97
+ }
98
+ export declare function getMCPCache(config?: CacheConfig): MCPCache;
99
+ export declare function resetMCPCache(): void;
100
+ export declare function withCache<T = any>(server: MCPServerName, tool: string, params: Record<string, any>, fetcher: () => Promise<MCPCallResult<T>>): Promise<MCPCallResult<T>>;
@@ -0,0 +1,395 @@
1
+ "use strict";
2
+ /**
3
+ * Genesis MCP Intelligent Cache
4
+ *
5
+ * Smart caching with per-server TTL, semantic deduplication,
6
+ * and LRU eviction.
7
+ *
8
+ * Features:
9
+ * - Per-server TTL configuration
10
+ * - Semantic key hashing (similar queries hit same cache)
11
+ * - LRU eviction with configurable max size
12
+ * - Cache statistics and monitoring
13
+ * - Invalidation patterns
14
+ * - Persistent cache option (filesystem)
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.MCPCache = void 0;
51
+ exports.getMCPCache = getMCPCache;
52
+ exports.resetMCPCache = resetMCPCache;
53
+ exports.withCache = withCache;
54
+ const crypto_1 = require("crypto");
55
+ const fs = __importStar(require("fs"));
56
+ const path = __importStar(require("path"));
57
+ // ============================================================================
58
+ // Default TTLs per server
59
+ // ============================================================================
60
+ const DEFAULT_SERVER_TTL = {
61
+ // Knowledge (can be cached longer)
62
+ 'arxiv': 1000 * 60 * 60 * 24, // 24 hours
63
+ 'semantic-scholar': 1000 * 60 * 60 * 24, // 24 hours
64
+ 'context7': 1000 * 60 * 60 * 12, // 12 hours
65
+ 'wolfram': 1000 * 60 * 60, // 1 hour
66
+ // Research (moderate caching)
67
+ 'gemini': 1000 * 60 * 30, // 30 minutes
68
+ 'brave-search': 1000 * 60 * 15, // 15 minutes (search results change)
69
+ 'exa': 1000 * 60 * 30, // 30 minutes
70
+ 'firecrawl': 1000 * 60 * 60, // 1 hour (scraped content)
71
+ // Creation (no caching by default)
72
+ 'openai': 0, // Don't cache AI responses
73
+ 'github': 1000 * 60 * 5, // 5 minutes (repos can change)
74
+ // Visual (no caching)
75
+ 'stability-ai': 0, // Don't cache generated images
76
+ // Storage (short cache)
77
+ 'memory': 1000 * 60 * 5, // 5 minutes
78
+ 'filesystem': 1000 * 60, // 1 minute
79
+ };
80
+ // ============================================================================
81
+ // Cache Implementation
82
+ // ============================================================================
83
+ class MCPCache {
84
+ cache = new Map();
85
+ accessOrder = []; // For LRU
86
+ stats = {
87
+ hits: 0,
88
+ misses: 0,
89
+ entries: 0,
90
+ totalSize: 0,
91
+ hitRate: 0,
92
+ byServer: {},
93
+ };
94
+ config;
95
+ constructor(config = {}) {
96
+ this.config = {
97
+ maxEntries: config.maxEntries ?? 1000,
98
+ maxSize: config.maxSize ?? 50 * 1024 * 1024, // 50MB
99
+ defaultTTL: config.defaultTTL ?? 1000 * 60 * 30, // 30 minutes
100
+ serverTTL: { ...DEFAULT_SERVER_TTL, ...config.serverTTL },
101
+ persistent: config.persistent ?? false,
102
+ persistPath: config.persistPath ?? path.join(process.cwd(), '.genesis-cache'),
103
+ semanticKeys: config.semanticKeys ?? true,
104
+ };
105
+ // Load persistent cache
106
+ if (this.config.persistent) {
107
+ this.loadFromDisk();
108
+ }
109
+ }
110
+ /**
111
+ * Get cached result
112
+ */
113
+ get(server, tool, params) {
114
+ const key = this.generateKey(server, tool, params);
115
+ const entry = this.cache.get(key);
116
+ // Initialize server stats if needed
117
+ if (!this.stats.byServer[server]) {
118
+ this.stats.byServer[server] = { hits: 0, misses: 0, entries: 0 };
119
+ }
120
+ if (!entry) {
121
+ this.stats.misses++;
122
+ this.stats.byServer[server].misses++;
123
+ this.updateHitRate();
124
+ return null;
125
+ }
126
+ // Check expiration
127
+ if (Date.now() > entry.expiresAt) {
128
+ this.delete(key);
129
+ this.stats.misses++;
130
+ this.stats.byServer[server].misses++;
131
+ this.updateHitRate();
132
+ return null;
133
+ }
134
+ // Update LRU order
135
+ this.updateAccessOrder(key);
136
+ entry.hits++;
137
+ this.stats.hits++;
138
+ this.stats.byServer[server].hits++;
139
+ this.updateHitRate();
140
+ return entry;
141
+ }
142
+ /**
143
+ * Cache a result
144
+ */
145
+ set(server, tool, params, data) {
146
+ const ttl = this.getTTL(server);
147
+ // Don't cache if TTL is 0
148
+ if (ttl === 0)
149
+ return;
150
+ const key = this.generateKey(server, tool, params);
151
+ const size = this.estimateSize(data);
152
+ // Evict if necessary
153
+ this.evictIfNeeded(size);
154
+ const entry = {
155
+ key,
156
+ data,
157
+ server,
158
+ tool,
159
+ createdAt: Date.now(),
160
+ expiresAt: Date.now() + ttl,
161
+ hits: 0,
162
+ size,
163
+ };
164
+ this.cache.set(key, entry);
165
+ this.updateAccessOrder(key);
166
+ // Update stats
167
+ this.stats.entries = this.cache.size;
168
+ this.stats.totalSize += size;
169
+ if (!this.stats.byServer[server]) {
170
+ this.stats.byServer[server] = { hits: 0, misses: 0, entries: 0 };
171
+ }
172
+ this.stats.byServer[server].entries++;
173
+ // Persist if enabled
174
+ if (this.config.persistent) {
175
+ this.persistEntry(entry);
176
+ }
177
+ }
178
+ /**
179
+ * Wrap an MCP call with caching
180
+ */
181
+ async wrap(server, tool, params, fetcher) {
182
+ // Check cache first
183
+ const cached = this.get(server, tool, params);
184
+ if (cached) {
185
+ return {
186
+ success: true,
187
+ data: cached.data,
188
+ server,
189
+ tool,
190
+ mode: 'real',
191
+ latency: 0,
192
+ timestamp: new Date(),
193
+ };
194
+ }
195
+ // Fetch and cache
196
+ const result = await fetcher();
197
+ if (result.success && result.data) {
198
+ this.set(server, tool, params, result.data);
199
+ }
200
+ return result;
201
+ }
202
+ /**
203
+ * Invalidate cache entries
204
+ */
205
+ invalidate(pattern) {
206
+ let invalidated = 0;
207
+ const now = Date.now();
208
+ for (const [key, entry] of this.cache) {
209
+ let shouldInvalidate = false;
210
+ if (pattern.server && entry.server === pattern.server) {
211
+ shouldInvalidate = true;
212
+ }
213
+ if (pattern.tool && entry.tool === pattern.tool) {
214
+ shouldInvalidate = true;
215
+ }
216
+ if (pattern.olderThan && now - entry.createdAt > pattern.olderThan) {
217
+ shouldInvalidate = true;
218
+ }
219
+ if (shouldInvalidate) {
220
+ this.delete(key);
221
+ invalidated++;
222
+ }
223
+ }
224
+ return invalidated;
225
+ }
226
+ /**
227
+ * Clear entire cache
228
+ */
229
+ clear() {
230
+ this.cache.clear();
231
+ this.accessOrder = [];
232
+ this.stats = {
233
+ hits: 0,
234
+ misses: 0,
235
+ entries: 0,
236
+ totalSize: 0,
237
+ hitRate: 0,
238
+ byServer: {},
239
+ };
240
+ if (this.config.persistent) {
241
+ this.clearDisk();
242
+ }
243
+ }
244
+ /**
245
+ * Get cache statistics
246
+ */
247
+ getStats() {
248
+ return { ...this.stats };
249
+ }
250
+ /**
251
+ * Get cache entries for debugging
252
+ */
253
+ getEntries() {
254
+ return Array.from(this.cache.values());
255
+ }
256
+ // ============================================================================
257
+ // Private Methods
258
+ // ============================================================================
259
+ generateKey(server, tool, params) {
260
+ let paramsStr = JSON.stringify(params, Object.keys(params).sort());
261
+ // Semantic key normalization
262
+ if (this.config.semanticKeys) {
263
+ paramsStr = this.normalizeParams(paramsStr);
264
+ }
265
+ const hash = (0, crypto_1.createHash)('sha256')
266
+ .update(`${server}:${tool}:${paramsStr}`)
267
+ .digest('hex')
268
+ .slice(0, 16);
269
+ return `${server}:${tool}:${hash}`;
270
+ }
271
+ normalizeParams(paramsStr) {
272
+ // Normalize whitespace and case for query-like params
273
+ return paramsStr
274
+ .toLowerCase()
275
+ .replace(/\s+/g, ' ')
276
+ .trim();
277
+ }
278
+ getTTL(server) {
279
+ return this.config.serverTTL[server] ?? this.config.defaultTTL;
280
+ }
281
+ estimateSize(data) {
282
+ try {
283
+ return JSON.stringify(data).length * 2; // Rough estimate for UTF-16
284
+ }
285
+ catch {
286
+ return 1000; // Default estimate
287
+ }
288
+ }
289
+ updateAccessOrder(key) {
290
+ const index = this.accessOrder.indexOf(key);
291
+ if (index > -1) {
292
+ this.accessOrder.splice(index, 1);
293
+ }
294
+ this.accessOrder.push(key);
295
+ }
296
+ evictIfNeeded(newSize) {
297
+ // Evict by count
298
+ while (this.cache.size >= this.config.maxEntries && this.accessOrder.length > 0) {
299
+ const oldest = this.accessOrder.shift();
300
+ this.delete(oldest);
301
+ }
302
+ // Evict by size
303
+ while (this.stats.totalSize + newSize > this.config.maxSize && this.accessOrder.length > 0) {
304
+ const oldest = this.accessOrder.shift();
305
+ this.delete(oldest);
306
+ }
307
+ }
308
+ delete(key) {
309
+ const entry = this.cache.get(key);
310
+ if (entry) {
311
+ this.stats.totalSize -= entry.size;
312
+ this.stats.entries--;
313
+ if (this.stats.byServer[entry.server]) {
314
+ this.stats.byServer[entry.server].entries--;
315
+ }
316
+ this.cache.delete(key);
317
+ const idx = this.accessOrder.indexOf(key);
318
+ if (idx > -1) {
319
+ this.accessOrder.splice(idx, 1);
320
+ }
321
+ }
322
+ }
323
+ updateHitRate() {
324
+ const total = this.stats.hits + this.stats.misses;
325
+ this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
326
+ }
327
+ // ============================================================================
328
+ // Persistence
329
+ // ============================================================================
330
+ loadFromDisk() {
331
+ try {
332
+ const indexPath = path.join(this.config.persistPath, 'cache-index.json');
333
+ if (fs.existsSync(indexPath)) {
334
+ const index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
335
+ for (const entry of index.entries) {
336
+ if (Date.now() < entry.expiresAt) {
337
+ this.cache.set(entry.key, entry);
338
+ this.accessOrder.push(entry.key);
339
+ }
340
+ }
341
+ this.stats.entries = this.cache.size;
342
+ }
343
+ }
344
+ catch {
345
+ // Ignore load errors
346
+ }
347
+ }
348
+ persistEntry(entry) {
349
+ try {
350
+ if (!fs.existsSync(this.config.persistPath)) {
351
+ fs.mkdirSync(this.config.persistPath, { recursive: true });
352
+ }
353
+ const indexPath = path.join(this.config.persistPath, 'cache-index.json');
354
+ const index = { entries: Array.from(this.cache.values()) };
355
+ fs.writeFileSync(indexPath, JSON.stringify(index));
356
+ }
357
+ catch {
358
+ // Ignore persist errors
359
+ }
360
+ }
361
+ clearDisk() {
362
+ try {
363
+ const indexPath = path.join(this.config.persistPath, 'cache-index.json');
364
+ if (fs.existsSync(indexPath)) {
365
+ fs.unlinkSync(indexPath);
366
+ }
367
+ }
368
+ catch {
369
+ // Ignore clear errors
370
+ }
371
+ }
372
+ }
373
+ exports.MCPCache = MCPCache;
374
+ // ============================================================================
375
+ // Singleton
376
+ // ============================================================================
377
+ let cacheInstance = null;
378
+ function getMCPCache(config) {
379
+ if (!cacheInstance) {
380
+ cacheInstance = new MCPCache(config);
381
+ }
382
+ return cacheInstance;
383
+ }
384
+ function resetMCPCache() {
385
+ if (cacheInstance) {
386
+ cacheInstance.clear();
387
+ }
388
+ cacheInstance = null;
389
+ }
390
+ // ============================================================================
391
+ // Decorator-style cache wrapper
392
+ // ============================================================================
393
+ function withCache(server, tool, params, fetcher) {
394
+ return getMCPCache().wrap(server, tool, params, fetcher);
395
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Genesis 6.8 - Real MCP Client Module
2
+ * Genesis 7.5 - Real MCP Client Module
3
3
  *
4
4
  * Connects to actual MCP servers using @modelcontextprotocol/sdk.
5
5
  * Spawns servers on demand and manages connections.
@@ -8,8 +8,22 @@
8
8
  * - GENESIS_MCP_MODE: 'real' | 'simulated' | 'hybrid' (default: 'simulated')
9
9
  * - GENESIS_MCP_TIMEOUT: Timeout in ms (default: 30000)
10
10
  * - GENESIS_MCP_LOG: Enable MCP call logging (default: false)
11
+ *
12
+ * New in 7.5: Frontier MCP capabilities
13
+ * - Tool Chaining: Automatic orchestration of dependent tool calls
14
+ * - Streaming: Real-time result streaming with progress
15
+ * - Multimodal: Image/media display in terminal
16
+ * - Cache: Intelligent per-server caching with TTL
17
+ * - DAG Executor: Parallel execution with dependency awareness
18
+ * - Transformers: Composable result transformations
11
19
  */
12
20
  export * from './resilient.js';
21
+ export * from './tool-chain.js';
22
+ export * from './streaming.js';
23
+ export * from './multimodal.js';
24
+ export * from './cache.js';
25
+ export * from './parallel-executor.js';
26
+ export * from './transformers.js';
13
27
  import { MCPServerName } from '../types.js';
14
28
  export type MCPMode = 'real' | 'simulated' | 'hybrid';
15
29
  export interface MCPCallOptions {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * Genesis 6.8 - Real MCP Client Module
3
+ * Genesis 7.5 - Real MCP Client Module
4
4
  *
5
5
  * Connects to actual MCP servers using @modelcontextprotocol/sdk.
6
6
  * Spawns servers on demand and manages connections.
@@ -9,6 +9,14 @@
9
9
  * - GENESIS_MCP_MODE: 'real' | 'simulated' | 'hybrid' (default: 'simulated')
10
10
  * - GENESIS_MCP_TIMEOUT: Timeout in ms (default: 30000)
11
11
  * - GENESIS_MCP_LOG: Enable MCP call logging (default: false)
12
+ *
13
+ * New in 7.5: Frontier MCP capabilities
14
+ * - Tool Chaining: Automatic orchestration of dependent tool calls
15
+ * - Streaming: Real-time result streaming with progress
16
+ * - Multimodal: Image/media display in terminal
17
+ * - Cache: Intelligent per-server caching with TTL
18
+ * - DAG Executor: Parallel execution with dependency awareness
19
+ * - Transformers: Composable result transformations
12
20
  */
13
21
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
22
  if (k2 === undefined) k2 = k;
@@ -33,6 +41,13 @@ exports.isSimulatedResult = isSimulatedResult;
33
41
  exports.logMCPMode = logMCPMode;
34
42
  // Re-export Phase 8: Resilient MCP Wrapper
35
43
  __exportStar(require("./resilient.js"), exports);
44
+ // Re-export Phase 10: Frontier MCP Capabilities
45
+ __exportStar(require("./tool-chain.js"), exports);
46
+ __exportStar(require("./streaming.js"), exports);
47
+ __exportStar(require("./multimodal.js"), exports);
48
+ __exportStar(require("./cache.js"), exports);
49
+ __exportStar(require("./parallel-executor.js"), exports);
50
+ __exportStar(require("./transformers.js"), exports);
36
51
  const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
37
52
  const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
38
53
  const crypto_1 = require("crypto");
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Genesis MCP Multimodal Handler
3
+ *
4
+ * Handles image, audio, and other media types from MCP tool results.
5
+ * Provides terminal display, file management, and format conversion.
6
+ *
7
+ * Features:
8
+ * - Detect media in tool results
9
+ * - Display images in terminal (iTerm2, Kitty, sixel)
10
+ * - Open media with system default apps
11
+ * - Convert between formats
12
+ * - Thumbnail generation
13
+ */
14
+ export type MediaType = 'image' | 'audio' | 'video' | 'document' | 'unknown';
15
+ export interface MediaInfo {
16
+ type: MediaType;
17
+ mimeType: string;
18
+ path?: string;
19
+ url?: string;
20
+ base64?: string;
21
+ width?: number;
22
+ height?: number;
23
+ size?: number;
24
+ format?: string;
25
+ }
26
+ export interface DisplayOptions {
27
+ maxWidth?: number;
28
+ maxHeight?: number;
29
+ autoOpen?: boolean;
30
+ inline?: boolean;
31
+ protocol?: TerminalProtocol;
32
+ }
33
+ export type TerminalProtocol = 'iterm2' | 'kitty' | 'sixel' | 'ascii' | 'none';
34
+ export interface MultimodalResult {
35
+ detected: boolean;
36
+ media: MediaInfo[];
37
+ displayedInline: boolean;
38
+ openedExternally: boolean;
39
+ }
40
+ export declare function detectMediaType(input: string | MediaInfo): MediaType;
41
+ export declare function extractMediaFromResult(result: any): MediaInfo[];
42
+ export declare function detectTerminalProtocol(): TerminalProtocol;
43
+ export declare function displayImageInline(imagePath: string, options?: DisplayOptions): Promise<boolean>;
44
+ export declare function openWithSystemViewer(filePath: string): Promise<boolean>;
45
+ export declare class MultimodalHandler {
46
+ private options;
47
+ constructor(options?: DisplayOptions);
48
+ handleResult(result: any): Promise<MultimodalResult>;
49
+ setOptions(options: Partial<DisplayOptions>): void;
50
+ }
51
+ export declare function getMultimodalHandler(options?: DisplayOptions): MultimodalHandler;
52
+ export declare function handleMultimodalResult(result: any): Promise<MultimodalResult>;