From 2dff6cd0afda4fb5e0f259d85882de15590d9f32 Mon Sep 17 00:00:00 2001
From: patrick-motsch
Date: Mon, 23 Feb 2026 23:01:28 +0100
Subject: [PATCH] fixed cursor feature
---
modules/aicore/aicoreModelSelector.py | 36 ++++++++++++++++---
.../codeeditor/datamodelCodeeditor.py | 1 +
.../features/codeeditor/fileContextManager.py | 4 ++-
modules/interfaces/interfaceAiObjects.py | 6 ++--
4 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/modules/aicore/aicoreModelSelector.py b/modules/aicore/aicoreModelSelector.py
index 4724356f..ea0a4198 100644
--- a/modules/aicore/aicoreModelSelector.py
+++ b/modules/aicore/aicoreModelSelector.py
@@ -6,17 +6,39 @@ No complex rules needed - just filter by properties and sort by priority!
"""
import logging
-from typing import List, Dict, Any, Optional
+import time
+from typing import List, Dict, Any, Optional, Tuple
from modules.datamodels.datamodelAi import AiModel, AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum
-# Configure logger
logger = logging.getLogger(__name__)
+_COOLDOWN_DURATION = 60.0
+
+
class ModelSelector:
- """Simple model selector based on properties and priority-based sorting."""
+ """Model selector with priority scoring and recent-failure cooldown."""
def __init__(self):
- logger.info("ModelSelector initialized with simplified approach")
+ self._failureLog: Dict[str, float] = {}
+ logger.info("ModelSelector initialized with failure cooldown support")
+
+ def reportFailure(self, modelName: str):
+ """Record that a model just failed (rate limit, error, etc.).
+ The model will be deprioritized for COOLDOWN_DURATION seconds."""
+ self._failureLog[modelName] = time.time()
+ logger.info(f"ModelSelector: Recorded failure for {modelName}, cooldown {_COOLDOWN_DURATION}s")
+
+ def _getCooldownPenalty(self, modelName: str) -> float:
+ """Return a score penalty (0.0 = no penalty, large negative = recently failed)."""
+ failedAt = self._failureLog.get(modelName)
+ if failedAt is None:
+ return 0.0
+ elapsed = time.time() - failedAt
+ if elapsed > _COOLDOWN_DURATION:
+ del self._failureLog[modelName]
+ return 0.0
+ remaining = _COOLDOWN_DURATION - elapsed
+ return -(remaining / _COOLDOWN_DURATION) * 5000.0
def selectModel(self,
prompt: str,
@@ -129,10 +151,14 @@ class ModelSelector:
maxAllowed = model.contextLength * 0.8 / 4 if model.contextLength > 0 else "unlimited"
logger.warning(f" - {model.name}: contextLength={model.contextLength} tokens, maxAllowed={maxAllowed} tokens")
- # Step 3: Calculate scores for each model
+ # Step 3: Calculate scores for each model (including cooldown penalties)
scoredModels = []
for model in promptFiltered:
score = self._calculateModelScore(model, promptSize, contextSize, totalSize, options)
+ penalty = self._getCooldownPenalty(model.name)
+ if penalty < 0:
+ logger.debug(f"Model {model.name}: base_score={score:.3f}, cooldown_penalty={penalty:.0f}")
+ score += penalty
scoredModels.append((model, score))
logger.debug(f"Model {model.name}: score={score:.3f}")
diff --git a/modules/features/codeeditor/datamodelCodeeditor.py b/modules/features/codeeditor/datamodelCodeeditor.py
index 72a4f9bc..448496bf 100644
--- a/modules/features/codeeditor/datamodelCodeeditor.py
+++ b/modules/features/codeeditor/datamodelCodeeditor.py
@@ -29,6 +29,7 @@ class FileContext(BaseModel):
content: Optional[str] = None
mimeType: str
sizeBytes: int = 0
+ modifiedAt: Optional[float] = None
tags: List[str] = Field(default_factory=list)
diff --git a/modules/features/codeeditor/fileContextManager.py b/modules/features/codeeditor/fileContextManager.py
index d0e2ff1b..af13f09b 100644
--- a/modules/features/codeeditor/fileContextManager.py
+++ b/modules/features/codeeditor/fileContextManager.py
@@ -62,12 +62,14 @@ def listTextFiles(dbManagement) -> List[FileContext]:
for fileItem in allFiles:
if isTextFile(fileItem.mimeType, fileItem.fileName):
+ modifiedAt = getattr(fileItem, "_modifiedAt", None) or getattr(fileItem, "creationDate", None)
textFiles.append(FileContext(
fileId=fileItem.id,
fileName=fileItem.fileName,
content=None,
mimeType=fileItem.mimeType,
- sizeBytes=fileItem.fileSize
+ sizeBytes=fileItem.fileSize,
+ modifiedAt=modifiedAt
))
return textFiles
diff --git a/modules/interfaces/interfaceAiObjects.py b/modules/interfaces/interfaceAiObjects.py
index 0214d231..f6a2c41b 100644
--- a/modules/interfaces/interfaceAiObjects.py
+++ b/modules/interfaces/interfaceAiObjects.py
@@ -135,11 +135,11 @@ class AiObjects:
except Exception as e:
lastError = e
- logger.warning(f"❌ AI call failed with model {model.name}: {str(e)}")
+ logger.warning(f"AI call failed with model {model.name}: {str(e)}")
+ modelSelector.reportFailure(model.name)
- # If this is not the last model, try the next one
if attempt < len(failoverModelList) - 1:
- logger.info(f"🔄 Trying next failover model...")
+ logger.info(f"Trying next failover model...")
continue
else:
# All models failed