open-node-content.ts
1 /** 2 * Copilot Node Content Opening 3 * 4 * Opens the appropriate fullscreen content for a DreamNode during copilot mode. 5 * Priority: DreamSong > DreamTalk > README 6 * 7 * This is copilot-specific because it's used for "invoking" nodes during conversation - 8 * opening their content as part of the video call experience. 9 */ 10 11 import { DreamNode } from '../../dreamnode'; 12 import { serviceManager } from '../../../core/services/service-manager'; 13 import { UIService } from '../../../core/services/ui-service'; 14 import type { VaultService } from '../../../core/services/vault-service'; 15 import type { CanvasParserService } from '../../dreamweaving/services/canvas-parser-service'; 16 17 // Singleton service for UI feedback 18 const uiService = new UIService(); 19 20 /** 21 * Opens the appropriate fullscreen content for a node during copilot mode. 22 * Tries DreamSong first, then DreamTalk media, then README as fallback. 23 * 24 * @param node - The DreamNode to open content for 25 * @param vaultService - VaultService for file existence checks 26 * @param canvasParserService - CanvasParserService for DreamSong parsing 27 */ 28 export async function openNodeContent( 29 node: DreamNode, 30 vaultService: VaultService | undefined, 31 canvasParserService: CanvasParserService | undefined 32 ): Promise<void> { 33 const leafManager = serviceManager.getLeafManagerService(); 34 35 if (!leafManager || !vaultService || !canvasParserService) { 36 console.error('Services not available for opening content'); 37 return; 38 } 39 40 try { 41 // Check for DreamSong first (most rich content) 42 const dreamSongPath = `${node.repoPath}/DreamSong.canvas`; 43 if (await vaultService.fileExists(dreamSongPath)) { 44 console.log(`🎭 [Copilot] Opening DreamSong for ${node.name}`); 45 46 // Parse and open DreamSong 47 const canvasData = await canvasParserService.parseCanvas(dreamSongPath); 48 const { parseCanvasToBlocks, resolveMediaPaths } = await import('../../dreamweaving/dreamsong/index'); 49 let blocks = parseCanvasToBlocks(canvasData, node.id); 50 blocks = await resolveMediaPaths(blocks, node.repoPath, vaultService); 51 52 await leafManager.openDreamSongFullScreen(node, blocks); 53 uiService.showSuccess(`Opened DreamSong for ${node.name}`); 54 return; 55 } 56 57 // Check for DreamTalk media 58 if (node.dreamTalkMedia && node.dreamTalkMedia.length > 0) { 59 console.log(`🎤 [Copilot] Opening DreamTalk for ${node.name}`); 60 await leafManager.openDreamTalkFullScreen(node, node.dreamTalkMedia[0]); 61 uiService.showSuccess(`Opened DreamTalk for ${node.name}`); 62 return; 63 } 64 65 // Try README as final fallback 66 const readmePath = `${node.repoPath}/README.md`; 67 if (await vaultService.fileExists(readmePath)) { 68 console.log(`📖 [Copilot] Opening README for ${node.name}`); 69 await leafManager.openReadmeFile(node); 70 uiService.showSuccess(`Opened README for ${node.name}`); 71 return; 72 } 73 74 // Nothing to display 75 console.log(`❌ [Copilot] No content found for ${node.name}`); 76 uiService.showInfo("Nothing to display"); 77 78 } catch (error) { 79 console.error(`Failed to open content for ${node.name}:`, error); 80 uiService.showError(`Failed to open content: ${error instanceof Error ? error.message : 'Unknown error'}`); 81 } 82 }