UNPKG

ai-persona-hub

Version:

AI Profile CLI - Create custom AI profiles run against dynamic LLM providers

308 lines 10.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChatInputHandler = void 0; const readline = __importStar(require("readline")); const chalk_1 = __importDefault(require("chalk")); class ChatInputHandler { history = []; historyIndex = -1; inputBuffer = ''; cursorPosition = 0; savedCurrentInput = ''; isRawMode = false; constructor(history = []) { this.history = [...history]; // Copy the history array } enableRawMode() { if (process.stdin.isTTY && !this.isRawMode) { process.stdin.setRawMode(true); this.isRawMode = true; } } disableRawMode() { if (process.stdin.isTTY && this.isRawMode) { process.stdin.setRawMode(false); this.isRawMode = false; } } renderInputLine() { // Clear the current line readline.clearLine(process.stdout, 0); readline.cursorTo(process.stdout, 0); // Write the prompt and current input const prompt = chalk_1.default.green('You: '); process.stdout.write(prompt + this.inputBuffer); // Position cursor correctly const promptLength = 5; // "You: " without ANSI codes readline.cursorTo(process.stdout, promptLength + this.cursorPosition); } parseAnsiSequence(data) { const input = data.toString(); // Arrow keys if (input === '\x1b[A') return 'up'; if (input === '\x1b[B') return 'down'; if (input === '\x1b[C') return 'right'; if (input === '\x1b[D') return 'left'; // Home/End if (input === '\x1b[H' || input === '\x1b[1~') return 'home'; if (input === '\x1b[F' || input === '\x1b[4~') return 'end'; // Delete if (input === '\x1b[3~') return 'delete'; return null; } handleKeyPress(data) { const input = data.toString(); // Handle ANSI escape sequences first if (input.startsWith('\x1b')) { const key = this.parseAnsiSequence(data); if (key) { this.handleSpecialKey(key); return; } } // Handle control characters if (input === '\x03') { // Ctrl+C process.exit(0); } if (input === '\x7f' || input === '\x08') { // Backspace this.handleBackspace(); return; } if (input === '\r' || input === '\n') { // Enter this.handleEnter(); return; } // Handle printable characters if (input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) <= 126) { this.insertCharacter(input); } } handleSpecialKey(key) { switch (key) { case 'up': this.navigateHistory('up'); break; case 'down': this.navigateHistory('down'); break; case 'left': if (this.cursorPosition > 0) { this.cursorPosition--; this.renderInputLine(); } break; case 'right': if (this.cursorPosition < this.inputBuffer.length) { this.cursorPosition++; this.renderInputLine(); } break; case 'home': this.cursorPosition = 0; this.renderInputLine(); break; case 'end': this.cursorPosition = this.inputBuffer.length; this.renderInputLine(); break; case 'delete': if (this.cursorPosition < this.inputBuffer.length) { this.inputBuffer = this.inputBuffer.slice(0, this.cursorPosition) + this.inputBuffer.slice(this.cursorPosition + 1); this.renderInputLine(); } break; } } insertCharacter(char) { // Reset history navigation when typing this.resetHistoryNavigation(); // Insert character at cursor position this.inputBuffer = this.inputBuffer.slice(0, this.cursorPosition) + char + this.inputBuffer.slice(this.cursorPosition); this.cursorPosition++; this.renderInputLine(); } handleBackspace() { // Reset history navigation when editing this.resetHistoryNavigation(); if (this.cursorPosition > 0) { this.inputBuffer = this.inputBuffer.slice(0, this.cursorPosition - 1) + this.inputBuffer.slice(this.cursorPosition); this.cursorPosition--; this.renderInputLine(); } } handleEnter() { // Move to next line process.stdout.write('\n'); // Reset history navigation this.resetHistoryNavigation(); // The input is complete, will be handled by promptForInput } navigateHistory(direction) { if (this.history.length === 0) return; if (direction === 'up') { if (this.historyIndex === -1) { // First time navigating, save current input this.savedCurrentInput = this.inputBuffer; this.historyIndex = 0; } else if (this.historyIndex < this.history.length - 1) { this.historyIndex++; } else { // Already at the oldest entry return; } // Load history entry this.inputBuffer = this.history[this.historyIndex]; this.cursorPosition = this.inputBuffer.length; } else if (direction === 'down') { if (this.historyIndex === -1) { // Not navigating history return; } else if (this.historyIndex > 0) { this.historyIndex--; // Load history entry this.inputBuffer = this.history[this.historyIndex]; this.cursorPosition = this.inputBuffer.length; } else { // Back to current input - clear if it was empty, otherwise restore if (this.savedCurrentInput.trim() === '') { this.clearInput(); } else { this.restoreCurrentInput(); } return; } } this.renderInputLine(); } restoreCurrentInput() { this.historyIndex = -1; this.inputBuffer = this.savedCurrentInput; this.cursorPosition = this.inputBuffer.length; this.savedCurrentInput = ''; this.renderInputLine(); } clearInput() { this.historyIndex = -1; this.inputBuffer = ''; this.cursorPosition = 0; this.savedCurrentInput = ''; this.renderInputLine(); } resetHistoryNavigation() { if (this.historyIndex !== -1) { this.historyIndex = -1; this.savedCurrentInput = ''; } } async promptForInput() { return new Promise(resolve => { // Reset input state this.inputBuffer = ''; this.cursorPosition = 0; this.resetHistoryNavigation(); // Show initial prompt process.stdout.write(chalk_1.default.green('You: ')); // Enable raw mode to capture individual keystrokes this.enableRawMode(); const dataHandler = (data) => { this.handleKeyPress(data); // Check if Enter was pressed (input is complete) const input = data.toString(); if (input === '\r' || input === '\n') { // Clean up and resolve process.stdin.removeListener('data', dataHandler); this.disableRawMode(); const result = this.inputBuffer.trim(); // Add non-empty answers to history if (result && !this.history.includes(result)) { this.history.unshift(result); // Keep history size manageable if (this.history.length > 100) { this.history = this.history.slice(0, 100); } } resolve(result); } }; process.stdin.on('data', dataHandler); // Handle process exit const exitHandler = () => { this.disableRawMode(); }; process.on('exit', exitHandler); process.on('SIGINT', exitHandler); process.on('SIGTERM', exitHandler); }); } updateHistory(newHistory) { this.history = [...newHistory]; this.resetHistoryNavigation(); } close() { this.disableRawMode(); } } exports.ChatInputHandler = ChatInputHandler; //# sourceMappingURL=chat-input-handler.js.map