@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3

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.
Files changed (120) hide show
  1. package/README.md +44 -54
  2. package/bin/cli.js +1 -115
  3. package/bin/loxia-terminal-v2.js +3 -0
  4. package/bin/loxia-terminal.js +3 -0
  5. package/bin/start-with-terminal.js +3 -0
  6. package/package.json +14 -15
  7. package/scripts/install-scanners.js +1 -235
  8. package/src/analyzers/CSSAnalyzer.js +1 -297
  9. package/src/analyzers/ConfigValidator.js +1 -690
  10. package/src/analyzers/ESLintAnalyzer.js +1 -320
  11. package/src/analyzers/JavaScriptAnalyzer.js +1 -261
  12. package/src/analyzers/PrettierFormatter.js +1 -247
  13. package/src/analyzers/PythonAnalyzer.js +1 -266
  14. package/src/analyzers/SecurityAnalyzer.js +1 -729
  15. package/src/analyzers/TypeScriptAnalyzer.js +1 -247
  16. package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
  17. package/src/analyzers/codeCloneDetector/detector.js +1 -203
  18. package/src/analyzers/codeCloneDetector/index.js +1 -160
  19. package/src/analyzers/codeCloneDetector/parser.js +1 -199
  20. package/src/analyzers/codeCloneDetector/reporter.js +1 -148
  21. package/src/analyzers/codeCloneDetector/scanner.js +1 -59
  22. package/src/core/agentPool.js +1 -1474
  23. package/src/core/agentScheduler.js +1 -2147
  24. package/src/core/contextManager.js +1 -709
  25. package/src/core/messageProcessor.js +1 -732
  26. package/src/core/orchestrator.js +1 -548
  27. package/src/core/stateManager.js +1 -877
  28. package/src/index.js +1 -631
  29. package/src/interfaces/cli.js +1 -549
  30. package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
  31. package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
  32. package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
  33. package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
  34. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
  35. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
  36. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
  37. package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
  38. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
  39. package/src/interfaces/terminal/api/apiClient.js +1 -0
  40. package/src/interfaces/terminal/api/messageRouter.js +1 -0
  41. package/src/interfaces/terminal/api/session.js +1 -0
  42. package/src/interfaces/terminal/api/websocket.js +1 -0
  43. package/src/interfaces/terminal/components/AgentCreator.js +1 -0
  44. package/src/interfaces/terminal/components/AgentEditor.js +1 -0
  45. package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
  46. package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
  47. package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
  48. package/src/interfaces/terminal/components/Header.js +1 -0
  49. package/src/interfaces/terminal/components/HelpPanel.js +1 -0
  50. package/src/interfaces/terminal/components/InputBox.js +1 -0
  51. package/src/interfaces/terminal/components/Layout.js +1 -0
  52. package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
  53. package/src/interfaces/terminal/components/MessageList.js +1 -0
  54. package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
  55. package/src/interfaces/terminal/components/SearchPanel.js +1 -0
  56. package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
  57. package/src/interfaces/terminal/components/StatusBar.js +1 -0
  58. package/src/interfaces/terminal/components/TextInput.js +1 -0
  59. package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
  60. package/src/interfaces/terminal/config/constants.js +1 -0
  61. package/src/interfaces/terminal/index.js +1 -0
  62. package/src/interfaces/terminal/state/useAgentControl.js +1 -0
  63. package/src/interfaces/terminal/state/useAgents.js +1 -0
  64. package/src/interfaces/terminal/state/useConnection.js +1 -0
  65. package/src/interfaces/terminal/state/useMessages.js +1 -0
  66. package/src/interfaces/terminal/state/useTools.js +1 -0
  67. package/src/interfaces/terminal/utils/debugLogger.js +1 -0
  68. package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
  69. package/src/interfaces/terminal/utils/theme.js +1 -0
  70. package/src/interfaces/webServer.js +1 -2162
  71. package/src/modules/fileExplorer/controller.js +1 -280
  72. package/src/modules/fileExplorer/index.js +1 -37
  73. package/src/modules/fileExplorer/middleware.js +1 -92
  74. package/src/modules/fileExplorer/routes.js +1 -125
  75. package/src/modules/fileExplorer/types.js +1 -44
  76. package/src/services/aiService.js +1 -1232
  77. package/src/services/apiKeyManager.js +1 -164
  78. package/src/services/benchmarkService.js +1 -366
  79. package/src/services/budgetService.js +1 -539
  80. package/src/services/contextInjectionService.js +1 -247
  81. package/src/services/conversationCompactionService.js +1 -637
  82. package/src/services/errorHandler.js +1 -810
  83. package/src/services/fileAttachmentService.js +1 -544
  84. package/src/services/modelRouterService.js +1 -366
  85. package/src/services/modelsService.js +1 -322
  86. package/src/services/qualityInspector.js +1 -796
  87. package/src/services/tokenCountingService.js +1 -536
  88. package/src/tools/agentCommunicationTool.js +1 -1344
  89. package/src/tools/agentDelayTool.js +1 -485
  90. package/src/tools/asyncToolManager.js +1 -604
  91. package/src/tools/baseTool.js +1 -800
  92. package/src/tools/browserTool.js +1 -920
  93. package/src/tools/cloneDetectionTool.js +1 -621
  94. package/src/tools/dependencyResolverTool.js +1 -1215
  95. package/src/tools/fileContentReplaceTool.js +1 -875
  96. package/src/tools/fileSystemTool.js +1 -1107
  97. package/src/tools/fileTreeTool.js +1 -853
  98. package/src/tools/imageTool.js +1 -901
  99. package/src/tools/importAnalyzerTool.js +1 -1060
  100. package/src/tools/jobDoneTool.js +1 -248
  101. package/src/tools/seekTool.js +1 -956
  102. package/src/tools/staticAnalysisTool.js +1 -1778
  103. package/src/tools/taskManagerTool.js +1 -2873
  104. package/src/tools/terminalTool.js +1 -2304
  105. package/src/tools/webTool.js +1 -1430
  106. package/src/types/agent.js +1 -519
  107. package/src/types/contextReference.js +1 -972
  108. package/src/types/conversation.js +1 -730
  109. package/src/types/toolCommand.js +1 -747
  110. package/src/utilities/attachmentValidator.js +1 -292
  111. package/src/utilities/configManager.js +1 -582
  112. package/src/utilities/constants.js +1 -722
  113. package/src/utilities/directoryAccessManager.js +1 -535
  114. package/src/utilities/fileProcessor.js +1 -307
  115. package/src/utilities/logger.js +1 -436
  116. package/src/utilities/tagParser.js +1 -1246
  117. package/src/utilities/toolConstants.js +1 -317
  118. package/web-ui/build/index.html +2 -2
  119. package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
  120. package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
