ollama-code-qwen
Version:
Un assistant IA en ligne de commande utilisant Ollama et le modèle qwen2.5-coder pour aider au développement, avec des capacités MCP améliorées et détection d'intentions en français et anglais
333 lines (289 loc) • 7.66 kB
JavaScript
/**
* Composant personnalisé de saisie pour contourner les problèmes du textbox de blessed
*/
import blessed from 'blessed';
export class CustomInput {
/**
* Crée un composant de saisie personnalisé
* @param {Object} options - Options de configuration
*/
constructor(options = {}) {
this.screen = options.screen;
this.onSubmit = options.onSubmit || (() => {});
this.onCancel = options.onCancel || (() => {});
// Position et dimensions
this.top = options.top || 0;
this.left = options.left || 0;
this.width = options.width || '100%';
this.height = options.height || 3;
// Styles
this.style = options.style || {
fg: 'white',
bg: 'black',
border: {
fg: 'blue'
}
};
// État interne
this.currentInput = '';
this.cursorPos = 0;
this.prefix = options.prefix || '> ';
// Historique
this.history = [];
this.historyIndex = -1;
// Créer le composant d'affichage
this._createDisplay();
// Mettre en place les gestionnaires d'événements
this._setupHandlers();
}
/**
* Crée le composant d'affichage
*/
_createDisplay() {
this.box = blessed.box({
top: this.top,
left: this.left,
width: this.width,
height: this.height,
tags: true,
border: {
type: 'line'
},
style: this.style,
content: this.prefix
});
// Ajouter à l'écran si fourni
if (this.screen) {
this.screen.append(this.box);
}
}
/**
* Met en place les gestionnaires d'événements
*/
_setupHandlers() {
// Capturer les événements clavier au niveau de l'écran
this.screen.on('keypress', (ch, key) => {
if (!this.box.focused) return;
// Traiter l'événement clavier
this._handleKeyPress(ch, key);
});
}
/**
* Traite les événements clavier
* @param {string} ch - Caractère saisi
* @param {Object} key - Informations sur la touche
*/
_handleKeyPress(ch, key) {
// Si c'est une touche spéciale (pas un caractère)
if (!ch || key.ctrl || key.meta || key.shift) {
// Touches spéciales
switch (key.name) {
case 'return':
case 'enter':
this._submit();
break;
case 'escape':
this._cancel();
break;
case 'backspace':
this._backspace();
break;
case 'delete':
this._delete();
break;
case 'left':
this._moveCursor(-1);
break;
case 'right':
this._moveCursor(1);
break;
case 'home':
this._moveCursorTo(0);
break;
case 'end':
this._moveCursorTo(this.currentInput.length);
break;
case 'up':
this._historyPrev();
break;
case 'down':
this._historyNext();
break;
}
return;
}
// Ajouter le caractère à la position du curseur
this._insertChar(ch);
}
/**
* Insère un caractère à la position actuelle du curseur
* @param {string} ch - Caractère à insérer
*/
_insertChar(ch) {
const before = this.currentInput.slice(0, this.cursorPos);
const after = this.currentInput.slice(this.cursorPos);
this.currentInput = before + ch + after;
this.cursorPos++;
this._updateDisplay();
}
/**
* Supprime le caractère à gauche du curseur
*/
_backspace() {
if (this.cursorPos > 0) {
const before = this.currentInput.slice(0, this.cursorPos - 1);
const after = this.currentInput.slice(this.cursorPos);
this.currentInput = before + after;
this.cursorPos--;
this._updateDisplay();
}
}
/**
* Supprime le caractère à la position du curseur
*/
_delete() {
if (this.cursorPos < this.currentInput.length) {
const before = this.currentInput.slice(0, this.cursorPos);
const after = this.currentInput.slice(this.cursorPos + 1);
this.currentInput = before + after;
this._updateDisplay();
}
}
/**
* Déplace le curseur
* @param {number} offset - Nombre de positions à déplacer
*/
_moveCursor(offset) {
const newPos = this.cursorPos + offset;
if (newPos >= 0 && newPos <= this.currentInput.length) {
this.cursorPos = newPos;
this._updateDisplay();
}
}
/**
* Déplace le curseur à une position spécifique
* @param {number} position - Position où déplacer le curseur
*/
_moveCursorTo(position) {
if (position >= 0 && position <= this.currentInput.length) {
this.cursorPos = position;
this._updateDisplay();
}
}
/**
* Navigation dans l'historique: précédent
*/
_historyPrev() {
if (this.history.length > 0 && this.historyIndex < this.history.length - 1) {
this.historyIndex++;
this.currentInput = this.history[this.historyIndex];
this.cursorPos = this.currentInput.length;
this._updateDisplay();
}
}
/**
* Navigation dans l'historique: suivant
*/
_historyNext() {
if (this.historyIndex > 0) {
this.historyIndex--;
this.currentInput = this.history[this.historyIndex];
this.cursorPos = this.currentInput.length;
} else if (this.historyIndex === 0) {
this.historyIndex = -1;
this.currentInput = '';
}
this._updateDisplay();
}
/**
* Met à jour l'affichage
*/
_updateDisplay() {
const before = this.currentInput.slice(0, this.cursorPos);
const current = this.currentInput[this.cursorPos] || ' ';
const after = this.currentInput.slice(this.cursorPos + 1);
// Afficher avec le curseur
const displayText = this.prefix + before + '{inverse}' + current + '{/inverse}' + after;
this.box.setContent(displayText);
this.screen.render();
}
/**
* Soumet l'entrée
*/
_submit() {
const text = this.currentInput;
if (text && this.onSubmit) {
this.addToHistory(text);
this.onSubmit(text);
}
// Effacer l'entrée
this.currentInput = '';
this.cursorPos = 0;
this._updateDisplay();
}
/**
* Annule l'entrée
*/
_cancel() {
if (this.onCancel) {
this.onCancel();
}
// Effacer l'entrée
this.currentInput = '';
this.cursorPos = 0;
this._updateDisplay();
}
/**
* Ajoute une entrée à l'historique
* @param {string} text - Texte à ajouter
*/
addToHistory(text) {
if (text && text.trim()) {
// Éviter les duplications
if (this.history.length === 0 || this.history[0] !== text) {
this.history.unshift(text);
}
// Limiter la taille de l'historique
if (this.history.length > 50) {
this.history.pop();
}
this.historyIndex = -1;
}
}
/**
* Définit le focus sur ce composant
*/
focus() {
this.box.focus();
this._updateDisplay();
}
/**
* Retourne le composant d'affichage
* @returns {Object} - Composant blessed
*/
getDisplay() {
return this.box;
}
/**
* Obtient la valeur actuelle
* @returns {string} - Entrée actuelle
*/
getValue() {
return this.currentInput;
}
/**
* Définit la valeur actuelle
* @param {string} value - Nouvelle valeur
*/
setValue(value) {
this.currentInput = value || '';
this.cursorPos = this.currentInput.length;
this._updateDisplay();
}
/**
* Efface la valeur actuelle
*/
clearValue() {
this.setValue('');
}
}