()
| 136 | |
| 137 | // Simple execution function |
| 138 | const executeIteration = async () => { |
| 139 | const loop = activeLoops[agentId]; |
| 140 | if (!loop?.isRunning || loop.isExecuting) return; |
| 141 | |
| 142 | // Check if agent is sleeping |
| 143 | if (loop.sleepUntil && Date.now() < loop.sleepUntil) { |
| 144 | const remainingMs = loop.sleepUntil - Date.now(); |
| 145 | Logger.debug(agentId, `Skipping iteration - agent sleeping for ${Math.round(remainingMs/1000)}s more`); |
| 146 | return; |
| 147 | } |
| 148 | |
| 149 | // Clear sleep state when resuming |
| 150 | if (loop.sleepUntil) { |
| 151 | Logger.debug(agentId, `Agent sleep period ended, resuming execution`); |
| 152 | loop.sleepUntil = null; |
| 153 | } |
| 154 | |
| 155 | loop.isExecuting = true; |
| 156 | |
| 157 | try { |
| 158 | await executeAgentIteration(agentId); |
| 159 | |
| 160 | } catch (error) { |
| 161 | // Any error stops the agent cleanly |
| 162 | const errorMessage = error instanceof Error ? error.message : String(error); |
| 163 | Logger.error(agentId, `Agent stopped due to error: ${errorMessage}`, { |
| 164 | error, |
| 165 | logType: 'agent-error', |
| 166 | content: { error: errorMessage } |
| 167 | }); |
| 168 | await stopAgentLoop(agentId); |
| 169 | |
| 170 | } finally { |
| 171 | // Always cleanup execution state |
| 172 | if (activeLoops[agentId]) { |
| 173 | activeLoops[agentId].isExecuting = false; |
| 174 | } |
| 175 | } |
| 176 | }; |
| 177 | |
| 178 | // Fixed-rhythm metronome timer |
| 179 | activeLoops[agentId].intervalId = window.setInterval(executeIteration, intervalMs); |
no test coverage detected