@@ -1,322 +1 @@
1
- /**
2
- * ModelsService - Manages available models from the backend API
3
- *
4
- * Purpose:
5
- * - Fetch available models from /llm/models endpoint
6
- * - Cache models for the session
7
- * - Provide model names for routing
8
- * - Handle fallback when API is unavailable
9
- */
10
-
11
- class ModelsService {
12
- constructor(config, logger) {
13
- this.config = config;
14
- this.logger = logger;
15
-
16
- this.models = null;
17
- this.lastFetched = null;
18
- this.isLoading = false;
19
- this.cacheExpiry = 5 * 60 * 1000; // 5 minutes cache
20
-
21
- this.backendUrl = 'https://autopilot-api.azurewebsites.net';
22
-
23
- // API Key Manager reference (will be set by LoxiaSystem)
24
- this.apiKeyManager = null;
25
- }
26
-
27
- /**
28
- * Set API key manager instance
29
- * @param {ApiKeyManager} apiKeyManager - API key manager instance
30
- */
31
- setApiKeyManager(apiKeyManager) {
32
- this.apiKeyManager = apiKeyManager;
33
-
34
- this.logger?.info('API key manager set for models service', {
35
- hasManager: !!apiKeyManager
36
- });
37
- }
38
-
39
- /**
40
- * Initialize the models service and fetch initial data
41
- */
42
- async initialize() {
43
- try {
44
- await this.fetchModels();
45
- this.logger.info('Models service initialized', {
46
- modelCount: this.models?.length || 0
47
- });
48
- } catch (error) {
49
- this.logger.error('Failed to initialize models service', {
50
- error: error.message
51
- });
52
- // Use fallback models on initialization failure
53
- this.models = this._getFallbackModels();
54
- }
55
- }
56
-
57
- /**
58
- * Get available model names for routing
59
- */
60
- getAvailableModelNames() {
61
- if (!this.models || this.models.length === 0) {
62
- this.logger.warn('No models available, using fallback');
63
- return this._getFallbackModelNames();
64
- }
65
-
66
- return this.models.map(model => model.name);
67
- }
68
-
69
- /**
70
- * Get all model information
71
- */
72
- getModels() {
73
- return this.models || this._getFallbackModels();
74
- }
75
-
76
- /**
77
- * Fetch models from backend API
78
- * @param {Object} context - Optional context with API key
79
- */
80
- async fetchModels(context = null) {
81
- if (this.isLoading) {
82
- this.logger.debug('Models fetch already in progress');
83
- return;
84
- }
85
-
86
- this.isLoading = true;
87
-
88
- try {
89
- const url = `${this.backendUrl}/llm/models`;
90
-
91
- // Get API key from multiple sources
92
- let apiKey = null;
93
-
94
- // First try to get from API key manager using session ID
95
- if (this.apiKeyManager && context && context.sessionId) {
96
- const keys = this.apiKeyManager.getKeysForRequest(context.sessionId, {
97
- platformProvided: true, // Models endpoint uses platform key
98
- vendor: null
99
- });
100
-
101
- apiKey = keys.loxiaApiKey;
102
-
103
- this.logger?.info('Retrieved API key from session manager for models fetch', {
104
- sessionId: context.sessionId,
105
- hasLoxiaKey: !!apiKey
106
- });
107
- }
108
-
109
- // Fallback to context, config, then environment
110
- if (!apiKey && context && context.apiKey) {
111
- apiKey = context.apiKey;
112
- } else if (!apiKey && this.config.apiKey) {
113
- apiKey = this.config.apiKey;
114
- } else if (!apiKey && process.env.LOXIA_API_KEY) {
115
- apiKey = process.env.LOXIA_API_KEY;
116
- }
117
-
118
- const fetchOptions = {
119
- method: 'GET',
120
- headers: {
121
- 'Content-Type': 'application/json',
122
- ...(apiKey && { 'Authorization': `Bearer ${apiKey}` })
123
- },
124
- timeout: 10000 // 10 second timeout
125
- };
126
-
127
- this.logger.debug('Fetching models from backend', {
128
- url,
129
- hasApiKey: !!apiKey,
130
- apiKeySource: context?.apiKey ? 'context' : this.config.apiKey ? 'config' : process.env.LOXIA_API_KEY ? 'env' : 'none'
131
- });
132
-
133
- const response = await fetch(url, fetchOptions);
134
-
135
- if (!response.ok) {
136
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
137
- }
138
-
139
- const data = await response.json();
140
-
141
- if (data.models && Array.isArray(data.models)) {
142
- this.models = data.models;
143
- this.lastFetched = new Date();
144
- this.needsRefresh = false;
145
-
146
- this.logger.info('Models fetched from backend', {
147
- modelCount: this.models.length,
148
- models: this.models.map(m => m.name)
149
- });
150
- } else {
151
- throw new Error('Invalid response format from models API');
152
- }
153
-
154
- } catch (error) {
155
- this.logger.warn('Failed to fetch models from backend, using fallback', {
156
- error: error.message
157
- });
158
-
159
- // Use fallback data on fetch error
160
- if (!this.models) {
161
- this.models = this._getFallbackModels();
162
- }
163
-
164
- } finally {
165
- this.isLoading = false;
166
- }
167
- }
168
-
169
- /**
170
- * Check if models cache needs refresh
171
- */
172
- needsRefresh() {
173
- if (!this.lastFetched) return true;
174
-
175
- const timeSinceUpdate = Date.now() - this.lastFetched.getTime();
176
- return timeSinceUpdate > this.cacheExpiry;
177
- }
178
-
179
- /**
180
- * Force refresh models from backend
181
- * @param {Object} context - Optional context with API key
182
- */
183
- async refresh(context = null) {
184
- this.logger.info('Force refreshing models');
185
- await this.fetchModels(context);
186
- }
187
-
188
- /**
189
- * Refresh models with API key context if needed
190
- * @param {Object} context - Context with API key
191
- */
192
- async refreshWithContext(context) {
193
- // Only refresh if we haven't successfully fetched or if we need a refresh
194
- if (this.needsRefresh || !this.lastFetched) {
195
- this.logger.debug('Refreshing models with API key context');
196
- await this.fetchModels(context);
197
- }
198
- }
199
-
200
- /**
201
- * Get fallback models when API is unavailable
202
- * @private
203
- */
204
- _getFallbackModels() {
205
- return [
206
- {
207
- name: 'anthropic-sonnet',
208
- category: 'anthropic',
209
- type: 'chat',
210
- maxTokens: 10000,
211
- supportsVision: true,
212
- supportsSystem: true,
213
- pricing: { input: 0.003, output: 0.015, unit: '1K tokens' }
214
- },
215
- {
216
- name: 'anthropic-opus',
217
- category: 'anthropic',
218
- type: 'chat',
219
- maxTokens: 10000,
220
- supportsVision: true,
221
- supportsSystem: true,
222
- pricing: { input: 0.015, output: 0.075, unit: '1K tokens' }
223
- },
224
- {
225
- name: 'anthropic-haiku',
226
- category: 'anthropic',
227
- type: 'chat',
228
- maxTokens: 10000,
229
- supportsVision: true,
230
- supportsSystem: true,
231
- pricing: { input: 0.00025, output: 0.00125, unit: '1K tokens' }
232
- },
233
- {
234
- name: 'gpt-4',
235
- category: 'openai',
236
- type: 'chat',
237
- maxTokens: 4096,
238
- supportsVision: false,
239
- supportsSystem: true,
240
- pricing: { input: 0.030, output: 0.060, unit: '1K tokens' }
241
- },
242
- {
243
- name: 'gpt-4-mini',
244
- category: 'openai',
245
- type: 'chat',
246
- maxTokens: 16384,
247
- supportsVision: false,
248
- supportsSystem: true,
249
- pricing: { input: 0.00015, output: 0.0006, unit: '1K tokens' }
250
- },
251
- {
252
- name: 'deepseek-r1',
253
- category: 'deepseek',
254
- type: 'chat',
255
- maxTokens: 8192,
256
- supportsVision: false,
257
- supportsSystem: true,
258
- pricing: { input: 0.014, output: 0.028, unit: '1K tokens' }
259
- },
260
- {
261
- name: 'azure-ai-grok3',
262
- category: 'azure',
263
- type: 'chat',
264
- maxTokens: 4096,
265
- supportsVision: false,
266
- supportsSystem: true,
267
- pricing: { input: 0.01, output: 0.02, unit: '1K tokens' }
268
- },
269
- {
270
- name: 'phi-4',
271
- category: 'microsoft',
272
- type: 'chat',
273
- maxTokens: 2048,
274
- supportsVision: false,
275
- supportsSystem: true,
276
- pricing: { input: 0.010, output: 0.020, unit: '1K tokens' }
277
- },
278
- {
279
- name: 'autopilot-model-router',
280
- category: 'azure',
281
- type: 'chat',
282
- maxTokens: 2048,
283
- supportsVision: false,
284
- supportsSystem: true,
285
- pricing: { input: 0.001, output: 0.002, unit: '1K tokens' }
286
- }
287
- ];
288
- }
289
-
290
- /**
291
- * Get fallback model names only
292
- * @private
293
- */
294
- _getFallbackModelNames() {
295
- return [
296
- 'anthropic-sonnet',
297
- 'anthropic-opus',
298
- 'anthropic-haiku',
299
- 'gpt-4',
300
- 'gpt-4-mini',
301
- 'deepseek-r1',
302
- 'azure-ai-grok3',
303
- 'phi-4',
304
- 'autopilot-model-router'
305
- ];
306
- }
307
-
308
- /**
309
- * Get service status
310
- */
311
- getStatus() {
312
- return {
313
- initialized: !!this.models,
314
- lastFetched: this.lastFetched?.toISOString() || null,
315
- modelCount: this.models?.length || 0,
316
- isLoading: this.isLoading,
317
- needsRefresh: this.needsRefresh()
318
- };
319
- }
320
- }
321
-
322
- export default ModelsService;
1
+ const a0_0x52e654=a0_0x46f4;function a0_0x143e(){const _0x548464=['x2nHBMnLBfjLDhj5','x3nJAgvKDwXLuMv0CNK','n0zZA09dCG','z2v0vgLTzq','Bg9Nz2vY','zxjYB3i','Bw9KzwXZ','BgfZDevYCM9Y','Bwf4uMv0CMLLCW','AxnbCNjHEq','r0vu','mJmWntiWmeLdrNbWBW','mZK1nZq0BLrrB2X4','BM93','yxbPs2v5twfUywDLCG','mtyXnZy5mgLXEKjSva','uMv0CNKGyxr0zw1WDcbMywLSzwq','zw52','BgfZDezLDgnOzwq','qMvHCMvYia','otm4AvD2CvrP','ntaWnZjuz0H5Dum','Dg9ju09tDhjPBMC','BM9Uzq','CMv0CNLuAw1LCG','rxHLy3v0Aw5NihnJAgvKDwXLzcbTB2rLBcbMzxrJAcbYzxrYEq','zMv0y2HnB2rLBhm','mZe3nhDqyLDfta','yMfJA2vUzfvYBa','yxbWBgLJyxrPB24VANnVBG','zgvIDwC','te9ysufFqvbjx0Tfwq','mta0nZC5mZvgrerArLm','y2fJAgvfEhbPCNK','yxbPs2v5','CMv0CNLbDhrLBxb0CW','tM8GBw9KzwXZigf2ywLSywjSzsaTiefqssbMzxrJAcbMywLSzwq','BMvLzhnszwzYzxnO','ndi2mdqWmNrgD2LWzG','BgvUz3rO','BwvZC2fNzq','Aw5MBW','l2fWAs9SBg0VBw9KzwXZ'];a0_0x143e=function(){return _0x548464;};return a0_0x143e();}(function(_0x5ed555,_0x2e3a3f){const _0x3d7911=a0_0x46f4,_0x19295e=_0x5ed555();while(!![]){try{const _0x31fd10=parseInt(_0x3d7911(0x127))/0x1+-parseInt(_0x3d7911(0x126))/0x2*(parseInt(_0x3d7911(0x12d))/0x3)+-parseInt(_0x3d7911(0x11d))/0x4+-parseInt(_0x3d7911(0x121))/0x5+parseInt(_0x3d7911(0x138))/0x6+-parseInt(_0x3d7911(0x13f))/0x7*(parseInt(_0x3d7911(0x11e))/0x8)+parseInt(_0x3d7911(0x132))/0x9;if(_0x31fd10===_0x2e3a3f)break;else _0x19295e['push'](_0x19295e['shift']());}catch(_0x380396){_0x19295e['push'](_0x19295e['shift']());}}}(a0_0x143e,0x74e7e));function a0_0x46f4(_0x3a047a,_0x55e640){_0x3a047a=_0x3a047a-0x118;const _0x143e66=a0_0x143e();let _0x46f459=_0x143e66[_0x3a047a];if(a0_0x46f4['UbBiiD']===undefined){var _0x43ef9d=function(_0x16f0a8){const _0x3c54c6='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5b3ee1='',_0x3f9a7e='';for(let _0x2ee484=0x0,_0x149cea,_0x2436da,_0x14dd43=0x0;_0x2436da=_0x16f0a8['charAt'](_0x14dd43++);~_0x2436da&&(_0x149cea=_0x2ee484%0x4?_0x149cea*0x40+_0x2436da:_0x2436da,_0x2ee484++%0x4)?_0x5b3ee1+=String['fromCharCode'](0xff&_0x149cea>>(-0x2*_0x2ee484&0x6)):0x0){_0x2436da=_0x3c54c6['indexOf'](_0x2436da);}for(let _0x626fe=0x0,_0x258168=_0x5b3ee1['length'];_0x626fe<_0x258168;_0x626fe++){_0x3f9a7e+='%'+('00'+_0x5b3ee1['charCodeAt'](_0x626fe)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3f9a7e);};a0_0x46f4['dOEcQe']=_0x43ef9d,a0_0x46f4['SOzyiG']={},a0_0x46f4['UbBiiD']=!![];}const _0x5a174b=_0x143e66[0x0],_0x9ef04b=_0x3a047a+_0x5a174b,_0x2e21f4=a0_0x46f4['SOzyiG'][_0x9ef04b];return!_0x2e21f4?(_0x46f459=a0_0x46f4['dOEcQe'](_0x46f459),a0_0x46f4['SOzyiG'][_0x9ef04b]=_0x46f459):_0x46f459=_0x2e21f4,_0x46f459;}class ModelsService{constructor(_0x5b3ee1,_0x3f9a7e){const _0x40021c=a0_0x46f4;this['config']=_0x5b3ee1,this[_0x40021c(0x141)]=_0x3f9a7e,this[_0x40021c(0x118)]=null,this['lastFetched']=null,this['isLoading']=![],this[_0x40021c(0x133)]=0x5*0x3c*0x3e8,this['backendUrl']=_0x5b3ee1[_0x40021c(0x12e)]||'http://localhost:8080',this['retryAttempts']=0x0,this['maxRetries']=0x3,this['retryDelay']=0x7d0,this['retryTimer']=null,this[_0x40021c(0x119)]=null,this[_0x40021c(0x120)]=null;}['setApiKeyManager'](_0x2ee484){const _0x88de63=a0_0x46f4;this['apiKeyManager']=_0x2ee484,this[_0x88de63(0x141)]?.[_0x88de63(0x13b)]('API\x20key\x20manager\x20set\x20for\x20models\x20service',{'hasManager':!!_0x2ee484});}async['initialize'](){const _0x454b12=a0_0x46f4;try{await this['fetchModels'](),this['logger']['info']('Models\x20service\x20initialized',{'modelCount':this[_0x454b12(0x118)]?.['length']||0x0});}catch(_0x149cea){this[_0x454b12(0x119)]=_0x149cea['message'],this['logger'][_0x454b12(0x142)]('Failed\x20to\x20initialize\x20models\x20service\x20-\x20NO\x20FALLBACK\x20AVAILABLE',{'error':_0x149cea['message'],'endpoint':this[_0x454b12(0x12e)]+_0x454b12(0x13c),'willRetry':!![]}),this['_scheduleRetry']();}}['getAvailableModelNames'](){const _0x417d0d=a0_0x46f4;if(!this['models']||this[_0x417d0d(0x118)]['length']===0x0)return this[_0x417d0d(0x141)]['error'](_0x417d0d(0x136),{'lastError':this['lastError'],'endpoint':this['backendUrl']+_0x417d0d(0x13c),'retryAttempt':this['retryAttempts'],'maxRetries':this['maxRetries']}),[];return this['models']['map'](_0x2436da=>_0x2436da['name']);}['getModels'](){const _0x40e484=a0_0x46f4;if(!this['models']||this['models'][_0x40e484(0x139)]===0x0)return this['logger']['error'](_0x40e484(0x136),{'lastError':this['lastError'],'endpoint':this['backendUrl']+_0x40e484(0x13c)}),[];return this['models'];}async[a0_0x52e654(0x12c)](_0x14dd43=null){const _0x2147c8=a0_0x52e654;if(this['isLoading']){this[_0x2147c8(0x141)]['debug']('Models\x20fetch\x20already\x20in\x20progress');return;}this['isLoading']=!![];try{const _0x626fe=this['backendUrl']+_0x2147c8(0x13c);let _0x258168=null;if(this['apiKeyManager']&&_0x14dd43&&_0x14dd43['sessionId']){const _0xb7e9f4=this['apiKeyManager']['getKeysForRequest'](_0x14dd43['sessionId'],{'platformProvided':!![],'vendor':null});_0x258168=_0xb7e9f4['loxiaApiKey'],this['logger']?.[_0x2147c8(0x13b)]('Retrieved API key from session manager for models fetch',{'sessionId':_0x14dd43['sessionId'],'hasLoxiaKey':!!_0x258168});}if(!_0x258168&&_0x14dd43&&_0x14dd43[_0x2147c8(0x134)])_0x258168=_0x14dd43['apiKey'];else{if(!_0x258168&&this['config']['apiKey'])_0x258168=this['config']['apiKey'];else!_0x258168&&process['env'][_0x2147c8(0x131)]&&(_0x258168=process['env'][_0x2147c8(0x131)]);}const _0x534037={'method':_0x2147c8(0x11c),'headers':{'Content-Type':_0x2147c8(0x12f),..._0x258168&&{'Authorization':_0x2147c8(0x125)+_0x258168}},'timeout':0x2710};this[_0x2147c8(0x141)]['debug']('Fetching models from backend',{'url':_0x626fe,'hasApiKey':!!_0x258168,'apiKeySource':_0x14dd43?.['apiKey']?'context':this['config'][_0x2147c8(0x134)]?'config':process['env'][_0x2147c8(0x131)]?_0x2147c8(0x123):_0x2147c8(0x129)});const _0x22e1a1=await fetch(_0x626fe,_0x534037);if(!_0x22e1a1['ok'])throw new Error('HTTP\x20'+_0x22e1a1['status']+':\x20'+_0x22e1a1['statusText']);const _0x886dd9=await _0x22e1a1['json']();if(_0x886dd9['models']&&Array[_0x2147c8(0x11b)](_0x886dd9['models']))this[_0x2147c8(0x118)]=_0x886dd9[_0x2147c8(0x118)],this['lastFetched']=new Date(),this['needsRefresh']=![],this[_0x2147c8(0x141)]['info']('Models fetched from backend',{'modelCount':this['models']['length'],'models':this[_0x2147c8(0x118)]['map'](_0x52bb42=>_0x52bb42['name'])});else throw new Error('Invalid response format from models API');}catch(_0x333552){this[_0x2147c8(0x119)]=_0x333552[_0x2147c8(0x13a)],this['logger'][_0x2147c8(0x142)]('Failed to fetch models from backend - NO FALLBACK',{'error':_0x333552[_0x2147c8(0x13a)],'endpoint':url,'retryAttempt':this['retryAttempts'],'maxRetries':this['maxRetries']}),this[_0x2147c8(0x13e)](_0x14dd43);if(!this['models'])throw _0x333552;}finally{this['isLoading']=![];}}['needsRefresh'](){const _0x1d0e37=a0_0x52e654;if(!this['lastFetched'])return!![];const _0xc4a180=Date[_0x1d0e37(0x11f)]()-this[_0x1d0e37(0x124)][_0x1d0e37(0x140)]();return _0xc4a180>this[_0x1d0e37(0x133)];}async['refresh'](_0x494832=null){const _0x56df75=a0_0x52e654;this['logger']['info']('Force\x20refreshing\x20models'),await this[_0x56df75(0x12c)](_0x494832);}async['refreshWithContext'](_0x18096f){const _0x21527c=a0_0x52e654;(this[_0x21527c(0x137)]||!this[_0x21527c(0x124)])&&(this['logger']['debug']('Refreshing\x20models\x20with\x20API\x20key\x20context'),await this[_0x21527c(0x12c)](_0x18096f));}['_scheduleRetry'](_0x3d5078=null){const _0x3095e1=a0_0x52e654;this['retryTimer']&&(clearTimeout(this[_0x3095e1(0x12a)]),this[_0x3095e1(0x12a)]=null);if(this['retryAttempts']>=this['maxRetries']){this['logger'][_0x3095e1(0x142)]('Max\x20retry\x20attempts\x20reached\x20for\x20model\x20fetch',{'attempts':this['retryAttempts'],'maxRetries':this[_0x3095e1(0x11a)],'lastError':this['lastError']});return;}const _0x4381e2=this['retryDelay']*Math['pow'](0x2,this[_0x3095e1(0x135)]);this[_0x3095e1(0x135)]++,this['logger'][_0x3095e1(0x13b)]('Scheduling\x20model\x20fetch\x20retry',{'attempt':this['retryAttempts'],'maxRetries':this['maxRetries'],'delayMs':_0x4381e2}),this[_0x3095e1(0x12a)]=setTimeout(async()=>{const _0x3d74f2=_0x3095e1;this['logger']['info'](_0x3d74f2(0x12b),{'attempt':this['retryAttempts']});try{await this['fetchModels'](_0x3d5078),this[_0x3d74f2(0x135)]=0x0,this['lastError']=null;}catch(_0xe6da68){this['logger']['warn'](_0x3d74f2(0x122),{'attempt':this[_0x3d74f2(0x135)],'error':_0xe6da68['message']});}},_0x4381e2);}[a0_0x52e654(0x13d)](){const _0x23e7d6=a0_0x52e654;this['retryTimer']&&(clearTimeout(this[_0x23e7d6(0x12a)]),this[_0x23e7d6(0x12a)]=null,this['logger'][_0x23e7d6(0x130)]('Cancelled\x20pending\x20model\x20fetch\x20retry'));}['getStatus'](){const _0x28ac52=a0_0x52e654;return{'initialized':!!this['models'],'lastFetched':this['lastFetched']?.[_0x28ac52(0x128)]()||null,'modelCount':this[_0x28ac52(0x118)]?.[_0x28ac52(0x139)]||0x0,'isLoading':this['isLoading'],'needsRefresh':this[_0x28ac52(0x137)](),'error':this[_0x28ac52(0x119)]||null,'retryAttempts':this[_0x28ac52(0x135)],'maxRetries':this[_0x28ac52(0x11a)],'hasError':!!this['lastError']};}}export default ModelsService;