174 lines
5.6 KiB
TypeScript
174 lines
5.6 KiB
TypeScript
|
|
import { FunctionDeclaration, Type } from '@google/genai';
|
|
|
|
export const NAVIGATION_TOOLS: FunctionDeclaration[] = [
|
|
{
|
|
name: 'navigate_app',
|
|
parameters: {
|
|
type: Type.OBJECT,
|
|
description: 'Navigates to a specific section of the application.',
|
|
properties: {
|
|
target: {
|
|
type: Type.STRING,
|
|
description: 'The destination keyword (e.g., "assignment", "calendar", "arcade", "home").'
|
|
}
|
|
},
|
|
required: ['target']
|
|
}
|
|
},
|
|
{
|
|
name: 'launch_game',
|
|
parameters: {
|
|
type: Type.OBJECT,
|
|
description: 'Opens a specific game directly within the Arcade.',
|
|
properties: {
|
|
game_name: {
|
|
type: Type.STRING,
|
|
description: 'The name of the game (e.g., Speed Zone, Danphe Rush, Memory Shore).'
|
|
}
|
|
},
|
|
required: ['game_name']
|
|
}
|
|
},
|
|
{
|
|
name: 'control_map_view',
|
|
parameters: {
|
|
type: Type.OBJECT,
|
|
description: 'Controls the Heritage Map. Use this when asked about "Introduction of [Site]", "Explain [Province]", or "Show me [Site]".',
|
|
properties: {
|
|
target_name: {
|
|
type: Type.STRING,
|
|
description: 'Name of the province or heritage site.'
|
|
},
|
|
type: {
|
|
type: Type.STRING,
|
|
enum: ['province', 'site', 'reset'],
|
|
description: 'Type of location.'
|
|
}
|
|
},
|
|
required: ['target_name', 'type']
|
|
}
|
|
},
|
|
{
|
|
name: 'start_navigation',
|
|
parameters: {
|
|
type: Type.OBJECT,
|
|
description: 'Initiates a navigation request to a physical location or finds nearest places (Google Maps).',
|
|
properties: {
|
|
destination: { type: Type.STRING, description: 'The name of the place to go or "nearest [place]".' }
|
|
},
|
|
required: ['destination']
|
|
}
|
|
}
|
|
];
|
|
|
|
export const executeNavigationTool = async (name: string, args: any, navigate: (path: string, state?: any) => void) => {
|
|
if (name === 'navigate_app') {
|
|
const t = args.target.toLowerCase();
|
|
|
|
// Comprehensive Fuzzy Intent Mapping
|
|
const mappings: Record<string, string> = {
|
|
'home': '/',
|
|
'dashboard': '/',
|
|
'main': '/',
|
|
'planner': '/planner',
|
|
'task': '/planner',
|
|
'library': '/library',
|
|
'book': '/library',
|
|
'calendar': '/culture',
|
|
'date': '/culture',
|
|
'holiday': '/culture',
|
|
'culture': '/culture',
|
|
'map': '/map',
|
|
'kitchen': '/recipes',
|
|
'recipe': '/recipes',
|
|
'community': '/community-chat',
|
|
'chat': '/community-chat',
|
|
'health': '/health',
|
|
'safety': '/safety',
|
|
'arcade': '/arcade',
|
|
'game': '/arcade',
|
|
'rewards': '/rewards',
|
|
'shop': '/rewards',
|
|
'settings': '/settings',
|
|
'profile': '/profile',
|
|
'guru': '/study-buddy',
|
|
'buddy': '/study-buddy'
|
|
};
|
|
|
|
let path = mappings[t];
|
|
|
|
if (!path) {
|
|
if (t.includes('assign') || t.includes('home') || t.includes('work')) path = '/planner';
|
|
else if (t.includes('book')) path = '/library';
|
|
else if (t.includes('map')) path = '/map';
|
|
else if (t.includes('game') || t.includes('play')) path = '/arcade';
|
|
else {
|
|
const foundKey = Object.keys(mappings).find(key => t.includes(key));
|
|
if (foundKey) path = mappings[foundKey];
|
|
}
|
|
}
|
|
|
|
if (path) {
|
|
navigate(path);
|
|
return { result: `Success: Navigating to ${t}.` };
|
|
}
|
|
return { result: `Error: Destination "${args.target}" not recognized.` };
|
|
}
|
|
|
|
if (name === 'launch_game') {
|
|
const gameQuery = args.game_name.toLowerCase();
|
|
const gameMap: Record<string, string> = {
|
|
'speed': 'speed',
|
|
'danphe': 'danphe',
|
|
'memory': 'memory',
|
|
'focus': 'attention',
|
|
'agility': 'flexibility',
|
|
'logic': 'problem'
|
|
};
|
|
|
|
const gameId = Object.keys(gameMap).find(k => gameQuery.includes(k));
|
|
if (gameId) {
|
|
navigate('/arcade', { state: { autoLaunch: gameMap[gameId] } });
|
|
return { result: `Success: Launching ${args.game_name}.` };
|
|
}
|
|
return { result: `Error: Game module "${args.game_name}" not found.` };
|
|
}
|
|
|
|
if (name === 'control_map_view') {
|
|
navigate('/map');
|
|
|
|
setTimeout(() => {
|
|
window.dispatchEvent(new CustomEvent('rudraksha-map-control', {
|
|
detail: { type: args.type, targetName: args.target_name }
|
|
}));
|
|
}, 800);
|
|
|
|
// CRITICAL: Return a prompt for the AI to start explaining
|
|
return {
|
|
result: `Opened map and focused on ${args.target_name}. Please provide a brief introduction and historical significance of ${args.target_name} now.`
|
|
};
|
|
}
|
|
|
|
if (name === 'start_navigation') {
|
|
const dest = args.destination.toLowerCase();
|
|
|
|
// Handle "Nearest" logic - Google Maps supports "nearest X" queries natively in search mode
|
|
// If user says "nearest hospital", we pass "hospital" to the search intent which works better for nearby places
|
|
|
|
if (dest.includes('nearest') || dest.includes('nearby')) {
|
|
// Open Google Maps Search for the place
|
|
window.open(`https://www.google.com/maps/search/${encodeURIComponent(dest)}`, '_blank');
|
|
return { result: `Searching for ${dest} on Google Maps.` };
|
|
} else {
|
|
// Send event to RudraAI to show overlay for specific navigation
|
|
window.dispatchEvent(new CustomEvent('rudraksha-nav-start', {
|
|
detail: { destination: args.destination, mode: 'w' }
|
|
}));
|
|
return { result: `Destination acquired: ${args.destination}. Navigation overlay initialized.` };
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|