@agenticmail/enterprise 0.5.212 → 0.5.213
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -344,91 +344,7 @@ function MetricsBar(props) {
|
|
|
344
344
|
);
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
-
//
|
|
348
|
-
function ChainFlowInline(props) {
|
|
349
|
-
var chain = props.chain;
|
|
350
|
-
var taskId = props.taskId;
|
|
351
|
-
var onClose = props.onClose;
|
|
352
|
-
var onClickTask = props.onClickTask;
|
|
353
|
-
if (!chain || chain.length === 0) return null;
|
|
354
|
-
|
|
355
|
-
var MINI_W = 180;
|
|
356
|
-
var MINI_H = 56;
|
|
357
|
-
var MINI_GAP = 40;
|
|
358
|
-
var totalW = chain.length * MINI_W + (chain.length - 1) * MINI_GAP + 40;
|
|
359
|
-
|
|
360
|
-
return h('div', { style: { borderTop: '1px solid rgba(255,255,255,0.08)', background: 'rgba(0,0,0,0.25)', padding: '12px 16px', flexShrink: 0, overflow: 'auto' } },
|
|
361
|
-
h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 } },
|
|
362
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
363
|
-
h('span', { style: { fontSize: 11, fontWeight: 600, color: 'rgba(255,255,255,0.5)', letterSpacing: '0.06em' } }, 'TASK FLOW'),
|
|
364
|
-
h('span', { style: { fontSize: 10, color: 'rgba(255,255,255,0.3)', fontFamily: 'var(--font-mono)' } }, chain[0].chainId ? '#' + chain[0].chainId.slice(0, 8) : ''),
|
|
365
|
-
h('span', { style: { fontSize: 10, color: 'rgba(255,255,255,0.3)' } }, chain.length + ' step' + (chain.length > 1 ? 's' : ''))
|
|
366
|
-
),
|
|
367
|
-
h('button', { onClick: onClose, style: { background: 'none', border: 'none', color: 'rgba(255,255,255,0.3)', cursor: 'pointer', fontSize: 16, padding: '0 4px' } }, '\u00D7')
|
|
368
|
-
),
|
|
369
|
-
h('div', { style: { position: 'relative', height: MINI_H + 20, minWidth: totalW } },
|
|
370
|
-
// SVG arrows
|
|
371
|
-
h('svg', { width: totalW, height: MINI_H + 20, style: { position: 'absolute', top: 0, left: 0, pointerEvents: 'none' } },
|
|
372
|
-
h('defs', null,
|
|
373
|
-
h('marker', { id: 'cf-arr', markerWidth: 6, markerHeight: 4, refX: 6, refY: 2, orient: 'auto' },
|
|
374
|
-
h('polygon', { points: '0 0, 6 2, 0 4', fill: 'rgba(99,102,241,0.5)' })
|
|
375
|
-
)
|
|
376
|
-
),
|
|
377
|
-
chain.map(function(ct, i) {
|
|
378
|
-
if (i === 0) return null;
|
|
379
|
-
var x1 = 20 + (i - 1) * (MINI_W + MINI_GAP) + MINI_W;
|
|
380
|
-
var x2 = 20 + i * (MINI_W + MINI_GAP);
|
|
381
|
-
var y = 10 + MINI_H / 2;
|
|
382
|
-
var dType = ct.delegationType || 'delegation';
|
|
383
|
-
var color = DELEGATION_COLORS[dType] || 'rgba(99,102,241,0.5)';
|
|
384
|
-
var isActive = chain[i - 1].status === 'in_progress' || ct.status === 'in_progress';
|
|
385
|
-
return h(Fragment, { key: 'e' + i },
|
|
386
|
-
h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: color + '88', strokeWidth: 2, markerEnd: 'url(#cf-arr)' }),
|
|
387
|
-
isActive && h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: STATUS_COLORS.in_progress, strokeWidth: 2, strokeDasharray: '4 12', className: 'tp-flow-active', style: { opacity: 0.7 } }),
|
|
388
|
-
dType !== 'delegation' && h('text', { x: (x1 + x2) / 2, y: y - 6, fill: color, fontSize: 8, textAnchor: 'middle', fontWeight: 600 }, dType)
|
|
389
|
-
);
|
|
390
|
-
})
|
|
391
|
-
),
|
|
392
|
-
// Task nodes
|
|
393
|
-
chain.map(function(ct, i) {
|
|
394
|
-
var x = 20 + i * (MINI_W + MINI_GAP);
|
|
395
|
-
var sc = STATUS_COLORS[ct.status] || '#6b7394';
|
|
396
|
-
var isMe = ct.id === taskId;
|
|
397
|
-
var isActive = ct.status === 'in_progress';
|
|
398
|
-
return h('div', {
|
|
399
|
-
key: ct.id,
|
|
400
|
-
onClick: function() { if (onClickTask) onClickTask(ct); },
|
|
401
|
-
style: {
|
|
402
|
-
position: 'absolute', left: x, top: 10, width: MINI_W, height: MINI_H,
|
|
403
|
-
background: isMe ? sc + '15' : 'rgba(255,255,255,0.02)',
|
|
404
|
-
border: '1.5px solid ' + (isMe ? sc : 'rgba(255,255,255,0.1)'),
|
|
405
|
-
borderLeft: '3px solid ' + sc,
|
|
406
|
-
borderRadius: 8, padding: '6px 10px', cursor: 'pointer',
|
|
407
|
-
display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 3,
|
|
408
|
-
transition: 'all 0.15s',
|
|
409
|
-
},
|
|
410
|
-
onMouseEnter: function(e) { e.currentTarget.style.background = 'rgba(255,255,255,0.05)'; },
|
|
411
|
-
onMouseLeave: function(e) { e.currentTarget.style.background = isMe ? sc + '15' : 'rgba(255,255,255,0.02)'; },
|
|
412
|
-
},
|
|
413
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 5 } },
|
|
414
|
-
h('div', { style: { width: 16, height: 16, borderRadius: '50%', background: sc + '33', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 7, fontWeight: 700, color: sc, flexShrink: 0 } },
|
|
415
|
-
(ct.assignedToName || '?').charAt(0).toUpperCase()
|
|
416
|
-
),
|
|
417
|
-
h('span', { style: { fontSize: 10, fontWeight: 600, color: '#fff', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 } }, ct.assignedToName || ct.assignedTo)
|
|
418
|
-
),
|
|
419
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
|
|
420
|
-
tag(sc, ct.status.replace('_', ' ')),
|
|
421
|
-
h('span', { style: { fontSize: 8, color: 'rgba(255,255,255,0.3)' } }, timeAgo(ct.createdAt)),
|
|
422
|
-
ct.actualDurationMs && h('span', { style: { fontSize: 8, color: 'rgba(255,255,255,0.3)', marginLeft: 'auto' } }, formatDuration(ct.actualDurationMs))
|
|
423
|
-
),
|
|
424
|
-
isActive && ct.progress > 0 && h('div', { style: { height: 2, background: 'rgba(255,255,255,0.08)', borderRadius: 1, overflow: 'hidden' } },
|
|
425
|
-
h('div', { style: { height: '100%', width: ct.progress + '%', background: sc, borderRadius: 1 } })
|
|
426
|
-
)
|
|
427
|
-
);
|
|
428
|
-
})
|
|
429
|
-
)
|
|
430
|
-
);
|
|
431
|
-
}
|
|
347
|
+
// (ChainFlowInline removed — chain flow now renders inline on canvas)
|
|
432
348
|
|
|
433
349
|
// ─── Main Page ───────────────────────────────────────────
|
|
434
350
|
export function TaskPipelinePage() {
|
|
@@ -802,7 +718,123 @@ export function TaskPipelinePage() {
|
|
|
802
718
|
h('div', { style: { height: '100%', width: t.progress + '%', background: sc, borderRadius: 1, transition: 'width 0.3s' } })
|
|
803
719
|
)
|
|
804
720
|
);
|
|
805
|
-
})
|
|
721
|
+
}),
|
|
722
|
+
|
|
723
|
+
// ── Expanded chain flow (rendered ON the canvas below clicked node) ──
|
|
724
|
+
expandedChain && expandedChain.length > 0 && (function() {
|
|
725
|
+
// Find the clicked node position to anchor below it
|
|
726
|
+
var anchor = nodes.find(function(n) { return n.id === expandedTaskId; });
|
|
727
|
+
if (!anchor) return null;
|
|
728
|
+
var flowY = anchor.y + anchor.h + 20;
|
|
729
|
+
var flowX = anchor.x;
|
|
730
|
+
var STEP_W = 120;
|
|
731
|
+
var STEP_H = 44;
|
|
732
|
+
var STEP_GAP = 48;
|
|
733
|
+
var ARROW_W = STEP_GAP;
|
|
734
|
+
|
|
735
|
+
// Build person-centric flow steps: createdBy → assignedTo for each chain task, then final status
|
|
736
|
+
var steps = [];
|
|
737
|
+
expandedChain.forEach(function(ct, i) {
|
|
738
|
+
if (i === 0 && ct.createdBy && ct.createdBy !== 'system') {
|
|
739
|
+
steps.push({ label: ct.createdByName || ct.createdBy, type: 'person', isHuman: ct.createdBy.indexOf('agent') === -1 && ct.createdBy !== 'system', status: null, arrow: ct.delegationType || 'assigned' });
|
|
740
|
+
} else if (i === 0 && ct.createdBy === 'system') {
|
|
741
|
+
steps.push({ label: 'System', type: 'system', isHuman: false, status: null, arrow: 'assigned' });
|
|
742
|
+
}
|
|
743
|
+
steps.push({ label: ct.assignedToName || ct.assignedTo, type: 'agent', isHuman: false, status: ct.status, taskId: ct.id, arrow: i < expandedChain.length - 1 ? (expandedChain[i + 1].delegationType || 'delegation') : null, duration: ct.actualDurationMs, progress: ct.progress });
|
|
744
|
+
});
|
|
745
|
+
// Add final status node
|
|
746
|
+
var lastTask = expandedChain[expandedChain.length - 1];
|
|
747
|
+
var isDone = lastTask.status === 'completed' || lastTask.status === 'failed' || lastTask.status === 'cancelled';
|
|
748
|
+
if (isDone) {
|
|
749
|
+
steps.push({ label: lastTask.status === 'completed' ? 'Completed!' : lastTask.status === 'failed' ? 'Failed' : 'Cancelled', type: 'terminal', isHuman: false, status: lastTask.status, arrow: null });
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
var totalW = steps.length * STEP_W + (steps.length - 1) * STEP_GAP;
|
|
753
|
+
|
|
754
|
+
return h('div', { style: { position: 'absolute', left: flowX, top: flowY, pointerEvents: 'auto' } },
|
|
755
|
+
// Background card
|
|
756
|
+
h('div', { style: { background: 'rgba(10,12,20,0.85)', border: '1px solid rgba(99,102,241,0.2)', borderRadius: 12, padding: '14px 16px 12px', backdropFilter: 'blur(8px)' } },
|
|
757
|
+
// Header
|
|
758
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 } },
|
|
759
|
+
h('span', { style: { fontSize: 10, fontWeight: 600, color: 'rgba(255,255,255,0.4)', letterSpacing: '0.06em' } }, 'TASK FLOW'),
|
|
760
|
+
expandedChain[0].chainId && h('span', { style: { fontSize: 9, color: 'rgba(255,255,255,0.2)', fontFamily: 'var(--font-mono)' } }, '#' + expandedChain[0].chainId.slice(0, 8)),
|
|
761
|
+
h('div', { style: { flex: 1 } }),
|
|
762
|
+
h('button', { className: 'tp-node', onClick: function() { setExpandedTaskId(null); }, style: { background: 'none', border: 'none', color: 'rgba(255,255,255,0.3)', cursor: 'pointer', fontSize: 14, padding: '0 2px' } }, '\u00D7')
|
|
763
|
+
),
|
|
764
|
+
// Flow
|
|
765
|
+
h('div', { style: { position: 'relative', height: STEP_H + 8, minWidth: totalW } },
|
|
766
|
+
// SVG arrows
|
|
767
|
+
h('svg', { width: totalW, height: STEP_H + 8, style: { position: 'absolute', top: 0, left: 0, pointerEvents: 'none' } },
|
|
768
|
+
h('defs', null,
|
|
769
|
+
h('marker', { id: 'fc-arr', markerWidth: 6, markerHeight: 4, refX: 6, refY: 2, orient: 'auto' },
|
|
770
|
+
h('polygon', { points: '0 0, 6 2, 0 4', fill: 'rgba(99,102,241,0.5)' })
|
|
771
|
+
)
|
|
772
|
+
),
|
|
773
|
+
steps.map(function(step, i) {
|
|
774
|
+
if (i === steps.length - 1 || !step.arrow) return null;
|
|
775
|
+
var x1 = i * (STEP_W + STEP_GAP) + STEP_W;
|
|
776
|
+
var x2 = (i + 1) * (STEP_W + STEP_GAP);
|
|
777
|
+
var y = 4 + STEP_H / 2;
|
|
778
|
+
var arrowColor = DELEGATION_COLORS[step.arrow] || 'rgba(99,102,241,0.5)';
|
|
779
|
+
var nextStep = steps[i + 1];
|
|
780
|
+
var isFlowActive = step.status === 'in_progress' || (nextStep && nextStep.status === 'in_progress');
|
|
781
|
+
return h(Fragment, { key: 'a' + i },
|
|
782
|
+
h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: arrowColor + '88', strokeWidth: 2, markerEnd: 'url(#fc-arr)' }),
|
|
783
|
+
isFlowActive && h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: STATUS_COLORS.in_progress, strokeWidth: 2, strokeDasharray: '4 12', className: 'tp-flow-active', style: { opacity: 0.7 } }),
|
|
784
|
+
step.arrow !== 'assigned' && step.arrow !== 'delegation' && h('text', { x: (x1 + x2) / 2, y: y - 6, fill: arrowColor, fontSize: 8, textAnchor: 'middle', fontWeight: 600 }, step.arrow)
|
|
785
|
+
);
|
|
786
|
+
})
|
|
787
|
+
),
|
|
788
|
+
// Step nodes
|
|
789
|
+
steps.map(function(step, i) {
|
|
790
|
+
var x = i * (STEP_W + STEP_GAP);
|
|
791
|
+
var sc = step.type === 'terminal'
|
|
792
|
+
? (STATUS_COLORS[step.status] || '#22c55e')
|
|
793
|
+
: step.type === 'person' || step.isHuman
|
|
794
|
+
? '#f59e0b'
|
|
795
|
+
: step.status ? (STATUS_COLORS[step.status] || '#6366f1') : '#6366f1';
|
|
796
|
+
var isTerminal = step.type === 'terminal';
|
|
797
|
+
var isMe = step.taskId === expandedTaskId;
|
|
798
|
+
|
|
799
|
+
return h('div', {
|
|
800
|
+
key: i,
|
|
801
|
+
className: 'tp-node',
|
|
802
|
+
onClick: function(e) { e.stopPropagation(); if (step.taskId) { var ct = expandedChain.find(function(c) { return c.id === step.taskId; }); if (ct) openTaskDetail(ct); } },
|
|
803
|
+
style: {
|
|
804
|
+
position: 'absolute', left: x, top: 4, width: STEP_W, height: STEP_H,
|
|
805
|
+
background: isTerminal ? sc + '15' : isMe ? 'rgba(255,255,255,0.06)' : 'rgba(255,255,255,0.02)',
|
|
806
|
+
border: '1.5px solid ' + (isTerminal ? sc + '44' : isMe ? sc : 'rgba(255,255,255,0.1)'),
|
|
807
|
+
borderRadius: isTerminal ? 22 : 10,
|
|
808
|
+
display: 'flex', alignItems: 'center', gap: 8, padding: '0 10px',
|
|
809
|
+
cursor: step.taskId ? 'pointer' : 'default',
|
|
810
|
+
},
|
|
811
|
+
},
|
|
812
|
+
// Avatar
|
|
813
|
+
h('div', { style: {
|
|
814
|
+
width: 26, height: 26, borderRadius: '50%', flexShrink: 0,
|
|
815
|
+
background: isTerminal ? sc + '33' : step.isHuman || step.type === 'person' ? 'linear-gradient(135deg, #f59e0b, #f97316)' : step.type === 'system' ? 'rgba(255,255,255,0.1)' : 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
|
816
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
817
|
+
fontSize: isTerminal ? 12 : 10, fontWeight: 700,
|
|
818
|
+
color: isTerminal ? sc : '#fff',
|
|
819
|
+
border: '2px solid ' + (isTerminal ? sc + '44' : 'transparent'),
|
|
820
|
+
} },
|
|
821
|
+
isTerminal ? (step.status === 'completed' ? '\u2714' : step.status === 'failed' ? '\u2716' : '\u2716') : step.label.charAt(0).toUpperCase()
|
|
822
|
+
),
|
|
823
|
+
// Info
|
|
824
|
+
h('div', { style: { overflow: 'hidden', flex: 1, minWidth: 0 } },
|
|
825
|
+
h('div', { style: { fontSize: 11, fontWeight: 600, color: isTerminal ? sc : '#fff', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, step.label),
|
|
826
|
+
!isTerminal && h('div', { style: { fontSize: 9, color: 'rgba(255,255,255,0.35)', marginTop: 1 } },
|
|
827
|
+
step.type === 'person' || step.isHuman ? 'Human' : step.type === 'system' ? 'System' : 'Agent',
|
|
828
|
+
step.duration ? ' \u00B7 ' + formatDuration(step.duration) : '',
|
|
829
|
+
step.status === 'in_progress' && step.progress > 0 ? ' \u00B7 ' + step.progress + '%' : ''
|
|
830
|
+
)
|
|
831
|
+
)
|
|
832
|
+
);
|
|
833
|
+
})
|
|
834
|
+
)
|
|
835
|
+
)
|
|
836
|
+
);
|
|
837
|
+
})()
|
|
806
838
|
)
|
|
807
839
|
),
|
|
808
840
|
|
|
@@ -824,14 +856,6 @@ export function TaskPipelinePage() {
|
|
|
824
856
|
)
|
|
825
857
|
),
|
|
826
858
|
|
|
827
|
-
// Inline chain flowchart (shown when a task is clicked)
|
|
828
|
-
expandedChain && expandedChain.length > 0 && h(ChainFlowInline, {
|
|
829
|
-
chain: expandedChain,
|
|
830
|
-
taskId: expandedTaskId,
|
|
831
|
-
onClose: function() { setExpandedTaskId(null); },
|
|
832
|
-
onClickTask: function(t) { openTaskDetail(t); }
|
|
833
|
-
}),
|
|
834
|
-
|
|
835
859
|
// Detail modal (double-click)
|
|
836
860
|
selectedTask && h(TaskDetail, { task: selectedTask, chain: selectedChain, onClose: function() { setSelectedTask(null); setSelectedChain(null); }, onCancel: cancelTask })
|
|
837
861
|
);
|
package/package.json
CHANGED
|
@@ -344,91 +344,7 @@ function MetricsBar(props) {
|
|
|
344
344
|
);
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
-
//
|
|
348
|
-
function ChainFlowInline(props) {
|
|
349
|
-
var chain = props.chain;
|
|
350
|
-
var taskId = props.taskId;
|
|
351
|
-
var onClose = props.onClose;
|
|
352
|
-
var onClickTask = props.onClickTask;
|
|
353
|
-
if (!chain || chain.length === 0) return null;
|
|
354
|
-
|
|
355
|
-
var MINI_W = 180;
|
|
356
|
-
var MINI_H = 56;
|
|
357
|
-
var MINI_GAP = 40;
|
|
358
|
-
var totalW = chain.length * MINI_W + (chain.length - 1) * MINI_GAP + 40;
|
|
359
|
-
|
|
360
|
-
return h('div', { style: { borderTop: '1px solid rgba(255,255,255,0.08)', background: 'rgba(0,0,0,0.25)', padding: '12px 16px', flexShrink: 0, overflow: 'auto' } },
|
|
361
|
-
h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 } },
|
|
362
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
363
|
-
h('span', { style: { fontSize: 11, fontWeight: 600, color: 'rgba(255,255,255,0.5)', letterSpacing: '0.06em' } }, 'TASK FLOW'),
|
|
364
|
-
h('span', { style: { fontSize: 10, color: 'rgba(255,255,255,0.3)', fontFamily: 'var(--font-mono)' } }, chain[0].chainId ? '#' + chain[0].chainId.slice(0, 8) : ''),
|
|
365
|
-
h('span', { style: { fontSize: 10, color: 'rgba(255,255,255,0.3)' } }, chain.length + ' step' + (chain.length > 1 ? 's' : ''))
|
|
366
|
-
),
|
|
367
|
-
h('button', { onClick: onClose, style: { background: 'none', border: 'none', color: 'rgba(255,255,255,0.3)', cursor: 'pointer', fontSize: 16, padding: '0 4px' } }, '\u00D7')
|
|
368
|
-
),
|
|
369
|
-
h('div', { style: { position: 'relative', height: MINI_H + 20, minWidth: totalW } },
|
|
370
|
-
// SVG arrows
|
|
371
|
-
h('svg', { width: totalW, height: MINI_H + 20, style: { position: 'absolute', top: 0, left: 0, pointerEvents: 'none' } },
|
|
372
|
-
h('defs', null,
|
|
373
|
-
h('marker', { id: 'cf-arr', markerWidth: 6, markerHeight: 4, refX: 6, refY: 2, orient: 'auto' },
|
|
374
|
-
h('polygon', { points: '0 0, 6 2, 0 4', fill: 'rgba(99,102,241,0.5)' })
|
|
375
|
-
)
|
|
376
|
-
),
|
|
377
|
-
chain.map(function(ct, i) {
|
|
378
|
-
if (i === 0) return null;
|
|
379
|
-
var x1 = 20 + (i - 1) * (MINI_W + MINI_GAP) + MINI_W;
|
|
380
|
-
var x2 = 20 + i * (MINI_W + MINI_GAP);
|
|
381
|
-
var y = 10 + MINI_H / 2;
|
|
382
|
-
var dType = ct.delegationType || 'delegation';
|
|
383
|
-
var color = DELEGATION_COLORS[dType] || 'rgba(99,102,241,0.5)';
|
|
384
|
-
var isActive = chain[i - 1].status === 'in_progress' || ct.status === 'in_progress';
|
|
385
|
-
return h(Fragment, { key: 'e' + i },
|
|
386
|
-
h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: color + '88', strokeWidth: 2, markerEnd: 'url(#cf-arr)' }),
|
|
387
|
-
isActive && h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: STATUS_COLORS.in_progress, strokeWidth: 2, strokeDasharray: '4 12', className: 'tp-flow-active', style: { opacity: 0.7 } }),
|
|
388
|
-
dType !== 'delegation' && h('text', { x: (x1 + x2) / 2, y: y - 6, fill: color, fontSize: 8, textAnchor: 'middle', fontWeight: 600 }, dType)
|
|
389
|
-
);
|
|
390
|
-
})
|
|
391
|
-
),
|
|
392
|
-
// Task nodes
|
|
393
|
-
chain.map(function(ct, i) {
|
|
394
|
-
var x = 20 + i * (MINI_W + MINI_GAP);
|
|
395
|
-
var sc = STATUS_COLORS[ct.status] || '#6b7394';
|
|
396
|
-
var isMe = ct.id === taskId;
|
|
397
|
-
var isActive = ct.status === 'in_progress';
|
|
398
|
-
return h('div', {
|
|
399
|
-
key: ct.id,
|
|
400
|
-
onClick: function() { if (onClickTask) onClickTask(ct); },
|
|
401
|
-
style: {
|
|
402
|
-
position: 'absolute', left: x, top: 10, width: MINI_W, height: MINI_H,
|
|
403
|
-
background: isMe ? sc + '15' : 'rgba(255,255,255,0.02)',
|
|
404
|
-
border: '1.5px solid ' + (isMe ? sc : 'rgba(255,255,255,0.1)'),
|
|
405
|
-
borderLeft: '3px solid ' + sc,
|
|
406
|
-
borderRadius: 8, padding: '6px 10px', cursor: 'pointer',
|
|
407
|
-
display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 3,
|
|
408
|
-
transition: 'all 0.15s',
|
|
409
|
-
},
|
|
410
|
-
onMouseEnter: function(e) { e.currentTarget.style.background = 'rgba(255,255,255,0.05)'; },
|
|
411
|
-
onMouseLeave: function(e) { e.currentTarget.style.background = isMe ? sc + '15' : 'rgba(255,255,255,0.02)'; },
|
|
412
|
-
},
|
|
413
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 5 } },
|
|
414
|
-
h('div', { style: { width: 16, height: 16, borderRadius: '50%', background: sc + '33', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 7, fontWeight: 700, color: sc, flexShrink: 0 } },
|
|
415
|
-
(ct.assignedToName || '?').charAt(0).toUpperCase()
|
|
416
|
-
),
|
|
417
|
-
h('span', { style: { fontSize: 10, fontWeight: 600, color: '#fff', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 } }, ct.assignedToName || ct.assignedTo)
|
|
418
|
-
),
|
|
419
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
|
|
420
|
-
tag(sc, ct.status.replace('_', ' ')),
|
|
421
|
-
h('span', { style: { fontSize: 8, color: 'rgba(255,255,255,0.3)' } }, timeAgo(ct.createdAt)),
|
|
422
|
-
ct.actualDurationMs && h('span', { style: { fontSize: 8, color: 'rgba(255,255,255,0.3)', marginLeft: 'auto' } }, formatDuration(ct.actualDurationMs))
|
|
423
|
-
),
|
|
424
|
-
isActive && ct.progress > 0 && h('div', { style: { height: 2, background: 'rgba(255,255,255,0.08)', borderRadius: 1, overflow: 'hidden' } },
|
|
425
|
-
h('div', { style: { height: '100%', width: ct.progress + '%', background: sc, borderRadius: 1 } })
|
|
426
|
-
)
|
|
427
|
-
);
|
|
428
|
-
})
|
|
429
|
-
)
|
|
430
|
-
);
|
|
431
|
-
}
|
|
347
|
+
// (ChainFlowInline removed — chain flow now renders inline on canvas)
|
|
432
348
|
|
|
433
349
|
// ─── Main Page ───────────────────────────────────────────
|
|
434
350
|
export function TaskPipelinePage() {
|
|
@@ -802,7 +718,123 @@ export function TaskPipelinePage() {
|
|
|
802
718
|
h('div', { style: { height: '100%', width: t.progress + '%', background: sc, borderRadius: 1, transition: 'width 0.3s' } })
|
|
803
719
|
)
|
|
804
720
|
);
|
|
805
|
-
})
|
|
721
|
+
}),
|
|
722
|
+
|
|
723
|
+
// ── Expanded chain flow (rendered ON the canvas below clicked node) ──
|
|
724
|
+
expandedChain && expandedChain.length > 0 && (function() {
|
|
725
|
+
// Find the clicked node position to anchor below it
|
|
726
|
+
var anchor = nodes.find(function(n) { return n.id === expandedTaskId; });
|
|
727
|
+
if (!anchor) return null;
|
|
728
|
+
var flowY = anchor.y + anchor.h + 20;
|
|
729
|
+
var flowX = anchor.x;
|
|
730
|
+
var STEP_W = 120;
|
|
731
|
+
var STEP_H = 44;
|
|
732
|
+
var STEP_GAP = 48;
|
|
733
|
+
var ARROW_W = STEP_GAP;
|
|
734
|
+
|
|
735
|
+
// Build person-centric flow steps: createdBy → assignedTo for each chain task, then final status
|
|
736
|
+
var steps = [];
|
|
737
|
+
expandedChain.forEach(function(ct, i) {
|
|
738
|
+
if (i === 0 && ct.createdBy && ct.createdBy !== 'system') {
|
|
739
|
+
steps.push({ label: ct.createdByName || ct.createdBy, type: 'person', isHuman: ct.createdBy.indexOf('agent') === -1 && ct.createdBy !== 'system', status: null, arrow: ct.delegationType || 'assigned' });
|
|
740
|
+
} else if (i === 0 && ct.createdBy === 'system') {
|
|
741
|
+
steps.push({ label: 'System', type: 'system', isHuman: false, status: null, arrow: 'assigned' });
|
|
742
|
+
}
|
|
743
|
+
steps.push({ label: ct.assignedToName || ct.assignedTo, type: 'agent', isHuman: false, status: ct.status, taskId: ct.id, arrow: i < expandedChain.length - 1 ? (expandedChain[i + 1].delegationType || 'delegation') : null, duration: ct.actualDurationMs, progress: ct.progress });
|
|
744
|
+
});
|
|
745
|
+
// Add final status node
|
|
746
|
+
var lastTask = expandedChain[expandedChain.length - 1];
|
|
747
|
+
var isDone = lastTask.status === 'completed' || lastTask.status === 'failed' || lastTask.status === 'cancelled';
|
|
748
|
+
if (isDone) {
|
|
749
|
+
steps.push({ label: lastTask.status === 'completed' ? 'Completed!' : lastTask.status === 'failed' ? 'Failed' : 'Cancelled', type: 'terminal', isHuman: false, status: lastTask.status, arrow: null });
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
var totalW = steps.length * STEP_W + (steps.length - 1) * STEP_GAP;
|
|
753
|
+
|
|
754
|
+
return h('div', { style: { position: 'absolute', left: flowX, top: flowY, pointerEvents: 'auto' } },
|
|
755
|
+
// Background card
|
|
756
|
+
h('div', { style: { background: 'rgba(10,12,20,0.85)', border: '1px solid rgba(99,102,241,0.2)', borderRadius: 12, padding: '14px 16px 12px', backdropFilter: 'blur(8px)' } },
|
|
757
|
+
// Header
|
|
758
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 } },
|
|
759
|
+
h('span', { style: { fontSize: 10, fontWeight: 600, color: 'rgba(255,255,255,0.4)', letterSpacing: '0.06em' } }, 'TASK FLOW'),
|
|
760
|
+
expandedChain[0].chainId && h('span', { style: { fontSize: 9, color: 'rgba(255,255,255,0.2)', fontFamily: 'var(--font-mono)' } }, '#' + expandedChain[0].chainId.slice(0, 8)),
|
|
761
|
+
h('div', { style: { flex: 1 } }),
|
|
762
|
+
h('button', { className: 'tp-node', onClick: function() { setExpandedTaskId(null); }, style: { background: 'none', border: 'none', color: 'rgba(255,255,255,0.3)', cursor: 'pointer', fontSize: 14, padding: '0 2px' } }, '\u00D7')
|
|
763
|
+
),
|
|
764
|
+
// Flow
|
|
765
|
+
h('div', { style: { position: 'relative', height: STEP_H + 8, minWidth: totalW } },
|
|
766
|
+
// SVG arrows
|
|
767
|
+
h('svg', { width: totalW, height: STEP_H + 8, style: { position: 'absolute', top: 0, left: 0, pointerEvents: 'none' } },
|
|
768
|
+
h('defs', null,
|
|
769
|
+
h('marker', { id: 'fc-arr', markerWidth: 6, markerHeight: 4, refX: 6, refY: 2, orient: 'auto' },
|
|
770
|
+
h('polygon', { points: '0 0, 6 2, 0 4', fill: 'rgba(99,102,241,0.5)' })
|
|
771
|
+
)
|
|
772
|
+
),
|
|
773
|
+
steps.map(function(step, i) {
|
|
774
|
+
if (i === steps.length - 1 || !step.arrow) return null;
|
|
775
|
+
var x1 = i * (STEP_W + STEP_GAP) + STEP_W;
|
|
776
|
+
var x2 = (i + 1) * (STEP_W + STEP_GAP);
|
|
777
|
+
var y = 4 + STEP_H / 2;
|
|
778
|
+
var arrowColor = DELEGATION_COLORS[step.arrow] || 'rgba(99,102,241,0.5)';
|
|
779
|
+
var nextStep = steps[i + 1];
|
|
780
|
+
var isFlowActive = step.status === 'in_progress' || (nextStep && nextStep.status === 'in_progress');
|
|
781
|
+
return h(Fragment, { key: 'a' + i },
|
|
782
|
+
h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: arrowColor + '88', strokeWidth: 2, markerEnd: 'url(#fc-arr)' }),
|
|
783
|
+
isFlowActive && h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: STATUS_COLORS.in_progress, strokeWidth: 2, strokeDasharray: '4 12', className: 'tp-flow-active', style: { opacity: 0.7 } }),
|
|
784
|
+
step.arrow !== 'assigned' && step.arrow !== 'delegation' && h('text', { x: (x1 + x2) / 2, y: y - 6, fill: arrowColor, fontSize: 8, textAnchor: 'middle', fontWeight: 600 }, step.arrow)
|
|
785
|
+
);
|
|
786
|
+
})
|
|
787
|
+
),
|
|
788
|
+
// Step nodes
|
|
789
|
+
steps.map(function(step, i) {
|
|
790
|
+
var x = i * (STEP_W + STEP_GAP);
|
|
791
|
+
var sc = step.type === 'terminal'
|
|
792
|
+
? (STATUS_COLORS[step.status] || '#22c55e')
|
|
793
|
+
: step.type === 'person' || step.isHuman
|
|
794
|
+
? '#f59e0b'
|
|
795
|
+
: step.status ? (STATUS_COLORS[step.status] || '#6366f1') : '#6366f1';
|
|
796
|
+
var isTerminal = step.type === 'terminal';
|
|
797
|
+
var isMe = step.taskId === expandedTaskId;
|
|
798
|
+
|
|
799
|
+
return h('div', {
|
|
800
|
+
key: i,
|
|
801
|
+
className: 'tp-node',
|
|
802
|
+
onClick: function(e) { e.stopPropagation(); if (step.taskId) { var ct = expandedChain.find(function(c) { return c.id === step.taskId; }); if (ct) openTaskDetail(ct); } },
|
|
803
|
+
style: {
|
|
804
|
+
position: 'absolute', left: x, top: 4, width: STEP_W, height: STEP_H,
|
|
805
|
+
background: isTerminal ? sc + '15' : isMe ? 'rgba(255,255,255,0.06)' : 'rgba(255,255,255,0.02)',
|
|
806
|
+
border: '1.5px solid ' + (isTerminal ? sc + '44' : isMe ? sc : 'rgba(255,255,255,0.1)'),
|
|
807
|
+
borderRadius: isTerminal ? 22 : 10,
|
|
808
|
+
display: 'flex', alignItems: 'center', gap: 8, padding: '0 10px',
|
|
809
|
+
cursor: step.taskId ? 'pointer' : 'default',
|
|
810
|
+
},
|
|
811
|
+
},
|
|
812
|
+
// Avatar
|
|
813
|
+
h('div', { style: {
|
|
814
|
+
width: 26, height: 26, borderRadius: '50%', flexShrink: 0,
|
|
815
|
+
background: isTerminal ? sc + '33' : step.isHuman || step.type === 'person' ? 'linear-gradient(135deg, #f59e0b, #f97316)' : step.type === 'system' ? 'rgba(255,255,255,0.1)' : 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
|
816
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
817
|
+
fontSize: isTerminal ? 12 : 10, fontWeight: 700,
|
|
818
|
+
color: isTerminal ? sc : '#fff',
|
|
819
|
+
border: '2px solid ' + (isTerminal ? sc + '44' : 'transparent'),
|
|
820
|
+
} },
|
|
821
|
+
isTerminal ? (step.status === 'completed' ? '\u2714' : step.status === 'failed' ? '\u2716' : '\u2716') : step.label.charAt(0).toUpperCase()
|
|
822
|
+
),
|
|
823
|
+
// Info
|
|
824
|
+
h('div', { style: { overflow: 'hidden', flex: 1, minWidth: 0 } },
|
|
825
|
+
h('div', { style: { fontSize: 11, fontWeight: 600, color: isTerminal ? sc : '#fff', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, step.label),
|
|
826
|
+
!isTerminal && h('div', { style: { fontSize: 9, color: 'rgba(255,255,255,0.35)', marginTop: 1 } },
|
|
827
|
+
step.type === 'person' || step.isHuman ? 'Human' : step.type === 'system' ? 'System' : 'Agent',
|
|
828
|
+
step.duration ? ' \u00B7 ' + formatDuration(step.duration) : '',
|
|
829
|
+
step.status === 'in_progress' && step.progress > 0 ? ' \u00B7 ' + step.progress + '%' : ''
|
|
830
|
+
)
|
|
831
|
+
)
|
|
832
|
+
);
|
|
833
|
+
})
|
|
834
|
+
)
|
|
835
|
+
)
|
|
836
|
+
);
|
|
837
|
+
})()
|
|
806
838
|
)
|
|
807
839
|
),
|
|
808
840
|
|
|
@@ -824,14 +856,6 @@ export function TaskPipelinePage() {
|
|
|
824
856
|
)
|
|
825
857
|
),
|
|
826
858
|
|
|
827
|
-
// Inline chain flowchart (shown when a task is clicked)
|
|
828
|
-
expandedChain && expandedChain.length > 0 && h(ChainFlowInline, {
|
|
829
|
-
chain: expandedChain,
|
|
830
|
-
taskId: expandedTaskId,
|
|
831
|
-
onClose: function() { setExpandedTaskId(null); },
|
|
832
|
-
onClickTask: function(t) { openTaskDetail(t); }
|
|
833
|
-
}),
|
|
834
|
-
|
|
835
859
|
// Detail modal (double-click)
|
|
836
860
|
selectedTask && h(TaskDetail, { task: selectedTask, chain: selectedChain, onClose: function() { setSelectedTask(null); setSelectedChain(null); }, onCancel: cancelTask })
|
|
837
861
|
);
|