tibiaway-ai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,141 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { getCharacter, addDiaryEntry } from '../utils/config.js';
5
+ import { askClaude, askClaudeWithImage } from '../utils/api.js';
6
+ import { error, success, highlight, separator, info } from '../utils/banner.js';
7
+
8
+ const IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif', 'webp'];
9
+ const TEXT_EXTENSIONS = ['txt', 'md', 'log'];
10
+
11
+ export async function handleAnalyze(filePath) {
12
+ const character = getCharacter();
13
+ if (!character) {
14
+ error('No hay personaje configurado. Ejecuta: tibiaway setup');
15
+ return;
16
+ }
17
+
18
+ console.log(chalk.hex('#FF6B1A').bold('🔍 ANALYZER\n'));
19
+
20
+ if (!filePath) {
21
+ error('Debes especificar un archivo. Ejemplo: tibiaway analyze ./screenshot.png');
22
+ return;
23
+ }
24
+
25
+ if (!existsSync(filePath)) {
26
+ error(`Archivo no encontrado: ${filePath}`);
27
+ return;
28
+ }
29
+
30
+ const ext = filePath.split('.').pop().toLowerCase();
31
+
32
+ if (IMAGE_EXTENSIONS.includes(ext)) {
33
+ await analyzeImage(filePath, character);
34
+ } else if (TEXT_EXTENSIONS.includes(ext)) {
35
+ await analyzeText(filePath, character);
36
+ } else {
37
+ error(`Formato no soportado: .${ext}. Usa: ${[...IMAGE_EXTENSIONS, ...TEXT_EXTENSIONS].join(', ')}`);
38
+ }
39
+ }
40
+
41
+ async function analyzeImage(filePath, character) {
42
+ info(`Analizando imagen: ${filePath}`);
43
+ console.log('');
44
+
45
+ const prompt = `Analiza esta captura de pantalla del juego Tibia.
46
+
47
+ Identifica qué tipo de screenshot es:
48
+ - Si muestra loot (ítems del suelo o contenedor): lista todos los ítems visibles y estima el valor total en gold
49
+ - Si muestra experiencia ganada / progress bar: extrae la exp ganada y estima exp/hora
50
+ - Si muestra el client con criaturas o hunting: analiza la situación y da tips
51
+ - Si muestra estadísticas, skills, o equipamiento: analiza y da recomendaciones
52
+ - Si muestra chat o mensajes: analiza el contexto y da sugerencias
53
+ - Si es otra cosa: describe qué ves y da insights relevantes
54
+
55
+ Para mi perfil de personaje, indica si lo que se ve es bueno, mejorable, o si hay algo importante que deba saber.
56
+
57
+ Al final, genera una nota resumida (1-2 líneas) para registrar en mi diario.
58
+ Termina la respuesta con la línea exacta:
59
+ NOTA_DIARIO: [la nota breve aquí]`;
60
+
61
+ const spinner = ora({ text: 'Analizando screenshot con visión IA...', color: 'yellow' }).start();
62
+
63
+ try {
64
+ const response = await askClaudeWithImage(prompt, filePath);
65
+ spinner.stop();
66
+ separator();
67
+ console.log('');
68
+ console.log(chalk.hex('#f0f0f0')(response));
69
+ console.log('');
70
+ separator();
71
+
72
+ const noteMatch = response.match(/NOTA_DIARIO:\s*(.+)/);
73
+ if (noteMatch) {
74
+ addDiaryEntry({
75
+ location: 'Análisis de screenshot',
76
+ note: noteMatch[1].trim(),
77
+ level: character.level,
78
+ });
79
+ success('Análisis guardado en el diario.');
80
+ }
81
+ } catch (err) {
82
+ spinner.stop();
83
+ error(`Error al analizar la imagen: ${err.message}`);
84
+ }
85
+ }
86
+
87
+ async function analyzeText(filePath, character) {
88
+ info(`Analizando archivo de texto: ${filePath}`);
89
+ console.log('');
90
+
91
+ const content = readFileSync(filePath, 'utf-8');
92
+
93
+ if (content.trim().length === 0) {
94
+ error('El archivo está vacío.');
95
+ return;
96
+ }
97
+
98
+ const prompt = `Analiza las siguientes notas de hunt / sesión de Tibia:
99
+
100
+ ---
101
+ ${content.slice(0, 4000)}
102
+ ---
103
+
104
+ Extrae y analiza:
105
+ 1. Qué tipo de información contienen estas notas
106
+ 2. Métricas clave (si hay): exp, gold, loot, tiempo, supplies
107
+ 3. Insights principales sobre la sesión
108
+ 4. ¿Qué se puede mejorar?
109
+ 5. Recomendaciones basadas en lo que se ve
110
+
111
+ Para mi perfil, indica si la sesión fue buena y qué cambios aplicarías.
112
+
113
+ Al final genera una nota resumida (1-2 líneas) para el diario.
114
+ Termina con la línea exacta:
115
+ NOTA_DIARIO: [la nota breve aquí]`;
116
+
117
+ const spinner = ora({ text: 'Analizando notas...', color: 'yellow' }).start();
118
+
119
+ try {
120
+ const response = await askClaude(prompt);
121
+ spinner.stop();
122
+ separator();
123
+ console.log('');
124
+ console.log(chalk.hex('#f0f0f0')(response));
125
+ console.log('');
126
+ separator();
127
+
128
+ const noteMatch = response.match(/NOTA_DIARIO:\s*(.+)/);
129
+ if (noteMatch) {
130
+ addDiaryEntry({
131
+ location: 'Análisis de notas',
132
+ note: noteMatch[1].trim(),
133
+ level: character.level,
134
+ });
135
+ success('Análisis guardado en el diario.');
136
+ }
137
+ } catch (err) {
138
+ spinner.stop();
139
+ error(`Error al analizar el archivo: ${err.message}`);
140
+ }
141
+ }
@@ -0,0 +1,85 @@
1
+ import inquirer from 'inquirer';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { getCharacter } from '../utils/config.js';
5
+ import { askClaude } from '../utils/api.js';
6
+ import { error, highlight, separator } from '../utils/banner.js';
7
+
8
+ export async function handleBoss(bossName) {
9
+ const character = getCharacter();
10
+ if (!character) {
11
+ error('No hay personaje configurado. Ejecuta: tibiaway setup');
12
+ return;
13
+ }
14
+
15
+ console.log(chalk.hex('#FF6B1A').bold('💀 BOSS ADVISOR\n'));
16
+
17
+ let targetBoss = bossName;
18
+
19
+ if (!targetBoss) {
20
+ const answer = await inquirer.prompt([
21
+ {
22
+ type: 'input',
23
+ name: 'boss',
24
+ message: highlight('¿Qué boss quieres enfrentar?'),
25
+ validate: (i) => i.trim().length > 0 || 'Ingresa el nombre del boss.',
26
+ },
27
+ ]);
28
+ targetBoss = answer.boss.trim();
29
+ }
30
+
31
+ const prompt = `Explícame todo sobre el boss: ${targetBoss}
32
+
33
+ Dame información completa y detallada:
34
+
35
+ 1. DESCRIPCIÓN GENERAL
36
+ - Qué es, dónde está, historia/lore relevante
37
+ - Cuándo aparece / cómo se invoca / periodicidad
38
+
39
+ 2. ESTADÍSTICAS CLAVE
40
+ - HP aproximado
41
+ - Debilidades elementales y resistencias
42
+ - Inmunidades importantes
43
+
44
+ 3. MECÁNICAS PRINCIPALES
45
+ - Ataques que usa y daño aproximado
46
+ - Mecánicas especiales (summons, fases, habilidades únicas)
47
+ - Comportamientos que hay que conocer sí o sí
48
+
49
+ 4. FASES (si aplica)
50
+ - Descripción de cada fase y cambios de comportamiento
51
+
52
+ 5. PREPARACIÓN RECOMENDADA PARA MI PERSONAJE
53
+ - Set óptimo e imbuements
54
+ - Supplies necesarios (con cantidades estimadas)
55
+ - Level mínimo recomendado para mi vocación
56
+
57
+ 6. ESTRATEGIA POR VOCACIÓN
58
+ - Cómo lo enfrento siendo ${character.vocation}
59
+ - Posicionamiento, skills a usar, rotación
60
+
61
+ 7. LOOT DESTACADO
62
+ - Items más valiosos o interesantes del drop
63
+
64
+ 8. ERRORES COMUNES Y TIPS
65
+ - Qué NO hacer
66
+ - Trucos que no son obvios
67
+
68
+ Sé específico. Si el boss tiene mecánicas que matan instant, mencionarlo claramente.`;
69
+
70
+ console.log(chalk.hex('#888888')(`Analizando: ${targetBoss}\n`));
71
+ const spinner = ora({ text: 'Consultando el libro de los bosses...', color: 'yellow' }).start();
72
+
73
+ try {
74
+ const response = await askClaude(prompt);
75
+ spinner.stop();
76
+ separator();
77
+ console.log('');
78
+ console.log(chalk.hex('#f0f0f0')(response));
79
+ console.log('');
80
+ separator();
81
+ } catch (err) {
82
+ spinner.stop();
83
+ error(`Error al consultar la IA: ${err.message}`);
84
+ }
85
+ }
@@ -0,0 +1,143 @@
1
+ import inquirer from 'inquirer';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { getCharacter, addDiaryEntry, getDiary } from '../utils/config.js';
5
+ import { askClaude } from '../utils/api.js';
6
+ import { error, success, highlight, separator, info, gold, dim } from '../utils/banner.js';
7
+
8
+ export async function handleDiary(subcommand) {
9
+ const character = getCharacter();
10
+ if (!character) {
11
+ error('No hay personaje configurado. Ejecuta: tibiaway setup');
12
+ return;
13
+ }
14
+
15
+ console.log(chalk.hex('#FF6B1A').bold('📖 DIARIO DE PROGRESO\n'));
16
+
17
+ const cmd = subcommand || await promptSubcommand();
18
+
19
+ if (cmd === 'add') {
20
+ await addEntry(character);
21
+ } else if (cmd === 'show') {
22
+ await showEntries();
23
+ } else if (cmd === 'summary') {
24
+ await generateSummary(character);
25
+ }
26
+ }
27
+
28
+ async function promptSubcommand() {
29
+ const { sub } = await inquirer.prompt([
30
+ {
31
+ type: 'list',
32
+ name: 'sub',
33
+ message: highlight('¿Qué quieres hacer?'),
34
+ choices: [
35
+ { name: 'Agregar nueva entrada', value: 'add' },
36
+ { name: 'Ver historial', value: 'show' },
37
+ { name: 'Resumen de progreso con IA', value: 'summary' },
38
+ ],
39
+ },
40
+ ]);
41
+ return sub;
42
+ }
43
+
44
+ async function addEntry(character) {
45
+ const answers = await inquirer.prompt([
46
+ {
47
+ type: 'input',
48
+ name: 'location',
49
+ message: highlight('¿Dónde cazaste / qué hiciste hoy?'),
50
+ validate: (i) => i.trim().length > 0 || 'Ingresa una ubicación o actividad.',
51
+ },
52
+ {
53
+ type: 'input',
54
+ name: 'note',
55
+ message: highlight('Nota del día (logros, observaciones, etc.):'),
56
+ validate: (i) => i.trim().length > 0 || 'Escribe algo en la nota.',
57
+ },
58
+ {
59
+ type: 'input',
60
+ name: 'level',
61
+ message: highlight(`¿En qué level estás? (actual: ${character.level})`),
62
+ default: String(character.level),
63
+ validate: (i) => !isNaN(parseInt(i)) || 'Ingresa un número.',
64
+ },
65
+ ]);
66
+
67
+ addDiaryEntry({
68
+ location: answers.location.trim(),
69
+ note: answers.note.trim(),
70
+ level: parseInt(answers.level),
71
+ });
72
+
73
+ success('Entrada añadida al diario.');
74
+ }
75
+
76
+ async function showEntries() {
77
+ const entries = getDiary();
78
+
79
+ if (entries.length === 0) {
80
+ info('El diario está vacío. Agrega una entrada con: tibiaway diary add');
81
+ return;
82
+ }
83
+
84
+ separator();
85
+ console.log(chalk.hex('#FFD700').bold(' HISTORIAL DEL DIARIO\n'));
86
+
87
+ for (const entry of entries.slice(-20).reverse()) {
88
+ const date = new Date(entry.date).toLocaleDateString('es-ES', {
89
+ day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit',
90
+ });
91
+ console.log(` ${gold(date)} ${dim('·')} ${chalk.hex('#FF6B1A')(`Lv ${entry.level}`)} ${dim('·')} ${chalk.white(entry.location)}`);
92
+ console.log(` ${dim('→')} ${chalk.hex('#f0f0f0')(entry.note)}`);
93
+ console.log('');
94
+ }
95
+
96
+ separator();
97
+ info(`Total de entradas: ${entries.length}`);
98
+ }
99
+
100
+ async function generateSummary(character) {
101
+ const entries = getDiary();
102
+
103
+ if (entries.length === 0) {
104
+ info('El diario está vacío. Agrega entradas primero con: tibiaway diary add');
105
+ return;
106
+ }
107
+
108
+ const entriesText = entries.slice(-30).map((e) => {
109
+ const date = new Date(e.date).toLocaleDateString('es-ES');
110
+ return `[${date}] Level ${e.level} - ${e.location}: ${e.note}`;
111
+ }).join('\n');
112
+
113
+ const prompt = `Analiza el siguiente diario de progreso de mi personaje en Tibia y dame un resumen inteligente:
114
+
115
+ ENTRADAS DEL DIARIO (últimas 30):
116
+ ${entriesText}
117
+
118
+ Por favor analiza:
119
+ 1. PROGRESO GENERAL: Cuántos levels subí, en qué periodo
120
+ 2. LUGARES FRECUENTADOS: Dónde paso más tiempo y si es óptimo para mi nivel
121
+ 3. TENDENCIAS: Qué patrones ves en mi forma de jugar
122
+ 4. LOGROS DESTACADOS: Qué cosas importantes sucedieron
123
+ 5. RECOMENDACIONES: Qué debería cambiar o mejorar basado en mi historial
124
+ 6. PRÓXIMOS OBJETIVOS SUGERIDOS: Qué debería hacer ahora
125
+
126
+ Sé analítico pero también alentador. Si hay áreas de mejora, mencionarlas con tacto.`;
127
+
128
+ console.log('');
129
+ const spinner = ora({ text: 'Analizando tu progreso...', color: 'yellow' }).start();
130
+
131
+ try {
132
+ const response = await askClaude(prompt);
133
+ spinner.stop();
134
+ separator();
135
+ console.log('');
136
+ console.log(chalk.hex('#f0f0f0')(response));
137
+ console.log('');
138
+ separator();
139
+ } catch (err) {
140
+ spinner.stop();
141
+ error(`Error al generar el resumen: ${err.message}`);
142
+ }
143
+ }
@@ -0,0 +1,86 @@
1
+ import inquirer from 'inquirer';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { getCharacter } from '../utils/config.js';
5
+ import { askClaude } from '../utils/api.js';
6
+ import { error, highlight, separator } from '../utils/banner.js';
7
+
8
+ export async function handleHunt() {
9
+ const character = getCharacter();
10
+ if (!character) {
11
+ error('No hay personaje configurado. Ejecuta: tibiaway setup');
12
+ return;
13
+ }
14
+
15
+ console.log(chalk.hex('#FF6B1A').bold('⚔ HUNT ADVISOR\n'));
16
+
17
+ const answers = await inquirer.prompt([
18
+ {
19
+ type: 'list',
20
+ name: 'objetivo',
21
+ message: highlight('¿Cuál es tu objetivo principal?'),
22
+ choices: [
23
+ { name: 'Máxima experiencia (exp/h)', value: 'exp' },
24
+ { name: 'Loot valioso', value: 'loot' },
25
+ { name: 'Mayor profit (balance positivo)', value: 'profit' },
26
+ { name: 'Tarea de bestiary/task', value: 'task' },
27
+ ],
28
+ },
29
+ {
30
+ type: 'list',
31
+ name: 'party',
32
+ message: highlight('¿Vas solo o en party?'),
33
+ choices: [
34
+ { name: 'Solo', value: 'solo' },
35
+ { name: 'Party (2-3 jugadores)', value: 'small_party' },
36
+ { name: 'Full party (4+ jugadores)', value: 'full_party' },
37
+ ],
38
+ },
39
+ {
40
+ type: 'confirm',
41
+ name: 'premium',
42
+ message: highlight('¿Tienes cuenta Premium?'),
43
+ default: true,
44
+ },
45
+ {
46
+ type: 'input',
47
+ name: 'restricciones',
48
+ message: highlight('¿Alguna restricción o preferencia? (zonas, criaturas, etc.) — Enter para saltar:'),
49
+ },
50
+ ]);
51
+
52
+ const prompt = `Dame las mejores recomendaciones de hunting spots para mi personaje.
53
+
54
+ Objetivo: ${answers.objetivo}
55
+ Modalidad: ${answers.party}
56
+ Cuenta Premium: ${answers.premium ? 'Sí' : 'No'}
57
+ ${answers.restricciones ? `Preferencias/restricciones: ${answers.restricciones}` : ''}
58
+
59
+ Por favor dame entre 3 y 5 hunting spots recomendados, ordenados por prioridad para mi objetivo.
60
+
61
+ Para cada spot incluye:
62
+ 1. Nombre del lugar y criaturas principales
63
+ 2. Exp/hora estimada para mi level y vocación
64
+ 3. Profit estimado (positivo o negativo)
65
+ 4. Requisitos de acceso (quests, level, etc.)
66
+ 5. Tips específicos para mi vocación
67
+ 6. ¿Necesita party o funciona bien solo?
68
+
69
+ Sé específico con los números. Si no tienes datos exactos, da rangos razonables.`;
70
+
71
+ console.log('');
72
+ const spinner = ora({ text: 'Consultando al oráculo tibian...', color: 'yellow' }).start();
73
+
74
+ try {
75
+ const response = await askClaude(prompt);
76
+ spinner.stop();
77
+ separator();
78
+ console.log('');
79
+ console.log(chalk.hex('#f0f0f0')(response));
80
+ console.log('');
81
+ separator();
82
+ } catch (err) {
83
+ spinner.stop();
84
+ error(`Error al consultar la IA: ${err.message}`);
85
+ }
86
+ }
@@ -0,0 +1,84 @@
1
+ import inquirer from 'inquirer';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { getCharacter } from '../utils/config.js';
5
+ import { askClaude } from '../utils/api.js';
6
+ import { error, highlight, separator } from '../utils/banner.js';
7
+
8
+ export async function handleProfit() {
9
+ const character = getCharacter();
10
+ if (!character) {
11
+ error('No hay personaje configurado. Ejecuta: tibiaway setup');
12
+ return;
13
+ }
14
+
15
+ console.log(chalk.hex('#FF6B1A').bold('💰 PROFIT CALCULATOR\n'));
16
+
17
+ const answers = await inquirer.prompt([
18
+ {
19
+ type: 'input',
20
+ name: 'lugar',
21
+ message: highlight('¿Dónde cazaste?'),
22
+ validate: (i) => i.trim().length > 0 || 'Ingresa el lugar.',
23
+ },
24
+ {
25
+ type: 'input',
26
+ name: 'tiempo',
27
+ message: highlight('¿Cuánto tiempo cazaste? (en minutos)'),
28
+ validate: (i) => (!isNaN(parseInt(i)) && parseInt(i) > 0) || 'Ingresa minutos válidos.',
29
+ },
30
+ {
31
+ type: 'input',
32
+ name: 'supplies',
33
+ message: highlight('¿Cuánto gastaste en supplies? (en gold)'),
34
+ validate: (i) => (!isNaN(parseInt(i)) && parseInt(i) >= 0) || 'Ingresa un número válido.',
35
+ },
36
+ {
37
+ type: 'input',
38
+ name: 'loot',
39
+ message: highlight('¿Qué loosteaste? (lista los ítems y cantidades, o el valor total en gold):'),
40
+ validate: (i) => i.trim().length > 0 || 'Ingresa el loot.',
41
+ },
42
+ {
43
+ type: 'input',
44
+ name: 'exp_ganada',
45
+ message: highlight('¿Cuánta experiencia ganaste? (0 si no sabes):'),
46
+ default: '0',
47
+ },
48
+ ]);
49
+
50
+ const prompt = `Analiza esta sesión de hunting y dame un reporte completo de profit/waste/exp.
51
+
52
+ Lugar de caza: ${answers.lugar}
53
+ Tiempo: ${answers.tiempo} minutos
54
+ Supplies gastados: ${answers.supplies} gold
55
+ Loot obtenido: ${answers.loot}
56
+ Experiencia ganada: ${answers.exp_ganada} xp
57
+
58
+ Calcula y muestra:
59
+ 1. Waste total (supplies - valor loot en tiendas)
60
+ 2. Valor estimado del loot (usa precios de mercado de Tibia actuales)
61
+ 3. Balance final (profit o loss, con símbolo + o -)
62
+ 4. Experiencia ganada y exp/hora estimada
63
+ 5. Evaluación del spot: ¿Vale la pena para mi perfil?
64
+ 6. Comparación con alternatives para mi level
65
+ 7. Sugerencias para mejorar el resultado
66
+
67
+ Usa formato claro con números. Separa bien cada sección.`;
68
+
69
+ console.log('');
70
+ const spinner = ora({ text: 'Calculando profit...', color: 'yellow' }).start();
71
+
72
+ try {
73
+ const response = await askClaude(prompt);
74
+ spinner.stop();
75
+ separator();
76
+ console.log('');
77
+ console.log(chalk.hex('#f0f0f0')(response));
78
+ console.log('');
79
+ separator();
80
+ } catch (err) {
81
+ spinner.stop();
82
+ error(`Error al consultar la IA: ${err.message}`);
83
+ }
84
+ }
@@ -0,0 +1,80 @@
1
+ import inquirer from 'inquirer';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { getCharacter } from '../utils/config.js';
5
+ import { askClaude } from '../utils/api.js';
6
+ import { error, highlight, separator } from '../utils/banner.js';
7
+
8
+ export async function handleQuest() {
9
+ const character = getCharacter();
10
+ if (!character) {
11
+ error('No hay personaje configurado. Ejecuta: tibiaway setup');
12
+ return;
13
+ }
14
+
15
+ console.log(chalk.hex('#FF6B1A').bold('📜 QUEST ADVISOR\n'));
16
+
17
+ const answers = await inquirer.prompt([
18
+ {
19
+ type: 'list',
20
+ name: 'objetivo',
21
+ message: highlight('¿Qué buscas con la quest?'),
22
+ choices: [
23
+ { name: 'Acceso a zona de caza importante', value: 'acceso' },
24
+ { name: 'Outfit o addon', value: 'outfit' },
25
+ { name: 'Achievement / title', value: 'achievement' },
26
+ { name: 'Reward de equipment', value: 'equipment' },
27
+ { name: 'Story quest / lore', value: 'story' },
28
+ { name: 'Desbloquear boss o área', value: 'boss_access' },
29
+ { name: 'No sé, recomiéndame algo', value: 'sugerencia' },
30
+ ],
31
+ },
32
+ {
33
+ type: 'confirm',
34
+ name: 'party',
35
+ message: highlight('¿Tienes party disponible?'),
36
+ default: false,
37
+ },
38
+ {
39
+ type: 'input',
40
+ name: 'contexto',
41
+ message: highlight('¿Algo específico que quieras o que ya hayas completado? (Enter para saltar):'),
42
+ },
43
+ ]);
44
+
45
+ const prompt = `Dame recomendaciones de quests para mi personaje.
46
+
47
+ Objetivo: ${answers.objetivo}
48
+ Party disponible: ${answers.party ? 'Sí' : 'No (solo)'}
49
+ ${answers.contexto ? `Contexto adicional: ${answers.contexto}` : ''}
50
+
51
+ Dame entre 3 y 5 quests recomendadas para mi level y vocación.
52
+
53
+ Para cada quest incluye:
54
+ 1. Nombre de la quest
55
+ 2. Por qué es relevante para mi perfil y objetivo
56
+ 3. Level mínimo recomendado
57
+ 4. Prerequisitos (otras quests, items, etc.)
58
+ 5. Dificultad estimada (fácil/media/difícil)
59
+ 6. Reward principal
60
+ 7. ¿Necesita party o se puede hacer solo?
61
+ 8. Tip o advertencia importante
62
+
63
+ Prioriza quests con mejor relación esfuerzo/recompensa para mi situación actual.`;
64
+
65
+ console.log('');
66
+ const spinner = ora({ text: 'Consultando el grimorio de quests...', color: 'yellow' }).start();
67
+
68
+ try {
69
+ const response = await askClaude(prompt);
70
+ spinner.stop();
71
+ separator();
72
+ console.log('');
73
+ console.log(chalk.hex('#f0f0f0')(response));
74
+ console.log('');
75
+ separator();
76
+ } catch (err) {
77
+ spinner.stop();
78
+ error(`Error al consultar la IA: ${err.message}`);
79
+ }
80
+ }