UNPKG

@hhoangphuoc/escape-room-cli

Version:

A CLI for playing AI-generated escape room games. Install globally with: npm install -g @hhoangphuoc/escape-room-cli

374 lines (373 loc) • 13.9 kB
// Display mode enum for flexible rendering export var DisplayMode; (function (DisplayMode) { DisplayMode["TEXT_ONLY"] = "text_only"; DisplayMode["STRUCTURED"] = "structured"; DisplayMode["ENHANCED"] = "enhanced"; DisplayMode["COMPONENT"] = "component"; // New: Use TSX components for rich display })(DisplayMode || (DisplayMode = {})); // Display AI Response export const displayAIResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; if (!response.success) { items.push({ type: 'error', text: response.message, responseType: 'ai' }); return items; } if (mode === DisplayMode.TEXT_ONLY) { let text = response.message; // if (response.reasoning?.tokens) { // text += `\n\n🧠 Reasoning tokens: ${response.reasoning.tokens}`; // } // if (response.reasoning?.steps && response.reasoning.steps.length > 0) { // text += '\n\nReasoning steps:\n'; // response.reasoning.steps.forEach((step, index) => { // text += ` ${index + 1}. ${step}\n`; // }); // } if (response.usage?.cost !== undefined) { text += `\n\nšŸ’° Cost: $${response.usage.cost?.toFixed(5)}`; } items.push({ type: 'response', text: text.trim(), responseType: 'ai' }); } else { items.push({ type: 'response', text: response.message, responseType: 'ai', data: response }); } return items; }; // Display Help Response export const displayHelpResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; if (mode === DisplayMode.TEXT_ONLY) { let helpText = response.message + '\n'; response.commands.forEach(cmd => { helpText += `${cmd.command} - ${cmd.description}\n`; }); if (response.currentContext) { helpText += '\nCurrent Status:\n'; if (response.currentContext.isAuthenticated) { helpText += `āœ“ Authenticated\n`; if (response.currentContext.currentRoom) { helpText += `\nšŸ  Room: ${response.currentContext.currentRoom}\n`; } if (response.currentContext.gameMode) { helpText += `šŸŽ® Mode: ${response.currentContext.gameMode}\n`; } } else { helpText += `āœ— Not authenticated\n`; } if (response.currentContext.hasAI) { helpText += `šŸ¤– AI: ${response.currentContext.currentModel || 'Available'}\n`; } } items.push({ type: 'response', text: helpText.trim(), responseType: 'help' }); } else if (mode === DisplayMode.COMPONENT) { items.push({ type: 'response', text: response.message, responseType: 'help', data: response }); } else { items.push({ type: 'response', text: response.message, responseType: 'help', data: response }); } return items; }; // Display Look Response export const displayLookResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; if (!response.success) { items.push({ type: 'error', text: response.message, responseType: 'generic' }); return items; } if (mode === DisplayMode.TEXT_ONLY) { let lookText = response.message + '\n\n'; lookText += `\nšŸ“ ${response.roomData.name}\n`; if (response.roomData.background) { lookText += `${response.roomData.background}\n\n`; } if (response.roomData.objects.length > 0) { lookText += `\nšŸ” Objects in this room:\n`; response.roomData.objects.forEach(obj => { lookText += ` • ${obj}\n`; }); } else { lookText += `\nšŸ” No objects visible in this room.\n`; } items.push({ type: 'response', text: lookText.trim(), responseType: 'look' }); } else { items.push({ type: 'response', text: response.message, responseType: 'look', data: response }); } return items; }; // Display Inspect Response export const displayInspectResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; if (!response.success) { items.push({ type: 'error', text: response.message, responseType: 'generic' }); return items; } if (mode === DisplayMode.TEXT_ONLY && response.objectData) { let inspectText = response.message + '\n\n'; inspectText += `\nšŸ”Ž ${response.objectData.name}\n`; inspectText += `\nšŸ“ ${response.objectData.description}\n`; if (response.objectData.puzzle) { inspectText += `\n🧩 Puzzle: ${response.objectData.puzzle}\n`; } if (response.objectData.unlocked) { inspectText += `\nšŸ”“ Status: Unlocked\n`; if (response.objectData.answer) { inspectText += `\nāœ… Answer: ${response.objectData.answer}\n`; } } else { inspectText += `\nšŸ”’ Status: Locked\n`; } if (response.objectData.details && response.objectData.details.length > 0) { inspectText += `\nšŸ“‹ Details:\n`; response.objectData.details.forEach(detail => { inspectText += ` • ${detail}\n`; }); } items.push({ type: 'response', text: inspectText.trim(), responseType: 'inspect' }); } else { items.push({ type: 'response', text: response.message, responseType: 'inspect', data: response }); } return items; }; // Display Guess Response export const displayGuessResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; const responseType = response.success ? (response.objectData.correctAnswer ? 'success' : 'response') : 'error'; if (mode === DisplayMode.TEXT_ONLY) { let guessText = response.message; if (response.success && response.objectData.correctAnswer) { guessText += `\n\nšŸŽ‰ Correct! ${response.objectData.name} is now unlocked!`; } else if (response.success && !response.objectData.correctAnswer) { guessText += `\n\nāŒ Incorrect guess for ${response.objectData.name}. Try again!`; } items.push({ type: responseType, text: guessText, responseType: 'guess' }); } else { items.push({ type: responseType, text: response.message, responseType: 'guess', data: response // Pass the full response object }); } return items; }; // Display Password Response export const displayPasswordResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; const responseType = response.success && response.gameResult.escaped ? 'success' : (response.success ? 'response' : 'error'); if (mode === DisplayMode.TEXT_ONLY) { let passwordText = response.message; if (response.gameResult.escaped) { passwordText += '\n\nšŸŽŠ Congratulations! You escaped!\n'; if (response.gameResult.timeElapsed) { passwordText += `\nā±ļø Time: ${response.gameResult.timeElapsed} seconds`; } if (response.gameResult.hintsUsed !== undefined) { passwordText += `\nšŸ’” Hints used: ${response.gameResult.hintsUsed}`; } if (response.gameResult.gameCompleted) { passwordText += '\n\nšŸ† Game completed! Well done!\n'; } } items.push({ type: responseType, text: passwordText, responseType: 'password' }); } else { items.push({ type: responseType, text: response.message, responseType: 'password', data: response // Pass the full response object }); } return items; }; // Display Hint Response export const displayHintResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; if (!response.success) { items.push({ type: 'error', text: response.message, responseType: 'generic' }); return items; } if (mode === DisplayMode.TEXT_ONLY) { let hintText = `\nšŸ’” Hint: ${response.hintData.hint}`; if (response.hintData.hintsUsed > 0) { hintText += `\nšŸ“Š Hints used so far: ${response.hintData.hintsUsed}`; } items.push({ type: 'info', text: hintText, responseType: 'hint' }); } else { items.push({ type: 'info', text: response.message, responseType: 'hint', data: response // Pass the full response object }); } return items; }; // Display New Game Response export const displayNewGameResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; if (!response.success) { items.push({ type: 'error', text: response.message, responseType: 'generic' }); return items; } if (mode === DisplayMode.TEXT_ONLY) { let gameText = `\nšŸŽ® ${response.message}\n\n`; gameText += `šŸ†” Game ID: ${response.gameData.id}\n`; gameText += `šŸ  Room: ${response.gameData.currentRoom}/${response.gameData.totalRooms}\n`; gameText += `šŸ“¦ Objects: ${response.gameData.objectCount}\n`; gameText += `šŸŽÆ Mode: ${response.gameData.mode}\n`; if (response.gameData.startTime) { gameText += `\n ā° Started: ${new Date(response.gameData.startTime).toLocaleTimeString()}\n`; } items.push({ type: 'success', text: gameText.trim(), responseType: 'newgame' }); } else { items.push({ type: 'success', text: response.message, responseType: 'newgame', data: response // Pass the full response object }); } return items; }; // Display Leaderboard Response export const displayLeaderboardResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; if (!response.success) { items.push({ type: 'error', text: response.message, responseType: 'generic' }); return items; } if (mode === DisplayMode.TEXT_ONLY) { items.push({ type: 'response', text: response.message, responseType: 'leaderboard' }); } else { items.push({ type: 'response', text: response.message, responseType: 'leaderboard', data: response // Pass the full response object }); } return items; }; // Display Auth Response export const displayAuthResponse = (response, mode = DisplayMode.COMPONENT) => { const items = []; const responseType = response.success ? 'success' : 'error'; if (mode === DisplayMode.TEXT_ONLY) { let authText = response.message; if (response.success && response.userData) { authText += `\nšŸ‘¤ Welcome, ${response.userData.userName}!`; authText += `\nšŸ†” User ID: ${response.userData.userId}`; if (response.userData.apiKey) { authText += `\nšŸ”‘ API key configured`; } } items.push({ type: responseType, text: authText, responseType: 'auth' }); } else { items.push({ type: responseType, text: response.message, responseType: 'auth', data: response // Pass the full response object }); } return items; }; // Generic display function that routes to specific handlers export const displayResponse = (response, mode = DisplayMode.COMPONENT) => { // Type guards to determine response type if ('commands' in response) { return displayHelpResponse(response, mode); } else if ('roomData' in response) { return displayLookResponse(response, mode); } else if ('objectData' in response && 'objectData' in response && typeof response.objectData === 'object' && 'unlocked' in response.objectData) { if ('correctAnswer' in response.objectData) { return displayGuessResponse(response, mode); } else { return displayInspectResponse(response, mode); } } else if ('gameResult' in response) { return displayPasswordResponse(response, mode); } else if ('hintData' in response) { return displayHintResponse(response, mode); } else if ('gameData' in response) { return displayNewGameResponse(response, mode); } else if ('leaderboardData' in response) { return displayLeaderboardResponse(response, mode); } else if ( // 'reasoning' in response || ('usage' in response && (response.model || response.usage?.model))) { return displayAIResponse(response, mode); } else if ('userData' in response || response.message.includes('login') || response.message.includes('logout')) { return displayAuthResponse(response, mode); } else { // Fallback for basic responses return [{ type: response.success ? 'response' : 'error', text: response.message, responseType: 'generic' }]; } }; // For response items, handle multi-line content with better formatting and colors export const getColorForResponseType = (type) => { switch (type) { case 'error': return 'red'; case 'success': return 'green'; case 'info': return 'cyan'; case 'response': return 'white'; default: return 'white'; } };