@agenticmail/enterprise 0.5.212 → 0.5.214
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.
- package/dist/agent-heartbeat-3UMSZXRT.js +510 -0
- package/dist/chunk-3OWONOAJ.js +455 -0
- package/dist/chunk-IP5HZWZM.js +3685 -0
- package/dist/chunk-NJRHVKVY.js +4457 -0
- package/dist/chunk-QRRW3LES.js +1224 -0
- package/dist/cli-agent-L3ESGKPF.js +1719 -0
- package/dist/cli-serve-JH3BKW6F.js +114 -0
- package/dist/cli.js +3 -3
- package/dist/dashboard/pages/task-pipeline.js +167 -135
- package/dist/index.js +3 -3
- package/dist/routes-W7M2THQV.js +13050 -0
- package/dist/runtime-MNKA2HG6.js +45 -0
- package/dist/server-ZDEYMGB5.js +15 -0
- package/dist/setup-RWUGYHIU.js +20 -0
- package/package.json +1 -1
- package/src/dashboard/pages/task-pipeline.js +167 -135
- package/src/engine/task-queue-routes.ts +2 -2
- package/src/engine/task-queue.ts +30 -2
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentRuntime,
|
|
3
|
+
EmailChannel,
|
|
4
|
+
FollowUpScheduler,
|
|
5
|
+
SessionManager,
|
|
6
|
+
SubAgentManager,
|
|
7
|
+
ToolRegistry,
|
|
8
|
+
callLLM,
|
|
9
|
+
createAgentRuntime,
|
|
10
|
+
createNoopHooks,
|
|
11
|
+
createRuntimeHooks,
|
|
12
|
+
estimateMessageTokens,
|
|
13
|
+
estimateTokens,
|
|
14
|
+
executeTool,
|
|
15
|
+
runAgentLoop,
|
|
16
|
+
toolsToDefinitions
|
|
17
|
+
} from "./chunk-NJRHVKVY.js";
|
|
18
|
+
import {
|
|
19
|
+
PROVIDER_REGISTRY,
|
|
20
|
+
listAllProviders,
|
|
21
|
+
resolveApiKeyForProvider,
|
|
22
|
+
resolveProvider
|
|
23
|
+
} from "./chunk-UF3ZJMJO.js";
|
|
24
|
+
import "./chunk-KFQGP6VL.js";
|
|
25
|
+
export {
|
|
26
|
+
AgentRuntime,
|
|
27
|
+
EmailChannel,
|
|
28
|
+
FollowUpScheduler,
|
|
29
|
+
PROVIDER_REGISTRY,
|
|
30
|
+
SessionManager,
|
|
31
|
+
SubAgentManager,
|
|
32
|
+
ToolRegistry,
|
|
33
|
+
callLLM,
|
|
34
|
+
createAgentRuntime,
|
|
35
|
+
createNoopHooks,
|
|
36
|
+
createRuntimeHooks,
|
|
37
|
+
estimateMessageTokens,
|
|
38
|
+
estimateTokens,
|
|
39
|
+
executeTool,
|
|
40
|
+
listAllProviders,
|
|
41
|
+
resolveApiKeyForProvider,
|
|
42
|
+
resolveProvider,
|
|
43
|
+
runAgentLoop,
|
|
44
|
+
toolsToDefinitions
|
|
45
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createServer
|
|
3
|
+
} from "./chunk-IP5HZWZM.js";
|
|
4
|
+
import "./chunk-OF4MUWWS.js";
|
|
5
|
+
import "./chunk-UF3ZJMJO.js";
|
|
6
|
+
import "./chunk-3OC6RH7W.js";
|
|
7
|
+
import "./chunk-2DDKGTD6.js";
|
|
8
|
+
import "./chunk-YVK6F5OD.js";
|
|
9
|
+
import "./chunk-MKRNEM5A.js";
|
|
10
|
+
import "./chunk-DRXMYYKN.js";
|
|
11
|
+
import "./chunk-6WSX7QXF.js";
|
|
12
|
+
import "./chunk-KFQGP6VL.js";
|
|
13
|
+
export {
|
|
14
|
+
createServer
|
|
15
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
promptCompanyInfo,
|
|
3
|
+
promptDatabase,
|
|
4
|
+
promptDeployment,
|
|
5
|
+
promptDomain,
|
|
6
|
+
promptRegistration,
|
|
7
|
+
provision,
|
|
8
|
+
runSetupWizard
|
|
9
|
+
} from "./chunk-QRRW3LES.js";
|
|
10
|
+
import "./chunk-VQQ4SYYQ.js";
|
|
11
|
+
import "./chunk-KFQGP6VL.js";
|
|
12
|
+
export {
|
|
13
|
+
promptCompanyInfo,
|
|
14
|
+
promptDatabase,
|
|
15
|
+
promptDeployment,
|
|
16
|
+
promptDomain,
|
|
17
|
+
promptRegistration,
|
|
18
|
+
provision,
|
|
19
|
+
runSetupWizard
|
|
20
|
+
};
|
package/package.json
CHANGED
|
@@ -14,8 +14,10 @@ var PAD = 40;
|
|
|
14
14
|
var STATUS_COLORS = { created: '#6366f1', assigned: '#f59e0b', in_progress: '#06b6d4', completed: '#22c55e', failed: '#ef4444', cancelled: '#6b7394' };
|
|
15
15
|
var PRIORITY_COLORS = { urgent: '#ef4444', high: '#f59e0b', normal: '#6366f1', low: '#6b7394' };
|
|
16
16
|
var DELEGATION_COLORS = { delegation: '#6366f1', review: '#f59e0b', revision: '#f97316', escalation: '#ef4444', return: '#22c55e' };
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
// Theme-aware: use CSS variables where possible, detect dark/light
|
|
18
|
+
function isDark() { try { return window.matchMedia('(prefers-color-scheme: dark)').matches || document.documentElement.classList.contains('dark') || document.body.getAttribute('data-theme') === 'dark'; } catch(e) { return true; } }
|
|
19
|
+
var BG = 'var(--bg-canvas, var(--bg-primary, #0a0c14))';
|
|
20
|
+
var EDGE_COLOR = 'var(--tp-edge, rgba(128,128,128,0.25))';
|
|
19
21
|
var EDGE_HL = 'rgba(99,102,241,0.7)';
|
|
20
22
|
|
|
21
23
|
// ─── CSS Keyframes (injected once) ──────────────────────
|
|
@@ -24,13 +26,15 @@ function injectCSS() {
|
|
|
24
26
|
if (_injected) return; _injected = true;
|
|
25
27
|
var style = document.createElement('style');
|
|
26
28
|
style.textContent = `
|
|
29
|
+
:root { --tp-bg: #0a0c14; --tp-text: #fff; --tp-text-dim: rgba(255,255,255,0.4); --tp-text-faint: rgba(255,255,255,0.15); --tp-border: rgba(255,255,255,0.08); --tp-card: rgba(255,255,255,0.02); --tp-card-hover: rgba(255,255,255,0.06); --tp-edge: rgba(255,255,255,0.18); --tp-toolbar: rgba(0,0,0,0.3); --tp-metrics: rgba(0,0,0,0.12); }
|
|
30
|
+
[data-theme="light"], .light, :root:not(.dark) { --tp-bg: var(--bg-primary, #f8fafc); --tp-text: var(--text-primary, #1e293b); --tp-text-dim: var(--text-muted, #64748b); --tp-text-faint: rgba(0,0,0,0.06); --tp-border: var(--border, rgba(0,0,0,0.08)); --tp-card: rgba(0,0,0,0.02); --tp-card-hover: rgba(0,0,0,0.05); --tp-edge: rgba(0,0,0,0.2); --tp-toolbar: rgba(0,0,0,0.03); --tp-metrics: rgba(0,0,0,0.02); }
|
|
31
|
+
@media (prefers-color-scheme: light) { :root:not(.dark) { --tp-bg: var(--bg-primary, #f8fafc); --tp-text: var(--text-primary, #1e293b); --tp-text-dim: var(--text-muted, #64748b); --tp-text-faint: rgba(0,0,0,0.06); --tp-border: var(--border, rgba(0,0,0,0.08)); --tp-card: rgba(0,0,0,0.02); --tp-card-hover: rgba(0,0,0,0.05); --tp-edge: rgba(0,0,0,0.2); --tp-toolbar: rgba(0,0,0,0.03); --tp-metrics: rgba(0,0,0,0.02); } }
|
|
27
32
|
@keyframes flowDash { to { stroke-dashoffset: -24; } }
|
|
28
33
|
@keyframes flowPulse { 0%,100% { opacity: 0.4; } 50% { opacity: 1; } }
|
|
29
34
|
@keyframes taskPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(6,182,212,0.3); } 50% { box-shadow: 0 0 8px 2px rgba(6,182,212,0.2); } }
|
|
30
35
|
.tp-flow-active { animation: flowDash 1.2s linear infinite; }
|
|
31
36
|
.tp-node-active { animation: taskPulse 2s ease-in-out infinite; }
|
|
32
37
|
.tp-node:hover { transform: scale(1.03); z-index: 10; }
|
|
33
|
-
.tp-customer-badge { background: linear-gradient(135deg, #6366f1, #a855f7); color: #fff; font-size: 9px; padding: 1px 6px; border-radius: 8px; font-weight: 600; }
|
|
34
38
|
.tp-chain-tag { font-size: 9px; padding: 1px 5px; border-radius: 4px; font-weight: 600; letter-spacing: 0.02em; }
|
|
35
39
|
`;
|
|
36
40
|
document.head.appendChild(style);
|
|
@@ -173,13 +177,13 @@ function formatDuration(ms) {
|
|
|
173
177
|
function tag(color, text) { return h('span', { className: 'tp-chain-tag', style: { background: color + '22', color: color } }, text); }
|
|
174
178
|
|
|
175
179
|
var toolbarBtnStyle = {
|
|
176
|
-
background: '
|
|
177
|
-
borderRadius: 6, color: '
|
|
180
|
+
background: 'var(--tp-border)', border: '1px solid rgba(255,255,255,0.12)',
|
|
181
|
+
borderRadius: 6, color: 'var(--tp-text)', fontSize: 12, fontWeight: 600, padding: '4px 10px', cursor: 'pointer',
|
|
178
182
|
};
|
|
179
183
|
function legendDot(color, label) {
|
|
180
184
|
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
|
|
181
185
|
h('div', { style: { width: 8, height: 8, borderRadius: '50%', background: color } }),
|
|
182
|
-
h('span', { style: { color: '
|
|
186
|
+
h('span', { style: { color: 'var(--tp-text-dim)', fontSize: 11 } }, label)
|
|
183
187
|
);
|
|
184
188
|
}
|
|
185
189
|
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
@@ -191,10 +195,10 @@ function CustomerBadge(props) {
|
|
|
191
195
|
var c = props.customer;
|
|
192
196
|
if (!c) return null;
|
|
193
197
|
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, padding: '4px 8px', background: 'rgba(99,102,241,0.08)', border: '1px solid rgba(99,102,241,0.2)', borderRadius: 8, fontSize: 11, marginBottom: 4 } },
|
|
194
|
-
h('div', { style: { width: 20, height: 20, borderRadius: '50%', background: 'linear-gradient(135deg, #6366f1, #a855f7)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '
|
|
198
|
+
h('div', { style: { width: 20, height: 20, borderRadius: '50%', background: 'linear-gradient(135deg, #6366f1, #a855f7)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--tp-text)', fontSize: 9, fontWeight: 700, flexShrink: 0 } }, (c.name || '?').charAt(0).toUpperCase()),
|
|
195
199
|
h('div', { style: { overflow: 'hidden' } },
|
|
196
|
-
h('div', { style: { fontWeight: 600, color: '
|
|
197
|
-
h('div', { style: { color: '
|
|
200
|
+
h('div', { style: { fontWeight: 600, color: 'var(--tp-text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, c.name || 'Unknown'),
|
|
201
|
+
h('div', { style: { color: 'var(--tp-text-dim)', fontSize: 9 } },
|
|
198
202
|
c.isNew ? 'New customer' : (c.company || c.email || c.channel || '')
|
|
199
203
|
)
|
|
200
204
|
)
|
|
@@ -227,7 +231,7 @@ function TaskDetail(props) {
|
|
|
227
231
|
|
|
228
232
|
// Customer context
|
|
229
233
|
task.customerContext && h('div', { style: { padding: 12, background: 'rgba(99,102,241,0.06)', border: '1px solid rgba(99,102,241,0.15)', borderRadius: 'var(--radius)', marginBottom: 16 } },
|
|
230
|
-
h('div', { style: { fontSize: 11, fontWeight: 600, color: '
|
|
234
|
+
h('div', { style: { fontSize: 11, fontWeight: 600, color: 'var(--tp-text-dim)', marginBottom: 8 } }, 'CUSTOMER'),
|
|
231
235
|
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '6px 16px', fontSize: 13 } },
|
|
232
236
|
task.customerContext.name && h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Name'), h('div', null, task.customerContext.name)),
|
|
233
237
|
task.customerContext.email && h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Email'), h('div', null, task.customerContext.email)),
|
|
@@ -267,7 +271,7 @@ function TaskDetail(props) {
|
|
|
267
271
|
return h(Fragment, { key: ct.id },
|
|
268
272
|
i > 0 && h('div', { style: { display: 'flex', alignItems: 'center', flexShrink: 0 } },
|
|
269
273
|
h('div', { style: { width: 32, height: 2, background: (DELEGATION_COLORS[ct.delegationType] || '#6366f1') + '66' } }),
|
|
270
|
-
h('div', { style: { fontSize: 8, color: '
|
|
274
|
+
h('div', { style: { fontSize: 8, color: 'var(--tp-text-dim)', position: 'relative', top: -8 } }, ct.delegationType || '')
|
|
271
275
|
),
|
|
272
276
|
h('div', { style: {
|
|
273
277
|
padding: '6px 10px', borderRadius: 8, fontSize: 11, flexShrink: 0,
|
|
@@ -312,123 +316,39 @@ function TaskDetail(props) {
|
|
|
312
316
|
function MetricsBar(props) {
|
|
313
317
|
var s = props.stats;
|
|
314
318
|
function chip(label, value, color) {
|
|
315
|
-
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 4, padding: '3px 8px', background: '
|
|
316
|
-
h('span', { style: { fontSize: 10, color: '
|
|
319
|
+
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 4, padding: '3px 8px', background: 'var(--tp-card)', borderRadius: 6 } },
|
|
320
|
+
h('span', { style: { fontSize: 10, color: 'var(--tp-text-dim)' } }, label),
|
|
317
321
|
h('span', { style: { fontSize: 11, fontWeight: 700, color: color } }, value)
|
|
318
322
|
);
|
|
319
323
|
}
|
|
320
324
|
var hasActivity = s.total > 0;
|
|
321
325
|
|
|
322
|
-
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, padding: '6px 16px', borderBottom: '1px solid
|
|
323
|
-
h('span', { style: { fontSize: 9, color: '
|
|
326
|
+
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, padding: '6px 16px', borderBottom: '1px solid var(--tp-border)', background: 'var(--tp-metrics)', flexShrink: 0, overflowX: 'auto', fontSize: 11 } },
|
|
327
|
+
h('span', { style: { fontSize: 9, color: 'var(--tp-text-faint)', fontWeight: 600, letterSpacing: '0.06em', marginRight: 2 } }, 'TODAY'),
|
|
324
328
|
chip('Done', s.todayCompleted || 0, '#22c55e'),
|
|
325
329
|
chip('Active', s.inProgress || 0, '#06b6d4'),
|
|
326
330
|
chip('New', s.todayCreated || 0, '#f59e0b'),
|
|
327
331
|
s.todayFailed > 0 && chip('Failed', s.todayFailed, '#ef4444'),
|
|
328
|
-
hasActivity && h('div', { style: { width: 1, height: 14, background: '
|
|
329
|
-
hasActivity && h('span', { style: { fontSize: 9, color: '
|
|
332
|
+
hasActivity && h('div', { style: { width: 1, height: 14, background: 'var(--tp-border)' } }),
|
|
333
|
+
hasActivity && h('span', { style: { fontSize: 9, color: 'var(--tp-text-faint)', fontWeight: 600, letterSpacing: '0.06em' } }, 'ALL'),
|
|
330
334
|
hasActivity && chip('Total', s.total, 'rgba(255,255,255,0.6)'),
|
|
331
335
|
s.avgDurationMs > 0 && chip('Avg', formatDuration(s.avgDurationMs), '#fff'),
|
|
332
336
|
s.totalTokens > 0 && chip('Tokens', s.totalTokens > 999999 ? (s.totalTokens / 1000000).toFixed(1) + 'M' : s.totalTokens > 999 ? (s.totalTokens / 1000).toFixed(1) + 'K' : s.totalTokens, '#a855f7'),
|
|
333
337
|
s.totalCost > 0 && chip('Cost', '$' + s.totalCost.toFixed(2), '#22c55e'),
|
|
334
338
|
s.topAgents && s.topAgents.length > 0 && h(Fragment, null,
|
|
335
|
-
h('div', { style: { width: 1, height: 14, background: '
|
|
339
|
+
h('div', { style: { width: 1, height: 14, background: 'var(--tp-border)' } }),
|
|
336
340
|
s.topAgents.slice(0, 3).map(function(a) {
|
|
337
|
-
return h('div', { key: a.agent, style: { display: 'flex', alignItems: 'center', gap: 3, padding: '2px 6px', background: '
|
|
341
|
+
return h('div', { key: a.agent, style: { display: 'flex', alignItems: 'center', gap: 3, padding: '2px 6px', background: 'var(--tp-card)', borderRadius: 6 } },
|
|
338
342
|
h('div', { style: { width: 12, height: 12, borderRadius: '50%', background: '#6366f133', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 7, fontWeight: 700, color: '#6366f1' } }, (a.name || '?').charAt(0).toUpperCase()),
|
|
339
|
-
h('span', { style: { fontSize: 10, color: '
|
|
340
|
-
h('span', { style: { fontSize: 9, color: '
|
|
343
|
+
h('span', { style: { fontSize: 10, color: 'var(--tp-text)', fontWeight: 600 } }, a.name),
|
|
344
|
+
h('span', { style: { fontSize: 9, color: 'var(--tp-text-dim)' } }, a.completed + '/' + a.active)
|
|
341
345
|
);
|
|
342
346
|
})
|
|
343
347
|
)
|
|
344
348
|
);
|
|
345
349
|
}
|
|
346
350
|
|
|
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
|
-
}
|
|
351
|
+
// (ChainFlowInline removed — chain flow now renders inline on canvas)
|
|
432
352
|
|
|
433
353
|
// ─── Main Page ───────────────────────────────────────────
|
|
434
354
|
export function TaskPipelinePage() {
|
|
@@ -612,8 +532,8 @@ export function TaskPipelinePage() {
|
|
|
612
532
|
var hoveredNode = hoveredId ? nodes.find(function(n) { return n.id === hoveredId; }) : null;
|
|
613
533
|
|
|
614
534
|
// ─── Toolbar ─────────────────────────────────────────
|
|
615
|
-
var toolbar = h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, padding: '10px 16px', borderBottom: '1px solid
|
|
616
|
-
h('div', { style: { fontWeight: 700, fontSize: 14, color: '
|
|
535
|
+
var toolbar = h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, padding: '10px 16px', borderBottom: '1px solid var(--tp-border)', background: 'var(--tp-toolbar)', flexShrink: 0, flexWrap: 'wrap' } },
|
|
536
|
+
h('div', { style: { fontWeight: 700, fontSize: 14, color: 'var(--tp-text)', display: 'flex', alignItems: 'center', gap: 6 } },
|
|
617
537
|
I.workflow(), 'Task Pipeline',
|
|
618
538
|
h(HelpButton, { label: 'Task Pipeline' },
|
|
619
539
|
h('p', null, 'Visual flow of all agent tasks. Tasks flow left-to-right showing delegation chains, multi-agent handoffs, and circular review loops.'),
|
|
@@ -638,9 +558,9 @@ export function TaskPipelinePage() {
|
|
|
638
558
|
),
|
|
639
559
|
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
|
|
640
560
|
h('div', { style: { width: 8, height: 8, borderRadius: '50%', background: '#22c55e', animation: 'flowPulse 2s infinite' } }),
|
|
641
|
-
h('span', { style: { color: '
|
|
561
|
+
h('span', { style: { color: 'var(--tp-text-dim)', fontSize: 11 } }, 'Live')
|
|
642
562
|
),
|
|
643
|
-
h('div', { style: { color: '
|
|
563
|
+
h('div', { style: { color: 'var(--tp-text-dim)', fontSize: 11 } },
|
|
644
564
|
(stats.inProgress || 0) + ' active \u00B7 ' + (stats.completed || 0) + ' done \u00B7 ' + (stats.total || 0) + ' total'
|
|
645
565
|
),
|
|
646
566
|
h('div', { style: { flex: 1 } }),
|
|
@@ -654,7 +574,7 @@ export function TaskPipelinePage() {
|
|
|
654
574
|
legendDot(STATUS_COLORS.failed, 'Failed'),
|
|
655
575
|
h('div', { style: { width: 1, height: 14, background: 'rgba(255,255,255,0.12)' } }),
|
|
656
576
|
h('button', { onClick: function() { setZoom(function(z) { return Math.min(3, z + 0.2); }); }, style: toolbarBtnStyle }, '+'),
|
|
657
|
-
h('div', { style: { color: '
|
|
577
|
+
h('div', { style: { color: 'var(--tp-text-dim)', fontSize: 11, minWidth: 36, textAlign: 'center' } }, Math.round(zoom * 100) + '%'),
|
|
658
578
|
h('button', { onClick: function() { setZoom(function(z) { return Math.max(0.15, z - 0.2); }); }, style: toolbarBtnStyle }, '\u2212'),
|
|
659
579
|
h('button', { onClick: fitToView, style: toolbarBtnStyle }, 'Fit'),
|
|
660
580
|
h('button', { onClick: loadData, style: toolbarBtnStyle }, 'Refresh'),
|
|
@@ -662,13 +582,13 @@ export function TaskPipelinePage() {
|
|
|
662
582
|
|
|
663
583
|
if (loading) return h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)' } }, 'Loading task pipeline...');
|
|
664
584
|
|
|
665
|
-
if (nodes.length === 0) return h('div', { style: { height: '100%', display: 'flex', flexDirection: 'column', background:
|
|
585
|
+
if (nodes.length === 0) return h('div', { style: { height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--tp-bg)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' } },
|
|
666
586
|
toolbar,
|
|
667
587
|
h(MetricsBar, { stats: stats }),
|
|
668
588
|
h('div', { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column' } },
|
|
669
589
|
h('div', { style: { width: 48, height: 48, borderRadius: 12, background: 'rgba(99,102,241,0.1)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16, color: '#6366f1' } }, I.workflow()),
|
|
670
|
-
h('div', { style: { fontSize: 16, fontWeight: 600, marginBottom: 6, color: '
|
|
671
|
-
h('div', { style: { color: '
|
|
590
|
+
h('div', { style: { fontSize: 16, fontWeight: 600, marginBottom: 6, color: 'var(--tp-text)' } }, 'No Tasks in Pipeline'),
|
|
591
|
+
h('div', { style: { color: 'var(--tp-text-dim)', fontSize: 13 } }, 'Tasks will appear here as agents are assigned work.')
|
|
672
592
|
)
|
|
673
593
|
);
|
|
674
594
|
|
|
@@ -684,7 +604,7 @@ export function TaskPipelinePage() {
|
|
|
684
604
|
}
|
|
685
605
|
}
|
|
686
606
|
|
|
687
|
-
return h('div', { style: { height: '100%', display: 'flex', flexDirection: 'column', background:
|
|
607
|
+
return h('div', { style: { height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--tp-bg)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' } },
|
|
688
608
|
toolbar,
|
|
689
609
|
// Metrics bar
|
|
690
610
|
h(MetricsBar, { stats: stats }),
|
|
@@ -699,7 +619,7 @@ export function TaskPipelinePage() {
|
|
|
699
619
|
|
|
700
620
|
// Chain labels (left side)
|
|
701
621
|
chainInfos.map(function(ci, i) {
|
|
702
|
-
return h('div', { key: ci.chainId, style: { position: 'absolute', left: 4, top: ci.y - 2, fontSize: 9, color: '
|
|
622
|
+
return h('div', { key: ci.chainId, style: { position: 'absolute', left: 4, top: ci.y - 2, fontSize: 9, color: 'var(--tp-text-faint)', fontFamily: 'var(--font-mono)', letterSpacing: '0.04em', maxWidth: PAD - 8, overflow: 'hidden' } },
|
|
703
623
|
ci.customer && h(CustomerBadge, { customer: ci.customer })
|
|
704
624
|
);
|
|
705
625
|
}),
|
|
@@ -788,21 +708,141 @@ export function TaskPipelinePage() {
|
|
|
788
708
|
h('div', { style: { width: 18, height: 18, borderRadius: '50%', background: sc + '33', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 8, fontWeight: 700, color: sc, flexShrink: 0, border: '1px solid ' + sc + '44' } },
|
|
789
709
|
(t.assignedToName || t.assignedTo || '?').charAt(0).toUpperCase()
|
|
790
710
|
),
|
|
791
|
-
h('span', { style: { fontSize: 11, fontWeight: 600, color: '
|
|
711
|
+
h('span', { style: { fontSize: 11, fontWeight: 600, color: 'var(--tp-text)', flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, t.title)
|
|
792
712
|
),
|
|
793
713
|
// Status + agent name + time
|
|
794
714
|
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4, flexWrap: 'wrap' } },
|
|
795
715
|
tag(sc, t.status.replace('_', ' ')),
|
|
796
|
-
h('span', { style: { fontSize: 9, color: '
|
|
716
|
+
h('span', { style: { fontSize: 9, color: 'var(--tp-text-dim)' } }, t.assignedToName || t.assignedTo),
|
|
797
717
|
t.delegationType && tag(DELEGATION_COLORS[t.delegationType] || '#6b7394', t.delegationType),
|
|
798
|
-
h('span', { style: { fontSize: 9, color: '
|
|
718
|
+
h('span', { style: { fontSize: 9, color: 'var(--tp-text-dim)', marginLeft: 'auto' } }, timeAgo(t.createdAt))
|
|
799
719
|
),
|
|
800
720
|
// Progress bar
|
|
801
|
-
isActive && t.progress > 0 && h('div', { style: { height: 2, background: '
|
|
721
|
+
isActive && t.progress > 0 && h('div', { style: { height: 2, background: 'var(--tp-border)', borderRadius: 1, overflow: 'hidden', marginTop: 1 } },
|
|
802
722
|
h('div', { style: { height: '100%', width: t.progress + '%', background: sc, borderRadius: 1, transition: 'width 0.3s' } })
|
|
803
723
|
)
|
|
804
724
|
);
|
|
805
|
-
})
|
|
725
|
+
}),
|
|
726
|
+
|
|
727
|
+
// ── Expanded chain flow (rendered ON the canvas below clicked node) ──
|
|
728
|
+
expandedChain && expandedChain.length > 0 && (function() {
|
|
729
|
+
// Find the clicked node position to anchor below it
|
|
730
|
+
var anchor = nodes.find(function(n) { return n.id === expandedTaskId; });
|
|
731
|
+
if (!anchor) return null;
|
|
732
|
+
var flowY = anchor.y + anchor.h + 20;
|
|
733
|
+
var flowX = anchor.x;
|
|
734
|
+
var STEP_W = 120;
|
|
735
|
+
var STEP_H = 44;
|
|
736
|
+
var STEP_GAP = 48;
|
|
737
|
+
var ARROW_W = STEP_GAP;
|
|
738
|
+
|
|
739
|
+
// Build person-centric flow steps: createdBy → assignedTo for each chain task, then final status
|
|
740
|
+
var steps = [];
|
|
741
|
+
expandedChain.forEach(function(ct, i) {
|
|
742
|
+
if (i === 0 && ct.createdBy && ct.createdBy !== 'system') {
|
|
743
|
+
steps.push({ label: ct.createdByName || ct.createdBy, type: 'person', isHuman: ct.createdBy.indexOf('agent') === -1 && ct.createdBy !== 'system', status: null, arrow: ct.delegationType || 'assigned' });
|
|
744
|
+
} else if (i === 0 && ct.createdBy === 'system') {
|
|
745
|
+
steps.push({ label: 'System', type: 'system', isHuman: false, status: null, arrow: 'assigned' });
|
|
746
|
+
}
|
|
747
|
+
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 });
|
|
748
|
+
});
|
|
749
|
+
// Add final status node
|
|
750
|
+
var lastTask = expandedChain[expandedChain.length - 1];
|
|
751
|
+
var isDone = lastTask.status === 'completed' || lastTask.status === 'failed' || lastTask.status === 'cancelled';
|
|
752
|
+
if (isDone) {
|
|
753
|
+
steps.push({ label: lastTask.status === 'completed' ? 'Completed!' : lastTask.status === 'failed' ? 'Failed' : 'Cancelled', type: 'terminal', isHuman: false, status: lastTask.status, arrow: null });
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
var totalW = steps.length * STEP_W + (steps.length - 1) * STEP_GAP;
|
|
757
|
+
|
|
758
|
+
var maxFlowW = Math.max(totalW + 40, 400);
|
|
759
|
+
var containerW = (containerRef.current ? containerRef.current.getBoundingClientRect().width / zoom : 800) - flowX;
|
|
760
|
+
if (maxFlowW > containerW) maxFlowW = Math.max(containerW, 320);
|
|
761
|
+
|
|
762
|
+
return h('div', { style: { position: 'absolute', left: flowX, top: flowY, pointerEvents: 'auto', maxWidth: maxFlowW, zIndex: 20 } },
|
|
763
|
+
// Background card
|
|
764
|
+
h('div', { style: { background: 'var(--bg-primary, rgba(10,12,20,0.95))', border: '1px solid rgba(99,102,241,0.2)', borderRadius: 12, padding: '14px 16px 12px', backdropFilter: 'blur(8px)', overflowX: 'auto', overflowY: 'hidden' } },
|
|
765
|
+
// Header
|
|
766
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 } },
|
|
767
|
+
h('span', { style: { fontSize: 10, fontWeight: 600, color: 'var(--tp-text-dim)', letterSpacing: '0.06em' } }, 'TASK FLOW'),
|
|
768
|
+
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)),
|
|
769
|
+
h('div', { style: { flex: 1 } }),
|
|
770
|
+
h('button', { className: 'tp-node', onClick: function() { setExpandedTaskId(null); }, style: { background: 'none', border: 'none', color: 'var(--tp-text-dim)', cursor: 'pointer', fontSize: 14, padding: '0 2px' } }, '\u00D7')
|
|
771
|
+
),
|
|
772
|
+
// Flow
|
|
773
|
+
h('div', { style: { position: 'relative', height: STEP_H + 8, minWidth: totalW } },
|
|
774
|
+
// SVG arrows
|
|
775
|
+
h('svg', { width: totalW, height: STEP_H + 8, style: { position: 'absolute', top: 0, left: 0, pointerEvents: 'none' } },
|
|
776
|
+
h('defs', null,
|
|
777
|
+
h('marker', { id: 'fc-arr', markerWidth: 6, markerHeight: 4, refX: 6, refY: 2, orient: 'auto' },
|
|
778
|
+
h('polygon', { points: '0 0, 6 2, 0 4', fill: 'rgba(99,102,241,0.5)' })
|
|
779
|
+
)
|
|
780
|
+
),
|
|
781
|
+
steps.map(function(step, i) {
|
|
782
|
+
if (i === steps.length - 1 || !step.arrow) return null;
|
|
783
|
+
var x1 = i * (STEP_W + STEP_GAP) + STEP_W;
|
|
784
|
+
var x2 = (i + 1) * (STEP_W + STEP_GAP);
|
|
785
|
+
var y = 4 + STEP_H / 2;
|
|
786
|
+
var arrowColor = DELEGATION_COLORS[step.arrow] || 'rgba(99,102,241,0.5)';
|
|
787
|
+
var nextStep = steps[i + 1];
|
|
788
|
+
var isFlowActive = step.status === 'in_progress' || (nextStep && nextStep.status === 'in_progress');
|
|
789
|
+
return h(Fragment, { key: 'a' + i },
|
|
790
|
+
h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: arrowColor + '88', strokeWidth: 2, markerEnd: 'url(#fc-arr)' }),
|
|
791
|
+
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 } }),
|
|
792
|
+
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)
|
|
793
|
+
);
|
|
794
|
+
})
|
|
795
|
+
),
|
|
796
|
+
// Step nodes
|
|
797
|
+
steps.map(function(step, i) {
|
|
798
|
+
var x = i * (STEP_W + STEP_GAP);
|
|
799
|
+
var sc = step.type === 'terminal'
|
|
800
|
+
? (STATUS_COLORS[step.status] || '#22c55e')
|
|
801
|
+
: step.type === 'person' || step.isHuman
|
|
802
|
+
? '#f59e0b'
|
|
803
|
+
: step.status ? (STATUS_COLORS[step.status] || '#6366f1') : '#6366f1';
|
|
804
|
+
var isTerminal = step.type === 'terminal';
|
|
805
|
+
var isMe = step.taskId === expandedTaskId;
|
|
806
|
+
|
|
807
|
+
return h('div', {
|
|
808
|
+
key: i,
|
|
809
|
+
className: 'tp-node',
|
|
810
|
+
onClick: function(e) { e.stopPropagation(); if (step.taskId) { var ct = expandedChain.find(function(c) { return c.id === step.taskId; }); if (ct) openTaskDetail(ct); } },
|
|
811
|
+
style: {
|
|
812
|
+
position: 'absolute', left: x, top: 4, width: STEP_W, height: STEP_H,
|
|
813
|
+
background: isTerminal ? sc + '15' : isMe ? 'rgba(255,255,255,0.06)' : 'rgba(255,255,255,0.02)',
|
|
814
|
+
border: '1.5px solid ' + (isTerminal ? sc + '44' : isMe ? sc : 'rgba(255,255,255,0.1)'),
|
|
815
|
+
borderRadius: isTerminal ? 22 : 10,
|
|
816
|
+
display: 'flex', alignItems: 'center', gap: 8, padding: '0 10px',
|
|
817
|
+
cursor: step.taskId ? 'pointer' : 'default',
|
|
818
|
+
},
|
|
819
|
+
},
|
|
820
|
+
// Avatar
|
|
821
|
+
h('div', { style: {
|
|
822
|
+
width: 26, height: 26, borderRadius: '50%', flexShrink: 0,
|
|
823
|
+
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)',
|
|
824
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
825
|
+
fontSize: isTerminal ? 12 : 10, fontWeight: 700,
|
|
826
|
+
color: isTerminal ? sc : '#fff',
|
|
827
|
+
border: '2px solid ' + (isTerminal ? sc + '44' : 'transparent'),
|
|
828
|
+
} },
|
|
829
|
+
isTerminal ? (step.status === 'completed' ? '\u2714' : step.status === 'failed' ? '\u2716' : '\u2716') : step.label.charAt(0).toUpperCase()
|
|
830
|
+
),
|
|
831
|
+
// Info
|
|
832
|
+
h('div', { style: { overflow: 'hidden', flex: 1, minWidth: 0 } },
|
|
833
|
+
h('div', { style: { fontSize: 11, fontWeight: 600, color: isTerminal ? sc : '#fff', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, step.label),
|
|
834
|
+
!isTerminal && h('div', { style: { fontSize: 9, color: 'var(--tp-text-dim)', marginTop: 1 } },
|
|
835
|
+
step.type === 'person' || step.isHuman ? 'Human' : step.type === 'system' ? 'System' : 'Agent',
|
|
836
|
+
step.duration ? ' \u00B7 ' + formatDuration(step.duration) : '',
|
|
837
|
+
step.status === 'in_progress' && step.progress > 0 ? ' \u00B7 ' + step.progress + '%' : ''
|
|
838
|
+
)
|
|
839
|
+
)
|
|
840
|
+
);
|
|
841
|
+
})
|
|
842
|
+
)
|
|
843
|
+
)
|
|
844
|
+
);
|
|
845
|
+
})()
|
|
806
846
|
)
|
|
807
847
|
),
|
|
808
848
|
|
|
@@ -814,24 +854,16 @@ export function TaskPipelinePage() {
|
|
|
814
854
|
padding: '10px 14px', pointerEvents: 'none', zIndex: 1000, minWidth: 180, maxWidth: 280,
|
|
815
855
|
}},
|
|
816
856
|
hoveredNode.task.customerContext && h(CustomerBadge, { customer: hoveredNode.task.customerContext }),
|
|
817
|
-
h('div', { style: { fontSize: 12, fontWeight: 600, color: '
|
|
857
|
+
h('div', { style: { fontSize: 12, fontWeight: 600, color: 'var(--tp-text)', marginBottom: 6 } }, hoveredNode.task.title),
|
|
818
858
|
h('div', { style: { display: 'flex', flexDirection: 'column', gap: 3, fontSize: 11 } },
|
|
819
|
-
h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: '
|
|
820
|
-
h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: '
|
|
821
|
-
hoveredNode.task.chainId && h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: '
|
|
822
|
-
hoveredNode.task.delegationType && h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: '
|
|
823
|
-
hoveredNode.task.progress > 0 && h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: '
|
|
859
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: 'var(--tp-text-dim)' } }, 'Agent'), h('span', { style: { fontWeight: 600 } }, hoveredNode.task.assignedToName || '-')),
|
|
860
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: 'var(--tp-text-dim)' } }, 'Status'), h('span', { style: { color: STATUS_COLORS[hoveredNode.task.status] } }, hoveredNode.task.status.replace('_', ' '))),
|
|
861
|
+
hoveredNode.task.chainId && h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: 'var(--tp-text-dim)' } }, 'Chain Step'), h('span', null, '#' + ((hoveredNode.task.chainSeq || 0) + 1))),
|
|
862
|
+
hoveredNode.task.delegationType && h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: 'var(--tp-text-dim)' } }, 'Type'), h('span', { style: { color: DELEGATION_COLORS[hoveredNode.task.delegationType] } }, hoveredNode.task.delegationType)),
|
|
863
|
+
hoveredNode.task.progress > 0 && h('div', { style: { display: 'flex', justifyContent: 'space-between' } }, h('span', { style: { color: 'var(--tp-text-dim)' } }, 'Progress'), h('span', { style: { color: STATUS_COLORS.in_progress } }, hoveredNode.task.progress + '%'))
|
|
824
864
|
)
|
|
825
865
|
),
|
|
826
866
|
|
|
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
867
|
// Detail modal (double-click)
|
|
836
868
|
selectedTask && h(TaskDetail, { task: selectedTask, chain: selectedChain, onClose: function() { setSelectedTask(null); setSelectedChain(null); }, onCancel: cancelTask })
|
|
837
869
|
);
|
|
@@ -28,9 +28,9 @@ export function createTaskQueueRoutes(taskQueue: TaskQueueManager) {
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
// GET /task-pipeline/stats — pipeline statistics
|
|
31
|
-
router.get('/stats', (c) => {
|
|
31
|
+
router.get('/stats', async (c) => {
|
|
32
32
|
const orgId = c.req.query('orgId') || '';
|
|
33
|
-
const stats = taskQueue.getPipelineStats(orgId);
|
|
33
|
+
const stats = await taskQueue.getPipelineStats(orgId);
|
|
34
34
|
return c.json(stats);
|
|
35
35
|
});
|
|
36
36
|
|
package/src/engine/task-queue.ts
CHANGED
|
@@ -385,11 +385,11 @@ export class TaskQueueManager {
|
|
|
385
385
|
return this.getAllTasks(orgId, limit);
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
-
getPipelineStats(orgId?: string): {
|
|
388
|
+
async getPipelineStats(orgId?: string): Promise<{
|
|
389
389
|
created: number; assigned: number; inProgress: number; completed: number; failed: number; cancelled: number; total: number;
|
|
390
390
|
todayCompleted: number; todayFailed: number; todayCreated: number; avgDurationMs: number; totalCost: number; totalTokens: number;
|
|
391
391
|
topAgents: Array<{ agent: string; name: string; completed: number; active: number }>;
|
|
392
|
-
} {
|
|
392
|
+
}> {
|
|
393
393
|
const stats = {
|
|
394
394
|
created: 0, assigned: 0, inProgress: 0, completed: 0, failed: 0, cancelled: 0, total: 0,
|
|
395
395
|
todayCompleted: 0, todayFailed: 0, todayCreated: 0, avgDurationMs: 0, totalCost: 0, totalTokens: 0,
|
|
@@ -434,6 +434,34 @@ export class TaskQueueManager {
|
|
|
434
434
|
.map(([agent, d]) => ({ agent, ...d }))
|
|
435
435
|
.sort((a, b) => (b.completed + b.active) - (a.completed + a.active))
|
|
436
436
|
.slice(0, 5);
|
|
437
|
+
|
|
438
|
+
// If DB available, also query today's stats from DB to catch anything not in memory
|
|
439
|
+
if (this.db) {
|
|
440
|
+
try {
|
|
441
|
+
const todayISO = todayStart.toISOString();
|
|
442
|
+
const dbToday = await this.db.get(
|
|
443
|
+
`SELECT COUNT(*) FILTER (WHERE status='completed' AND completed_at >= ?) as dc,
|
|
444
|
+
COUNT(*) FILTER (WHERE status='failed' AND completed_at >= ?) as df,
|
|
445
|
+
COUNT(*) FILTER (WHERE created_at >= ?) as dn
|
|
446
|
+
FROM task_pipeline` + (orgId ? ` WHERE org_id = ?` : ''),
|
|
447
|
+
orgId ? [todayISO, todayISO, todayISO, orgId] : [todayISO, todayISO, todayISO]
|
|
448
|
+
).catch(() => null);
|
|
449
|
+
// Postgres FILTER may not work on all DBs, fallback to separate counts
|
|
450
|
+
if (!dbToday || dbToday.dc === undefined) {
|
|
451
|
+
const r1 = await this.db.get(`SELECT COUNT(*) as c FROM task_pipeline WHERE status='completed' AND completed_at >= ?`, [todayISO]).catch(() => null);
|
|
452
|
+
const r2 = await this.db.get(`SELECT COUNT(*) as c FROM task_pipeline WHERE status='failed' AND completed_at >= ?`, [todayISO]).catch(() => null);
|
|
453
|
+
const r3 = await this.db.get(`SELECT COUNT(*) as c FROM task_pipeline WHERE created_at >= ?`, [todayISO]).catch(() => null);
|
|
454
|
+
if (r1?.c > stats.todayCompleted) stats.todayCompleted = r1.c;
|
|
455
|
+
if (r2?.c > stats.todayFailed) stats.todayFailed = r2.c;
|
|
456
|
+
if (r3?.c > stats.todayCreated) stats.todayCreated = r3.c;
|
|
457
|
+
} else {
|
|
458
|
+
if (dbToday.dc > stats.todayCompleted) stats.todayCompleted = dbToday.dc;
|
|
459
|
+
if (dbToday.df > stats.todayFailed) stats.todayFailed = dbToday.df;
|
|
460
|
+
if (dbToday.dn > stats.todayCreated) stats.todayCreated = dbToday.dn;
|
|
461
|
+
}
|
|
462
|
+
} catch { /* ignore — in-memory stats are fine */ }
|
|
463
|
+
}
|
|
464
|
+
|
|
437
465
|
return stats;
|
|
438
466
|
}
|
|
439
467
|
|