(agentId: string)
| 205 | } |
| 206 | |
| 207 | export async function stopAgentLoop(agentId: string): Promise<void> { |
| 208 | const loop = activeLoops[agentId]; |
| 209 | if (loop?.isRunning) { |
| 210 | if (loop.intervalId !== null) window.clearInterval(loop.intervalId); |
| 211 | |
| 212 | // Clear any active sleep state |
| 213 | wakeAgentLoop(agentId); |
| 214 | |
| 215 | // --- SUBSCRIBER CLEANUP --- |
| 216 | // Destroy all transcription subscribers for this agent |
| 217 | StreamManager.destroySubscribersForAgent(agentId); |
| 218 | |
| 219 | // --- STREAM MANAGEMENT --- |
| 220 | // Tell the StreamManager this agent no longer needs these streams. |
| 221 | // The manager will handle stopping the hardware if it's the last user. |
| 222 | Logger.debug(agentId, "Releasing all potential streams for stopping agent."); |
| 223 | |
| 224 | StreamManager.releaseStreamsForAgent(agentId); |
| 225 | |
| 226 | // Clear change detection data |
| 227 | clearAgentChangeData(agentId); |
| 228 | |
| 229 | // Note: Agent crop configurations are preserved across stop/start cycles |
| 230 | |
| 231 | |
| 232 | // End the current session and save to IndexedDB |
| 233 | await IterationStore.endSession(agentId); |
| 234 | |
| 235 | // ------------------------- |
| 236 | |
| 237 | activeLoops[agentId] = { ...loop, isRunning: false, intervalId: null, sleepUntil: null }; |
| 238 | |
| 239 | if (getRunningAgentIds().length === 0) { |
| 240 | // This was the last running agent, so shut down the recorder. |
| 241 | recordingManager.forceStop(); |
| 242 | } |
| 243 | |
| 244 | // Logger dispatches the window event automatically |
| 245 | Logger.info(agentId, 'Agent stopped', { |
| 246 | logType: 'agent-status-changed', |
| 247 | content: { agentId, status: 'stopped' } |
| 248 | }); |
| 249 | } else { |
| 250 | Logger.warn(agentId, `Attempted to stop agent that wasn't running`); |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Execute a single iteration of the agent's loop |
no test coverage detected