/ src / features / conversational-copilot / utils / open-node-content.ts
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  }