* Execute a scheduled job: call agent.handleMessage and push results. * Returns { text, notifyFailed } so callers can produce accurate status.
(
jobConfig: ScheduledJobConfig,
)
| 214 | // ------------------------------------------------------------------------- |
| 215 | |
| 216 | /** |
| 217 | * Execute a scheduled job: call agent.handleMessage and push results. |
| 218 | * Returns { text, notifyFailed } so callers can produce accurate status. |
| 219 | */ |
| 220 | private async runJob( |
| 221 | jobConfig: ScheduledJobConfig, |
| 222 | ): Promise<{ text: string; notifyFailed: boolean }> { |
| 223 | const channelId = `scheduler-${jobConfig.id}`; |
| 224 | const job = this.jobs.get(jobConfig.id); |
| 225 | |
| 226 | if (job?.running) { |
| 227 | console.warn( |
| 228 | `[Scheduler] Job "${jobConfig.name}" is already running, skipping this trigger`, |
| 229 | ); |
| 230 | return { text: "", notifyFailed: false }; |
| 231 | } |
| 232 | |
| 233 | if (job) job.running = true; |
| 234 | |
| 235 | console.log(`[Scheduler] Running job "${jobConfig.name}"`); |
| 236 | |
| 237 | let fullText = ""; |
| 238 | let agentFailed = false; |
| 239 | let loggedFirstTextDelta = false; |
| 240 | let sawAgentStart = false; |
| 241 | let sawAgentEnd = false; |
| 242 | const pendingFiles: Array<{ filePath: string; caption?: string }> = []; |
| 243 | |
| 244 | const onEvent = (event: AgentEvent) => { |
| 245 | if (event.type === "agent_start") { |
| 246 | sawAgentStart = true; |
| 247 | } else if (event.type === "agent_end") { |
| 248 | sawAgentEnd = true; |
| 249 | } |
| 250 | |
| 251 | if (event.type === "agent_start" || event.type === "agent_end") { |
| 252 | console.log( |
| 253 | `[Scheduler] Forwarding ${event.type} for ${channelId} (ipc=${this.ipcBroadcaster ? "yes" : "no"})`, |
| 254 | ); |
| 255 | } else if (event.type === "text_delta" && !loggedFirstTextDelta) { |
| 256 | loggedFirstTextDelta = true; |
| 257 | console.log( |
| 258 | `[Scheduler] Forwarding first text_delta for ${channelId} (${event.delta.length} chars, ipc=${this.ipcBroadcaster ? "yes" : "no"})`, |
| 259 | ); |
| 260 | } |
| 261 | |
| 262 | this.ipcBroadcaster?.broadcastAgentEvent(channelId, event); |
| 263 | if (event.type === "text_delta") fullText += event.delta; |
| 264 | if (event.type === "file_output") { |
| 265 | pendingFiles.push({ |
| 266 | filePath: event.filePath, |
| 267 | caption: event.caption, |
| 268 | }); |
| 269 | } |
| 270 | }; |
| 271 | |
| 272 | try { |
| 273 | await this.clearJobContext(channelId); |
no test coverage detected