@hhoangphuoc/escape-room-cli
Version:
A CLI for playing AI-generated escape room games. Install globally with: npm install -g @hhoangphuoc/escape-room-cli
332 lines (331 loc) ⢠12.5 kB
JavaScript
// 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 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 ('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';
}
};