genesis-ai-cli 7.4.5
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/.env.example +78 -0
- package/README.md +282 -0
- package/dist/src/active-inference/actions.d.ts +75 -0
- package/dist/src/active-inference/actions.js +250 -0
- package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
- package/dist/src/active-inference/autonomous-loop.js +289 -0
- package/dist/src/active-inference/core.d.ts +85 -0
- package/dist/src/active-inference/core.js +555 -0
- package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
- package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
- package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
- package/dist/src/active-inference/demo-value-integration.js +174 -0
- package/dist/src/active-inference/index.d.ts +32 -0
- package/dist/src/active-inference/index.js +88 -0
- package/dist/src/active-inference/integration.d.ts +114 -0
- package/dist/src/active-inference/integration.js +698 -0
- package/dist/src/active-inference/memory-integration.d.ts +51 -0
- package/dist/src/active-inference/memory-integration.js +232 -0
- package/dist/src/active-inference/observations.d.ts +67 -0
- package/dist/src/active-inference/observations.js +147 -0
- package/dist/src/active-inference/test-active-inference.d.ts +8 -0
- package/dist/src/active-inference/test-active-inference.js +320 -0
- package/dist/src/active-inference/test-value-integration.d.ts +6 -0
- package/dist/src/active-inference/test-value-integration.js +168 -0
- package/dist/src/active-inference/types.d.ts +150 -0
- package/dist/src/active-inference/types.js +59 -0
- package/dist/src/active-inference/value-integration.d.ts +164 -0
- package/dist/src/active-inference/value-integration.js +459 -0
- package/dist/src/agents/base-agent.d.ts +53 -0
- package/dist/src/agents/base-agent.js +178 -0
- package/dist/src/agents/builder.d.ts +67 -0
- package/dist/src/agents/builder.js +537 -0
- package/dist/src/agents/critic.d.ts +35 -0
- package/dist/src/agents/critic.js +322 -0
- package/dist/src/agents/ethicist.d.ts +54 -0
- package/dist/src/agents/ethicist.js +393 -0
- package/dist/src/agents/explorer.d.ts +26 -0
- package/dist/src/agents/explorer.js +216 -0
- package/dist/src/agents/feeling.d.ts +41 -0
- package/dist/src/agents/feeling.js +320 -0
- package/dist/src/agents/index.d.ts +111 -0
- package/dist/src/agents/index.js +222 -0
- package/dist/src/agents/memory.d.ts +69 -0
- package/dist/src/agents/memory.js +404 -0
- package/dist/src/agents/message-bus.d.ts +88 -0
- package/dist/src/agents/message-bus.js +267 -0
- package/dist/src/agents/narrator.d.ts +90 -0
- package/dist/src/agents/narrator.js +473 -0
- package/dist/src/agents/planner.d.ts +38 -0
- package/dist/src/agents/planner.js +341 -0
- package/dist/src/agents/predictor.d.ts +73 -0
- package/dist/src/agents/predictor.js +506 -0
- package/dist/src/agents/sensor.d.ts +88 -0
- package/dist/src/agents/sensor.js +377 -0
- package/dist/src/agents/test-agents.d.ts +6 -0
- package/dist/src/agents/test-agents.js +73 -0
- package/dist/src/agents/types.d.ts +194 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/brain/index.d.ts +185 -0
- package/dist/src/brain/index.js +843 -0
- package/dist/src/brain/trace.d.ts +91 -0
- package/dist/src/brain/trace.js +327 -0
- package/dist/src/brain/types.d.ts +165 -0
- package/dist/src/brain/types.js +51 -0
- package/dist/src/cli/chat.d.ts +237 -0
- package/dist/src/cli/chat.js +1959 -0
- package/dist/src/cli/dispatcher.d.ts +182 -0
- package/dist/src/cli/dispatcher.js +718 -0
- package/dist/src/cli/human-loop.d.ts +170 -0
- package/dist/src/cli/human-loop.js +543 -0
- package/dist/src/cli/index.d.ts +12 -0
- package/dist/src/cli/index.js +28 -0
- package/dist/src/cli/interactive.d.ts +141 -0
- package/dist/src/cli/interactive.js +757 -0
- package/dist/src/cli/ui.d.ts +205 -0
- package/dist/src/cli/ui.js +632 -0
- package/dist/src/consciousness/attention-schema.d.ts +154 -0
- package/dist/src/consciousness/attention-schema.js +432 -0
- package/dist/src/consciousness/global-workspace.d.ts +149 -0
- package/dist/src/consciousness/global-workspace.js +422 -0
- package/dist/src/consciousness/index.d.ts +186 -0
- package/dist/src/consciousness/index.js +476 -0
- package/dist/src/consciousness/phi-calculator.d.ts +119 -0
- package/dist/src/consciousness/phi-calculator.js +445 -0
- package/dist/src/consciousness/phi-decisions.d.ts +169 -0
- package/dist/src/consciousness/phi-decisions.js +383 -0
- package/dist/src/consciousness/phi-monitor.d.ts +153 -0
- package/dist/src/consciousness/phi-monitor.js +465 -0
- package/dist/src/consciousness/types.d.ts +260 -0
- package/dist/src/consciousness/types.js +44 -0
- package/dist/src/daemon/dream-mode.d.ts +115 -0
- package/dist/src/daemon/dream-mode.js +470 -0
- package/dist/src/daemon/index.d.ts +162 -0
- package/dist/src/daemon/index.js +542 -0
- package/dist/src/daemon/maintenance.d.ts +139 -0
- package/dist/src/daemon/maintenance.js +549 -0
- package/dist/src/daemon/process.d.ts +82 -0
- package/dist/src/daemon/process.js +442 -0
- package/dist/src/daemon/scheduler.d.ts +90 -0
- package/dist/src/daemon/scheduler.js +494 -0
- package/dist/src/daemon/types.d.ts +213 -0
- package/dist/src/daemon/types.js +50 -0
- package/dist/src/epistemic/index.d.ts +74 -0
- package/dist/src/epistemic/index.js +225 -0
- package/dist/src/grounding/epistemic-stack.d.ts +100 -0
- package/dist/src/grounding/epistemic-stack.js +408 -0
- package/dist/src/grounding/feedback.d.ts +98 -0
- package/dist/src/grounding/feedback.js +276 -0
- package/dist/src/grounding/index.d.ts +123 -0
- package/dist/src/grounding/index.js +224 -0
- package/dist/src/grounding/verifier.d.ts +149 -0
- package/dist/src/grounding/verifier.js +484 -0
- package/dist/src/healing/detector.d.ts +110 -0
- package/dist/src/healing/detector.js +436 -0
- package/dist/src/healing/fixer.d.ts +138 -0
- package/dist/src/healing/fixer.js +572 -0
- package/dist/src/healing/index.d.ts +23 -0
- package/dist/src/healing/index.js +43 -0
- package/dist/src/hooks/index.d.ts +135 -0
- package/dist/src/hooks/index.js +317 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.js +1266 -0
- package/dist/src/kernel/index.d.ts +155 -0
- package/dist/src/kernel/index.js +795 -0
- package/dist/src/kernel/invariants.d.ts +153 -0
- package/dist/src/kernel/invariants.js +355 -0
- package/dist/src/kernel/test-kernel.d.ts +6 -0
- package/dist/src/kernel/test-kernel.js +108 -0
- package/dist/src/kernel/test-real-mcp.d.ts +10 -0
- package/dist/src/kernel/test-real-mcp.js +295 -0
- package/dist/src/llm/index.d.ts +146 -0
- package/dist/src/llm/index.js +428 -0
- package/dist/src/llm/router.d.ts +136 -0
- package/dist/src/llm/router.js +510 -0
- package/dist/src/mcp/index.d.ts +85 -0
- package/dist/src/mcp/index.js +657 -0
- package/dist/src/mcp/resilient.d.ts +139 -0
- package/dist/src/mcp/resilient.js +417 -0
- package/dist/src/memory/cache.d.ts +118 -0
- package/dist/src/memory/cache.js +356 -0
- package/dist/src/memory/cognitive-workspace.d.ts +231 -0
- package/dist/src/memory/cognitive-workspace.js +521 -0
- package/dist/src/memory/consolidation.d.ts +99 -0
- package/dist/src/memory/consolidation.js +443 -0
- package/dist/src/memory/episodic.d.ts +114 -0
- package/dist/src/memory/episodic.js +394 -0
- package/dist/src/memory/forgetting.d.ts +134 -0
- package/dist/src/memory/forgetting.js +324 -0
- package/dist/src/memory/index.d.ts +211 -0
- package/dist/src/memory/index.js +367 -0
- package/dist/src/memory/indexer.d.ts +123 -0
- package/dist/src/memory/indexer.js +479 -0
- package/dist/src/memory/procedural.d.ts +136 -0
- package/dist/src/memory/procedural.js +479 -0
- package/dist/src/memory/semantic.d.ts +132 -0
- package/dist/src/memory/semantic.js +497 -0
- package/dist/src/memory/types.d.ts +193 -0
- package/dist/src/memory/types.js +15 -0
- package/dist/src/orchestrator.d.ts +65 -0
- package/dist/src/orchestrator.js +317 -0
- package/dist/src/persistence/index.d.ts +257 -0
- package/dist/src/persistence/index.js +763 -0
- package/dist/src/pipeline/executor.d.ts +51 -0
- package/dist/src/pipeline/executor.js +695 -0
- package/dist/src/pipeline/index.d.ts +7 -0
- package/dist/src/pipeline/index.js +11 -0
- package/dist/src/self-production.d.ts +67 -0
- package/dist/src/self-production.js +205 -0
- package/dist/src/subagents/executor.d.ts +58 -0
- package/dist/src/subagents/executor.js +283 -0
- package/dist/src/subagents/index.d.ts +37 -0
- package/dist/src/subagents/index.js +53 -0
- package/dist/src/subagents/registry.d.ts +23 -0
- package/dist/src/subagents/registry.js +167 -0
- package/dist/src/subagents/types.d.ts +79 -0
- package/dist/src/subagents/types.js +14 -0
- package/dist/src/tools/bash.d.ts +139 -0
- package/dist/src/tools/bash.js +583 -0
- package/dist/src/tools/edit.d.ts +125 -0
- package/dist/src/tools/edit.js +424 -0
- package/dist/src/tools/git.d.ts +179 -0
- package/dist/src/tools/git.js +504 -0
- package/dist/src/tools/index.d.ts +21 -0
- package/dist/src/tools/index.js +163 -0
- package/dist/src/types.d.ts +145 -0
- package/dist/src/types.js +7 -0
- package/dist/src/world-model/decoder.d.ts +163 -0
- package/dist/src/world-model/decoder.js +517 -0
- package/dist/src/world-model/digital-twin.d.ts +219 -0
- package/dist/src/world-model/digital-twin.js +695 -0
- package/dist/src/world-model/encoder.d.ts +141 -0
- package/dist/src/world-model/encoder.js +564 -0
- package/dist/src/world-model/index.d.ts +221 -0
- package/dist/src/world-model/index.js +772 -0
- package/dist/src/world-model/predictor.d.ts +161 -0
- package/dist/src/world-model/predictor.js +681 -0
- package/dist/src/world-model/test-value-jepa.d.ts +8 -0
- package/dist/src/world-model/test-value-jepa.js +430 -0
- package/dist/src/world-model/types.d.ts +341 -0
- package/dist/src/world-model/types.js +69 -0
- package/dist/src/world-model/value-jepa.d.ts +247 -0
- package/dist/src/world-model/value-jepa.js +622 -0
- package/dist/test/brain.test.d.ts +11 -0
- package/dist/test/brain.test.js +358 -0
- package/dist/test/cli/dispatcher.test.d.ts +4 -0
- package/dist/test/cli/dispatcher.test.js +332 -0
- package/dist/test/cli/human-loop.test.d.ts +4 -0
- package/dist/test/cli/human-loop.test.js +270 -0
- package/dist/test/grounding/feedback.test.d.ts +4 -0
- package/dist/test/grounding/feedback.test.js +462 -0
- package/dist/test/grounding/verifier.test.d.ts +4 -0
- package/dist/test/grounding/verifier.test.js +442 -0
- package/dist/test/grounding.test.d.ts +6 -0
- package/dist/test/grounding.test.js +246 -0
- package/dist/test/healing/detector.test.d.ts +4 -0
- package/dist/test/healing/detector.test.js +266 -0
- package/dist/test/healing/fixer.test.d.ts +4 -0
- package/dist/test/healing/fixer.test.js +369 -0
- package/dist/test/integration.test.d.ts +5 -0
- package/dist/test/integration.test.js +290 -0
- package/dist/test/tools/bash.test.d.ts +4 -0
- package/dist/test/tools/bash.test.js +348 -0
- package/dist/test/tools/edit.test.d.ts +4 -0
- package/dist/test/tools/edit.test.js +350 -0
- package/dist/test/tools/git.test.d.ts +4 -0
- package/dist/test/tools/git.test.js +350 -0
- package/package.json +60 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis 6.8 - Hybrid LLM Router
|
|
4
|
+
*
|
|
5
|
+
* Intelligent routing between local (Ollama) and cloud (OpenAI/Anthropic) LLMs.
|
|
6
|
+
*
|
|
7
|
+
* Routing Logic:
|
|
8
|
+
* - Simple tasks (syntax fix, file ops, search) -> Local (fast, free)
|
|
9
|
+
* - Complex tasks (architecture, design, creative) -> Cloud (high quality)
|
|
10
|
+
*
|
|
11
|
+
* Factors considered:
|
|
12
|
+
* - Task complexity (heuristic analysis)
|
|
13
|
+
* - Token count estimation
|
|
14
|
+
* - Ollama availability
|
|
15
|
+
* - User preference
|
|
16
|
+
* - Cost optimization
|
|
17
|
+
*/
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.HybridRouter = void 0;
|
|
53
|
+
exports.detectHardware = detectHardware;
|
|
54
|
+
exports.analyzeComplexity = analyzeComplexity;
|
|
55
|
+
exports.estimateTokens = estimateTokens;
|
|
56
|
+
exports.estimateCost = estimateCost;
|
|
57
|
+
exports.getHybridRouter = getHybridRouter;
|
|
58
|
+
exports.resetHybridRouter = resetHybridRouter;
|
|
59
|
+
exports.smartChat = smartChat;
|
|
60
|
+
exports.localChat = localChat;
|
|
61
|
+
exports.cloudChat = cloudChat;
|
|
62
|
+
const index_js_1 = require("./index.js");
|
|
63
|
+
const os = __importStar(require("os"));
|
|
64
|
+
/**
|
|
65
|
+
* Detect hardware capabilities and recommend router config
|
|
66
|
+
*/
|
|
67
|
+
function detectHardware() {
|
|
68
|
+
const cpus = os.cpus();
|
|
69
|
+
const cpu = cpus[0]?.model || 'Unknown';
|
|
70
|
+
const cores = cpus.length;
|
|
71
|
+
const memoryGB = Math.round(os.totalmem() / (1024 ** 3));
|
|
72
|
+
// Detect Apple Silicon
|
|
73
|
+
const isAppleSilicon = cpu.includes('Apple M') ||
|
|
74
|
+
process.arch === 'arm64' && process.platform === 'darwin';
|
|
75
|
+
// Determine tier
|
|
76
|
+
let tier;
|
|
77
|
+
let recommendedThreshold;
|
|
78
|
+
let recommendedMaxTokens;
|
|
79
|
+
if (isAppleSilicon && memoryGB >= 24) {
|
|
80
|
+
// M3 Pro/Max/Ultra or M4 Pro/Max - top tier
|
|
81
|
+
tier = 'ultra';
|
|
82
|
+
recommendedThreshold = 'creative'; // Only creative to cloud
|
|
83
|
+
recommendedMaxTokens = 16384; // Can handle large context
|
|
84
|
+
}
|
|
85
|
+
else if (isAppleSilicon && memoryGB >= 16) {
|
|
86
|
+
// M1/M2/M3/M4 base with good RAM
|
|
87
|
+
tier = 'high';
|
|
88
|
+
recommendedThreshold = 'creative';
|
|
89
|
+
recommendedMaxTokens = 8192;
|
|
90
|
+
}
|
|
91
|
+
else if (cores >= 8 && memoryGB >= 16) {
|
|
92
|
+
// Good desktop/laptop
|
|
93
|
+
tier = 'medium';
|
|
94
|
+
recommendedThreshold = 'complex';
|
|
95
|
+
recommendedMaxTokens = 4096;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
// Limited hardware
|
|
99
|
+
tier = 'low';
|
|
100
|
+
recommendedThreshold = 'moderate'; // Route more to cloud
|
|
101
|
+
recommendedMaxTokens = 2048;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
cpu,
|
|
105
|
+
isAppleSilicon,
|
|
106
|
+
cores,
|
|
107
|
+
memoryGB,
|
|
108
|
+
tier,
|
|
109
|
+
recommendedThreshold,
|
|
110
|
+
recommendedMaxTokens,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// ============================================================================
|
|
114
|
+
// Default Config
|
|
115
|
+
// ============================================================================
|
|
116
|
+
const DEFAULT_CONFIG = {
|
|
117
|
+
preferLocal: true,
|
|
118
|
+
forceCloud: false,
|
|
119
|
+
localMaxTokens: 8192, // M4 Pro can handle larger context
|
|
120
|
+
cloudThreshold: 'creative', // Only creative → cloud (M4 Pro is fast enough for complex)
|
|
121
|
+
autoFallback: true,
|
|
122
|
+
logDecisions: false,
|
|
123
|
+
};
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Complexity Analysis
|
|
126
|
+
// ============================================================================
|
|
127
|
+
const COMPLEXITY_SCORES = {
|
|
128
|
+
trivial: 0,
|
|
129
|
+
simple: 1,
|
|
130
|
+
moderate: 2,
|
|
131
|
+
complex: 3,
|
|
132
|
+
creative: 4,
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Keywords that indicate simple/local tasks
|
|
136
|
+
*/
|
|
137
|
+
const LOCAL_KEYWORDS = [
|
|
138
|
+
// Syntax & Formatting
|
|
139
|
+
'fix syntax', 'typo', 'spelling', 'indent', 'format',
|
|
140
|
+
'semicolon', 'bracket', 'parenthesis', 'quote',
|
|
141
|
+
// File Operations
|
|
142
|
+
'rename', 'move file', 'delete file', 'list files',
|
|
143
|
+
'find file', 'search', 'grep', 'locate',
|
|
144
|
+
// Simple Code Tasks
|
|
145
|
+
'add import', 'remove import', 'update import',
|
|
146
|
+
'add export', 'rename variable', 'rename function',
|
|
147
|
+
'add comment', 'remove comment', 'update comment',
|
|
148
|
+
// Git Operations
|
|
149
|
+
'git status', 'git diff', 'git log', 'git add',
|
|
150
|
+
'commit message', 'branch name',
|
|
151
|
+
// Quick Fixes
|
|
152
|
+
'missing semicolon', 'missing bracket', 'missing import',
|
|
153
|
+
'unused variable', 'undefined variable',
|
|
154
|
+
'type error', 'typescript error',
|
|
155
|
+
];
|
|
156
|
+
/**
|
|
157
|
+
* Keywords that indicate complex/cloud tasks
|
|
158
|
+
*/
|
|
159
|
+
const CLOUD_KEYWORDS = [
|
|
160
|
+
// Architecture
|
|
161
|
+
'design', 'architect', 'structure', 'pattern',
|
|
162
|
+
'refactor', 'restructure', 'reorganize',
|
|
163
|
+
// Creative
|
|
164
|
+
'create', 'implement', 'build', 'develop',
|
|
165
|
+
'new feature', 'add feature', 'write from scratch',
|
|
166
|
+
// Complex Analysis
|
|
167
|
+
'analyze', 'review', 'evaluate', 'assess',
|
|
168
|
+
'optimize', 'improve', 'enhance',
|
|
169
|
+
// Documentation
|
|
170
|
+
'document', 'explain', 'describe', 'tutorial',
|
|
171
|
+
'readme', 'api docs', 'specification',
|
|
172
|
+
// Testing
|
|
173
|
+
'write tests', 'test coverage', 'integration test',
|
|
174
|
+
'e2e test', 'test strategy',
|
|
175
|
+
// Multi-step
|
|
176
|
+
'step by step', 'multiple files', 'across the codebase',
|
|
177
|
+
'entire project', 'all files',
|
|
178
|
+
];
|
|
179
|
+
/**
|
|
180
|
+
* Analyze task complexity from the prompt
|
|
181
|
+
*/
|
|
182
|
+
function analyzeComplexity(prompt) {
|
|
183
|
+
const lower = prompt.toLowerCase();
|
|
184
|
+
const indicators = [];
|
|
185
|
+
let localScore = 0;
|
|
186
|
+
let cloudScore = 0;
|
|
187
|
+
// Check local keywords
|
|
188
|
+
for (const keyword of LOCAL_KEYWORDS) {
|
|
189
|
+
if (lower.includes(keyword)) {
|
|
190
|
+
localScore++;
|
|
191
|
+
indicators.push(`local: "${keyword}"`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Check cloud keywords
|
|
195
|
+
for (const keyword of CLOUD_KEYWORDS) {
|
|
196
|
+
if (lower.includes(keyword)) {
|
|
197
|
+
cloudScore++;
|
|
198
|
+
indicators.push(`cloud: "${keyword}"`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Additional heuristics
|
|
202
|
+
const wordCount = prompt.split(/\s+/).length;
|
|
203
|
+
const hasCode = prompt.includes('```') || prompt.includes('function ') || prompt.includes('class ');
|
|
204
|
+
const hasMultipleQuestions = (prompt.match(/\?/g) || []).length > 1;
|
|
205
|
+
const hasNumberedList = /\d+\.\s/.test(prompt);
|
|
206
|
+
if (wordCount > 200) {
|
|
207
|
+
cloudScore += 2;
|
|
208
|
+
indicators.push('long prompt');
|
|
209
|
+
}
|
|
210
|
+
if (hasCode && wordCount > 100) {
|
|
211
|
+
cloudScore++;
|
|
212
|
+
indicators.push('code + explanation');
|
|
213
|
+
}
|
|
214
|
+
if (hasMultipleQuestions) {
|
|
215
|
+
cloudScore++;
|
|
216
|
+
indicators.push('multiple questions');
|
|
217
|
+
}
|
|
218
|
+
if (hasNumberedList) {
|
|
219
|
+
cloudScore++;
|
|
220
|
+
indicators.push('multi-step task');
|
|
221
|
+
}
|
|
222
|
+
// Calculate final complexity
|
|
223
|
+
const netScore = cloudScore - localScore;
|
|
224
|
+
let complexity;
|
|
225
|
+
if (netScore <= -2)
|
|
226
|
+
complexity = 'trivial';
|
|
227
|
+
else if (netScore <= 0)
|
|
228
|
+
complexity = 'simple';
|
|
229
|
+
else if (netScore <= 2)
|
|
230
|
+
complexity = 'moderate';
|
|
231
|
+
else if (netScore <= 4)
|
|
232
|
+
complexity = 'complex';
|
|
233
|
+
else
|
|
234
|
+
complexity = 'creative';
|
|
235
|
+
// Confidence based on indicator count
|
|
236
|
+
const totalIndicators = localScore + cloudScore;
|
|
237
|
+
const confidence = Math.min(0.9, 0.3 + (totalIndicators * 0.1));
|
|
238
|
+
return { complexity, confidence, indicators };
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Estimate token count from prompt
|
|
242
|
+
*/
|
|
243
|
+
function estimateTokens(text) {
|
|
244
|
+
// Rough estimation: ~4 characters per token for English
|
|
245
|
+
return Math.ceil(text.length / 4);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Estimate cost for cloud provider
|
|
249
|
+
*/
|
|
250
|
+
function estimateCost(inputTokens, outputTokens, provider) {
|
|
251
|
+
// Prices per 1M tokens (as of 2024)
|
|
252
|
+
const prices = {
|
|
253
|
+
openai: { input: 2.5, output: 10 }, // GPT-4o
|
|
254
|
+
anthropic: { input: 3, output: 15 }, // Claude Sonnet
|
|
255
|
+
ollama: { input: 0, output: 0 }, // Free!
|
|
256
|
+
};
|
|
257
|
+
const p = prices[provider];
|
|
258
|
+
return ((inputTokens * p.input) + (outputTokens * p.output)) / 1_000_000;
|
|
259
|
+
}
|
|
260
|
+
// ============================================================================
|
|
261
|
+
// Hybrid Router Class
|
|
262
|
+
// ============================================================================
|
|
263
|
+
class HybridRouter {
|
|
264
|
+
config;
|
|
265
|
+
stats = {
|
|
266
|
+
totalRequests: 0,
|
|
267
|
+
localRequests: 0,
|
|
268
|
+
cloudRequests: 0,
|
|
269
|
+
fallbacks: 0,
|
|
270
|
+
avgLocalLatency: 0,
|
|
271
|
+
avgCloudLatency: 0,
|
|
272
|
+
estimatedSavings: 0,
|
|
273
|
+
};
|
|
274
|
+
localBridge = null;
|
|
275
|
+
cloudBridge = null;
|
|
276
|
+
hardwareProfile;
|
|
277
|
+
constructor(config) {
|
|
278
|
+
// Detect hardware and auto-configure
|
|
279
|
+
this.hardwareProfile = detectHardware();
|
|
280
|
+
// Apply hardware-based defaults, then user overrides
|
|
281
|
+
this.config = {
|
|
282
|
+
...DEFAULT_CONFIG,
|
|
283
|
+
cloudThreshold: this.hardwareProfile.recommendedThreshold,
|
|
284
|
+
localMaxTokens: this.hardwareProfile.recommendedMaxTokens,
|
|
285
|
+
...config,
|
|
286
|
+
};
|
|
287
|
+
if (this.config.logDecisions) {
|
|
288
|
+
console.log(`[Router] Hardware: ${this.hardwareProfile.tier} tier (${this.hardwareProfile.cpu})`);
|
|
289
|
+
console.log(`[Router] Config: cloudThreshold=${this.config.cloudThreshold}, localMaxTokens=${this.config.localMaxTokens}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Get detected hardware profile
|
|
294
|
+
*/
|
|
295
|
+
getHardwareProfile() {
|
|
296
|
+
return { ...this.hardwareProfile };
|
|
297
|
+
}
|
|
298
|
+
// ==========================================================================
|
|
299
|
+
// Routing Logic
|
|
300
|
+
// ==========================================================================
|
|
301
|
+
/**
|
|
302
|
+
* Decide which provider to use
|
|
303
|
+
*/
|
|
304
|
+
async route(prompt) {
|
|
305
|
+
const { complexity, confidence, indicators } = analyzeComplexity(prompt);
|
|
306
|
+
const estimatedTokens = estimateTokens(prompt);
|
|
307
|
+
const estimatedOutputTokens = Math.min(estimatedTokens * 2, 2000);
|
|
308
|
+
// Force cloud if configured
|
|
309
|
+
if (this.config.forceCloud) {
|
|
310
|
+
return {
|
|
311
|
+
provider: process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai',
|
|
312
|
+
reason: 'Force cloud mode enabled',
|
|
313
|
+
complexity,
|
|
314
|
+
confidence: 1,
|
|
315
|
+
estimatedTokens,
|
|
316
|
+
estimatedCost: estimateCost(estimatedTokens, estimatedOutputTokens, 'anthropic'),
|
|
317
|
+
tryLocalFirst: false,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
// Check if Ollama is available
|
|
321
|
+
const ollamaAvailable = await this.isOllamaAvailable();
|
|
322
|
+
// Prefer local if configured and available
|
|
323
|
+
if (this.config.preferLocal && ollamaAvailable) {
|
|
324
|
+
const threshold = COMPLEXITY_SCORES[this.config.cloudThreshold];
|
|
325
|
+
const score = COMPLEXITY_SCORES[complexity];
|
|
326
|
+
if (score < threshold) {
|
|
327
|
+
return {
|
|
328
|
+
provider: 'ollama',
|
|
329
|
+
reason: `Task complexity (${complexity}) below cloud threshold (${this.config.cloudThreshold})`,
|
|
330
|
+
complexity,
|
|
331
|
+
confidence,
|
|
332
|
+
estimatedTokens,
|
|
333
|
+
estimatedCost: 0,
|
|
334
|
+
tryLocalFirst: true,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// Token limit check for local
|
|
339
|
+
if (estimatedTokens > this.config.localMaxTokens) {
|
|
340
|
+
return {
|
|
341
|
+
provider: process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai',
|
|
342
|
+
reason: `Token count (${estimatedTokens}) exceeds local limit (${this.config.localMaxTokens})`,
|
|
343
|
+
complexity,
|
|
344
|
+
confidence,
|
|
345
|
+
estimatedTokens,
|
|
346
|
+
estimatedCost: estimateCost(estimatedTokens, estimatedOutputTokens, 'anthropic'),
|
|
347
|
+
tryLocalFirst: false,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
// Default: use local if available, else cloud
|
|
351
|
+
if (ollamaAvailable) {
|
|
352
|
+
return {
|
|
353
|
+
provider: 'ollama',
|
|
354
|
+
reason: 'Local model available, using for cost savings',
|
|
355
|
+
complexity,
|
|
356
|
+
confidence,
|
|
357
|
+
estimatedTokens,
|
|
358
|
+
estimatedCost: 0,
|
|
359
|
+
tryLocalFirst: true,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
provider: process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai',
|
|
364
|
+
reason: 'Ollama not available, using cloud',
|
|
365
|
+
complexity,
|
|
366
|
+
confidence,
|
|
367
|
+
estimatedTokens,
|
|
368
|
+
estimatedCost: estimateCost(estimatedTokens, estimatedOutputTokens, 'anthropic'),
|
|
369
|
+
tryLocalFirst: false,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Execute request with routing
|
|
374
|
+
*/
|
|
375
|
+
async execute(prompt, systemPrompt) {
|
|
376
|
+
const decision = await this.route(prompt);
|
|
377
|
+
if (this.config.logDecisions) {
|
|
378
|
+
console.log(`[Router] ${decision.provider}: ${decision.reason} (${decision.complexity}, ${decision.confidence.toFixed(2)})`);
|
|
379
|
+
}
|
|
380
|
+
this.stats.totalRequests++;
|
|
381
|
+
try {
|
|
382
|
+
const bridge = this.getBridge(decision.provider);
|
|
383
|
+
const response = await bridge.chat(prompt, systemPrompt);
|
|
384
|
+
// Update stats
|
|
385
|
+
if (decision.provider === 'ollama') {
|
|
386
|
+
this.stats.localRequests++;
|
|
387
|
+
this.stats.avgLocalLatency = this.updateAverage(this.stats.avgLocalLatency, response.latency, this.stats.localRequests);
|
|
388
|
+
// Calculate savings vs cloud
|
|
389
|
+
const cloudCost = estimateCost(response.usage?.inputTokens || 0, response.usage?.outputTokens || 0, 'anthropic');
|
|
390
|
+
this.stats.estimatedSavings += cloudCost;
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
this.stats.cloudRequests++;
|
|
394
|
+
this.stats.avgCloudLatency = this.updateAverage(this.stats.avgCloudLatency, response.latency, this.stats.cloudRequests);
|
|
395
|
+
}
|
|
396
|
+
return { ...response, routingDecision: decision };
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
// Auto-fallback if enabled
|
|
400
|
+
if (this.config.autoFallback && decision.provider === 'ollama') {
|
|
401
|
+
console.log('[Router] Local failed, falling back to cloud...');
|
|
402
|
+
this.stats.fallbacks++;
|
|
403
|
+
const fallbackProvider = process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai';
|
|
404
|
+
const bridge = this.getBridge(fallbackProvider);
|
|
405
|
+
const response = await bridge.chat(prompt, systemPrompt);
|
|
406
|
+
return {
|
|
407
|
+
...response,
|
|
408
|
+
routingDecision: {
|
|
409
|
+
...decision,
|
|
410
|
+
provider: fallbackProvider,
|
|
411
|
+
reason: `Fallback from Ollama: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
412
|
+
},
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
// ==========================================================================
|
|
419
|
+
// Helpers
|
|
420
|
+
// ==========================================================================
|
|
421
|
+
async isOllamaAvailable() {
|
|
422
|
+
try {
|
|
423
|
+
const response = await fetch('http://localhost:11434/api/tags', {
|
|
424
|
+
signal: AbortSignal.timeout(1000),
|
|
425
|
+
});
|
|
426
|
+
return response.ok;
|
|
427
|
+
}
|
|
428
|
+
catch {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
getBridge(provider) {
|
|
433
|
+
if (provider === 'ollama') {
|
|
434
|
+
if (!this.localBridge) {
|
|
435
|
+
this.localBridge = new index_js_1.LLMBridge({ provider: 'ollama' });
|
|
436
|
+
}
|
|
437
|
+
return this.localBridge;
|
|
438
|
+
}
|
|
439
|
+
if (!this.cloudBridge) {
|
|
440
|
+
this.cloudBridge = new index_js_1.LLMBridge({ provider });
|
|
441
|
+
}
|
|
442
|
+
return this.cloudBridge;
|
|
443
|
+
}
|
|
444
|
+
updateAverage(current, newValue, count) {
|
|
445
|
+
return current + (newValue - current) / count;
|
|
446
|
+
}
|
|
447
|
+
// ==========================================================================
|
|
448
|
+
// Stats & Config
|
|
449
|
+
// ==========================================================================
|
|
450
|
+
getStats() {
|
|
451
|
+
return { ...this.stats };
|
|
452
|
+
}
|
|
453
|
+
resetStats() {
|
|
454
|
+
this.stats = {
|
|
455
|
+
totalRequests: 0,
|
|
456
|
+
localRequests: 0,
|
|
457
|
+
cloudRequests: 0,
|
|
458
|
+
fallbacks: 0,
|
|
459
|
+
avgLocalLatency: 0,
|
|
460
|
+
avgCloudLatency: 0,
|
|
461
|
+
estimatedSavings: 0,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
getConfig() {
|
|
465
|
+
return { ...this.config };
|
|
466
|
+
}
|
|
467
|
+
setConfig(config) {
|
|
468
|
+
this.config = { ...this.config, ...config };
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
exports.HybridRouter = HybridRouter;
|
|
472
|
+
// ============================================================================
|
|
473
|
+
// Singleton
|
|
474
|
+
// ============================================================================
|
|
475
|
+
let routerInstance = null;
|
|
476
|
+
function getHybridRouter(config) {
|
|
477
|
+
if (!routerInstance) {
|
|
478
|
+
routerInstance = new HybridRouter(config);
|
|
479
|
+
}
|
|
480
|
+
return routerInstance;
|
|
481
|
+
}
|
|
482
|
+
function resetHybridRouter() {
|
|
483
|
+
routerInstance = null;
|
|
484
|
+
}
|
|
485
|
+
// ============================================================================
|
|
486
|
+
// Convenience Functions
|
|
487
|
+
// ============================================================================
|
|
488
|
+
/**
|
|
489
|
+
* Smart chat: automatically routes to best provider
|
|
490
|
+
*/
|
|
491
|
+
async function smartChat(prompt, systemPrompt) {
|
|
492
|
+
const router = getHybridRouter();
|
|
493
|
+
const result = await router.execute(prompt, systemPrompt);
|
|
494
|
+
return result;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Force local chat (Ollama)
|
|
498
|
+
*/
|
|
499
|
+
async function localChat(prompt, systemPrompt) {
|
|
500
|
+
const bridge = new index_js_1.LLMBridge({ provider: 'ollama' });
|
|
501
|
+
return bridge.chat(prompt, systemPrompt);
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Force cloud chat
|
|
505
|
+
*/
|
|
506
|
+
async function cloudChat(prompt, systemPrompt) {
|
|
507
|
+
const provider = process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai';
|
|
508
|
+
const bridge = new index_js_1.LLMBridge({ provider });
|
|
509
|
+
return bridge.chat(prompt, systemPrompt);
|
|
510
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis 6.8 - Real MCP Client Module
|
|
3
|
+
*
|
|
4
|
+
* Connects to actual MCP servers using @modelcontextprotocol/sdk.
|
|
5
|
+
* Spawns servers on demand and manages connections.
|
|
6
|
+
*
|
|
7
|
+
* Environment Variables:
|
|
8
|
+
* - GENESIS_MCP_MODE: 'real' | 'simulated' | 'hybrid' (default: 'simulated')
|
|
9
|
+
* - GENESIS_MCP_TIMEOUT: Timeout in ms (default: 30000)
|
|
10
|
+
* - GENESIS_MCP_LOG: Enable MCP call logging (default: false)
|
|
11
|
+
*/
|
|
12
|
+
export * from './resilient.js';
|
|
13
|
+
import { MCPServerName } from '../types.js';
|
|
14
|
+
export type MCPMode = 'real' | 'simulated' | 'hybrid';
|
|
15
|
+
export interface MCPCallOptions {
|
|
16
|
+
timeout?: number;
|
|
17
|
+
retries?: number;
|
|
18
|
+
fallbackToSimulated?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface MCPCallResult<T = any> {
|
|
21
|
+
success: boolean;
|
|
22
|
+
data?: T;
|
|
23
|
+
error?: string;
|
|
24
|
+
server: MCPServerName;
|
|
25
|
+
tool: string;
|
|
26
|
+
mode: 'real' | 'simulated';
|
|
27
|
+
latency: number;
|
|
28
|
+
timestamp: Date;
|
|
29
|
+
}
|
|
30
|
+
export interface MCPClientConfig {
|
|
31
|
+
mode: MCPMode;
|
|
32
|
+
timeout: number;
|
|
33
|
+
logCalls: boolean;
|
|
34
|
+
onCall?: (server: MCPServerName, tool: string, params: any) => void;
|
|
35
|
+
onResult?: (result: MCPCallResult) => void;
|
|
36
|
+
}
|
|
37
|
+
interface MCPServerInfo {
|
|
38
|
+
command: string;
|
|
39
|
+
args: string[] | (() => string[]);
|
|
40
|
+
envVars?: Record<string, string> | (() => Record<string, string>);
|
|
41
|
+
tools: string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Registry of MCP servers and how to spawn them.
|
|
45
|
+
* These are the 13 MCP servers Genesis uses.
|
|
46
|
+
*
|
|
47
|
+
* Package sources (verified on npm):
|
|
48
|
+
* - Official: @modelcontextprotocol/server-*
|
|
49
|
+
* - Third-party: arxiv-mcp-server, @brave/brave-search-mcp-server, etc.
|
|
50
|
+
*/
|
|
51
|
+
declare const MCP_SERVER_REGISTRY: Record<MCPServerName, MCPServerInfo>;
|
|
52
|
+
/**
|
|
53
|
+
* MCP Tool definition with full schema (from MCP SDK)
|
|
54
|
+
*/
|
|
55
|
+
export interface MCPToolDefinition {
|
|
56
|
+
name: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
inputSchema?: {
|
|
59
|
+
type: 'object';
|
|
60
|
+
properties?: Record<string, {
|
|
61
|
+
type?: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
enum?: string[];
|
|
64
|
+
items?: any;
|
|
65
|
+
}>;
|
|
66
|
+
required?: string[];
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export interface IMCPClient {
|
|
70
|
+
call<T = any>(server: MCPServerName, tool: string, params: Record<string, any>, options?: MCPCallOptions): Promise<MCPCallResult<T>>;
|
|
71
|
+
listTools(server: MCPServerName): Promise<string[]>;
|
|
72
|
+
listToolsWithSchema(server: MCPServerName): Promise<MCPToolDefinition[]>;
|
|
73
|
+
discoverAllTools(): Promise<Record<MCPServerName, MCPToolDefinition[]>>;
|
|
74
|
+
isAvailable(server: MCPServerName): Promise<boolean>;
|
|
75
|
+
getMode(): MCPMode;
|
|
76
|
+
setMode(mode: MCPMode): void;
|
|
77
|
+
close(): Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
export declare function getMCPClient(config?: Partial<MCPClientConfig>): IMCPClient;
|
|
80
|
+
export declare function resetMCPClient(): void;
|
|
81
|
+
export declare const mcpClient: IMCPClient;
|
|
82
|
+
export declare function isSimulatedMode(): boolean;
|
|
83
|
+
export declare function isSimulatedResult(result: MCPCallResult): boolean;
|
|
84
|
+
export declare function logMCPMode(): void;
|
|
85
|
+
export { MCP_SERVER_REGISTRY };
|