genesis-ai-cli 14.3.0 → 14.4.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/dist/src/cli/agentic.js +26 -4
- package/dist/src/index.js +47 -6
- package/dist/src/llm/router.d.ts +6 -0
- package/dist/src/llm/router.js +17 -1
- package/dist/src/memory/vector-store.d.ts +5 -1
- package/dist/src/memory/vector-store.js +27 -11
- package/dist/src/streaming/hybrid-executor.js +57 -15
- package/package.json +1 -1
package/dist/src/cli/agentic.js
CHANGED
|
@@ -298,7 +298,12 @@ class AgenticToolExecutor {
|
|
|
298
298
|
}
|
|
299
299
|
// Read file with line numbers
|
|
300
300
|
async readFile(args) {
|
|
301
|
-
|
|
301
|
+
// Accept both file_path and path for flexibility
|
|
302
|
+
const inputPath = args.file_path || args.path;
|
|
303
|
+
if (!inputPath) {
|
|
304
|
+
return 'Error: file_path is required';
|
|
305
|
+
}
|
|
306
|
+
const filePath = path.isAbsolute(inputPath) ? inputPath : path.join(this.cwd, inputPath);
|
|
302
307
|
if (!fs.existsSync(filePath)) {
|
|
303
308
|
return `File not found: ${filePath}`;
|
|
304
309
|
}
|
|
@@ -317,7 +322,11 @@ class AgenticToolExecutor {
|
|
|
317
322
|
}
|
|
318
323
|
// Write file
|
|
319
324
|
async writeFile(args) {
|
|
320
|
-
const
|
|
325
|
+
const inputPath = args.file_path || args.path;
|
|
326
|
+
if (!inputPath) {
|
|
327
|
+
return 'Error: file_path is required';
|
|
328
|
+
}
|
|
329
|
+
const filePath = path.isAbsolute(inputPath) ? inputPath : path.join(this.cwd, inputPath);
|
|
321
330
|
// Ensure directory exists
|
|
322
331
|
const dir = path.dirname(filePath);
|
|
323
332
|
if (!fs.existsSync(dir)) {
|
|
@@ -328,7 +337,11 @@ class AgenticToolExecutor {
|
|
|
328
337
|
}
|
|
329
338
|
// Edit file with string replacement
|
|
330
339
|
async editFile(args) {
|
|
331
|
-
const
|
|
340
|
+
const inputPath = args.file_path || args.path;
|
|
341
|
+
if (!inputPath) {
|
|
342
|
+
return 'Error: file_path is required';
|
|
343
|
+
}
|
|
344
|
+
const filePath = path.isAbsolute(inputPath) ? inputPath : path.join(this.cwd, inputPath);
|
|
332
345
|
if (!fs.existsSync(filePath)) {
|
|
333
346
|
return `File not found: ${filePath}`;
|
|
334
347
|
}
|
|
@@ -677,8 +690,17 @@ ${colorize('Commands:', 'cyan')}
|
|
|
677
690
|
const toolMatch = content.match(/```tool\s*\n([\s\S]*?)\n```/);
|
|
678
691
|
if (toolMatch) {
|
|
679
692
|
try {
|
|
680
|
-
const
|
|
693
|
+
const rawJson = toolMatch[1].trim();
|
|
694
|
+
const toolCall = JSON.parse(rawJson);
|
|
695
|
+
// Ensure arguments exists
|
|
696
|
+
if (!toolCall.arguments) {
|
|
697
|
+
toolCall.arguments = {};
|
|
698
|
+
}
|
|
681
699
|
console.log((0, ui_js_1.muted)(`\n ⚙ ${toolCall.name}...`));
|
|
700
|
+
// Debug: show what arguments were parsed
|
|
701
|
+
if (Object.keys(toolCall.arguments).length === 0) {
|
|
702
|
+
console.log((0, ui_js_1.muted)(` ⚠ No arguments parsed. Raw JSON: ${rawJson.slice(0, 200)}`));
|
|
703
|
+
}
|
|
682
704
|
const result = await this.executor.execute({
|
|
683
705
|
id: `tool-${Date.now()}`,
|
|
684
706
|
name: toolCall.name,
|
package/dist/src/index.js
CHANGED
|
@@ -225,7 +225,13 @@ async function cmdPipeline(specOrFile, options) {
|
|
|
225
225
|
console.error(c(`Error: Spec file not found: ${specOrFile}`, 'red'));
|
|
226
226
|
process.exit(1);
|
|
227
227
|
}
|
|
228
|
-
|
|
228
|
+
try {
|
|
229
|
+
spec = JSON.parse(fs.readFileSync(specOrFile, 'utf-8'));
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
console.error(c(`Error: Invalid JSON in spec file: ${err instanceof Error ? err.message : String(err)}`, 'red'));
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
229
235
|
}
|
|
230
236
|
else {
|
|
231
237
|
spec = specOrFile;
|
|
@@ -296,7 +302,14 @@ async function cmdDesign(specFile) {
|
|
|
296
302
|
console.error(c(`Error: Spec file not found: ${specFile}`, 'red'));
|
|
297
303
|
process.exit(1);
|
|
298
304
|
}
|
|
299
|
-
|
|
305
|
+
let spec;
|
|
306
|
+
try {
|
|
307
|
+
spec = JSON.parse(fs.readFileSync(specFile, 'utf-8'));
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
console.error(c(`Error: Invalid JSON in spec file: ${err instanceof Error ? err.message : String(err)}`, 'red'));
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
300
313
|
console.log(c(`\nDesigning architecture for: ${spec.name}\n`, 'bold'));
|
|
301
314
|
const orchestrator = (0, orchestrator_js_1.createOrchestrator)({ verbose: true });
|
|
302
315
|
const prompt = orchestrator.buildArchitecturePrompt(spec, {
|
|
@@ -319,7 +332,14 @@ async function cmdGenerate(specFile) {
|
|
|
319
332
|
console.error(c(`Error: Spec file not found: ${specFile}`, 'red'));
|
|
320
333
|
process.exit(1);
|
|
321
334
|
}
|
|
322
|
-
|
|
335
|
+
let spec;
|
|
336
|
+
try {
|
|
337
|
+
spec = JSON.parse(fs.readFileSync(specFile, 'utf-8'));
|
|
338
|
+
}
|
|
339
|
+
catch (err) {
|
|
340
|
+
console.error(c(`Error: Invalid JSON in spec file: ${err instanceof Error ? err.message : String(err)}`, 'red'));
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
323
343
|
console.log(c(`\nGenerating code for: ${spec.name}\n`, 'bold'));
|
|
324
344
|
const orchestrator = (0, orchestrator_js_1.createOrchestrator)({ verbose: true });
|
|
325
345
|
const prompt = orchestrator.buildCodePrompt(spec, { components: [], relations: [], invariants: [], operations: [], events: [] }, 'typescript');
|
|
@@ -337,7 +357,14 @@ async function cmdVisualize(specFile) {
|
|
|
337
357
|
console.error(c(`Error: Spec file not found: ${specFile}`, 'red'));
|
|
338
358
|
process.exit(1);
|
|
339
359
|
}
|
|
340
|
-
|
|
360
|
+
let spec;
|
|
361
|
+
try {
|
|
362
|
+
spec = JSON.parse(fs.readFileSync(specFile, 'utf-8'));
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
console.error(c(`Error: Invalid JSON in spec file: ${err instanceof Error ? err.message : String(err)}`, 'red'));
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
341
368
|
console.log(c(`\nCreating visuals for: ${spec.name}\n`, 'bold'));
|
|
342
369
|
const orchestrator = (0, orchestrator_js_1.createOrchestrator)({ verbose: true });
|
|
343
370
|
const visualTypes = ['architecture', 'concept', 'logo'];
|
|
@@ -355,7 +382,14 @@ async function cmdPublish(specFile) {
|
|
|
355
382
|
console.error(c(`Error: Spec file not found: ${specFile}`, 'red'));
|
|
356
383
|
process.exit(1);
|
|
357
384
|
}
|
|
358
|
-
|
|
385
|
+
let spec;
|
|
386
|
+
try {
|
|
387
|
+
spec = JSON.parse(fs.readFileSync(specFile, 'utf-8'));
|
|
388
|
+
}
|
|
389
|
+
catch (err) {
|
|
390
|
+
console.error(c(`Error: Invalid JSON in spec file: ${err instanceof Error ? err.message : String(err)}`, 'red'));
|
|
391
|
+
process.exit(1);
|
|
392
|
+
}
|
|
359
393
|
console.log(c(`\nPublishing: ${spec.name}\n`, 'bold'));
|
|
360
394
|
console.log(c('Steps:', 'cyan'));
|
|
361
395
|
console.log(' 1. Create GitHub repository');
|
|
@@ -1805,7 +1839,14 @@ async function cmdAgentic(subcommand, options) {
|
|
|
1805
1839
|
// ============================================================================
|
|
1806
1840
|
async function cmdInstall(options) {
|
|
1807
1841
|
const { execSync, spawn } = await import('child_process');
|
|
1808
|
-
|
|
1842
|
+
let pkg;
|
|
1843
|
+
try {
|
|
1844
|
+
pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf-8'));
|
|
1845
|
+
}
|
|
1846
|
+
catch (err) {
|
|
1847
|
+
console.error(c('Error: Could not read package.json', 'red'));
|
|
1848
|
+
process.exit(1);
|
|
1849
|
+
}
|
|
1809
1850
|
const version = pkg.version;
|
|
1810
1851
|
console.log(c(`\n=== Genesis Installation (v${version}) ===\n`, 'bold'));
|
|
1811
1852
|
// Check current installation
|
package/dist/src/llm/router.d.ts
CHANGED
|
@@ -101,6 +101,8 @@ export declare class HybridRouter {
|
|
|
101
101
|
private localBridge;
|
|
102
102
|
private cloudBridge;
|
|
103
103
|
private hardwareProfile;
|
|
104
|
+
private ollamaAvailableCache;
|
|
105
|
+
private static readonly OLLAMA_CACHE_TTL_MS;
|
|
104
106
|
constructor(config?: Partial<RouterConfig>);
|
|
105
107
|
/**
|
|
106
108
|
* Get detected hardware profile
|
|
@@ -116,6 +118,10 @@ export declare class HybridRouter {
|
|
|
116
118
|
execute(prompt: string, systemPrompt?: string): Promise<LLMResponse & {
|
|
117
119
|
routingDecision: RoutingDecision;
|
|
118
120
|
}>;
|
|
121
|
+
/**
|
|
122
|
+
* Check if Ollama is available
|
|
123
|
+
* v14.4.0: Results cached for 5 seconds to avoid repeated network calls
|
|
124
|
+
*/
|
|
119
125
|
private isOllamaAvailable;
|
|
120
126
|
private getBridge;
|
|
121
127
|
private updateAverage;
|
package/dist/src/llm/router.js
CHANGED
|
@@ -298,6 +298,9 @@ class HybridRouter {
|
|
|
298
298
|
localBridge = null;
|
|
299
299
|
cloudBridge = null;
|
|
300
300
|
hardwareProfile;
|
|
301
|
+
// v14.4.0: Cache Ollama availability to avoid repeated network calls
|
|
302
|
+
ollamaAvailableCache = null;
|
|
303
|
+
static OLLAMA_CACHE_TTL_MS = 5000; // 5 seconds
|
|
301
304
|
constructor(config) {
|
|
302
305
|
// Detect hardware and auto-configure
|
|
303
306
|
this.hardwareProfile = detectHardware();
|
|
@@ -445,14 +448,27 @@ class HybridRouter {
|
|
|
445
448
|
// ==========================================================================
|
|
446
449
|
// Helpers
|
|
447
450
|
// ==========================================================================
|
|
451
|
+
/**
|
|
452
|
+
* Check if Ollama is available
|
|
453
|
+
* v14.4.0: Results cached for 5 seconds to avoid repeated network calls
|
|
454
|
+
*/
|
|
448
455
|
async isOllamaAvailable() {
|
|
456
|
+
const now = Date.now();
|
|
457
|
+
// Return cached result if fresh
|
|
458
|
+
if (this.ollamaAvailableCache &&
|
|
459
|
+
(now - this.ollamaAvailableCache.timestamp) < HybridRouter.OLLAMA_CACHE_TTL_MS) {
|
|
460
|
+
return this.ollamaAvailableCache.result;
|
|
461
|
+
}
|
|
449
462
|
try {
|
|
450
463
|
const response = await fetch('http://localhost:11434/api/tags', {
|
|
451
464
|
signal: AbortSignal.timeout(1000),
|
|
452
465
|
});
|
|
453
|
-
|
|
466
|
+
const result = response.ok;
|
|
467
|
+
this.ollamaAvailableCache = { result, timestamp: now };
|
|
468
|
+
return result;
|
|
454
469
|
}
|
|
455
470
|
catch {
|
|
471
|
+
this.ollamaAvailableCache = { result: false, timestamp: now };
|
|
456
472
|
return false;
|
|
457
473
|
}
|
|
458
474
|
}
|
|
@@ -29,6 +29,8 @@ export interface VectorDocument {
|
|
|
29
29
|
createdAt: Date;
|
|
30
30
|
/** Last updated timestamp */
|
|
31
31
|
updatedAt: Date;
|
|
32
|
+
/** v14.4.0: Last accessed timestamp for LRU eviction */
|
|
33
|
+
accessedAt: Date;
|
|
32
34
|
/** Optional namespace/collection */
|
|
33
35
|
namespace?: string;
|
|
34
36
|
}
|
|
@@ -95,6 +97,7 @@ export declare class VectorStore {
|
|
|
95
97
|
delete(id: string): boolean;
|
|
96
98
|
/**
|
|
97
99
|
* Get a document by ID
|
|
100
|
+
* v14.4.0: Updates accessedAt for LRU tracking
|
|
98
101
|
*/
|
|
99
102
|
get(id: string): VectorDocument | undefined;
|
|
100
103
|
/**
|
|
@@ -119,8 +122,9 @@ export declare class VectorStore {
|
|
|
119
122
|
filter?: Record<string, unknown>;
|
|
120
123
|
}): Promise<VectorSearchResult[]>;
|
|
121
124
|
/**
|
|
122
|
-
* Maintain size limits
|
|
125
|
+
* Maintain size limits using LRU eviction
|
|
123
126
|
* v9.4.0: Prevents unbounded memory growth
|
|
127
|
+
* v14.4.0: Changed to LRU (least recently used) instead of FIFO
|
|
124
128
|
*/
|
|
125
129
|
private maintainSize;
|
|
126
130
|
/**
|
|
@@ -87,13 +87,15 @@ class VectorStore {
|
|
|
87
87
|
async add(id, text, metadata = {}, namespace) {
|
|
88
88
|
// Generate embedding
|
|
89
89
|
const result = await this.embeddings.embed(text);
|
|
90
|
+
const now = new Date();
|
|
90
91
|
const doc = {
|
|
91
92
|
id,
|
|
92
93
|
text,
|
|
93
94
|
vector: result.vector,
|
|
94
95
|
metadata,
|
|
95
|
-
createdAt:
|
|
96
|
-
updatedAt:
|
|
96
|
+
createdAt: now,
|
|
97
|
+
updatedAt: now,
|
|
98
|
+
accessedAt: now,
|
|
97
99
|
namespace: namespace || this.config.defaultNamespace,
|
|
98
100
|
};
|
|
99
101
|
this.documents.set(id, doc);
|
|
@@ -113,6 +115,7 @@ class VectorStore {
|
|
|
113
115
|
const texts = items.map(i => i.text);
|
|
114
116
|
const embedResults = await this.embeddings.embedBatch(texts);
|
|
115
117
|
const docs = [];
|
|
118
|
+
const now = new Date();
|
|
116
119
|
for (let i = 0; i < items.length; i++) {
|
|
117
120
|
const item = items[i];
|
|
118
121
|
const doc = {
|
|
@@ -120,8 +123,9 @@ class VectorStore {
|
|
|
120
123
|
text: item.text,
|
|
121
124
|
vector: embedResults[i].vector,
|
|
122
125
|
metadata: item.metadata || {},
|
|
123
|
-
createdAt:
|
|
124
|
-
updatedAt:
|
|
126
|
+
createdAt: now,
|
|
127
|
+
updatedAt: now,
|
|
128
|
+
accessedAt: now,
|
|
125
129
|
namespace: item.namespace || this.config.defaultNamespace,
|
|
126
130
|
};
|
|
127
131
|
this.documents.set(item.id, doc);
|
|
@@ -148,12 +152,14 @@ class VectorStore {
|
|
|
148
152
|
const result = await this.embeddings.embed(text);
|
|
149
153
|
vector = result.vector;
|
|
150
154
|
}
|
|
155
|
+
const now = new Date();
|
|
151
156
|
const updated = {
|
|
152
157
|
...existing,
|
|
153
158
|
text: text || existing.text,
|
|
154
159
|
vector,
|
|
155
160
|
metadata: metadata ? { ...existing.metadata, ...metadata } : existing.metadata,
|
|
156
|
-
updatedAt:
|
|
161
|
+
updatedAt: now,
|
|
162
|
+
accessedAt: now,
|
|
157
163
|
};
|
|
158
164
|
this.documents.set(id, updated);
|
|
159
165
|
this.dirty = true;
|
|
@@ -178,9 +184,15 @@ class VectorStore {
|
|
|
178
184
|
}
|
|
179
185
|
/**
|
|
180
186
|
* Get a document by ID
|
|
187
|
+
* v14.4.0: Updates accessedAt for LRU tracking
|
|
181
188
|
*/
|
|
182
189
|
get(id) {
|
|
183
|
-
|
|
190
|
+
const doc = this.documents.get(id);
|
|
191
|
+
if (doc) {
|
|
192
|
+
// Update access time for LRU
|
|
193
|
+
doc.accessedAt = new Date();
|
|
194
|
+
}
|
|
195
|
+
return doc;
|
|
184
196
|
}
|
|
185
197
|
/**
|
|
186
198
|
* Check if document exists
|
|
@@ -262,17 +274,18 @@ class VectorStore {
|
|
|
262
274
|
// Size Management (v9.4.0)
|
|
263
275
|
// ============================================================================
|
|
264
276
|
/**
|
|
265
|
-
* Maintain size limits
|
|
277
|
+
* Maintain size limits using LRU eviction
|
|
266
278
|
* v9.4.0: Prevents unbounded memory growth
|
|
279
|
+
* v14.4.0: Changed to LRU (least recently used) instead of FIFO
|
|
267
280
|
*/
|
|
268
281
|
maintainSize() {
|
|
269
282
|
const maxDocs = this.config.maxDocuments || 50000;
|
|
270
283
|
if (this.documents.size <= maxDocs)
|
|
271
284
|
return;
|
|
272
|
-
// Convert to array and sort by
|
|
285
|
+
// Convert to array and sort by access date (least recently accessed first)
|
|
273
286
|
const sorted = Array.from(this.documents.values())
|
|
274
|
-
.sort((a, b) => a.
|
|
275
|
-
// Remove
|
|
287
|
+
.sort((a, b) => a.accessedAt.getTime() - b.accessedAt.getTime());
|
|
288
|
+
// Remove least recently accessed documents until under limit
|
|
276
289
|
const toRemove = sorted.slice(0, this.documents.size - maxDocs);
|
|
277
290
|
for (const doc of toRemove) {
|
|
278
291
|
this.documents.delete(doc.id);
|
|
@@ -348,12 +361,13 @@ class VectorStore {
|
|
|
348
361
|
if (!this.config.persistPath)
|
|
349
362
|
return;
|
|
350
363
|
const data = {
|
|
351
|
-
version: '1.
|
|
364
|
+
version: '1.1', // v14.4.0: Added accessedAt for LRU
|
|
352
365
|
documents: Array.from(this.documents.entries()).map(([id, doc]) => ({
|
|
353
366
|
...doc,
|
|
354
367
|
id,
|
|
355
368
|
createdAt: doc.createdAt.toISOString(),
|
|
356
369
|
updatedAt: doc.updatedAt.toISOString(),
|
|
370
|
+
accessedAt: doc.accessedAt.toISOString(),
|
|
357
371
|
})),
|
|
358
372
|
savedAt: new Date().toISOString(),
|
|
359
373
|
};
|
|
@@ -377,6 +391,7 @@ class VectorStore {
|
|
|
377
391
|
const data = JSON.parse(content);
|
|
378
392
|
this.documents.clear();
|
|
379
393
|
for (const doc of data.documents) {
|
|
394
|
+
const accessedAt = doc.accessedAt;
|
|
380
395
|
this.documents.set(doc.id, {
|
|
381
396
|
id: doc.id,
|
|
382
397
|
text: doc.text,
|
|
@@ -384,6 +399,7 @@ class VectorStore {
|
|
|
384
399
|
metadata: doc.metadata,
|
|
385
400
|
createdAt: new Date(doc.createdAt),
|
|
386
401
|
updatedAt: new Date(doc.updatedAt),
|
|
402
|
+
accessedAt: accessedAt ? new Date(accessedAt) : new Date(doc.updatedAt),
|
|
387
403
|
namespace: doc.namespace,
|
|
388
404
|
});
|
|
389
405
|
}
|
|
@@ -77,9 +77,13 @@ class HybridStreamExecutor {
|
|
|
77
77
|
try {
|
|
78
78
|
// Get API key from environment (HybridStreamOptions doesn't include apiKey)
|
|
79
79
|
const apiKey = process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || '';
|
|
80
|
-
// Create LLM bridge
|
|
80
|
+
// Create LLM bridge - validate provider is supported
|
|
81
|
+
const validProviders = ['ollama', 'openai', 'anthropic'];
|
|
82
|
+
const provider = validProviders.includes(this.options.provider)
|
|
83
|
+
? this.options.provider
|
|
84
|
+
: 'anthropic'; // Default to anthropic if unknown provider
|
|
81
85
|
const bridge = new index_js_1.LLMBridge({
|
|
82
|
-
provider
|
|
86
|
+
provider,
|
|
83
87
|
model: this.options.model,
|
|
84
88
|
apiKey,
|
|
85
89
|
temperature: this.options.temperature || 0.7,
|
|
@@ -376,44 +380,72 @@ class HybridStreamExecutor {
|
|
|
376
380
|
// ==========================================================================
|
|
377
381
|
// Event Creation
|
|
378
382
|
// ==========================================================================
|
|
379
|
-
createEvent(type, data) {
|
|
383
|
+
createEvent(type, data = {}) {
|
|
380
384
|
const baseEvent = {
|
|
381
385
|
id: `evt_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
382
386
|
timestamp: new Date().toISOString(),
|
|
383
387
|
};
|
|
384
388
|
switch (type) {
|
|
385
389
|
case 'token':
|
|
386
|
-
return { ...baseEvent, type: 'token', content: data.token };
|
|
390
|
+
return { ...baseEvent, type: 'token', content: String(data.token || '') };
|
|
387
391
|
case 'tool_start':
|
|
388
|
-
return {
|
|
392
|
+
return {
|
|
393
|
+
...baseEvent,
|
|
394
|
+
type: 'tool_start',
|
|
395
|
+
toolCallId: String(data.toolCallId || ''),
|
|
396
|
+
name: String(data.name || ''),
|
|
397
|
+
args: data.args || {}
|
|
398
|
+
};
|
|
389
399
|
case 'tool_result':
|
|
390
|
-
return {
|
|
400
|
+
return {
|
|
401
|
+
...baseEvent,
|
|
402
|
+
type: 'tool_result',
|
|
403
|
+
toolCallId: String(data.toolCallId || ''),
|
|
404
|
+
content: data.content,
|
|
405
|
+
success: Boolean(data.success),
|
|
406
|
+
duration: Number(data.duration || 0),
|
|
407
|
+
error: data.error ? String(data.error) : undefined
|
|
408
|
+
};
|
|
391
409
|
case 'thinking_start':
|
|
392
410
|
return { ...baseEvent, type: 'thinking_start' };
|
|
393
411
|
case 'thinking_token':
|
|
394
|
-
return { ...baseEvent, type: 'thinking_token', content: data.content };
|
|
412
|
+
return { ...baseEvent, type: 'thinking_token', content: String(data.content || '') };
|
|
395
413
|
case 'thinking_end':
|
|
396
414
|
return { ...baseEvent, type: 'thinking_end' };
|
|
397
415
|
case 'metadata':
|
|
398
|
-
return {
|
|
416
|
+
return {
|
|
417
|
+
...baseEvent,
|
|
418
|
+
type: 'metadata',
|
|
419
|
+
provider: this.options.provider,
|
|
420
|
+
model: this.options.model,
|
|
421
|
+
usage: data.usage,
|
|
422
|
+
cost: data.cost
|
|
423
|
+
};
|
|
399
424
|
case 'error':
|
|
400
425
|
return {
|
|
401
426
|
...baseEvent,
|
|
402
427
|
type: 'error',
|
|
403
428
|
code: 'EXECUTION_ERROR',
|
|
404
|
-
message: data.error,
|
|
405
|
-
retryable: data.recoverable,
|
|
429
|
+
message: String(data.error || 'Unknown error'),
|
|
430
|
+
retryable: Boolean(data.recoverable),
|
|
406
431
|
};
|
|
407
432
|
case 'done':
|
|
408
433
|
return {
|
|
409
434
|
...baseEvent,
|
|
410
435
|
type: 'done',
|
|
411
|
-
content: data.finalContent,
|
|
436
|
+
content: String(data.finalContent || ''),
|
|
412
437
|
reason: 'stop',
|
|
413
438
|
metrics: data.metrics,
|
|
414
439
|
};
|
|
415
440
|
default:
|
|
416
|
-
return
|
|
441
|
+
// For unknown event types, return error event
|
|
442
|
+
return {
|
|
443
|
+
...baseEvent,
|
|
444
|
+
type: 'error',
|
|
445
|
+
code: 'UNKNOWN_EVENT',
|
|
446
|
+
message: `Unknown event type: ${type}`,
|
|
447
|
+
retryable: false
|
|
448
|
+
};
|
|
417
449
|
}
|
|
418
450
|
}
|
|
419
451
|
// ==========================================================================
|
|
@@ -519,11 +551,21 @@ async function hybridStreamCollect(options) {
|
|
|
519
551
|
metrics = event.metrics;
|
|
520
552
|
}
|
|
521
553
|
}
|
|
554
|
+
// Get final metrics from done event if available
|
|
555
|
+
if (!metrics && events.length > 0) {
|
|
556
|
+
const lastEvent = events[events.length - 1];
|
|
557
|
+
if (lastEvent.type === 'done') {
|
|
558
|
+
metrics = lastEvent.metrics;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
522
561
|
return {
|
|
523
562
|
content,
|
|
524
563
|
events,
|
|
525
|
-
metrics: metrics ||
|
|
526
|
-
|
|
527
|
-
:
|
|
564
|
+
metrics: metrics || {
|
|
565
|
+
tokensPerSecond: 0, totalTokens: 0, inputTokens: 0, outputTokens: 0,
|
|
566
|
+
thinkingTokens: 0, cost: 0, confidence: 0, toolCallCount: 0,
|
|
567
|
+
toolLatencyTotal: 0, toolLatencyAverage: 0, modelUpgrades: 0,
|
|
568
|
+
startTime: new Date().toISOString(), elapsed: 0, state: 'completed', retries: 0
|
|
569
|
+
},
|
|
528
570
|
};
|
|
529
571
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genesis-ai-cli",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.4.0",
|
|
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",
|