(workflow)
| 1003 | }; |
| 1004 | |
| 1005 | const buildWorkflowCard = (workflow) => { |
| 1006 | if (!workflow || typeof workflow !== 'object') return ''; |
| 1007 | const title = String(workflow.title || formatWorkflowLabel(workflow.name)).trim() || 'Workflow'; |
| 1008 | const folder = String(workflow.folder || '').trim(); |
| 1009 | const summary = String(workflow.summary || '').trim(); |
| 1010 | const token = String(workflow.token || '').trim(); |
| 1011 | const expiresAt = String(workflow.expiresAt || '').trim(); |
| 1012 | const estimatedFiles = Number(workflow.estimatedFiles || 0); |
| 1013 | const estimatedTotal = Number(workflow.estimatedTotalInFolder || 0); |
| 1014 | const maxFiles = Number(workflow.maxFiles || 0); |
| 1015 | const processed = Number(workflow.processed || 0); |
| 1016 | const failed = Number(workflow.failed || 0); |
| 1017 | const filtered = Number(workflow.filtered || 0); |
| 1018 | const status = String(workflow.status || '').trim().toLowerCase(); |
| 1019 | const truncated = !!workflow.truncated; |
| 1020 | const sampleErrors = Array.isArray(workflow.sampleErrors) ? workflow.sampleErrors.filter((v) => String(v || '').trim() !== '') : []; |
| 1021 | const isPending = !!workflow.pending; |
| 1022 | const isConfirmed = !!workflow.confirmed; |
| 1023 | const isQueued = status === 'queued' || !!workflow.queued; |
| 1024 | const isRunning = status === 'running' || !!workflow.running; |
| 1025 | const isBlocked = status === 'blocked' || !!workflow.blocked; |
| 1026 | const isFinal = isConfirmed || status === 'completed' || status === 'failed' || status === 'dead' || status === 'canceled'; |
| 1027 | const lines = []; |
| 1028 | |
| 1029 | if (folder) lines.push(`Folder: ${folder}`); |
| 1030 | if (summary && (!isFinal || isBlocked)) lines.push(summary); |
| 1031 | if ((estimatedFiles > 0 || isPending) && !isFinal) { |
| 1032 | let estimateText = `Estimated: ${estimatedFiles}`; |
| 1033 | if (estimatedTotal > 0) estimateText += ` of ${estimatedTotal}`; |
| 1034 | if (maxFiles > 0) estimateText += ` (cap ${maxFiles})`; |
| 1035 | lines.push(estimateText); |
| 1036 | } |
| 1037 | if (processed > 0 || failed > 0 || filtered > 0 || isConfirmed || isRunning) { |
| 1038 | let resultText = `Processed: ${processed}`; |
| 1039 | if (filtered > 0) resultText += ` | Filtered: ${filtered}`; |
| 1040 | resultText += ` | Failed: ${failed}`; |
| 1041 | lines.push(resultText); |
| 1042 | } |
| 1043 | if (truncated && maxFiles > 0) { |
| 1044 | lines.push(`Truncated at plan cap: ${maxFiles}`); |
| 1045 | } |
| 1046 | formatWorkflowParams(workflow).forEach((line) => lines.push(line)); |
| 1047 | if (sampleErrors.length) { |
| 1048 | lines.push(`Errors: ${sampleErrors.slice(0, 3).join(' | ')}`); |
| 1049 | } |
| 1050 | if (token) lines.push(`Confirm: /confirm ${token}`); |
| 1051 | if (expiresAt) lines.push(`Expires: ${expiresAt}`); |
| 1052 | if (status && !isPending) { |
| 1053 | lines.push(`Status: ${status}`); |
| 1054 | } else if (isPending) { |
| 1055 | lines.push('Status: awaiting confirmation'); |
| 1056 | } else if (isQueued) { |
| 1057 | lines.push('Status: queued'); |
| 1058 | } else if (isRunning) { |
| 1059 | lines.push('Status: running'); |
| 1060 | } else if (isConfirmed) { |
| 1061 | lines.push('Status: completed'); |
| 1062 | } |
no test coverage detected