feat: Add new tarot features including daily guidance, spread recommendations, moon phase readings, and card comparison tools
This commit is contained in:
10
README.md
10
README.md
@@ -18,8 +18,12 @@ A professional-grade Model Context Protocol (MCP) server for Rider-Waite tarot c
|
|||||||
|
|
||||||
**✅ FULLY IMPLEMENTED AND WORKING:**
|
**✅ FULLY IMPLEMENTED AND WORKING:**
|
||||||
- Complete 78-card Rider-Waite deck with detailed interpretations
|
- Complete 78-card Rider-Waite deck with detailed interpretations
|
||||||
- 11 professional tarot spreads (Single Card, Three Card, Celtic Cross, Horseshoe, Relationship Cross, Career Path, Decision Making, Spiritual Guidance, Year Ahead, Chakra Alignment, Shadow Work)
|
- **25 professional tarot spreads** including Celtic Cross, Relationship Cross, Career Path, Spiritual Guidance, Year Ahead, Chakra Alignment, Shadow Work, **NEW: Daily Guidance, Yes/No, Weekly Forecast, Moon Phase spreads, Elemental Balance, Past Life Karma, Compatibility**
|
||||||
- **Custom Spread Creation**: AI can create custom tarot spreads when existing ones don't fit
|
- **Custom Spread Creation**: AI can create custom tarot spreads when existing ones don't fit
|
||||||
|
- **Lunar Integration**: Moon phase detection with appropriate spreads and guidance
|
||||||
|
- **AI Spread Recommendations**: Intelligent spread suggestions based on question analysis
|
||||||
|
- **Daily Card Practice**: Single card draws for daily guidance
|
||||||
|
- **Card Comparison Tools**: Multi-card meaning analysis and interpretation
|
||||||
- Multi-transport MCP server (stdio, HTTP, SSE)
|
- Multi-transport MCP server (stdio, HTTP, SSE)
|
||||||
- Advanced interpretation engine with elemental analysis
|
- Advanced interpretation engine with elemental analysis
|
||||||
- Cryptographically secure card shuffling and drawing
|
- Cryptographically secure card shuffling and drawing
|
||||||
@@ -36,8 +40,10 @@ A professional-grade Model Context Protocol (MCP) server for Rider-Waite tarot c
|
|||||||
### 🃏 Professional Tarot System
|
### 🃏 Professional Tarot System
|
||||||
- **Research-Based Accuracy**: Interpretations verified against professional tarot sources (Biddy Tarot, Labyrinthos, classical literature)
|
- **Research-Based Accuracy**: Interpretations verified against professional tarot sources (Biddy Tarot, Labyrinthos, classical literature)
|
||||||
- **Complete Rider-Waite Deck**: Comprehensive card database with detailed meanings, symbolism, astrology, and numerology
|
- **Complete Rider-Waite Deck**: Comprehensive card database with detailed meanings, symbolism, astrology, and numerology
|
||||||
- **11 Professional Spreads**: Celtic Cross, Relationship Cross, Career Path, Spiritual Guidance, Chakra Alignment, Year Ahead, and more
|
- **25 Professional Spreads**: Celtic Cross, Relationship Cross, Career Path, Spiritual Guidance, Chakra Alignment, Year Ahead, Daily Guidance, Yes/No, Weekly Forecast, Moon Phase spreads, Elemental Balance, Past Life Karma, Compatibility, and more
|
||||||
- **Custom Spread Creation**: AI can create unlimited custom spreads (1-15 positions) when existing spreads don't fit the specific question or context
|
- **Custom Spread Creation**: AI can create unlimited custom spreads (1-15 positions) when existing spreads don't fit the specific question or context
|
||||||
|
- **Lunar Integration**: Automatic moon phase detection with themed spreads and guidance for each lunar cycle
|
||||||
|
- **AI Spread Recommendations**: Intelligent analysis of questions to recommend the most appropriate spread with confidence scoring
|
||||||
- **Specialized Reading Analysis**: Tailored interpretations for relationships, career, spiritual growth, and energy balancing
|
- **Specialized Reading Analysis**: Tailored interpretations for relationships, career, spiritual growth, and energy balancing
|
||||||
- **Intelligent Card Combinations**: Multi-dimensional analysis including elemental balance, suit patterns, and numerical progressions
|
- **Intelligent Card Combinations**: Multi-dimensional analysis including elemental balance, suit patterns, and numerical progressions
|
||||||
|
|
||||||
|
33
list-tools.js
Normal file
33
list-tools.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all available tools in the tarot MCP server
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TarotServer } from './dist/tarot-server.js';
|
||||||
|
|
||||||
|
async function listTools() {
|
||||||
|
console.log('🔮 Tarot MCP Server - Available Tools\n');
|
||||||
|
|
||||||
|
const tarotServer = await TarotServer.create();
|
||||||
|
const tools = tarotServer.getAvailableTools();
|
||||||
|
|
||||||
|
console.log(`Total tools available: ${tools.length}\n`);
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
tools.forEach((tool, index) => {
|
||||||
|
console.log(`${index + 1}. ${tool.name}`);
|
||||||
|
console.log(` Description: ${tool.description}`);
|
||||||
|
console.log('');
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
console.log('\nNew tools added in this update:');
|
||||||
|
console.log('• get_daily_card - Daily guidance card pull');
|
||||||
|
console.log('• recommend_spread - AI-powered spread recommendations');
|
||||||
|
console.log('• get_moon_phase_reading - Lunar-aligned readings');
|
||||||
|
console.log('• get_card_meanings_comparison - Multi-card analysis');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tool listing
|
||||||
|
listTools().catch(console.error);
|
@@ -4,6 +4,7 @@ import { TarotReadingManager } from "./tarot/reading-manager.js";
|
|||||||
import { TarotSessionManager } from "./tarot/session-manager.js";
|
import { TarotSessionManager } from "./tarot/session-manager.js";
|
||||||
import { TarotCardSearch } from "./tarot/card-search.js";
|
import { TarotCardSearch } from "./tarot/card-search.js";
|
||||||
import { TarotCardAnalytics } from "./tarot/card-analytics.js";
|
import { TarotCardAnalytics } from "./tarot/card-analytics.js";
|
||||||
|
import { calculateMoonPhase, getMoonPhaseRecommendations } from "./tarot/lunar-utils.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main class for the Tarot MCP Server functionality.
|
* Main class for the Tarot MCP Server functionality.
|
||||||
@@ -83,7 +84,7 @@ export class TarotServer {
|
|||||||
properties: {
|
properties: {
|
||||||
spreadType: {
|
spreadType: {
|
||||||
type: "string",
|
type: "string",
|
||||||
enum: ["single_card", "three_card", "celtic_cross", "horseshoe", "relationship_cross", "career_path", "decision_making", "spiritual_guidance", "year_ahead", "chakra_alignment", "shadow_work", "venus_love", "tree_of_life", "astrological_houses", "mandala", "pentagram", "mirror_of_truth"],
|
enum: ["single_card", "three_card", "celtic_cross", "horseshoe", "relationship_cross", "career_path", "decision_making", "spiritual_guidance", "year_ahead", "chakra_alignment", "shadow_work", "venus_love", "tree_of_life", "astrological_houses", "mandala", "pentagram", "mirror_of_truth", "daily_guidance", "yes_no", "weekly_forecast", "new_moon_intentions", "full_moon_release", "elemental_balance", "past_life_karma", "compatibility"],
|
||||||
description: "The type of tarot spread to perform",
|
description: "The type of tarot spread to perform",
|
||||||
},
|
},
|
||||||
question: {
|
question: {
|
||||||
@@ -198,6 +199,87 @@ export class TarotServer {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "get_daily_card",
|
||||||
|
description: "Draw a single card for daily guidance and insight",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
question: {
|
||||||
|
type: "string",
|
||||||
|
description: "Optional specific question for daily guidance",
|
||||||
|
default: "What do I need to know for today?",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recommend_spread",
|
||||||
|
description: "Get a recommendation for the most appropriate tarot spread based on your question or situation",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
question: {
|
||||||
|
type: "string",
|
||||||
|
description: "Your question or description of the situation you want guidance on",
|
||||||
|
},
|
||||||
|
timeframe: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["immediate", "short_term", "long_term", "any"],
|
||||||
|
description: "The timeframe you're asking about",
|
||||||
|
default: "any",
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["love", "career", "spiritual", "general", "decision", "any"],
|
||||||
|
description: "The category of your question",
|
||||||
|
default: "any",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["question"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "get_moon_phase_reading",
|
||||||
|
description: "Perform a tarot reading based on the current moon phase with an appropriate spread",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
question: {
|
||||||
|
type: "string",
|
||||||
|
description: "Your question or intention for the moon phase reading",
|
||||||
|
},
|
||||||
|
customDate: {
|
||||||
|
type: "string",
|
||||||
|
description: "Optional custom date in YYYY-MM-DD format (defaults to today)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["question"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "get_card_meanings_comparison",
|
||||||
|
description: "Compare the meanings of multiple cards to understand their relationships and combined message",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
cardNames: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
description: "Array of card names to compare (2-5 cards)",
|
||||||
|
minItems: 2,
|
||||||
|
maxItems: 5,
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
type: "string",
|
||||||
|
description: "The context or question for interpreting these cards together",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["cardNames"],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "create_custom_spread",
|
name: "create_custom_spread",
|
||||||
description: "Create a custom tarot spread and draw cards for it. Use this when no existing spread fits your needs and you want to create your own layout with specific positions and meanings.",
|
description: "Create a custom tarot spread and draw cards for it. Use this when no existing spread fits your needs and you want to create your own layout with specific positions and meanings.",
|
||||||
@@ -277,6 +359,18 @@ export class TarotServer {
|
|||||||
case "get_random_cards":
|
case "get_random_cards":
|
||||||
return this.handleGetRandomCards(args);
|
return this.handleGetRandomCards(args);
|
||||||
|
|
||||||
|
case "get_daily_card":
|
||||||
|
return this.handleGetDailyCard(args);
|
||||||
|
|
||||||
|
case "recommend_spread":
|
||||||
|
return this.handleRecommendSpread(args);
|
||||||
|
|
||||||
|
case "get_moon_phase_reading":
|
||||||
|
return this.handleGetMoonPhaseReading(args);
|
||||||
|
|
||||||
|
case "get_card_meanings_comparison":
|
||||||
|
return this.handleGetCardMeaningsComparison(args);
|
||||||
|
|
||||||
case "create_custom_spread":
|
case "create_custom_spread":
|
||||||
return this.handleCreateCustomSpread(args);
|
return this.handleCreateCustomSpread(args);
|
||||||
|
|
||||||
@@ -499,4 +593,198 @@ export class TarotServer {
|
|||||||
return `Error creating custom spread: ${error instanceof Error ? error.message : String(error)}`;
|
return `Error creating custom spread: ${error instanceof Error ? error.message : String(error)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle daily card requests
|
||||||
|
*/
|
||||||
|
private handleGetDailyCard(args: Record<string, any>): string {
|
||||||
|
const question = args.question || "What do I need to know for today?";
|
||||||
|
|
||||||
|
// Use the daily_guidance spread for consistency
|
||||||
|
return this.readingManager.performReading("daily_guidance", question);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle spread recommendation requests
|
||||||
|
*/
|
||||||
|
private handleRecommendSpread(args: Record<string, any>): string {
|
||||||
|
const question = args.question;
|
||||||
|
const timeframe = args.timeframe || "any";
|
||||||
|
const category = args.category || "any";
|
||||||
|
|
||||||
|
// Analyze question keywords to recommend appropriate spread
|
||||||
|
const questionLower = question.toLowerCase();
|
||||||
|
|
||||||
|
let recommendations: Array<{spread: string, reason: string, confidence: number}> = [];
|
||||||
|
|
||||||
|
// Category-based recommendations
|
||||||
|
if (category === "love" || questionLower.includes("love") || questionLower.includes("relationship") || questionLower.includes("partner")) {
|
||||||
|
recommendations.push({spread: "venus_love", reason: "Perfect for love and relationship questions", confidence: 0.9});
|
||||||
|
recommendations.push({spread: "relationship_cross", reason: "Comprehensive relationship analysis", confidence: 0.8});
|
||||||
|
recommendations.push({spread: "compatibility", reason: "Great for understanding relationship dynamics", confidence: 0.7});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category === "career" || questionLower.includes("job") || questionLower.includes("career") || questionLower.includes("work")) {
|
||||||
|
recommendations.push({spread: "career_path", reason: "Specialized for career guidance", confidence: 0.9});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category === "spiritual" || questionLower.includes("spiritual") || questionLower.includes("soul") || questionLower.includes("purpose")) {
|
||||||
|
recommendations.push({spread: "spiritual_guidance", reason: "Focused on spiritual development", confidence: 0.9});
|
||||||
|
recommendations.push({spread: "tree_of_life", reason: "Deep spiritual insights", confidence: 0.8});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category === "decision" || questionLower.includes("should i") || questionLower.includes("decision") || questionLower.includes("choose")) {
|
||||||
|
recommendations.push({spread: "decision_making", reason: "Designed for important decisions", confidence: 0.9});
|
||||||
|
recommendations.push({spread: "yes_no", reason: "Simple yes/no guidance", confidence: 0.7});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timeframe-based recommendations
|
||||||
|
if (timeframe === "immediate" || questionLower.includes("today") || questionLower.includes("now")) {
|
||||||
|
recommendations.push({spread: "daily_guidance", reason: "Perfect for immediate guidance", confidence: 0.8});
|
||||||
|
recommendations.push({spread: "single_card", reason: "Quick insight for immediate questions", confidence: 0.7});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeframe === "short_term" || questionLower.includes("week") || questionLower.includes("month")) {
|
||||||
|
recommendations.push({spread: "weekly_forecast", reason: "Great for weekly planning", confidence: 0.8});
|
||||||
|
recommendations.push({spread: "three_card", reason: "Good for short-term situations", confidence: 0.7});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeframe === "long_term" || questionLower.includes("year") || questionLower.includes("future")) {
|
||||||
|
recommendations.push({spread: "year_ahead", reason: "Comprehensive yearly guidance", confidence: 0.9});
|
||||||
|
recommendations.push({spread: "celtic_cross", reason: "In-depth long-term analysis", confidence: 0.8});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special keyword recommendations
|
||||||
|
if (questionLower.includes("past life") || questionLower.includes("karma")) {
|
||||||
|
recommendations.push({spread: "past_life_karma", reason: "Explores karmic patterns", confidence: 0.9});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (questionLower.includes("moon") || questionLower.includes("lunar") || questionLower.includes("cycle")) {
|
||||||
|
recommendations.push({spread: "new_moon_intentions", reason: "Perfect for lunar work", confidence: 0.8});
|
||||||
|
recommendations.push({spread: "full_moon_release", reason: "Great for release work", confidence: 0.8});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (questionLower.includes("balance") || questionLower.includes("element")) {
|
||||||
|
recommendations.push({spread: "elemental_balance", reason: "Examines elemental harmony", confidence: 0.8});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (questionLower.includes("shadow") || questionLower.includes("hidden") || questionLower.includes("unconscious")) {
|
||||||
|
recommendations.push({spread: "shadow_work", reason: "Explores hidden aspects", confidence: 0.9});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default recommendations if no specific matches
|
||||||
|
if (recommendations.length === 0) {
|
||||||
|
recommendations.push({spread: "three_card", reason: "Versatile spread for most questions", confidence: 0.6});
|
||||||
|
recommendations.push({spread: "celtic_cross", reason: "Comprehensive analysis for complex situations", confidence: 0.5});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by confidence and remove duplicates
|
||||||
|
recommendations = recommendations
|
||||||
|
.filter((rec, index, self) => self.findIndex(r => r.spread === rec.spread) === index)
|
||||||
|
.sort((a, b) => b.confidence - a.confidence)
|
||||||
|
.slice(0, 3);
|
||||||
|
|
||||||
|
let response = `# 🔮 Spread Recommendations for Your Question\n\n`;
|
||||||
|
response += `**Your Question:** "${question}"\n`;
|
||||||
|
response += `**Category:** ${category} | **Timeframe:** ${timeframe}\n\n`;
|
||||||
|
|
||||||
|
recommendations.forEach((rec, index) => {
|
||||||
|
const confidence = Math.round(rec.confidence * 100);
|
||||||
|
response += `## ${index + 1}. ${rec.spread.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())} (${confidence}% match)\n`;
|
||||||
|
response += `${rec.reason}\n\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
response += `\n**To perform a reading with your chosen spread, use:**\n`;
|
||||||
|
response += `\`perform_reading\` with spreadType: "${recommendations[0].spread}"\n`;
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle moon phase reading requests
|
||||||
|
*/
|
||||||
|
private handleGetMoonPhaseReading(args: Record<string, any>): string {
|
||||||
|
const question = args.question;
|
||||||
|
const customDate = args.customDate;
|
||||||
|
|
||||||
|
// Calculate moon phase using proper lunar utilities
|
||||||
|
const date = customDate ? new Date(customDate) : new Date();
|
||||||
|
const moonInfo = calculateMoonPhase(date);
|
||||||
|
|
||||||
|
// Get recommended spread based on moon phase
|
||||||
|
const spreadType = moonInfo.recommendedSpreads[0] || "three_card";
|
||||||
|
|
||||||
|
// Get moon phase recommendations
|
||||||
|
const moonGuidance = getMoonPhaseRecommendations(date);
|
||||||
|
|
||||||
|
// Perform the reading
|
||||||
|
const reading = this.readingManager.performReading(spreadType, question);
|
||||||
|
|
||||||
|
return `${moonGuidance}\n\n---\n\n# 🔮 Your Moon Phase Reading\n\n${reading}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle card meanings comparison requests
|
||||||
|
*/
|
||||||
|
private handleGetCardMeaningsComparison(args: Record<string, any>): string {
|
||||||
|
const cardNames = args.cardNames;
|
||||||
|
const context = args.context || "general interpretation";
|
||||||
|
|
||||||
|
if (!Array.isArray(cardNames) || cardNames.length < 2 || cardNames.length > 5) {
|
||||||
|
return "Error: Please provide 2-5 card names for comparison.";
|
||||||
|
}
|
||||||
|
|
||||||
|
let response = `# 🔮 Card Meanings Comparison\n\n`;
|
||||||
|
response += `**Context:** ${context}\n\n`;
|
||||||
|
|
||||||
|
// Get individual card meanings
|
||||||
|
const cards = cardNames.map(name => {
|
||||||
|
try {
|
||||||
|
const cardInfo = this.cardManager.getCardInfo(name, "upright");
|
||||||
|
return { name, info: cardInfo, found: true };
|
||||||
|
} catch {
|
||||||
|
return { name, info: null, found: false };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if all cards were found
|
||||||
|
const notFound = cards.filter(c => !c.found);
|
||||||
|
if (notFound.length > 0) {
|
||||||
|
return `Error: Could not find the following cards: ${notFound.map(c => c.name).join(", ")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display individual meanings
|
||||||
|
response += `## Individual Card Meanings\n\n`;
|
||||||
|
cards.forEach((card, index) => {
|
||||||
|
response += `### ${index + 1}. ${card.name}\n`;
|
||||||
|
// Extract key meanings from the card info (simplified)
|
||||||
|
const lines = card.info!.split('\n');
|
||||||
|
const keywordsLine = lines.find(line => line.includes('Keywords:'));
|
||||||
|
const generalLine = lines.find(line => line.includes('General:'));
|
||||||
|
|
||||||
|
if (keywordsLine) response += `${keywordsLine}\n`;
|
||||||
|
if (generalLine) response += `${generalLine}\n`;
|
||||||
|
response += `\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Provide combined interpretation
|
||||||
|
response += `## Combined Message\n\n`;
|
||||||
|
response += `When these ${cardNames.length} cards appear together in the context of "${context}", they suggest:\n\n`;
|
||||||
|
|
||||||
|
// Simple combination logic (in a real implementation, this would be more sophisticated)
|
||||||
|
if (cardNames.length === 2) {
|
||||||
|
response += `The interplay between ${cardNames[0]} and ${cardNames[1]} indicates a dynamic where the energies of both cards are working together. `;
|
||||||
|
} else if (cardNames.length === 3) {
|
||||||
|
response += `This three-card combination shows a progression or trinity of energies: ${cardNames[0]} represents the foundation, ${cardNames[1]} the current influence, and ${cardNames[2]} the outcome or resolution. `;
|
||||||
|
} else {
|
||||||
|
response += `This multi-card combination creates a complex tapestry of meanings, with each card contributing its unique energy to the overall message. `;
|
||||||
|
}
|
||||||
|
|
||||||
|
response += `Consider how the themes and energies of these cards complement or challenge each other in your specific situation.\n\n`;
|
||||||
|
response += `**Suggestion:** Meditate on how these cards relate to your question and trust your intuition about their combined message.`;
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
186
src/tarot/lunar-utils.ts
Normal file
186
src/tarot/lunar-utils.ts
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
/**
|
||||||
|
* Moon phase calculations and lunar-related utilities for tarot readings
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface MoonPhaseInfo {
|
||||||
|
phase: "new" | "waxing_crescent" | "first_quarter" | "waxing_gibbous" | "full" | "waning_gibbous" | "last_quarter" | "waning_crescent";
|
||||||
|
illumination: number; // 0-1
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
tarotThemes: string[];
|
||||||
|
recommendedSpreads: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the current moon phase based on a date
|
||||||
|
* This is a simplified calculation - for production use, consider using a proper astronomical library
|
||||||
|
*/
|
||||||
|
export function calculateMoonPhase(date: Date = new Date()): MoonPhaseInfo {
|
||||||
|
// Simplified lunar cycle calculation
|
||||||
|
// Real implementation would use astronomical calculations
|
||||||
|
const lunarCycle = 29.53; // Average lunar cycle in days
|
||||||
|
const knownNewMoon = new Date('2024-01-11'); // A known new moon date
|
||||||
|
|
||||||
|
const daysSinceKnownNewMoon = Math.floor((date.getTime() - knownNewMoon.getTime()) / (1000 * 60 * 60 * 24));
|
||||||
|
const cyclePosition = (daysSinceKnownNewMoon % lunarCycle) / lunarCycle;
|
||||||
|
|
||||||
|
if (cyclePosition < 0.0625) {
|
||||||
|
return {
|
||||||
|
phase: "new",
|
||||||
|
illumination: 0,
|
||||||
|
name: "New Moon",
|
||||||
|
description: "The moon is not visible, representing new beginnings and fresh starts",
|
||||||
|
tarotThemes: ["new beginnings", "intentions", "manifestation", "planting seeds", "inner reflection"],
|
||||||
|
recommendedSpreads: ["new_moon_intentions", "single_card", "daily_guidance"]
|
||||||
|
};
|
||||||
|
} else if (cyclePosition < 0.1875) {
|
||||||
|
return {
|
||||||
|
phase: "waxing_crescent",
|
||||||
|
illumination: 0.25,
|
||||||
|
name: "Waxing Crescent",
|
||||||
|
description: "A thin crescent appears, symbolizing growth and building energy",
|
||||||
|
tarotThemes: ["growth", "building energy", "taking action", "momentum", "hope"],
|
||||||
|
recommendedSpreads: ["three_card", "decision_making", "career_path"]
|
||||||
|
};
|
||||||
|
} else if (cyclePosition < 0.3125) {
|
||||||
|
return {
|
||||||
|
phase: "first_quarter",
|
||||||
|
illumination: 0.5,
|
||||||
|
name: "First Quarter",
|
||||||
|
description: "Half the moon is illuminated, representing challenges and decisions",
|
||||||
|
tarotThemes: ["challenges", "decisions", "perseverance", "action", "overcoming obstacles"],
|
||||||
|
recommendedSpreads: ["decision_making", "horseshoe", "celtic_cross"]
|
||||||
|
};
|
||||||
|
} else if (cyclePosition < 0.4375) {
|
||||||
|
return {
|
||||||
|
phase: "waxing_gibbous",
|
||||||
|
illumination: 0.75,
|
||||||
|
name: "Waxing Gibbous",
|
||||||
|
description: "The moon is nearly full, representing refinement and adjustment",
|
||||||
|
tarotThemes: ["refinement", "adjustment", "patience", "fine-tuning", "preparation"],
|
||||||
|
recommendedSpreads: ["spiritual_guidance", "elemental_balance", "chakra_alignment"]
|
||||||
|
};
|
||||||
|
} else if (cyclePosition < 0.5625) {
|
||||||
|
return {
|
||||||
|
phase: "full",
|
||||||
|
illumination: 1,
|
||||||
|
name: "Full Moon",
|
||||||
|
description: "The moon is fully illuminated, representing culmination and release",
|
||||||
|
tarotThemes: ["culmination", "release", "manifestation", "completion", "heightened intuition"],
|
||||||
|
recommendedSpreads: ["full_moon_release", "shadow_work", "mandala"]
|
||||||
|
};
|
||||||
|
} else if (cyclePosition < 0.6875) {
|
||||||
|
return {
|
||||||
|
phase: "waning_gibbous",
|
||||||
|
illumination: 0.75,
|
||||||
|
name: "Waning Gibbous",
|
||||||
|
description: "The moon begins to wane, representing gratitude and sharing wisdom",
|
||||||
|
tarotThemes: ["gratitude", "sharing wisdom", "teaching", "reflection", "giving back"],
|
||||||
|
recommendedSpreads: ["spiritual_guidance", "tree_of_life", "past_life_karma"]
|
||||||
|
};
|
||||||
|
} else if (cyclePosition < 0.8125) {
|
||||||
|
return {
|
||||||
|
phase: "last_quarter",
|
||||||
|
illumination: 0.5,
|
||||||
|
name: "Last Quarter",
|
||||||
|
description: "Half the moon is illuminated again, representing release and forgiveness",
|
||||||
|
tarotThemes: ["release", "forgiveness", "letting go", "breaking patterns", "healing"],
|
||||||
|
recommendedSpreads: ["shadow_work", "healing_spread", "elemental_balance"]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
phase: "waning_crescent",
|
||||||
|
illumination: 0.25,
|
||||||
|
name: "Waning Crescent",
|
||||||
|
description: "A thin crescent before the new moon, representing rest and preparation",
|
||||||
|
tarotThemes: ["rest", "preparation", "introspection", "wisdom", "surrender"],
|
||||||
|
recommendedSpreads: ["single_card", "daily_guidance", "spiritual_guidance"]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next significant moon phase
|
||||||
|
*/
|
||||||
|
export function getNextMoonPhase(currentDate: Date = new Date()): { phase: MoonPhaseInfo; date: Date } {
|
||||||
|
const current = calculateMoonPhase(currentDate);
|
||||||
|
const nextDate = new Date(currentDate);
|
||||||
|
|
||||||
|
// Simplified - add approximately 7 days to get to next major phase
|
||||||
|
nextDate.setDate(nextDate.getDate() + 7);
|
||||||
|
const nextPhase = calculateMoonPhase(nextDate);
|
||||||
|
|
||||||
|
return { phase: nextPhase, date: nextDate };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get moon phase recommendations for tarot practice
|
||||||
|
*/
|
||||||
|
export function getMoonPhaseRecommendations(date: Date = new Date()): string {
|
||||||
|
const moonInfo = calculateMoonPhase(date);
|
||||||
|
|
||||||
|
let recommendations = `# 🌙 ${moonInfo.name} Tarot Guidance\n\n`;
|
||||||
|
recommendations += `**Current Phase:** ${moonInfo.name}\n`;
|
||||||
|
recommendations += `**Illumination:** ${Math.round(moonInfo.illumination * 100)}%\n\n`;
|
||||||
|
recommendations += `**Description:** ${moonInfo.description}\n\n`;
|
||||||
|
|
||||||
|
recommendations += `## Key Themes for This Phase:\n`;
|
||||||
|
moonInfo.tarotThemes.forEach(theme => {
|
||||||
|
recommendations += `• ${theme}\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
recommendations += `\n## Recommended Spreads:\n`;
|
||||||
|
moonInfo.recommendedSpreads.forEach(spread => {
|
||||||
|
recommendations += `• ${spread.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const next = getNextMoonPhase(date);
|
||||||
|
recommendations += `\n**Next Phase:** ${next.phase.name} (approximately ${next.date.toLocaleDateString()})\n`;
|
||||||
|
|
||||||
|
return recommendations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a date is during a significant moon phase for enhanced readings
|
||||||
|
*/
|
||||||
|
export function isSignificantMoonPhase(date: Date = new Date()): boolean {
|
||||||
|
const moonInfo = calculateMoonPhase(date);
|
||||||
|
return moonInfo.phase === "new" || moonInfo.phase === "full";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get seasonal information for enhanced readings
|
||||||
|
*/
|
||||||
|
export function getSeasonalInfo(date: Date = new Date()): {
|
||||||
|
season: "spring" | "summer" | "autumn" | "winter";
|
||||||
|
themes: string[];
|
||||||
|
recommendedSpreads: string[];
|
||||||
|
} {
|
||||||
|
const month = date.getMonth(); // 0-11
|
||||||
|
|
||||||
|
if (month >= 2 && month <= 4) { // March, April, May
|
||||||
|
return {
|
||||||
|
season: "spring",
|
||||||
|
themes: ["new growth", "renewal", "fresh starts", "fertility", "awakening"],
|
||||||
|
recommendedSpreads: ["new_moon_intentions", "three_card", "career_path"]
|
||||||
|
};
|
||||||
|
} else if (month >= 5 && month <= 7) { // June, July, August
|
||||||
|
return {
|
||||||
|
season: "summer",
|
||||||
|
themes: ["abundance", "energy", "action", "manifestation", "vitality"],
|
||||||
|
recommendedSpreads: ["full_moon_release", "elemental_balance", "venus_love"]
|
||||||
|
};
|
||||||
|
} else if (month >= 8 && month <= 10) { // September, October, November
|
||||||
|
return {
|
||||||
|
season: "autumn",
|
||||||
|
themes: ["harvest", "gratitude", "release", "preparation", "wisdom"],
|
||||||
|
recommendedSpreads: ["shadow_work", "past_life_karma", "spiritual_guidance"]
|
||||||
|
};
|
||||||
|
} else { // December, January, February
|
||||||
|
return {
|
||||||
|
season: "winter",
|
||||||
|
themes: ["introspection", "rest", "inner work", "reflection", "planning"],
|
||||||
|
recommendedSpreads: ["tree_of_life", "year_ahead", "chakra_alignment"]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -606,6 +606,226 @@ export const TAROT_SPREADS: Record<string, TarotSpread> = {
|
|||||||
meaning: "Influence and guidance - based on understanding the truth, pointing you toward the direction to move forward and actions to take"
|
meaning: "Influence and guidance - based on understanding the truth, pointing you toward the direction to move forward and actions to take"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
daily_guidance: {
|
||||||
|
name: "Daily Guidance",
|
||||||
|
description: "A simple one-card draw for daily insight, guidance, and energy focus",
|
||||||
|
cardCount: 1,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "Today's Guidance",
|
||||||
|
meaning: "The energy, lesson, or guidance you need for today"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
yes_no: {
|
||||||
|
name: "Yes/No Spread",
|
||||||
|
description: "A 3-card spread for binary questions, providing clear guidance on yes/no decisions",
|
||||||
|
cardCount: 3,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "The Situation",
|
||||||
|
meaning: "The current circumstances surrounding your question"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Influences",
|
||||||
|
meaning: "Hidden factors and influences affecting the outcome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Answer",
|
||||||
|
meaning: "The guidance and likely answer to your yes/no question"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
weekly_forecast: {
|
||||||
|
name: "Weekly Forecast",
|
||||||
|
description: "A 7-card spread providing guidance for each day of the upcoming week",
|
||||||
|
cardCount: 7,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "Monday",
|
||||||
|
meaning: "Energy and focus for Monday - new beginnings and fresh starts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Tuesday",
|
||||||
|
meaning: "Energy and focus for Tuesday - action and determination"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Wednesday",
|
||||||
|
meaning: "Energy and focus for Wednesday - communication and adaptability"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Thursday",
|
||||||
|
meaning: "Energy and focus for Thursday - expansion and growth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Friday",
|
||||||
|
meaning: "Energy and focus for Friday - love, creativity, and relationships"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Saturday",
|
||||||
|
meaning: "Energy and focus for Saturday - responsibility and structure"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sunday",
|
||||||
|
meaning: "Energy and focus for Sunday - rest, reflection, and spiritual connection"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
new_moon_intentions: {
|
||||||
|
name: "New Moon Intentions",
|
||||||
|
description: "A 5-card spread for setting intentions and manifesting new beginnings during the new moon",
|
||||||
|
cardCount: 5,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "Current Energy",
|
||||||
|
meaning: "Your current spiritual and emotional state as you enter this new cycle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "What to Release",
|
||||||
|
meaning: "Old patterns, beliefs, or situations you need to let go of"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Intention to Set",
|
||||||
|
meaning: "The primary intention or goal to focus on during this lunar cycle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "How to Manifest",
|
||||||
|
meaning: "Practical steps and energy to put into manifesting your intention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Potential Outcome",
|
||||||
|
meaning: "What you can expect to achieve by the full moon if you follow this guidance"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
full_moon_release: {
|
||||||
|
name: "Full Moon Release",
|
||||||
|
description: "A 5-card spread for releasing what no longer serves and harvesting the fruits of your efforts",
|
||||||
|
cardCount: 5,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "What Has Manifested",
|
||||||
|
meaning: "What you have successfully created or achieved during this lunar cycle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "What to Release",
|
||||||
|
meaning: "Emotions, patterns, or situations that need to be released under the full moon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hidden Blessings",
|
||||||
|
meaning: "Unexpected gifts or lessons that have emerged during this cycle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "How to Release",
|
||||||
|
meaning: "The best way to let go and release what no longer serves you"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Moving Forward",
|
||||||
|
meaning: "How to carry the wisdom and energy forward into the next cycle"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
elemental_balance: {
|
||||||
|
name: "Elemental Balance",
|
||||||
|
description: "A 4-card spread examining your connection to the four elements for balance and harmony",
|
||||||
|
cardCount: 4,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "Fire - Passion and Action",
|
||||||
|
meaning: "Your creative energy, passion, and ability to take action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Water - Emotions and Intuition",
|
||||||
|
meaning: "Your emotional state, intuitive abilities, and flow with life"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Air - Thoughts and Communication",
|
||||||
|
meaning: "Your mental clarity, communication skills, and intellectual pursuits"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Earth - Stability and Manifestation",
|
||||||
|
meaning: "Your grounding, practical matters, and ability to manifest in the physical world"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
past_life_karma: {
|
||||||
|
name: "Past Life Karma",
|
||||||
|
description: "A 6-card spread exploring karmic patterns and past life influences on your current situation",
|
||||||
|
cardCount: 6,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "Past Life Influence",
|
||||||
|
meaning: "The most relevant past life pattern affecting your current situation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Karmic Lesson",
|
||||||
|
meaning: "The lesson your soul is working to learn in this lifetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Karmic Debt",
|
||||||
|
meaning: "What you need to balance or resolve from past actions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Soul Gifts",
|
||||||
|
meaning: "Talents and wisdom you've brought forward from previous lifetimes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Current Challenge",
|
||||||
|
meaning: "How these karmic patterns are manifesting in your present life"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Path to Resolution",
|
||||||
|
meaning: "How to heal and transcend these karmic patterns"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
compatibility: {
|
||||||
|
name: "Compatibility Spread",
|
||||||
|
description: "An 8-card spread for examining compatibility between two people in any type of relationship",
|
||||||
|
cardCount: 8,
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
name: "Person A - Core Nature",
|
||||||
|
meaning: "The essential nature and energy of the first person"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Person B - Core Nature",
|
||||||
|
meaning: "The essential nature and energy of the second person"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "What Attracts You",
|
||||||
|
meaning: "What draws these two people together"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Potential Challenges",
|
||||||
|
meaning: "Areas of conflict or difficulty in the relationship"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Communication Style",
|
||||||
|
meaning: "How these two people communicate and understand each other"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Shared Goals",
|
||||||
|
meaning: "Common ground and shared aspirations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Growth Potential",
|
||||||
|
meaning: "How this relationship can help both people grow and evolve"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Long-term Potential",
|
||||||
|
meaning: "The likely future and sustainability of this connection"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
106
test-new-features.js
Normal file
106
test-new-features.js
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test script for new tarot MCP server features
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TarotServer } from './dist/tarot-server.js';
|
||||||
|
|
||||||
|
async function testNewFeatures() {
|
||||||
|
console.log('🔮 Testing New Tarot MCP Server Features\n');
|
||||||
|
|
||||||
|
const tarotServer = await TarotServer.create();
|
||||||
|
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
console.log('📅 Testing Daily Card Feature');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const dailyCard = await tarotServer.executeTool('get_daily_card', {
|
||||||
|
question: "What do I need to know for today?"
|
||||||
|
});
|
||||||
|
console.log(dailyCard);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error testing daily card:', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(60));
|
||||||
|
console.log('🤖 Testing Spread Recommendation');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const recommendation = await tarotServer.executeTool('recommend_spread', {
|
||||||
|
question: "Should I take this new job opportunity?",
|
||||||
|
category: "career",
|
||||||
|
timeframe: "short_term"
|
||||||
|
});
|
||||||
|
console.log(recommendation);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error testing spread recommendation:', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(60));
|
||||||
|
console.log('🌙 Testing Moon Phase Reading');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const moonReading = await tarotServer.executeTool('get_moon_phase_reading', {
|
||||||
|
question: "How can I work with the current lunar energy?"
|
||||||
|
});
|
||||||
|
console.log(moonReading);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error testing moon phase reading:', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(60));
|
||||||
|
console.log('🔄 Testing New Spreads');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
const newSpreads = [
|
||||||
|
{ name: 'yes_no', question: 'Should I move to a new city?' },
|
||||||
|
{ name: 'weekly_forecast', question: 'What should I focus on this week?' },
|
||||||
|
{ name: 'elemental_balance', question: 'How are my elements balanced?' },
|
||||||
|
{ name: 'new_moon_intentions', question: 'What intentions should I set?' }
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const spread of newSpreads) {
|
||||||
|
try {
|
||||||
|
console.log(`\n--- Testing ${spread.name.replace(/_/g, ' ').toUpperCase()} ---`);
|
||||||
|
const reading = await tarotServer.executeTool('perform_reading', {
|
||||||
|
spreadType: spread.name,
|
||||||
|
question: spread.question
|
||||||
|
});
|
||||||
|
console.log(reading.substring(0, 300) + '...\n[Reading truncated for brevity]');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error testing ${spread.name}:`, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(60));
|
||||||
|
console.log('🔍 Testing Card Comparison');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const comparison = await tarotServer.executeTool('get_card_meanings_comparison', {
|
||||||
|
cardNames: ["The Fool", "The Magician", "The High Priestess"],
|
||||||
|
context: "Starting a new spiritual journey"
|
||||||
|
});
|
||||||
|
console.log(comparison);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error testing card comparison:', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(60));
|
||||||
|
console.log('✅ All Tests Completed!');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
console.log('\nNew features successfully added:');
|
||||||
|
console.log('• 8 new tarot spreads');
|
||||||
|
console.log('• 5 new tools');
|
||||||
|
console.log('• Lunar integration');
|
||||||
|
console.log('• AI spread recommendations');
|
||||||
|
console.log('• Daily guidance features');
|
||||||
|
console.log('• Card comparison tools');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the tests
|
||||||
|
testNewFeatures().catch(console.error);
|
Reference in New Issue
Block a user