()
| 1314 | watchedJobs.set(numericJobId, state); |
| 1315 | |
| 1316 | const poll = async () => { |
| 1317 | if (state.done) return; |
| 1318 | try { |
| 1319 | const detail = await apiGet(`/api/pro/automation/jobs/get.php?id=${encodeURIComponent(numericJobId)}`); |
| 1320 | const job = (detail && typeof detail === 'object' && detail.job && typeof detail.job === 'object') ? detail.job : null; |
| 1321 | const status = String(job?.status || '').toLowerCase(); |
| 1322 | const payload = (job && job.payload && typeof job.payload === 'object') ? job.payload : null; |
| 1323 | const progress = (payload && payload.aiProgress && typeof payload.aiProgress === 'object') ? payload.aiProgress : null; |
| 1324 | const progressKey = progress |
| 1325 | ? `${Number(progress.processedCount || 0)}|${Number(progress.filteredOutCount || 0)}|${Number(progress.failedCount || 0)}|${String(progress.lastFile || '')}` |
| 1326 | : ''; |
| 1327 | const workflowDetail = buildAutomationWorkflowFromDetail(state.workflow, detail); |
| 1328 | |
| 1329 | if ((status === 'queued' || status === 'running') && progress && progressKey !== '' && progressKey !== state.lastProgressKey) { |
| 1330 | state.lastProgressKey = progressKey; |
| 1331 | if (state.messageHandle) { |
| 1332 | state.messageHandle.setWorkflow(workflowDetail); |
| 1333 | state.messageHandle.setText(`Job #${numericJobId} is running.`); |
| 1334 | } else { |
| 1335 | appendMessage( |
| 1336 | 'assistant', |
| 1337 | `Job #${numericJobId} running: processed ${Number(progress.processedCount || 0)}, filtered ${Number(progress.filteredOutCount || 0)}, failed ${Number(progress.failedCount || 0)}${progress.lastFile ? `, last file ${String(progress.lastFile)}` : ''}.`, |
| 1338 | { workflow: workflowDetail } |
| 1339 | ); |
| 1340 | } |
| 1341 | } else if ((status === 'queued' || status === 'running') && state.lastStatus !== status) { |
| 1342 | state.lastStatus = status; |
| 1343 | if (state.messageHandle) { |
| 1344 | state.messageHandle.setWorkflow(workflowDetail); |
| 1345 | state.messageHandle.setText(`Job #${numericJobId} ${status}.`); |
| 1346 | } else { |
| 1347 | appendMessage('assistant', `Job #${numericJobId} ${status}.`, { workflow: workflowDetail }); |
| 1348 | } |
| 1349 | } |
| 1350 | |
| 1351 | if (status === 'succeeded' || status === 'failed' || status === 'dead' || status === 'canceled') { |
| 1352 | state.done = true; |
| 1353 | watchedJobs.delete(numericJobId); |
| 1354 | const result = (payload && payload.aiResult && typeof payload.aiResult === 'object') ? payload.aiResult : null; |
| 1355 | const saved = (result?.savedOutputFile && typeof result.savedOutputFile === 'object') ? result.savedOutputFile : null; |
| 1356 | const summary = describeJobCompletion(detail); |
| 1357 | if (state.messageHandle) { |
| 1358 | state.messageHandle.setWorkflow(workflowDetail); |
| 1359 | if (summary !== '') { |
| 1360 | state.messageHandle.setText(summary); |
| 1361 | } |
| 1362 | } else if (summary !== '') { |
| 1363 | appendMessage('assistant', summary, { workflow: workflowDetail }); |
| 1364 | } |
| 1365 | refreshVisibleFolderForOutputFile(saved); |
| 1366 | refreshVisibleFolderForAutomationDetail(detail); |
| 1367 | return; |
| 1368 | } |
| 1369 | } catch (err) { |
| 1370 | // Ignore transient polling errors; next poll will retry. |
| 1371 | } |
| 1372 | state.timer = window.setTimeout(poll, 2500); |
| 1373 | }; |
nothing calls this directly
no test coverage detected