@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.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.
- package/README.md +44 -54
- package/bin/cli.js +1 -115
- package/bin/loxia-terminal-v2.js +3 -0
- package/bin/loxia-terminal.js +3 -0
- package/bin/start-with-terminal.js +3 -0
- package/package.json +15 -15
- package/scripts/install-scanners.js +1 -235
- package/src/analyzers/CSSAnalyzer.js +1 -297
- package/src/analyzers/ConfigValidator.js +1 -690
- package/src/analyzers/ESLintAnalyzer.js +1 -320
- package/src/analyzers/JavaScriptAnalyzer.js +1 -261
- package/src/analyzers/PrettierFormatter.js +1 -247
- package/src/analyzers/PythonAnalyzer.js +1 -266
- package/src/analyzers/SecurityAnalyzer.js +1 -729
- package/src/analyzers/TypeScriptAnalyzer.js +1 -247
- package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
- package/src/analyzers/codeCloneDetector/detector.js +1 -203
- package/src/analyzers/codeCloneDetector/index.js +1 -160
- package/src/analyzers/codeCloneDetector/parser.js +1 -199
- package/src/analyzers/codeCloneDetector/reporter.js +1 -148
- package/src/analyzers/codeCloneDetector/scanner.js +1 -59
- package/src/core/agentPool.js +1 -1474
- package/src/core/agentScheduler.js +1 -2147
- package/src/core/contextManager.js +1 -709
- package/src/core/messageProcessor.js +1 -732
- package/src/core/orchestrator.js +1 -548
- package/src/core/stateManager.js +1 -877
- package/src/index.js +1 -631
- package/src/interfaces/cli.js +1 -549
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
- package/src/interfaces/terminal/api/apiClient.js +1 -0
- package/src/interfaces/terminal/api/messageRouter.js +1 -0
- package/src/interfaces/terminal/api/session.js +1 -0
- package/src/interfaces/terminal/api/websocket.js +1 -0
- package/src/interfaces/terminal/components/AgentCreator.js +1 -0
- package/src/interfaces/terminal/components/AgentEditor.js +1 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
- package/src/interfaces/terminal/components/Header.js +1 -0
- package/src/interfaces/terminal/components/HelpPanel.js +1 -0
- package/src/interfaces/terminal/components/InputBox.js +1 -0
- package/src/interfaces/terminal/components/Layout.js +1 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
- package/src/interfaces/terminal/components/MessageList.js +1 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
- package/src/interfaces/terminal/components/SearchPanel.js +1 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
- package/src/interfaces/terminal/components/StatusBar.js +1 -0
- package/src/interfaces/terminal/components/TextInput.js +1 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
- package/src/interfaces/terminal/config/constants.js +1 -0
- package/src/interfaces/terminal/index.js +1 -0
- package/src/interfaces/terminal/state/useAgentControl.js +1 -0
- package/src/interfaces/terminal/state/useAgents.js +1 -0
- package/src/interfaces/terminal/state/useConnection.js +1 -0
- package/src/interfaces/terminal/state/useMessages.js +1 -0
- package/src/interfaces/terminal/state/useTools.js +1 -0
- package/src/interfaces/terminal/utils/debugLogger.js +1 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
- package/src/interfaces/terminal/utils/theme.js +1 -0
- package/src/interfaces/webServer.js +1 -2162
- package/src/modules/fileExplorer/controller.js +1 -280
- package/src/modules/fileExplorer/index.js +1 -37
- package/src/modules/fileExplorer/middleware.js +1 -92
- package/src/modules/fileExplorer/routes.js +1 -125
- package/src/modules/fileExplorer/types.js +1 -44
- package/src/services/aiService.js +1 -1232
- package/src/services/apiKeyManager.js +1 -164
- package/src/services/benchmarkService.js +1 -366
- package/src/services/budgetService.js +1 -539
- package/src/services/contextInjectionService.js +1 -247
- package/src/services/conversationCompactionService.js +1 -637
- package/src/services/errorHandler.js +1 -810
- package/src/services/fileAttachmentService.js +1 -544
- package/src/services/modelRouterService.js +1 -366
- package/src/services/modelsService.js +1 -322
- package/src/services/qualityInspector.js +1 -796
- package/src/services/tokenCountingService.js +1 -536
- package/src/tools/agentCommunicationTool.js +1 -1344
- package/src/tools/agentDelayTool.js +1 -485
- package/src/tools/asyncToolManager.js +1 -604
- package/src/tools/baseTool.js +1 -800
- package/src/tools/browserTool.js +1 -920
- package/src/tools/cloneDetectionTool.js +1 -621
- package/src/tools/dependencyResolverTool.js +1 -1215
- package/src/tools/fileContentReplaceTool.js +1 -875
- package/src/tools/fileSystemTool.js +1 -1107
- package/src/tools/fileTreeTool.js +1 -853
- package/src/tools/imageTool.js +1 -901
- package/src/tools/importAnalyzerTool.js +1 -1060
- package/src/tools/jobDoneTool.js +1 -248
- package/src/tools/seekTool.js +1 -956
- package/src/tools/staticAnalysisTool.js +1 -1778
- package/src/tools/taskManagerTool.js +1 -2873
- package/src/tools/terminalTool.js +1 -2304
- package/src/tools/webTool.js +1 -1430
- package/src/types/agent.js +1 -519
- package/src/types/contextReference.js +1 -972
- package/src/types/conversation.js +1 -730
- package/src/types/toolCommand.js +1 -747
- package/src/utilities/attachmentValidator.js +1 -292
- package/src/utilities/configManager.js +1 -582
- package/src/utilities/constants.js +1 -722
- package/src/utilities/directoryAccessManager.js +1 -535
- package/src/utilities/fileProcessor.js +1 -307
- package/src/utilities/logger.js +1 -436
- package/src/utilities/tagParser.js +1 -1246
- package/src/utilities/toolConstants.js +1 -317
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
- package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
|
@@ -1,366 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ModelRouterService - Uses PHI-4 to make intelligent model routing decisions
|
|
3
|
-
*
|
|
4
|
-
* Purpose:
|
|
5
|
-
* - Analyze incoming messages and conversation context
|
|
6
|
-
* - Use PHI-4 to determine optimal model for each message
|
|
7
|
-
* - Provide fallback to previous model on errors
|
|
8
|
-
* - Consider benchmark data and recent message history
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { MODEL_ROUTER_CONFIG, HTTP_STATUS, MODELS } from '../utilities/constants.js';
|
|
12
|
-
|
|
13
|
-
class ModelRouterService {
|
|
14
|
-
constructor(config, logger, benchmarkService, aiService) {
|
|
15
|
-
this.config = config;
|
|
16
|
-
this.logger = logger;
|
|
17
|
-
this.benchmarkService = benchmarkService;
|
|
18
|
-
this.aiService = aiService;
|
|
19
|
-
|
|
20
|
-
this.routerModel = MODEL_ROUTER_CONFIG.ROUTER_MODEL;
|
|
21
|
-
this.contextMessagesCount = MODEL_ROUTER_CONFIG.CONTEXT_MESSAGES_COUNT;
|
|
22
|
-
this.requestTimeout = MODEL_ROUTER_CONFIG.REQUEST_TIMEOUT;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Route message to optimal model using autopilot-model-router analysis
|
|
27
|
-
* @param {Object} message - Current message to route
|
|
28
|
-
* @param {Array} recentMessages - Recent conversation history
|
|
29
|
-
* @param {string} currentModel - Current model being used
|
|
30
|
-
* @param {Array} availableModels - Models available for routing
|
|
31
|
-
* @param {Object} context - Message context with API keys
|
|
32
|
-
* @returns {Promise<string>} Selected model name
|
|
33
|
-
*/
|
|
34
|
-
async routeMessage(message, recentMessages = [], currentModel = '', availableModels = [], context = {}) {
|
|
35
|
-
try {
|
|
36
|
-
this.logger.debug('Starting model routing analysis', {
|
|
37
|
-
messageLength: message.content?.length || 0,
|
|
38
|
-
recentMessagesCount: recentMessages.length,
|
|
39
|
-
currentModel,
|
|
40
|
-
availableModelsCount: availableModels.length
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Build context for autopilot-model-router
|
|
44
|
-
const routingContext = this._buildRoutingContext(
|
|
45
|
-
message,
|
|
46
|
-
recentMessages,
|
|
47
|
-
currentModel,
|
|
48
|
-
availableModels
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
// Get benchmark data
|
|
52
|
-
const benchmarkTable = this.benchmarkService.getBenchmarkTable();
|
|
53
|
-
|
|
54
|
-
// Create routing prompt for autopilot-model-router
|
|
55
|
-
const routingPrompt = this._createRoutingPrompt(routingContext, benchmarkTable);
|
|
56
|
-
|
|
57
|
-
// Send to autopilot-model-router for analysis
|
|
58
|
-
const routingDecision = await this._askForRouting(routingPrompt, context);
|
|
59
|
-
|
|
60
|
-
// Validate and return model selection
|
|
61
|
-
const selectedModel = this._validateModelSelection(routingDecision, availableModels, currentModel);
|
|
62
|
-
|
|
63
|
-
this.logger.info('Model routing completed', {
|
|
64
|
-
selectedModel,
|
|
65
|
-
previousModel: currentModel,
|
|
66
|
-
changed: selectedModel !== currentModel,
|
|
67
|
-
reasoning: routingDecision.reasoning?.substring(0, 100) || 'No reasoning provided'
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Return full routing result object for AgentScheduler
|
|
71
|
-
return {
|
|
72
|
-
selectedModel,
|
|
73
|
-
previousModel: currentModel,
|
|
74
|
-
changed: selectedModel !== currentModel,
|
|
75
|
-
reasoning: routingDecision.reasoning || 'No reasoning provided'
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
} catch (error) {
|
|
79
|
-
this.logger.error('Model routing failed, falling back to current model', {
|
|
80
|
-
error: error.message,
|
|
81
|
-
currentModel
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// Fallback to current model on any error
|
|
85
|
-
const fallbackModel = currentModel || availableModels[0] || MODELS.ANTHROPIC_SONNET;
|
|
86
|
-
return {
|
|
87
|
-
selectedModel: fallbackModel,
|
|
88
|
-
previousModel: currentModel,
|
|
89
|
-
changed: false,
|
|
90
|
-
reasoning: 'Routing failed, using fallback model'
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Build routing context from message and conversation history
|
|
97
|
-
* @private
|
|
98
|
-
*/
|
|
99
|
-
_buildRoutingContext(message, recentMessages, currentModel, availableModels) {
|
|
100
|
-
// Get recent messages (configurable count)
|
|
101
|
-
const contextMessages = recentMessages
|
|
102
|
-
.slice(-this.contextMessagesCount)
|
|
103
|
-
.map(msg => ({
|
|
104
|
-
role: msg.role,
|
|
105
|
-
content: msg.content?.substring(0, 500) || '', // Limit content length
|
|
106
|
-
timestamp: msg.timestamp
|
|
107
|
-
}));
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
currentMessage: {
|
|
111
|
-
content: message.content?.substring(0, 1000) || '', // Limit current message
|
|
112
|
-
role: message.role || 'user',
|
|
113
|
-
hasContextReferences: !!(message.contextReferences?.length),
|
|
114
|
-
contextTypes: message.contextReferences?.map(ref => ref.type) || []
|
|
115
|
-
},
|
|
116
|
-
recentMessages: contextMessages,
|
|
117
|
-
currentModel,
|
|
118
|
-
availableModels: availableModels.map(model => ({
|
|
119
|
-
name: model,
|
|
120
|
-
isCurrentModel: model === currentModel
|
|
121
|
-
})),
|
|
122
|
-
messageCount: recentMessages.length + 1,
|
|
123
|
-
timestamp: new Date().toISOString()
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Create routing prompt for autopilot-model-router
|
|
129
|
-
* @private
|
|
130
|
-
*/
|
|
131
|
-
_createRoutingPrompt(context, benchmarkTable) {
|
|
132
|
-
return `You are a model routing assistant. Your job is to analyze a conversation and select the optimal AI model for the next response.
|
|
133
|
-
|
|
134
|
-
## Current Situation
|
|
135
|
-
- **Current Model**: ${context.currentModel || 'None'}
|
|
136
|
-
- **Message Count**: ${context.messageCount}
|
|
137
|
-
- **Available Models**: ${context.availableModels.map(m => m.name).join(', ')}
|
|
138
|
-
|
|
139
|
-
## Recent Conversation Context
|
|
140
|
-
${this._formatRecentMessages(context.recentMessages)}
|
|
141
|
-
|
|
142
|
-
## Current Message to Route
|
|
143
|
-
**Role**: ${context.currentMessage.role}
|
|
144
|
-
**Content**: ${context.currentMessage.content}
|
|
145
|
-
**Has Context References**: ${context.currentMessage.hasContextReferences}
|
|
146
|
-
${context.currentMessage.contextTypes.length > 0 ? `**Context Types**: ${context.currentMessage.contextTypes.join(', ')}` : ''}
|
|
147
|
-
|
|
148
|
-
## Model Benchmark Data
|
|
149
|
-
${this._formatBenchmarkData(benchmarkTable)}
|
|
150
|
-
|
|
151
|
-
## Routing Decision
|
|
152
|
-
Analyze the current message and conversation context to select the best model. Consider:
|
|
153
|
-
|
|
154
|
-
1. **Task Type**: Infer from conversation content - is this coding, analysis, creative writing, or a quick task?
|
|
155
|
-
2. **Complexity**: Does it require deep reasoning or is it straightforward?
|
|
156
|
-
3. **Context**: Are there code files or technical references?
|
|
157
|
-
4. **Conversation Flow**: What has been discussed recently to understand the overall task?
|
|
158
|
-
5. **Efficiency**: Balance performance with cost/speed needs
|
|
159
|
-
|
|
160
|
-
Respond with JSON only:
|
|
161
|
-
{
|
|
162
|
-
"selectedModel": "model-name",
|
|
163
|
-
"taskType": "coding|analysis|creative|quick-tasks",
|
|
164
|
-
"confidence": 0.85,
|
|
165
|
-
"reasoning": "Brief explanation of why this model was chosen",
|
|
166
|
-
"factors": ["factor1", "factor2", "factor3"]
|
|
167
|
-
}`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Format recent messages for prompt
|
|
172
|
-
* @private
|
|
173
|
-
*/
|
|
174
|
-
_formatRecentMessages(messages) {
|
|
175
|
-
if (!messages.length) {
|
|
176
|
-
return 'No recent messages available.';
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return messages.map((msg, i) =>
|
|
180
|
-
`${i + 1}. **${msg.role}**: ${msg.content}`
|
|
181
|
-
).join('\n');
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Format benchmark data for prompt
|
|
186
|
-
* @private
|
|
187
|
-
*/
|
|
188
|
-
_formatBenchmarkData(benchmarkTable) {
|
|
189
|
-
const models = benchmarkTable.models || [];
|
|
190
|
-
const tasks = benchmarkTable.tasks || {};
|
|
191
|
-
const summary = benchmarkTable.summary || {};
|
|
192
|
-
|
|
193
|
-
let formatted = '### Model Performance Summary\n';
|
|
194
|
-
|
|
195
|
-
// Task recommendations
|
|
196
|
-
Object.entries(tasks).forEach(([taskType, taskInfo]) => {
|
|
197
|
-
formatted += `**${taskType.toUpperCase()}** (${taskInfo.description}): ${taskInfo.topModels?.join(', ') || 'No data'}\n`;
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
formatted += '\n### Model Details\n';
|
|
201
|
-
|
|
202
|
-
// Model details (limit to available models)
|
|
203
|
-
models.slice(0, 8).forEach(model => {
|
|
204
|
-
formatted += `**${model.name}**: `;
|
|
205
|
-
const taskScores = Object.entries(model.tasks || {})
|
|
206
|
-
.map(([task, info]) => `${task}(${info.score})`)
|
|
207
|
-
.join(', ');
|
|
208
|
-
formatted += `${taskScores} | Strengths: ${model.strengths?.join(', ') || 'N/A'}\n`;
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
return formatted;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Send routing request to autopilot-model-router
|
|
216
|
-
* @private
|
|
217
|
-
*/
|
|
218
|
-
async _askForRouting(prompt, context = {}) {
|
|
219
|
-
try {
|
|
220
|
-
// Use AI service to send request to autopilot-model-router
|
|
221
|
-
const response = await this.aiService.sendMessage(
|
|
222
|
-
this.routerModel,
|
|
223
|
-
prompt,
|
|
224
|
-
{
|
|
225
|
-
agentId: 'model-router',
|
|
226
|
-
systemPrompt: 'You are a model routing expert. Analyze conversations and select optimal AI models. Always respond with valid JSON only.',
|
|
227
|
-
temperature: 0.3, // Low temperature for consistent routing decisions
|
|
228
|
-
maxTokens: 500,
|
|
229
|
-
timeout: this.requestTimeout,
|
|
230
|
-
sessionId: context.sessionId, // CRITICAL: Pass sessionId for API key retrieval
|
|
231
|
-
apiKey: context.apiKey || this.config.apiKey, // Fallback to API key from context if available
|
|
232
|
-
customApiKeys: context.customApiKeys,
|
|
233
|
-
platformProvided: true // autopilot-model-router is a platform model
|
|
234
|
-
}
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
if (!response.content) {
|
|
238
|
-
throw new Error('No response content from autopilot-model-router');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Parse JSON response
|
|
242
|
-
const routingDecision = this._parseRoutingResponse(response.content);
|
|
243
|
-
|
|
244
|
-
return routingDecision;
|
|
245
|
-
|
|
246
|
-
} catch (error) {
|
|
247
|
-
this.logger.error('autopilot-model-router routing request failed', {
|
|
248
|
-
error: error.message,
|
|
249
|
-
routerModel: this.routerModel
|
|
250
|
-
});
|
|
251
|
-
throw error;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Parse autopilot-model-router routing response
|
|
257
|
-
* @private
|
|
258
|
-
*/
|
|
259
|
-
_parseRoutingResponse(content) {
|
|
260
|
-
try {
|
|
261
|
-
// Try to extract JSON from response
|
|
262
|
-
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
263
|
-
if (!jsonMatch) {
|
|
264
|
-
throw new Error('No JSON found in autopilot-model-router response');
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const parsed = JSON.parse(jsonMatch[0]);
|
|
268
|
-
|
|
269
|
-
// Validate required fields
|
|
270
|
-
if (!parsed.selectedModel) {
|
|
271
|
-
throw new Error('Missing selectedModel in autopilot-model-router response');
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return {
|
|
275
|
-
selectedModel: parsed.selectedModel,
|
|
276
|
-
taskType: parsed.taskType || 'unknown',
|
|
277
|
-
confidence: parsed.confidence || 0.5,
|
|
278
|
-
reasoning: parsed.reasoning || 'No reasoning provided',
|
|
279
|
-
factors: parsed.factors || []
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
} catch (error) {
|
|
283
|
-
this.logger.warn('Failed to parse autopilot-model-router routing response', {
|
|
284
|
-
error: error.message,
|
|
285
|
-
content: content.substring(0, 200)
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
// Return default response on parse error
|
|
289
|
-
return {
|
|
290
|
-
selectedModel: null,
|
|
291
|
-
taskType: 'unknown',
|
|
292
|
-
confidence: 0.0,
|
|
293
|
-
reasoning: 'Failed to parse routing response',
|
|
294
|
-
factors: ['parsing-error']
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Validate model selection against available models
|
|
301
|
-
* @private
|
|
302
|
-
*/
|
|
303
|
-
_validateModelSelection(routingDecision, availableModels, currentModel) {
|
|
304
|
-
const { selectedModel } = routingDecision;
|
|
305
|
-
|
|
306
|
-
// If no model selected or parsing failed, use current model
|
|
307
|
-
if (!selectedModel) {
|
|
308
|
-
this.logger.debug('No model selected by router, using current model');
|
|
309
|
-
return currentModel;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Check if selected model is available
|
|
313
|
-
if (!availableModels.includes(selectedModel)) {
|
|
314
|
-
this.logger.warn('Router selected unavailable model, using current model', {
|
|
315
|
-
selectedModel,
|
|
316
|
-
availableModels
|
|
317
|
-
});
|
|
318
|
-
return currentModel;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Model is valid
|
|
322
|
-
return selectedModel;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Get router service status
|
|
327
|
-
*/
|
|
328
|
-
getStatus() {
|
|
329
|
-
return {
|
|
330
|
-
routerModel: this.routerModel,
|
|
331
|
-
contextMessagesCount: this.contextMessagesCount,
|
|
332
|
-
requestTimeout: this.requestTimeout,
|
|
333
|
-
benchmarkServiceStatus: this.benchmarkService.getStatus(),
|
|
334
|
-
isAvailable: true
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Test router with sample data
|
|
340
|
-
*/
|
|
341
|
-
async testRouter() {
|
|
342
|
-
try {
|
|
343
|
-
const testMessage = {
|
|
344
|
-
content: 'Can you help me debug this JavaScript function?',
|
|
345
|
-
role: 'user'
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
const testResult = await this.routeMessage(
|
|
349
|
-
testMessage,
|
|
350
|
-
[],
|
|
351
|
-
MODELS.ANTHROPIC_SONNET,
|
|
352
|
-
[MODELS.ANTHROPIC_SONNET, MODELS.ANTHROPIC_OPUS, MODELS.GPT_4, MODELS.DEEPSEEK_R1],
|
|
353
|
-
{ apiKey: 'test-key' } // Mock context for testing
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
this.logger.info('Router test completed', { selectedModel: testResult });
|
|
357
|
-
return { success: true, selectedModel: testResult };
|
|
358
|
-
|
|
359
|
-
} catch (error) {
|
|
360
|
-
this.logger.error('Router test failed', { error: error.message });
|
|
361
|
-
return { success: false, error: error.message };
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
export default ModelRouterService;
|
|
1
|
+
const a0_0x17a711=a0_0x2a19;(function(_0x753418,_0xaeb4a0){const _0x1dc841=a0_0x2a19,_0x58f3ad=_0x753418();while(!![]){try{const _0x1942a8=-parseInt(_0x1dc841(0x1f8))/0x1+-parseInt(_0x1dc841(0x221))/0x2+parseInt(_0x1dc841(0x21d))/0x3+-parseInt(_0x1dc841(0x1f3))/0x4*(-parseInt(_0x1dc841(0x1ee))/0x5)+parseInt(_0x1dc841(0x1e1))/0x6*(-parseInt(_0x1dc841(0x1fe))/0x7)+parseInt(_0x1dc841(0x212))/0x8+parseInt(_0x1dc841(0x1ea))/0x9*(-parseInt(_0x1dc841(0x1e6))/0xa);if(_0x1942a8===_0xaeb4a0)break;else _0x58f3ad['push'](_0x58f3ad['shift']());}catch(_0x1fac5a){_0x58f3ad['push'](_0x58f3ad['shift']());}}}(a0_0x5a81,0x2c419));function a0_0x2a19(_0x4537a7,_0x1d9f00){_0x4537a7=_0x4537a7-0x1e1;const _0x5a81ab=a0_0x5a81();let _0x2a196a=_0x5a81ab[_0x4537a7];if(a0_0x2a19['DXvxDq']===undefined){var _0x423a8b=function(_0x1ea9a2){const _0x39e3b2='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x575109='',_0x485728='';for(let _0x4c5688=0x0,_0x3dec92,_0x2ff9c2,_0x495e4d=0x0;_0x2ff9c2=_0x1ea9a2['charAt'](_0x495e4d++);~_0x2ff9c2&&(_0x3dec92=_0x4c5688%0x4?_0x3dec92*0x40+_0x2ff9c2:_0x2ff9c2,_0x4c5688++%0x4)?_0x575109+=String['fromCharCode'](0xff&_0x3dec92>>(-0x2*_0x4c5688&0x6)):0x0){_0x2ff9c2=_0x39e3b2['indexOf'](_0x2ff9c2);}for(let _0x23cc7f=0x0,_0x801b3a=_0x575109['length'];_0x23cc7f<_0x801b3a;_0x23cc7f++){_0x485728+='%'+('00'+_0x575109['charCodeAt'](_0x23cc7f)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x485728);};a0_0x2a19['YXuRkn']=_0x423a8b,a0_0x2a19['SDyLpM']={},a0_0x2a19['DXvxDq']=!![];}const _0x32597e=_0x5a81ab[0x0],_0x1d1bca=_0x4537a7+_0x32597e,_0x223fb3=a0_0x2a19['SDyLpM'][_0x1d1bca];return!_0x223fb3?(_0x2a196a=a0_0x2a19['YXuRkn'](_0x2a196a),a0_0x2a19['SDyLpM'][_0x1d1bca]=_0x2a196a):_0x2a196a=_0x223fb3,_0x2a196a;}function a0_0x5a81(){const _0x192612=['uKvrvuvtvf9usu1ft1vu','ywLtzxj2AwnL','qu5usfjpueLdx09qvvm','ndu1ntbUu3HlB1e','yMvUy2HTyxjRu2vYDMLJzq','Dw5RBM93BG','C3vTBwfYEq','z2v0u3rHDhvZ','tM8GsLnptIbMB3vUzcbPBIbHDxrVCgLSB3qTBw9KzwWTCM91DgvYihjLC3bVBNnL','n3rSBLLwsW','CMvXDwvZDfrPBwvVDxq','yxzHAwXHyMXLtw9KzwXZ','ktOG','BgvUz3rO','AM9PBG','tM8GCMvHC29UAw5NihbYB3zPzgvK','x2zVCM1HDfjLy2vUDe1LC3nHz2vZ','y29UDgvUDa','y3vYCMvUDe1VzgvS','lIaQkG','zgvIDwC','y3vYCMvUDe1LC3nHz2u','CM9Szq','CMvHC29UAw5N','revfufnfruTFuJe','C2vSzwn0zwrnB2rLBa','C2vUze1LC3nHz2u','tw9KzwWGCM91DgLUzYbMywLSzwqSigzHBgXPBMCGyMfJAYb0BYbJDxjYzw50ig1VzgvS','x3zHBgLKyxrLtw9KzwXtzwXLy3rPB24','mJa0mJy0mg1gDNfXuW','x3bHCNnLuM91DgLUz1jLC3bVBNnL','kIPdB250zxH0ifr5CgvZkIO6ia','uM91DgLUzYbMywLSzwqSihvZAw5NigzHBgXIywnRig1VzgvS','x2fZA0zVCLjVDxrPBMC','zMfJDg9YCW','Aw5MBW','rMfPBgvKihrVihbHCNnLigf1Dg9WAwXVDc1TB2rLBc1YB3v0zxiGCM91DgLUzYbYzxnWB25Zzq','C3vIC3rYAw5N','DxnLCG','DgfZA3m','nZC5ntK4u25Jr2Tb','cGOJiYbdDxjYzw50ie1LC3nHz2uGDg8GuM91DgukkIPsB2XLkIO6ia','y29UDgv4De1LC3nHz2vZq291BNq','Dg9Wtw9KzwXZ','ntK3mZa2vevnuuLA','uM91DgvYihnLBgvJDgvKihvUyxzHAwXHyMXLig1VzgvSlcb1C2LUzYbJDxjYzw50ig1VzgvS','ihWGu3rYzw5NDgHZoIa','tM8Gzgf0yq','BwvZC2fNzq','CM91DgvYtw9KzwW','BwvZC2fNzunVDw50','tI9b','uM91DgvYihrLC3qGzMfPBgvK','Bw9KzwWTCM91DgvY','CgfYC2LUzY1LCNjVCG','x2j1AwXKuM91DgLUz0nVBNrLEhq','r1buxZq','mZy2nZm4wKnby0Pz','BwfW','AgfZq29UDgv4DfjLzMvYzw5Jzxm','y29UzMLN','cGOJiYbnB2rLBcbczw5JAg1HCMSGrgf0yqO','mJaWu0PnAfn0','q2fUihLVDsbOzwXWig1LigrLyNvNihrOAxmGsMf2yvnJCMLWDcbMDw5JDgLVBJ8','Dg9vChbLCKnHC2u','tw9KzwWGCM91DgLUzYbJB21WBgv0zwq','ote2mtfrCgzgv1C','x2nYzwf0zvjVDxrPBMDqCM9TChq','ww91igfYzsbHig1VzgvSihjVDxrPBMCGzxHWzxj0lIbbBMfSExPLignVBNzLCNnHDgLVBNmGyw5KihnLBgvJDcbVChrPBwfSiefjig1VzgvSCY4GqwX3yxLZihjLC3bVBMqGD2L0Acb2ywXPzcbku09oig9UBhKU','BMfTzq','mtm3ndKXnxLPCgrrCW','y29UzMLKzw5Jzq','Bg9Nz2vY','yxbPs2v5','kIO6ia','ne5oB3nntG','tM9Uzq'];a0_0x5a81=function(){return _0x192612;};return a0_0x5a81();}import{MODEL_ROUTER_CONFIG,HTTP_STATUS,MODELS}from'../utilities/constants.js';class ModelRouterService{constructor(_0x575109,_0x485728,_0x4c5688,_0x3dec92){const _0x5c016d=a0_0x2a19;this[_0x5c016d(0x1e4)]=_0x575109,this['logger']=_0x485728,this[_0x5c016d(0x1f9)]=_0x4c5688,this[_0x5c016d(0x1f6)]=_0x3dec92,this['routerModel']=MODEL_ROUTER_CONFIG['ROUTER_MODEL'],this[_0x5c016d(0x21f)]=MODEL_ROUTER_CONFIG['CONTEXT_MESSAGES_COUNT'],this['requestTimeout']=MODEL_ROUTER_CONFIG[_0x5c016d(0x1f5)];}async['routeMessage'](_0x2ff9c2,_0x495e4d=[],_0x23cc7f='',_0x801b3a=[],_0x4ab6e9={}){const _0x5e2494=a0_0x2a19;try{this[_0x5e2494(0x1f0)][_0x5e2494(0x209)]('Starting\x20model\x20routing\x20analysis',{'messageLength':_0x2ff9c2[_0x5e2494(0x206)]?.['length']||0x0,'recentMessagesCount':_0x495e4d[_0x5e2494(0x202)],'currentModel':_0x23cc7f,'availableModelsCount':_0x801b3a[_0x5e2494(0x202)]});const _0x457fb5=this[_0x5e2494(0x22c)](_0x2ff9c2,_0x495e4d,_0x23cc7f,_0x801b3a),_0x425441=this[_0x5e2494(0x1f9)]['getBenchmarkTable'](),_0x502dfd=this[_0x5e2494(0x1eb)](_0x457fb5,_0x425441),_0x792009=await this[_0x5e2494(0x216)](_0x502dfd,_0x4ab6e9),_0x8a9ac7=this[_0x5e2494(0x211)](_0x792009,_0x801b3a,_0x23cc7f);return this['logger'][_0x5e2494(0x218)](_0x5e2494(0x1e9),{'selectedModel':_0x8a9ac7,'previousModel':_0x23cc7f,'changed':_0x8a9ac7!==_0x23cc7f,'reasoning':_0x792009[_0x5e2494(0x20c)]?.['substring'](0x0,0x64)||_0x5e2494(0x204)}),{'selectedModel':_0x8a9ac7,'previousModel':_0x23cc7f,'changed':_0x8a9ac7!==_0x23cc7f,'reasoning':_0x792009['reasoning']||_0x5e2494(0x204)};}catch(_0x49825e){this[_0x5e2494(0x1f0)]['error'](_0x5e2494(0x210),{'error':_0x49825e['message'],'currentModel':_0x23cc7f});const _0x50b989=_0x23cc7f||_0x801b3a[0x0]||MODELS['ANTHROPIC_SONNET'];return{'selectedModel':_0x50b989,'previousModel':_0x23cc7f,'changed':![],'reasoning':_0x5e2494(0x215)};}}[a0_0x17a711(0x22c)](_0x453fcb,_0x56eca2,_0x54647f,_0x5c058d){const _0x269c1f=a0_0x17a711,_0x157996=_0x56eca2['slice'](-this['contextMessagesCount'])[_0x269c1f(0x1e2)](_0x3fd6a5=>({'role':_0x3fd6a5['role'],'content':_0x3fd6a5['content']?.['substring'](0x0,0x1f4)||'','timestamp':_0x3fd6a5['timestamp']}));return{'currentMessage':{'content':_0x453fcb[_0x269c1f(0x206)]?.[_0x269c1f(0x21a)](0x0,0x3e8)||'','role':_0x453fcb[_0x269c1f(0x20b)]||'user','hasContextReferences':!!_0x453fcb['contextReferences']?.[_0x269c1f(0x202)],'contextTypes':_0x453fcb['contextReferences']?.[_0x269c1f(0x1e2)](_0x5279c0=>_0x5279c0['type'])||[]},'recentMessages':_0x157996,'currentModel':_0x54647f,'availableModels':_0x5c058d[_0x269c1f(0x1e2)](_0x1602de=>({'name':_0x1602de,'isCurrentModel':_0x1602de===_0x54647f})),'messageCount':_0x56eca2[_0x269c1f(0x202)]+0x1,'timestamp':new Date()['toISOString']()};}['_createRoutingPrompt'](_0x1986f5,_0x3ccfcb){const _0x232a16=a0_0x17a711;return'You\x20are\x20a\x20model\x20routing\x20assistant.\x20Your\x20job\x20is\x20to\x20analyze\x20a\x20conversation\x20and\x20select\x20the\x20optimal\x20AI\x20model\x20for\x20the\x20next\x20response.\x0a\x0a##\x20Current\x20Situation\x0a-\x20**Current\x20Model**:\x20'+(_0x1986f5[_0x232a16(0x207)]||_0x232a16(0x1f4))+'\x0a-\x20**Message\x20Count**:\x20'+_0x1986f5[_0x232a16(0x227)]+'\x0a-\x20**Available\x20Models**:\x20'+_0x1986f5[_0x232a16(0x200)]['map'](_0x3f9cf1=>_0x3f9cf1['name'])[_0x232a16(0x203)](',\x20')+'\x0a\x0a##\x20Recent\x20Conversation\x20Context\x0a'+this['_formatRecentMessages'](_0x1986f5['recentMessages'])+_0x232a16(0x21e)+_0x1986f5[_0x232a16(0x20a)]['role']+'\x0a**Content**:\x20'+_0x1986f5[_0x232a16(0x20a)][_0x232a16(0x206)]+'\x0a**Has\x20Context\x20References**:\x20'+_0x1986f5[_0x232a16(0x20a)][_0x232a16(0x1e3)]+'\x0a'+(_0x1986f5['currentMessage']['contextTypes'][_0x232a16(0x202)]>0x0?_0x232a16(0x214)+_0x1986f5['currentMessage']['contextTypes']['join'](',\x20'):'')+_0x232a16(0x1e5)+this['_formatBenchmarkData'](_0x3ccfcb)+'\x0a\x0a##\x20Routing\x20Decision\x0aAnalyze\x20the\x20current\x20message\x20and\x20conversation\x20context\x20to\x20select\x20the\x20best\x20model.\x20Consider:\x0a\x0a1.\x20**Task\x20Type**:\x20Infer\x20from\x20conversation\x20content\x20-\x20is\x20this\x20coding,\x20analysis,\x20creative\x20writing,\x20or\x20a\x20quick\x20task?\x0a2.\x20**Complexity**:\x20Does\x20it\x20require\x20deep\x20reasoning\x20or\x20is\x20it\x20straightforward?\x0a3.\x20**Context**:\x20Are\x20there\x20code\x20files\x20or\x20technical\x20references?\x0a4.\x20**Conversation\x20Flow**:\x20What\x20has\x20been\x20discussed\x20recently\x20to\x20understand\x20the\x20overall\x20task?\x0a5.\x20**Efficiency**:\x20Balance\x20performance\x20with\x20cost/speed\x20needs\x0a\x0aRespond\x20with\x20JSON\x20only:\x0a{\x0a\x20\x20\x22selectedModel\x22:\x20\x22model-name\x22,\x0a\x20\x20\x22taskType\x22:\x20\x22coding|analysis|creative|quick-tasks\x22,\x0a\x20\x20\x22confidence\x22:\x200.85,\x0a\x20\x20\x22reasoning\x22:\x20\x22Brief\x20explanation\x20of\x20why\x20this\x20model\x20was\x20chosen\x22,\x0a\x20\x20\x22factors\x22:\x20[\x22factor1\x22,\x20\x22factor2\x22,\x20\x22factor3\x22]\x0a}';}[a0_0x17a711(0x205)](_0xeeace1){const _0x25213b=a0_0x17a711;if(!_0xeeace1['length'])return'No\x20recent\x20messages\x20available.';return _0xeeace1['map']((_0x44d900,_0x4a200c)=>_0x4a200c+0x1+_0x25213b(0x208)+_0x44d900['role']+_0x25213b(0x1f2)+_0x44d900[_0x25213b(0x206)])[_0x25213b(0x203)]('\x0a');}['_formatBenchmarkData'](_0x383bdf){const _0x51a468=a0_0x17a711,_0x520513=_0x383bdf['models']||[],_0x30dbdd=_0x383bdf['tasks']||{},_0x4e4c96=_0x383bdf[_0x51a468(0x1fb)]||{};let _0x1d2326='###\x20Model\x20Performance\x20Summary\x0a';return Object['entries'](_0x30dbdd)['forEach'](([_0x3a6222,_0x1b06f7])=>{const _0x444dba=_0x51a468;_0x1d2326+='**'+_0x3a6222[_0x444dba(0x1e8)]()+'**\x20('+_0x1b06f7['description']+_0x444dba(0x201)+(_0x1b06f7[_0x444dba(0x220)]?.['join'](',\x20')||_0x444dba(0x224))+'\x0a';}),_0x1d2326+='\x0a###\x20Model\x20Details\x0a',_0x520513['slice'](0x0,0x8)['forEach'](_0x18632e=>{const _0x5a1344=_0x51a468;_0x1d2326+='**'+_0x18632e[_0x5a1344(0x1ed)]+_0x5a1344(0x1f2);const _0x4d718d=Object['entries'](_0x18632e[_0x5a1344(0x21c)]||{})[_0x5a1344(0x1e2)](([_0x2f93fd,_0x2c95de])=>_0x2f93fd+'('+_0x2c95de['score']+')')[_0x5a1344(0x203)](',\x20');_0x1d2326+=_0x4d718d+_0x5a1344(0x223)+(_0x18632e['strengths']?.[_0x5a1344(0x203)](',\x20')||_0x5a1344(0x228))+'\x0a';}),_0x1d2326;}async['_askForRouting'](_0x282540,_0x4db012={}){const _0x489c25=a0_0x17a711;try{const _0x534052=await this[_0x489c25(0x1f6)][_0x489c25(0x20f)](this['routerModel'],_0x282540,{'agentId':_0x489c25(0x22a),'systemPrompt':_0x489c25(0x1ec),'temperature':0.3,'maxTokens':0x1f4,'timeout':this[_0x489c25(0x1ff)],'sessionId':_0x4db012['sessionId'],'apiKey':_0x4db012['apiKey']||this[_0x489c25(0x1e4)][_0x489c25(0x1f1)],'customApiKeys':_0x4db012['customApiKeys'],'platformProvided':!![]});if(!_0x534052['content'])throw new Error('No response content from autopilot-model-router');const _0x51904f=this['_parseRoutingResponse'](_0x534052['content']);return _0x51904f;}catch(_0x4aec91){this['logger']['error']('autopilot-model-router\x20routing\x20request\x20failed',{'error':_0x4aec91[_0x489c25(0x225)],'routerModel':this[_0x489c25(0x226)]});throw _0x4aec91;}}[a0_0x17a711(0x213)](_0x2c14ac){const _0xf77ad5=a0_0x17a711;try{const _0x2fd341=_0x2c14ac['match'](/\{[\s\S]*\}/);if(!_0x2fd341)throw new Error(_0xf77ad5(0x1fd));const _0xeb460=JSON['parse'](_0x2fd341[0x0]);if(!_0xeb460[_0xf77ad5(0x20e)])throw new Error('Missing\x20selectedModel\x20in\x20autopilot-model-router\x20response');return{'selectedModel':_0xeb460[_0xf77ad5(0x20e)],'taskType':_0xeb460['taskType']||_0xf77ad5(0x1fa),'confidence':_0xeb460[_0xf77ad5(0x1ef)]||0.5,'reasoning':_0xeb460[_0xf77ad5(0x20c)]||_0xf77ad5(0x204),'factors':_0xeb460[_0xf77ad5(0x217)]||[]};}catch(_0x45daf6){return this[_0xf77ad5(0x1f0)]['warn'](_0xf77ad5(0x219),{'error':_0x45daf6[_0xf77ad5(0x225)],'content':_0x2c14ac['substring'](0x0,0xc8)}),{'selectedModel':null,'taskType':_0xf77ad5(0x1fa),'confidence':0x0,'reasoning':'Failed\x20to\x20parse\x20routing\x20response','factors':[_0xf77ad5(0x22b)]};}}['_validateModelSelection'](_0xb27b49,_0x4c9b67,_0x3d89f4){const _0xf9a727=a0_0x17a711,{selectedModel:_0x3769dd}=_0xb27b49;if(!_0x3769dd)return this['logger'][_0xf9a727(0x209)]('No\x20model\x20selected\x20by\x20router,\x20using\x20current\x20model'),_0x3d89f4;if(!_0x4c9b67['includes'](_0x3769dd))return this['logger']['warn'](_0xf9a727(0x222),{'selectedModel':_0x3769dd,'availableModels':_0x4c9b67}),_0x3d89f4;return _0x3769dd;}[a0_0x17a711(0x1fc)](){const _0xf32871=a0_0x17a711;return{'routerModel':this[_0xf32871(0x226)],'contextMessagesCount':this[_0xf32871(0x21f)],'requestTimeout':this['requestTimeout'],'benchmarkServiceStatus':this[_0xf32871(0x1f9)]['getStatus'](),'isAvailable':!![]};}async['testRouter'](){const _0x66f66e=a0_0x17a711;try{const _0x54024d={'content':_0x66f66e(0x1e7),'role':_0x66f66e(0x21b)},_0x1711a4=await this['routeMessage'](_0x54024d,[],MODELS['ANTHROPIC_SONNET'],[MODELS['ANTHROPIC_SONNET'],MODELS[_0x66f66e(0x1f7)],MODELS[_0x66f66e(0x22d)],MODELS[_0x66f66e(0x20d)]],{'apiKey':'test-key'});return this['logger']['info']('Router\x20test\x20completed',{'selectedModel':_0x1711a4}),{'success':!![],'selectedModel':_0x1711a4};}catch(_0x1ebfe3){return this[_0x66f66e(0x1f0)]['error'](_0x66f66e(0x229),{'error':_0x1ebfe3[_0x66f66e(0x225)]}),{'success':![],'error':_0x1ebfe3[_0x66f66e(0x225)]};}}}export default ModelRouterService;
|