The primary method for acquiring streams, using a "blueprint" approach.
(agentId: string, requiredStreams: PseudoStreamType[])
| 94 | |
| 95 | /** The primary method for acquiring streams, using a "blueprint" approach. */ |
| 96 | public async requestStreamsForAgent(agentId: string, requiredStreams: PseudoStreamType[]): Promise<void> { |
| 97 | Logger.debug("StreamManager", `Processing stream blueprint for agent '${agentId}': [${requiredStreams.join(', ')}]`); |
| 98 | |
| 99 | // Get the appropriate capture implementation based on platform |
| 100 | const captureImpl = isWeb() ? browserStreamCapture : tauriStreamCapture; |
| 101 | |
| 102 | // Let the platform-specific implementation map pseudo streams to master streams |
| 103 | const requiredMasterStreams = new Set<MasterStreamType>(); |
| 104 | for (const type of requiredStreams) { |
| 105 | const masterStreams = captureImpl.getMasterStreamsForPseudoStream(type); |
| 106 | masterStreams.forEach(ms => requiredMasterStreams.add(ms)); |
| 107 | } |
| 108 | |
| 109 | const acquisitionPromises: Promise<void>[] = []; |
| 110 | requiredMasterStreams.forEach(masterType => acquisitionPromises.push(this.ensureMasterStream(masterType, captureImpl))); |
| 111 | |
| 112 | try { |
| 113 | await Promise.all(acquisitionPromises); |
| 114 | |
| 115 | for (const type of requiredStreams) { |
| 116 | if (!this.isPseudoStreamAvailable(type)) { |
| 117 | throw new Error(`Failed to acquire required stream component '${type}'. Permission may have been denied.`); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | // --- Centralized Transcription & Mixer Logic --- |
| 122 | // Start transcription services and auto-subscribe the agent to each stream type. |
| 123 | // This ensures the agent receives all transcribed text from the moment streams are acquired. |
| 124 | if (requiredStreams.includes('allAudio')) { |
| 125 | await this.initializeAudioMixer(); |
| 126 | } |
| 127 | if (requiredStreams.includes('microphone') && this.microphoneStream) { |
| 128 | await this.startTranscriptionForStream('microphone', this.microphoneStream); |
| 129 | this.getOrCreateSubscriber(agentId, 'microphone'); |
| 130 | } |
| 131 | if (requiredStreams.includes('screenAudio') && this.screenAudioStream) { |
| 132 | await this.startTranscriptionForStream('screenAudio', this.screenAudioStream); |
| 133 | this.getOrCreateSubscriber(agentId, 'screenAudio'); |
| 134 | } |
| 135 | // Notify listeners after subscribers are created so hooks can detect them |
| 136 | this.notifyListeners(); |
| 137 | // --- END --- |
| 138 | |
| 139 | requiredStreams.forEach(type => this.userSets.get(type)?.add(agentId)); |
| 140 | |
| 141 | } catch (error) { |
| 142 | Logger.error("StreamManager", `Failed to fulfill stream blueprint for agent '${agentId}'.`, error); |
| 143 | throw error; |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | /** Releases all streams used by a specific agent. */ |
| 148 | public releaseStreamsForAgent(agentId: string): void { |
no test coverage detected