@agenticmail/enterprise 0.5.319 → 0.5.321
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/CHANGELOG.md +68 -0
- package/CODE_OF_CONDUCT.md +31 -0
- package/README.md +118 -38
- package/SECURITY.md +42 -0
- package/dist/agent-heartbeat-3FWNHZFX.js +510 -0
- package/dist/agent-heartbeat-4RWHZR7H.js +510 -0
- package/dist/agent-heartbeat-6ZGB5ILY.js +510 -0
- package/dist/agent-heartbeat-BIVHLKFM.js +510 -0
- package/dist/agent-heartbeat-HRKVFK2T.js +510 -0
- package/dist/agent-heartbeat-JC5GWVXD.js +510 -0
- package/dist/agent-heartbeat-K6A4HMHB.js +510 -0
- package/dist/agent-heartbeat-LCDXWFVB.js +510 -0
- package/dist/agent-heartbeat-P7HZCZAQ.js +510 -0
- package/dist/agent-heartbeat-PUIRSNIO.js +510 -0
- package/dist/agent-heartbeat-SN5ILQ6Y.js +510 -0
- package/dist/agent-heartbeat-TW5YTDYC.js +510 -0
- package/dist/agent-heartbeat-Z2QQXROL.js +510 -0
- package/dist/agent-notify-OEQBCZLN.js +43 -0
- package/dist/{agent-tools-263HM5QU.js → agent-tools-3W7XLUYA.js} +1 -1
- package/dist/agent-tools-4QK7LLNP.js +9 -0
- package/dist/agent-tools-54VZGT6L.js +9 -0
- package/dist/{agent-tools-AT4D276V.js → agent-tools-AYYDPO27.js} +7 -7
- package/dist/{agent-tools-MSTAPX2I.js → agent-tools-F2X47FKF.js} +7 -7
- package/dist/{agent-tools-FA26SY5O.js → agent-tools-O6W3QAZL.js} +11 -6
- package/dist/agent-tools-OAWVZBMW.js +9 -0
- package/dist/agent-tools-QCCU74PN.js +13949 -0
- package/dist/chunk-2LHUARN6.js +4929 -0
- package/dist/chunk-2WVCNCYC.js +5087 -0
- package/dist/{chunk-6PWDS7KY.js → chunk-3FM6YQUK.js} +20 -20
- package/dist/chunk-3UAFHUEC.js +212 -0
- package/dist/{chunk-WJO57PMO.js → chunk-46GOWZT4.js} +20 -20
- package/dist/{chunk-BNRE7TSX.js → chunk-5KYJAUZV.js} +3 -3
- package/dist/chunk-6C5PKREN.js +467 -0
- package/dist/{chunk-447MTPZF.js → chunk-6ZMLNEHB.js} +3 -3
- package/dist/chunk-BPZQT5N5.js +25652 -0
- package/dist/chunk-BQM7MBPS.js +1380 -0
- package/dist/{chunk-ZRFKGPIU.js → chunk-C52OQNNY.js} +20 -20
- package/dist/chunk-C7HGQF4Y.js +25652 -0
- package/dist/chunk-CAHNZGGK.js +25656 -0
- package/dist/{chunk-FL3CH3ET.js → chunk-CK7R6UHE.js} +51 -27
- package/dist/chunk-D36RPWB7.js +25652 -0
- package/dist/{chunk-36NM2B4C.js → chunk-DJK2UPFH.js} +63 -93
- package/dist/chunk-DM7FTF7W.js +4929 -0
- package/dist/chunk-DMD24UFZ.js +5101 -0
- package/dist/{chunk-36XNMIHA.js → chunk-DXZGPUAF.js} +20 -20
- package/dist/chunk-F46WB5IL.js +5087 -0
- package/dist/chunk-F5QG5SQH.js +5087 -0
- package/dist/{chunk-JGEVQZDR.js → chunk-FLQ5FLHW.js} +13 -16
- package/dist/chunk-H7GP733U.js +5087 -0
- package/dist/{chunk-OZSQLOV6.js → chunk-HHBXWB5U.js} +415 -19
- package/dist/{chunk-D24JY75H.js → chunk-IMXS4N6W.js} +3 -3
- package/dist/{chunk-6PVBV6ZP.js → chunk-JNMDD7JY.js} +3 -3
- package/dist/chunk-JTV5LA47.js +1519 -0
- package/dist/chunk-KV6G7NZX.js +1519 -0
- package/dist/chunk-MU5MEBIK.js +1519 -0
- package/dist/chunk-NLT5MC7X.js +465 -0
- package/dist/{chunk-GTFZZUXX.js → chunk-NVLYIM4J.js} +51 -27
- package/dist/{chunk-6G5SXLXC.js → chunk-NZY2BIZH.js} +63 -93
- package/dist/chunk-O42L6G67.js +1519 -0
- package/dist/chunk-OCNERGGM.js +4891 -0
- package/dist/chunk-OJSNHONE.js +1519 -0
- package/dist/{chunk-2TAZJWJN.js → chunk-OWL3QVH7.js} +18 -0
- package/dist/{chunk-P3HVY2HS.js → chunk-OWTLNV4Q.js} +382 -7
- package/dist/chunk-PCNYEP6T.js +4891 -0
- package/dist/{chunk-YL3Z5KPR.js → chunk-PI4AQ4Z6.js} +438 -15
- package/dist/chunk-PN3EGTCA.js +194 -0
- package/dist/chunk-Q37UKNRC.js +1519 -0
- package/dist/chunk-QXTC6J7H.js +5087 -0
- package/dist/{chunk-SPBQVNDI.js → chunk-RKERL5LZ.js} +25 -21
- package/dist/chunk-RVBK2IOX.js +25652 -0
- package/dist/chunk-SAKODCZ5.js +4891 -0
- package/dist/{chunk-XV4TU65E.js → chunk-SALGFC5L.js} +51 -27
- package/dist/chunk-STGWZ2MS.js +1519 -0
- package/dist/chunk-UY3ZVQDP.js +25652 -0
- package/dist/chunk-V6OSD62M.js +5087 -0
- package/dist/chunk-VP6YAHX4.js +1519 -0
- package/dist/chunk-WDYJOEAI.js +5087 -0
- package/dist/chunk-WEAFQNOS.js +195 -0
- package/dist/chunk-XKUSAZGP.js +5087 -0
- package/dist/chunk-Z6K5FKAB.js +548 -0
- package/dist/chunk-ZGE3XAXY.js +1519 -0
- package/dist/chunk-ZGYVXYQQ.js +3296 -0
- package/dist/cli-agent-7TB2BWS6.js +2370 -0
- package/dist/cli-agent-AKXFFST2.js +2370 -0
- package/dist/cli-agent-DZTKLITB.js +2357 -0
- package/dist/cli-agent-FOF7PFEP.js +2357 -0
- package/dist/cli-agent-H74M2ZYN.js +2357 -0
- package/dist/cli-agent-HORWVPHB.js +2370 -0
- package/dist/cli-agent-HSZT6SKF.js +2423 -0
- package/dist/cli-agent-JLUQ4ZU6.js +2424 -0
- package/dist/cli-agent-MVCDH4HV.js +2370 -0
- package/dist/cli-agent-NZXOEPJ2.js +2357 -0
- package/dist/cli-agent-PADN3QRC.js +2357 -0
- package/dist/cli-agent-QAYEX3BE.js +2441 -0
- package/dist/cli-agent-QT64DT5J.js +2370 -0
- package/dist/cli-agent-TFL2M6UK.js +2424 -0
- package/dist/cli-agent-UIKXATTD.js +2357 -0
- package/dist/cli-agent-UJN6FYTO.js +2370 -0
- package/dist/cli-agent-VIQAYVY4.js +2357 -0
- package/dist/cli-agent-WNWFVOFM.js +2370 -0
- package/dist/cli-agent-XBQX67VJ.js +2423 -0
- package/dist/cli-agent-ZLSC6FF4.js +2357 -0
- package/dist/cli-serve-2IL5DTEY.js +153 -0
- package/dist/cli-serve-47N5UKKW.js +153 -0
- package/dist/cli-serve-4XGZFUV2.js +140 -0
- package/dist/cli-serve-6OT3UEAN.js +140 -0
- package/dist/cli-serve-7L6EY5UH.js +153 -0
- package/dist/cli-serve-BDGOOOKQ.js +260 -0
- package/dist/cli-serve-BFNIW2LF.js +153 -0
- package/dist/cli-serve-C7MN6U5Q.js +153 -0
- package/dist/cli-serve-CR3OY3IM.js +153 -0
- package/dist/cli-serve-DAJFRWQ7.js +153 -0
- package/dist/cli-serve-FW6FHFW4.js +153 -0
- package/dist/cli-serve-GEEOQS77.js +153 -0
- package/dist/cli-serve-H562I3ZK.js +153 -0
- package/dist/cli-serve-HDQZF4C4.js +153 -0
- package/dist/cli-serve-LICAOMEB.js +140 -0
- package/dist/cli-serve-LLGYLWFS.js +153 -0
- package/dist/cli-serve-N3OISDNB.js +153 -0
- package/dist/cli-serve-TIZ27EVR.js +153 -0
- package/dist/cli-serve-TUNI2RCN.js +153 -0
- package/dist/cli-serve-WNOZMAWD.js +153 -0
- package/dist/cli-validate-Z726VJCN.js +150 -0
- package/dist/cli.js +4 -4
- package/dist/connection-manager-KAWEUWUR.js +9 -0
- package/dist/dashboard/app.js +9 -3
- package/dist/dashboard/components/knowledge-link.js +15 -0
- package/dist/dashboard/components/settings-help.js +4 -2
- package/dist/dashboard/docs/agent-deployment.html +33 -1
- package/dist/dashboard/docs/settings-network.html +321 -0
- package/dist/dashboard/docs/settings-security.html +347 -0
- package/dist/dashboard/docs/settings-tool-security.html +176 -0
- package/dist/dashboard/docs/settings.html +36 -16
- package/dist/dashboard/pages/agent-detail/deployment.js +39 -6
- package/dist/dashboard/pages/agent-detail/tools.js +10 -0
- package/dist/dashboard/pages/database-access.js +4 -3
- package/dist/dashboard/pages/settings.js +174 -37
- package/dist/dashboard/pages/task-pipeline.js +400 -843
- package/dist/db-adapter-2T56ORSD.js +7 -0
- package/dist/db-adapter-IRHOUMVC.js +7 -0
- package/dist/index.js +41 -41
- package/dist/microsoft-VREAZ7M2.js +3955 -0
- package/dist/routes-3MMLQTB6.js +90 -0
- package/dist/routes-4ZUIJ4HE.js +90 -0
- package/dist/routes-5MXHKKH4.js +90 -0
- package/dist/routes-64NJFK3B.js +90 -0
- package/dist/routes-6AKQ2LBV.js +90 -0
- package/dist/routes-CRRBUDO4.js +90 -0
- package/dist/routes-DIAF3MC3.js +90 -0
- package/dist/routes-KMUNU6CY.js +90 -0
- package/dist/routes-LRRLXIZR.js +90 -0
- package/dist/routes-N647AJYG.js +90 -0
- package/dist/routes-SSSELAAR.js +90 -0
- package/dist/routes-STERVGKJ.js +90 -0
- package/dist/routes-ZEZZACZP.js +90 -0
- package/dist/runtime-5EQN4GFM.js +45 -0
- package/dist/runtime-5LP7PUD4.js +45 -0
- package/dist/runtime-6BULDBR3.js +45 -0
- package/dist/runtime-6YEENDN3.js +45 -0
- package/dist/runtime-7LQFRG3B.js +45 -0
- package/dist/runtime-AMXJU2MB.js +45 -0
- package/dist/runtime-D6WSE7FG.js +45 -0
- package/dist/runtime-EYVN7NFJ.js +45 -0
- package/dist/runtime-F6RPWQVW.js +45 -0
- package/dist/runtime-FYMJURFC.js +45 -0
- package/dist/runtime-JRNBL4O4.js +45 -0
- package/dist/runtime-OM2NIBMI.js +45 -0
- package/dist/runtime-QWPVD7CY.js +45 -0
- package/dist/runtime-YLIIPTE4.js +45 -0
- package/dist/runtime-YU6P22CG.js +45 -0
- package/dist/screen-unlock-4RPZBHOI.js +118 -0
- package/dist/server-AMCSXINC.js +28 -0
- package/dist/server-CU6LVQS4.js +28 -0
- package/dist/server-DFYGH2CV.js +28 -0
- package/dist/server-EELWOC3X.js +28 -0
- package/dist/server-EN5E2OWQ.js +28 -0
- package/dist/server-GW2HYJYI.js +28 -0
- package/dist/server-J25NCRWJ.js +28 -0
- package/dist/server-JDGNOTFV.js +28 -0
- package/dist/server-NE5HD5DJ.js +28 -0
- package/dist/server-NQOT7W77.js +28 -0
- package/dist/server-PWE5PQTR.js +28 -0
- package/dist/server-Q2Q32H2B.js +28 -0
- package/dist/server-Q77ME7TL.js +28 -0
- package/dist/server-WLLH4WST.js +28 -0
- package/dist/server-WTUJ2O3F.js +28 -0
- package/dist/server-X4CJTHHF.js +28 -0
- package/dist/server-XK3ILCJC.js +28 -0
- package/dist/server-ZRD3NDJE.js +28 -0
- package/dist/setup-44VBAO4J.js +20 -0
- package/dist/setup-4ONNQBWB.js +20 -0
- package/dist/setup-4OSBXSCL.js +20 -0
- package/dist/setup-4QFGRBLZ.js +20 -0
- package/dist/setup-6766SGAR.js +20 -0
- package/dist/setup-AYY24DKM.js +20 -0
- package/dist/setup-B34N4HPU.js +20 -0
- package/dist/setup-E2YLC2EY.js +20 -0
- package/dist/setup-ER6NXTY5.js +20 -0
- package/dist/setup-H2AGCBW5.js +20 -0
- package/dist/setup-ICOZRKCX.js +20 -0
- package/dist/setup-JFTJH7UF.js +20 -0
- package/dist/setup-PRFNI6YW.js +20 -0
- package/dist/setup-RAHBMYHE.js +20 -0
- package/dist/setup-TXPR5UQX.js +20 -0
- package/dist/setup-XCJMELVU.js +20 -0
- package/dist/setup-XIYEIFVK.js +20 -0
- package/dist/setup-Z4PZSHBI.js +20 -0
- package/dist/skills-FR7I5V7H.js +16 -0
- package/dist/skills-HCVBA6PK.js +16 -0
- package/dist/system-prompts-TM7OA32C.js +913 -0
- package/dist/task-queue-O7IVZYUO.js +9 -0
- package/dist/transport-encryption-2T7PIXKG.js +25 -0
- package/logs/cloudflared-error.log +61 -0
- package/logs/cloudflared-out.log +0 -0
- package/logs/enterprise-error.log +0 -0
- package/logs/enterprise-out.log +3 -0
- package/logs/fola-error.log +0 -0
- package/logs/fola-out.log +0 -0
- package/logs/john-error.log +8 -0
- package/logs/john-out.log +0 -0
- package/package.json +31 -3
- package/src/agent-tools/tool-resolver.ts +50 -61
- package/src/agent-tools/tools/enterprise-database.ts +5 -5
- package/src/agent-tools/tools/local/dependency-manager.ts +2 -2
- package/src/agent-tools/tools/microsoft/graph-api.ts +137 -26
- package/src/agent-tools/tools/microsoft/outlook-mail.ts +392 -100
- package/src/agent-tools/tools/microsoft/teams.ts +267 -48
- package/src/auth/routes.ts +4 -4
- package/src/cli-agent.ts +108 -8
- package/src/cli-serve.ts +140 -0
- package/src/dashboard/app.js +9 -3
- package/src/dashboard/components/knowledge-link.js +15 -0
- package/src/dashboard/components/settings-help.js +4 -2
- package/src/dashboard/docs/agent-deployment.html +33 -1
- package/src/dashboard/docs/settings-network.html +321 -0
- package/src/dashboard/docs/settings-security.html +347 -0
- package/src/dashboard/docs/settings-tool-security.html +176 -0
- package/src/dashboard/docs/settings.html +36 -16
- package/src/dashboard/pages/agent-detail/deployment.js +39 -6
- package/src/dashboard/pages/agent-detail/tools.js +10 -0
- package/src/dashboard/pages/database-access.js +4 -3
- package/src/dashboard/pages/settings.js +174 -37
- package/src/dashboard/pages/task-pipeline.js +400 -843
- package/src/database-access/agent-tools.ts +78 -63
- package/src/database-access/connection-manager.ts +13 -2
- package/src/database-access/routes.ts +13 -1
- package/src/db/adapter.ts +1 -0
- package/src/engine/agent-memory.ts +2 -1
- package/src/engine/agent-notify.ts +50 -0
- package/src/engine/agent-routes.ts +257 -4
- package/src/engine/db-adapter.ts +16 -0
- package/src/engine/lifecycle.ts +4 -0
- package/src/engine/routes.ts +4 -3
- package/src/engine/screen-unlock.ts +136 -0
- package/src/engine/skills/database-access.ts +78 -0
- package/src/engine/skills/index.ts +3 -2
- package/src/engine/skills.ts +2 -0
- package/src/engine/task-queue-routes.ts +18 -0
- package/src/engine/task-queue.ts +15 -2
- package/src/middleware/transport-encryption.ts +1 -4
- package/src/runtime/agent-loop.ts +4 -0
- package/src/runtime/index.ts +15 -6
- package/src/server.ts +14 -1
- package/src/system-prompts/google/index.ts +1 -2
- package/src/system-prompts/index.ts +1 -1
- package/src/system-prompts/microsoft/contacts.ts +34 -0
- package/src/system-prompts/microsoft/excel.ts +52 -0
- package/src/system-prompts/microsoft/index.ts +31 -0
- package/src/system-prompts/microsoft/onedrive.ts +41 -0
- package/src/system-prompts/microsoft/onenote.ts +36 -0
- package/src/system-prompts/microsoft/outlook-calendar.ts +37 -0
- package/src/system-prompts/microsoft/outlook-mail.ts +46 -0
- package/src/system-prompts/microsoft/planner.ts +37 -0
- package/src/system-prompts/microsoft/powerbi.ts +38 -0
- package/src/system-prompts/microsoft/powerpoint.ts +35 -0
- package/src/system-prompts/microsoft/sharepoint.ts +44 -0
- package/src/system-prompts/microsoft/teams.ts +49 -0
- package/src/system-prompts/microsoft/todo.ts +37 -0
- package/src/types/hono-env.ts +4 -0
- package/.github/CODEOWNERS +0 -23
- package/.github/workflows/publish-community-skills.yml +0 -121
- package/.github/workflows/validate-community-skills.yml +0 -172
- package/agriculture_southwest_nigeria_research.txt +0 -10
- package/boa_credit_cards_research.txt +0 -10
- package/customer_support_research_feb2026.txt +0 -10
- package/dist/agent-tools-LRA7PPXG.js +0 -13922
- package/dist/agent-tools-VAU5DOQB.js +0 -13910
- package/dist/agent-tools-VWV7OWXU.js +0 -13922
- package/dist/chunk-2Z7MWTCX.js +0 -4977
- package/dist/chunk-3T4XU3VV.js +0 -5010
- package/dist/chunk-445QM4NX.js +0 -5061
- package/dist/chunk-5TW3Y7DJ.js +0 -1519
- package/dist/chunk-6I7VY3LT.js +0 -5060
- package/dist/chunk-6W5EK3UP.js +0 -4977
- package/dist/chunk-AQMSHJQT.js +0 -5069
- package/dist/chunk-ASSQW7HX.js +0 -5051
- package/dist/chunk-CIN27FGC.js +0 -5037
- package/dist/chunk-CMXY3NUB.js +0 -4977
- package/dist/chunk-DRLMRUDP.js +0 -5052
- package/dist/chunk-EHI7Z446.js +0 -1519
- package/dist/chunk-FEAILFAQ.js +0 -1519
- package/dist/chunk-GA3PYBZL.js +0 -1519
- package/dist/chunk-GWX63G5J.js +0 -1519
- package/dist/chunk-HHMZ4UY6.js +0 -1519
- package/dist/chunk-HVQMNF7E.js +0 -4921
- package/dist/chunk-HXM7F3YN.js +0 -1519
- package/dist/chunk-K6NGOUXG.js +0 -5060
- package/dist/chunk-KPG5WINJ.js +0 -4977
- package/dist/chunk-LBCUBYDL.js +0 -1519
- package/dist/chunk-LIRQSWLR.js +0 -5014
- package/dist/chunk-LRCKO5KE.js +0 -1519
- package/dist/chunk-M7XL3DJD.js +0 -5069
- package/dist/chunk-MHJULEIQ.js +0 -1519
- package/dist/chunk-MJGGW6MC.js +0 -106
- package/dist/chunk-MMYBDHDB.js +0 -4921
- package/dist/chunk-MQT5FXKD.js +0 -1519
- package/dist/chunk-OIMPEQF5.js +0 -4977
- package/dist/chunk-OOU7JUYE.js +0 -542
- package/dist/chunk-OW4GLBHP.js +0 -1519
- package/dist/chunk-Q4K4MMLU.js +0 -4977
- package/dist/chunk-RUK4CRPF.js +0 -1519
- package/dist/chunk-T7H65XQY.js +0 -1519
- package/dist/chunk-TQVFWG57.js +0 -5064
- package/dist/chunk-UEPK3IMC.js +0 -1519
- package/dist/chunk-VUWTXJH6.js +0 -1519
- package/dist/chunk-WCPGGSAD.js +0 -1519
- package/dist/chunk-WO63NZOJ.js +0 -1519
- package/dist/chunk-YPJDRVUM.js +0 -5064
- package/dist/chunk-ZROMH5DL.js +0 -4921
- package/src/dashboard/docs/_template.txt +0 -92
|
@@ -6,17 +6,11 @@ import { useOrgContext } from '../components/org-switcher.js';
|
|
|
6
6
|
import { KnowledgeLink } from '../components/knowledge-link.js';
|
|
7
7
|
|
|
8
8
|
// ─── Constants ───────────────────────────────────────────
|
|
9
|
-
var
|
|
10
|
-
var NODE_H = 52;
|
|
11
|
-
var AGENT_W = 130;
|
|
12
|
-
var AGENT_H = 40;
|
|
13
|
-
var H_GAP = 32; // horizontal gap (left→right flow)
|
|
14
|
-
var V_GAP = 12; // vertical gap between lanes
|
|
15
|
-
var PAD = 16;
|
|
16
|
-
|
|
9
|
+
var PAGE_SIZES = [25, 50, 100];
|
|
17
10
|
var STATUS_COLORS = { created: '#6366f1', assigned: '#991b1b', in_progress: '#06b6d4', completed: '#15803d', failed: '#ef4444', cancelled: '#6b7394' };
|
|
18
11
|
var PRIORITY_COLORS = { urgent: '#ef4444', high: '#991b1b', normal: '#6366f1', low: '#6b7394' };
|
|
19
12
|
var DELEGATION_COLORS = { delegation: '#6366f1', review: '#991b1b', revision: '#f97316', escalation: '#ef4444', return: '#15803d' };
|
|
13
|
+
|
|
20
14
|
function sourceBadge(src) {
|
|
21
15
|
var meta = { telegram: { color: '#0088cc' }, whatsapp: { color: '#25d366' }, email: { color: '#ea4335' }, google_chat: { color: '#1a73e8' }, internal: { color: '#6b7394' }, api: { color: '#8b5cf6' } };
|
|
22
16
|
var icons = { telegram: E.telegram, whatsapp: E.whatsapp, email: E.email, google_chat: E.google, internal: E.gear, api: E.link };
|
|
@@ -25,157 +19,11 @@ function sourceBadge(src) {
|
|
|
25
19
|
var label = src ? src.replace(/_/g, ' ').replace(/\b\w/g, function(c) { return c.toUpperCase(); }) : 'Unknown';
|
|
26
20
|
return h('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 3, fontSize: 9, padding: '1px 5px', borderRadius: 4, background: m.color + '18', color: m.color, fontWeight: 600, whiteSpace: 'nowrap', flexShrink: 0 } }, iconFn(10), ' ', label);
|
|
27
21
|
}
|
|
28
|
-
// Theme-aware: use CSS variables where possible, detect dark/light
|
|
29
|
-
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; } }
|
|
30
|
-
var BG = 'var(--bg-canvas, var(--bg-primary, #0a0c14))';
|
|
31
|
-
var EDGE_COLOR = 'var(--tp-edge, rgba(128,128,128,0.25))';
|
|
32
|
-
var EDGE_HL = 'rgba(99,102,241,0.7)';
|
|
33
22
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
function injectCSS() {
|
|
37
|
-
if (_injected) return; _injected = true;
|
|
38
|
-
var style = document.createElement('style');
|
|
39
|
-
style.textContent = `
|
|
40
|
-
: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); }
|
|
41
|
-
[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); }
|
|
42
|
-
@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); } }
|
|
43
|
-
@keyframes flowDash { to { stroke-dashoffset: -24; } }
|
|
44
|
-
@keyframes flowPulse { 0%,100% { opacity: 0.4; } 50% { opacity: 1; } }
|
|
45
|
-
@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); } }
|
|
46
|
-
.tp-flow-active { animation: flowDash 1.2s linear infinite; }
|
|
47
|
-
.tp-node-active { animation: taskPulse 2s ease-in-out infinite; }
|
|
48
|
-
.tp-node:hover { transform: scale(1.03); z-index: 10; }
|
|
49
|
-
.tp-chain-tag { font-size: 9px; padding: 1px 5px; border-radius: 4px; font-weight: 600; letter-spacing: 0.02em; white-space: nowrap; flex-shrink: 0; }
|
|
50
|
-
`;
|
|
51
|
-
document.head.appendChild(style);
|
|
23
|
+
function tag(color, text) {
|
|
24
|
+
return h('span', { style: { display: 'inline-block', fontSize: 9, padding: '1px 5px', borderRadius: 4, fontWeight: 600, letterSpacing: '0.02em', whiteSpace: 'nowrap', background: color + '22', color: color } }, text);
|
|
52
25
|
}
|
|
53
26
|
|
|
54
|
-
// ─── Layout: Left-to-Right Chain Flow ────────────────────
|
|
55
|
-
// Tasks flow horizontally. Each chain = a horizontal row.
|
|
56
|
-
// Multiple chains stack vertically. Circular flows curve back.
|
|
57
|
-
|
|
58
|
-
function layoutChains(tasks) {
|
|
59
|
-
if (!tasks.length) return { nodes: [], edges: [], width: 0, height: 0, chains: [] };
|
|
60
|
-
|
|
61
|
-
// Group by chainId — but single-task chains are treated as orphans (no chain)
|
|
62
|
-
var chainMap = new Map();
|
|
63
|
-
var orphans = [];
|
|
64
|
-
var tempChains = new Map();
|
|
65
|
-
tasks.forEach(function(t) {
|
|
66
|
-
if (t.chainId) {
|
|
67
|
-
if (!tempChains.has(t.chainId)) tempChains.set(t.chainId, []);
|
|
68
|
-
tempChains.get(t.chainId).push(t);
|
|
69
|
-
} else {
|
|
70
|
-
orphans.push(t);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
// Only keep chains with 2+ tasks; singles become orphans
|
|
74
|
-
tempChains.forEach(function(arr, key) {
|
|
75
|
-
if (arr.length > 1) { chainMap.set(key, arr); }
|
|
76
|
-
else { orphans = orphans.concat(arr); }
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Sort each chain by chainSeq
|
|
80
|
-
chainMap.forEach(function(arr) { arr.sort(function(a, b) { return (a.chainSeq || 0) - (b.chainSeq || 0); }); });
|
|
81
|
-
|
|
82
|
-
// Also group orphans by agent for a simpler layout
|
|
83
|
-
var orphansByAgent = new Map();
|
|
84
|
-
orphans.forEach(function(t) {
|
|
85
|
-
var key = t.assignedTo || 'unassigned';
|
|
86
|
-
if (!orphansByAgent.has(key)) orphansByAgent.set(key, []);
|
|
87
|
-
orphansByAgent.get(key).push(t);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
var allNodes = [];
|
|
91
|
-
var allEdges = [];
|
|
92
|
-
var chainInfos = [];
|
|
93
|
-
var y = PAD;
|
|
94
|
-
|
|
95
|
-
// Layout each chain as a horizontal row
|
|
96
|
-
chainMap.forEach(function(chainTasks, chainId) {
|
|
97
|
-
var x = PAD;
|
|
98
|
-
var rowNodes = [];
|
|
99
|
-
var maxH = NODE_H;
|
|
100
|
-
|
|
101
|
-
chainTasks.forEach(function(t, i) {
|
|
102
|
-
var node = { id: t.id, task: t, x: x, y: y, w: NODE_W, h: NODE_H, isAgent: false, chainId: chainId };
|
|
103
|
-
rowNodes.push(node);
|
|
104
|
-
allNodes.push(node);
|
|
105
|
-
|
|
106
|
-
if (i > 0) {
|
|
107
|
-
var prev = rowNodes[i - 1];
|
|
108
|
-
var dtype = t.delegationType || 'delegation';
|
|
109
|
-
var isReturn = dtype === 'return' || dtype === 'revision';
|
|
110
|
-
// Check for circular: does this task go back to an agent already seen?
|
|
111
|
-
var seenAgents = chainTasks.slice(0, i).map(function(ct) { return ct.assignedTo; });
|
|
112
|
-
var isCircular = seenAgents.indexOf(t.assignedTo) !== -1 && isReturn;
|
|
113
|
-
|
|
114
|
-
allEdges.push({
|
|
115
|
-
from: prev, to: node,
|
|
116
|
-
delegationType: dtype,
|
|
117
|
-
isCircular: isCircular,
|
|
118
|
-
isActive: prev.task.status === 'in_progress' || t.status === 'in_progress',
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
x += NODE_W + H_GAP;
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// Customer context badge on first node
|
|
126
|
-
var firstTask = chainTasks[0];
|
|
127
|
-
chainInfos.push({
|
|
128
|
-
chainId: chainId,
|
|
129
|
-
y: y,
|
|
130
|
-
taskCount: chainTasks.length,
|
|
131
|
-
customer: firstTask.customerContext,
|
|
132
|
-
status: chainTasks[chainTasks.length - 1].status,
|
|
133
|
-
title: firstTask.title,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
y += maxH + V_GAP + 8; // space between chains
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// Layout orphans horizontally in a single row (with wrap if too many)
|
|
140
|
-
var orphanList = [];
|
|
141
|
-
orphansByAgent.forEach(function(agentTasks) { orphanList = orphanList.concat(agentTasks); });
|
|
142
|
-
if (orphanList.length > 0) {
|
|
143
|
-
var x = PAD;
|
|
144
|
-
orphanList.forEach(function(t) {
|
|
145
|
-
allNodes.push({ id: t.id, task: t, x: x, y: y, w: NODE_W, h: NODE_H, isAgent: false, chainId: null });
|
|
146
|
-
x += NODE_W + H_GAP;
|
|
147
|
-
});
|
|
148
|
-
y += NODE_H + V_GAP;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
var maxX = 0;
|
|
152
|
-
allNodes.forEach(function(n) { maxX = Math.max(maxX, n.x + n.w); });
|
|
153
|
-
|
|
154
|
-
return { nodes: allNodes, edges: allEdges, width: maxX + PAD, height: y + PAD, chains: chainInfos };
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// ─── SVG Edge Paths ──────────────────────────────────────
|
|
158
|
-
function horizontalPath(from, to) {
|
|
159
|
-
var x1 = from.x + from.w;
|
|
160
|
-
var y1 = from.y + from.h / 2;
|
|
161
|
-
var x2 = to.x;
|
|
162
|
-
var y2 = to.y + to.h / 2;
|
|
163
|
-
var midX = x1 + (x2 - x1) * 0.5;
|
|
164
|
-
return 'M ' + x1 + ' ' + y1 + ' C ' + midX + ' ' + y1 + ', ' + midX + ' ' + y2 + ', ' + x2 + ' ' + y2;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function circularPath(from, to) {
|
|
168
|
-
// Arc back: goes up and curves back left
|
|
169
|
-
var x1 = from.x + from.w;
|
|
170
|
-
var y1 = from.y + from.h / 2;
|
|
171
|
-
var x2 = to.x;
|
|
172
|
-
var y2 = to.y + to.h / 2;
|
|
173
|
-
var lift = 28;
|
|
174
|
-
var topY = Math.min(y1, y2) - lift;
|
|
175
|
-
return 'M ' + x1 + ' ' + y1 + ' C ' + (x1 + 50) + ' ' + topY + ', ' + (x2 - 50) + ' ' + topY + ', ' + x2 + ' ' + y2;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// ─── Helpers ─────────────────────────────────────────────
|
|
179
27
|
function timeAgo(ts) {
|
|
180
28
|
if (!ts) return '-';
|
|
181
29
|
var diff = Date.now() - new Date(ts).getTime();
|
|
@@ -185,6 +33,7 @@ function timeAgo(ts) {
|
|
|
185
33
|
if (diff < 86400000) return Math.floor(diff / 3600000) + 'h ago';
|
|
186
34
|
return Math.floor(diff / 86400000) + 'd ago';
|
|
187
35
|
}
|
|
36
|
+
|
|
188
37
|
function formatDuration(ms) {
|
|
189
38
|
if (!ms) return '-';
|
|
190
39
|
var s = Math.floor(ms / 1000);
|
|
@@ -193,154 +42,189 @@ function formatDuration(ms) {
|
|
|
193
42
|
if (m < 60) return m + 'm ' + (s % 60) + 's';
|
|
194
43
|
return Math.floor(m / 60) + 'h ' + (m % 60) + 'm';
|
|
195
44
|
}
|
|
196
|
-
function tag(color, text) { return h('span', { className: 'tp-chain-tag', style: { background: color + '22', color: color } }, text); }
|
|
197
45
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
46
|
+
// ─── CSS (injected once) ─────────────────────────────────
|
|
47
|
+
var _injected = false;
|
|
48
|
+
function injectCSS() {
|
|
49
|
+
if (_injected) return; _injected = true;
|
|
50
|
+
var style = document.createElement('style');
|
|
51
|
+
style.textContent = [
|
|
52
|
+
'@keyframes flowPulse { 0%,100% { opacity: 0.4; } 50% { opacity: 1; } }',
|
|
53
|
+
'@keyframes taskPulse { 0%,100% { box-shadow: none; } 50% { box-shadow: 0 0 0 2px rgba(6,182,212,0.15); } }',
|
|
54
|
+
'.tp-row { transition: background 0.15s; }',
|
|
55
|
+
'.tp-row:hover { background: var(--bg-secondary) !important; }',
|
|
56
|
+
'.tp-row-active { animation: taskPulse 3s ease-in-out infinite; }',
|
|
57
|
+
'.tp-tab { padding: 6px 14px; font-size: 12px; font-weight: 600; border: none; background: none; color: var(--text-muted); cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.15s; white-space: nowrap; }',
|
|
58
|
+
'.tp-tab:hover { color: var(--text-primary); }',
|
|
59
|
+
'.tp-tab-active { color: var(--text-primary); border-bottom-color: #6366f1; }',
|
|
60
|
+
'@keyframes flowDash { to { stroke-dashoffset: -24; } }',
|
|
61
|
+
'.tp-flow-active { animation: flowDash 1.2s linear infinite; }',
|
|
62
|
+
].join('\n');
|
|
63
|
+
document.head.appendChild(style);
|
|
207
64
|
}
|
|
208
|
-
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
209
|
-
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
210
|
-
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
211
65
|
|
|
212
|
-
// ───
|
|
213
|
-
function
|
|
214
|
-
var
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
h('div', { style: {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
66
|
+
// ─── Stats Cards ─────────────────────────────────────────
|
|
67
|
+
function StatsRow(props) {
|
|
68
|
+
var s = props.stats;
|
|
69
|
+
function card(label, value, color, sub) {
|
|
70
|
+
return h('div', { style: { flex: '1 1 0', minWidth: 100, padding: '12px 16px', background: 'var(--bg-secondary)', borderRadius: 'var(--radius)', border: '1px solid var(--border)' } },
|
|
71
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4 } }, label),
|
|
72
|
+
h('div', { style: { fontSize: 22, fontWeight: 700, color: color, lineHeight: 1 } }, value),
|
|
73
|
+
sub && h('div', { style: { fontSize: 10, color: 'var(--text-muted)', marginTop: 4 } }, sub)
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
return h('div', { style: { display: 'flex', gap: 10, marginBottom: 16, flexWrap: 'wrap' } },
|
|
77
|
+
card('Active', s.inProgress || 0, '#06b6d4', (s.created || 0) + ' created, ' + (s.assigned || 0) + ' assigned'),
|
|
78
|
+
card('Completed', s.completed || 0, '#15803d', (s.todayCompleted || 0) + ' today'),
|
|
79
|
+
card('Failed', (s.failed || 0) + (s.cancelled || 0), '#ef4444', (s.todayFailed || 0) + ' today'),
|
|
80
|
+
card('Total', s.total || 0, 'var(--text-primary)', s.avgDurationMs > 0 ? 'Avg ' + formatDuration(s.avgDurationMs) : ''),
|
|
81
|
+
(s.totalCost > 0 || s.totalTokens > 0) && card('Usage',
|
|
82
|
+
s.totalTokens > 999999 ? (s.totalTokens / 1000000).toFixed(1) + 'M' : s.totalTokens > 999 ? (s.totalTokens / 1000).toFixed(1) + 'K' : s.totalTokens || 0,
|
|
83
|
+
'#a855f7',
|
|
84
|
+
s.totalCost > 0 ? '$' + s.totalCost.toFixed(2) + ' spent' : 'tokens'
|
|
223
85
|
)
|
|
224
86
|
);
|
|
225
87
|
}
|
|
226
88
|
|
|
227
|
-
// ───
|
|
228
|
-
// ─── Activity Log Component ──────────────────────────────
|
|
229
|
-
var ACTIVITY_PAGE_SIZE = 10;
|
|
89
|
+
// ─── Activity Log ────────────────────────────────────────
|
|
230
90
|
var ACTIVITY_TYPE_COLORS = {
|
|
231
91
|
created: '#6366f1', assigned: '#991b1b', started: '#06b6d4', in_progress: '#06b6d4',
|
|
232
92
|
completed: '#15803d', failed: '#ef4444', cancelled: '#6b7394', delegated: '#a855f7',
|
|
233
|
-
compaction: '#8b5cf6', error: '#ef4444',
|
|
234
|
-
crash: '#dc2626', recovery: '#f59e0b', note: '#3b82f6',
|
|
93
|
+
compaction: '#8b5cf6', error: '#ef4444', crash: '#dc2626', recovery: '#f59e0b', note: '#3b82f6',
|
|
235
94
|
};
|
|
236
95
|
|
|
237
96
|
function ActivityLog(props) {
|
|
238
97
|
var entries = props.entries || [];
|
|
239
|
-
var _search = useState(''); var search = _search[0]; var setSearch = _search[1];
|
|
240
|
-
var _typeFilter = useState('all'); var typeFilter = _typeFilter[0]; var setTypeFilter = _typeFilter[1];
|
|
241
98
|
var _page = useState(0); var page = _page[0]; var setPage = _page[1];
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
var
|
|
245
|
-
var seen = {};
|
|
246
|
-
entries.forEach(function(e) { if (e.type && !seen[e.type]) { seen[e.type] = true; types.push(e.type); } });
|
|
247
|
-
|
|
248
|
-
// Filter
|
|
249
|
-
var filtered = entries.filter(function(e) {
|
|
250
|
-
if (typeFilter !== 'all' && e.type !== typeFilter) return false;
|
|
251
|
-
if (search) {
|
|
252
|
-
var q = search.toLowerCase();
|
|
253
|
-
return (e.type || '').toLowerCase().includes(q) || (e.detail || '').toLowerCase().includes(q) || (e.agent || '').toLowerCase().includes(q);
|
|
254
|
-
}
|
|
255
|
-
return true;
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
var totalPages = Math.max(1, Math.ceil(filtered.length / ACTIVITY_PAGE_SIZE));
|
|
259
|
-
if (page >= totalPages) page = totalPages - 1;
|
|
260
|
-
var pageEntries = filtered.slice(page * ACTIVITY_PAGE_SIZE, (page + 1) * ACTIVITY_PAGE_SIZE);
|
|
99
|
+
var perPage = 10;
|
|
100
|
+
var totalPages = Math.max(1, Math.ceil(entries.length / perPage));
|
|
101
|
+
var pageEntries = entries.slice(page * perPage, (page + 1) * perPage);
|
|
261
102
|
|
|
262
103
|
return h('div', { style: { marginBottom: 16 } },
|
|
263
|
-
h('div', { style: {
|
|
264
|
-
h('div', { style: { fontSize: 12, fontWeight: 600, color: 'var(--text-muted)' } }, 'ACTIVITY LOG (' + filtered.length + ')'),
|
|
265
|
-
h('div', { style: { display: 'flex', gap: 6, alignItems: 'center' } },
|
|
266
|
-
h('input', {
|
|
267
|
-
placeholder: 'Search...', value: search,
|
|
268
|
-
onChange: function(e) { setSearch(e.target.value); setPage(0); },
|
|
269
|
-
style: { padding: '3px 8px', fontSize: 11, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: 'var(--text-primary)', width: 120, outline: 'none' }
|
|
270
|
-
}),
|
|
271
|
-
h('select', {
|
|
272
|
-
value: typeFilter,
|
|
273
|
-
onChange: function(e) { setTypeFilter(e.target.value); setPage(0); },
|
|
274
|
-
style: { padding: '3px 8px', fontSize: 11, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: 'var(--text-primary)', outline: 'none' }
|
|
275
|
-
},
|
|
276
|
-
h('option', { value: 'all' }, 'All types'),
|
|
277
|
-
types.map(function(t) { return h('option', { key: t, value: t }, t); })
|
|
278
|
-
)
|
|
279
|
-
)
|
|
280
|
-
),
|
|
104
|
+
h('div', { style: { fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 6 } }, 'ACTIVITY LOG (' + entries.length + ')'),
|
|
281
105
|
h('div', { style: { border: '1px solid var(--border)', borderRadius: 'var(--radius)', overflow: 'hidden' } },
|
|
282
106
|
pageEntries.map(function(entry, i) {
|
|
283
107
|
var tc = ACTIVITY_TYPE_COLORS[entry.type] || 'var(--text-muted)';
|
|
284
|
-
return h('div', { key: page *
|
|
108
|
+
return h('div', { key: page * perPage + i, style: { display: 'flex', gap: 8, padding: '5px 10px', borderBottom: i < pageEntries.length - 1 ? '1px solid var(--border)' : 'none', fontSize: 11, alignItems: 'flex-start' } },
|
|
285
109
|
h('span', { style: { color: 'var(--text-muted)', flexShrink: 0, fontFamily: 'var(--font-mono)', fontSize: 10, minWidth: 65 } }, entry.ts ? new Date(entry.ts).toLocaleTimeString() : ''),
|
|
286
110
|
h('span', { style: { fontWeight: 600, flexShrink: 0, minWidth: 70, color: tc, padding: '0 4px', borderRadius: 4, background: tc + '15' } }, entry.type),
|
|
287
111
|
h('span', { style: { color: 'var(--text-secondary)', wordBreak: 'break-word' } }, entry.detail)
|
|
288
112
|
);
|
|
289
113
|
}),
|
|
290
|
-
pageEntries.length === 0 && h('div', { style: { padding:
|
|
114
|
+
pageEntries.length === 0 && h('div', { style: { padding: 12, fontSize: 11, color: 'var(--text-muted)', textAlign: 'center' } }, 'No entries')
|
|
291
115
|
),
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
h('span', { style: { color: 'var(--text-muted)' } }, 'Page ' + (page + 1) + ' of ' + totalPages),
|
|
116
|
+
totalPages > 1 && h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 4, fontSize: 11 } },
|
|
117
|
+
h('span', { style: { color: 'var(--text-muted)' } }, 'Page ' + (page + 1) + '/' + totalPages),
|
|
295
118
|
h('div', { style: { display: 'flex', gap: 4 } },
|
|
296
|
-
h('button', {
|
|
297
|
-
|
|
298
|
-
onClick: function() { setPage(page - 1); },
|
|
299
|
-
style: { padding: '2px 8px', fontSize: 11, borderRadius: 4, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: page === 0 ? 'var(--text-muted)' : 'var(--text-primary)', cursor: page === 0 ? 'default' : 'pointer' }
|
|
300
|
-
}, 'Prev'),
|
|
301
|
-
h('button', {
|
|
302
|
-
disabled: page >= totalPages - 1,
|
|
303
|
-
onClick: function() { setPage(page + 1); },
|
|
304
|
-
style: { padding: '2px 8px', fontSize: 11, borderRadius: 4, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: page >= totalPages - 1 ? 'var(--text-muted)' : 'var(--text-primary)', cursor: page >= totalPages - 1 ? 'default' : 'pointer' }
|
|
305
|
-
}, 'Next')
|
|
119
|
+
h('button', { className: 'btn btn-ghost btn-sm', disabled: page === 0, onClick: function() { setPage(page - 1); } }, 'Prev'),
|
|
120
|
+
h('button', { className: 'btn btn-ghost btn-sm', disabled: page >= totalPages - 1, onClick: function() { setPage(page + 1); } }, 'Next')
|
|
306
121
|
)
|
|
307
122
|
)
|
|
308
123
|
);
|
|
309
124
|
}
|
|
310
125
|
|
|
126
|
+
// ─── Chain Flow (inline in detail modal) ─────────────────
|
|
127
|
+
function ChainFlow(props) {
|
|
128
|
+
var chain = props.chain;
|
|
129
|
+
var currentId = props.currentId;
|
|
130
|
+
var agentMap = props.agentMap || {};
|
|
131
|
+
if (!chain || chain.length < 2) return null;
|
|
132
|
+
|
|
133
|
+
var STEP_W = 110;
|
|
134
|
+
var STEP_H = 40;
|
|
135
|
+
var STEP_GAP = 36;
|
|
136
|
+
var totalW = chain.length * STEP_W + (chain.length - 1) * STEP_GAP;
|
|
137
|
+
|
|
138
|
+
// Build steps
|
|
139
|
+
var steps = chain.map(function(ct, i) {
|
|
140
|
+
var nextArrow = i < chain.length - 1 ? (chain[i + 1].delegationType || 'delegation') : null;
|
|
141
|
+
return { task: ct, label: ct.assignedToName || ct.assignedTo, status: ct.status, arrow: nextArrow, duration: ct.actualDurationMs, progress: ct.progress };
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return h('div', { style: { marginBottom: 16 } },
|
|
145
|
+
h('div', { style: { fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 8 } }, 'DELEGATION CHAIN'),
|
|
146
|
+
h('div', { style: { overflowX: 'auto', padding: '4px 0' } },
|
|
147
|
+
h('div', { style: { position: 'relative', height: STEP_H + 12, minWidth: totalW } },
|
|
148
|
+
// SVG arrows
|
|
149
|
+
h('svg', { width: totalW, height: STEP_H + 12, style: { position: 'absolute', top: 0, left: 0, pointerEvents: 'none' } },
|
|
150
|
+
h('defs', null,
|
|
151
|
+
h('marker', { id: 'chain-arr', markerWidth: 7, markerHeight: 5, refX: 7, refY: 2.5, orient: 'auto' },
|
|
152
|
+
h('polygon', { points: '0 0, 7 2.5, 0 5', fill: 'var(--text-muted)' })
|
|
153
|
+
)
|
|
154
|
+
),
|
|
155
|
+
steps.map(function(step, i) {
|
|
156
|
+
if (!step.arrow || i >= steps.length - 1) return null;
|
|
157
|
+
var x1 = i * (STEP_W + STEP_GAP) + STEP_W;
|
|
158
|
+
var x2 = (i + 1) * (STEP_W + STEP_GAP);
|
|
159
|
+
var y = 6 + STEP_H / 2;
|
|
160
|
+
var arrowColor = DELEGATION_COLORS[step.arrow] || 'rgba(99,102,241,0.5)';
|
|
161
|
+
var isActive = step.status === 'in_progress';
|
|
162
|
+
return h(Fragment, { key: 'a' + i },
|
|
163
|
+
h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: arrowColor, strokeWidth: 2, markerEnd: 'url(#chain-arr)' }),
|
|
164
|
+
isActive && h('line', { x1: x1, y1: y, x2: x2, y2: y, stroke: '#06b6d4', strokeWidth: 2, strokeDasharray: '4 12', className: 'tp-flow-active', style: { opacity: 0.7 } }),
|
|
165
|
+
step.arrow !== 'delegation' && h('text', { x: (x1 + x2) / 2, y: y - 6, fill: arrowColor, fontSize: 8, textAnchor: 'middle', fontWeight: 600 }, step.arrow)
|
|
166
|
+
);
|
|
167
|
+
})
|
|
168
|
+
),
|
|
169
|
+
// Step nodes
|
|
170
|
+
steps.map(function(step, i) {
|
|
171
|
+
var x = i * (STEP_W + STEP_GAP);
|
|
172
|
+
var sc = STATUS_COLORS[step.status] || '#6366f1';
|
|
173
|
+
var isMe = step.task.id === currentId;
|
|
174
|
+
var agent = agentMap[step.task.assignedTo];
|
|
175
|
+
return h('div', { key: i, style: {
|
|
176
|
+
position: 'absolute', left: x, top: 6, width: STEP_W, height: STEP_H,
|
|
177
|
+
background: isMe ? sc + '15' : 'var(--bg-secondary)',
|
|
178
|
+
border: '1px solid ' + (isMe ? sc : 'var(--border)'),
|
|
179
|
+
borderRadius: 8, display: 'flex', alignItems: 'center', gap: 6, padding: '0 8px', overflow: 'hidden',
|
|
180
|
+
} },
|
|
181
|
+
agent && agent.avatar
|
|
182
|
+
? h('img', { src: agent.avatar, style: { width: 18, height: 18, borderRadius: '50%', objectFit: 'cover', flexShrink: 0 } })
|
|
183
|
+
: 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 } }, step.label.charAt(0).toUpperCase()),
|
|
184
|
+
h('div', { style: { overflow: 'hidden', flex: 1, minWidth: 0 } },
|
|
185
|
+
h('div', { style: { fontSize: 10, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, step.label),
|
|
186
|
+
h('div', { style: { fontSize: 8, color: 'var(--text-muted)' } }, step.status.replace('_', ' '), step.duration ? ' · ' + formatDuration(step.duration) : '')
|
|
187
|
+
)
|
|
188
|
+
);
|
|
189
|
+
})
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ─── Task Detail Modal ───────────────────────────────────
|
|
311
196
|
function TaskDetail(props) {
|
|
312
197
|
var task = props.task;
|
|
313
198
|
var chain = props.chain;
|
|
314
199
|
var onClose = props.onClose;
|
|
315
200
|
var onCancel = props.onCancel;
|
|
201
|
+
var agentMap = props.agentMap || {};
|
|
316
202
|
if (!task) return null;
|
|
317
|
-
var
|
|
203
|
+
var sc = STATUS_COLORS[task.status] || '#6b7394';
|
|
318
204
|
|
|
319
205
|
return h('div', { className: 'modal-overlay', onClick: onClose },
|
|
320
206
|
h('div', { className: 'modal', onClick: function(e) { e.stopPropagation(); }, style: { width: 640, maxHeight: '85vh', overflow: 'auto' } },
|
|
321
207
|
h('div', { className: 'modal-header' },
|
|
322
|
-
h('h2', { style: { fontSize: 16 } }, task.title),
|
|
208
|
+
h('h2', { style: { fontSize: 16, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, task.title),
|
|
323
209
|
h('button', { className: 'btn btn-ghost btn-icon', onClick: onClose }, '\u00D7')
|
|
324
210
|
),
|
|
325
211
|
h('div', { className: 'modal-body', style: { padding: 20 } },
|
|
326
|
-
//
|
|
212
|
+
// Badges
|
|
327
213
|
h('div', { style: { display: 'flex', gap: 6, marginBottom: 16, alignItems: 'center', flexWrap: 'wrap' } },
|
|
328
|
-
h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 11, fontWeight: 600, background:
|
|
329
|
-
h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 11, background: (PRIORITY_COLORS[task.priority] || '#6366f1') + '22', color: PRIORITY_COLORS[task.priority] || '#6366f1' } }, task.priority.toUpperCase()),
|
|
214
|
+
h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 11, fontWeight: 600, background: sc + '22', color: sc, border: '1px solid ' + sc + '44' } }, task.status.replace('_', ' ').toUpperCase()),
|
|
215
|
+
h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 11, background: (PRIORITY_COLORS[task.priority] || '#6366f1') + '22', color: PRIORITY_COLORS[task.priority] || '#6366f1' } }, (task.priority || 'normal').toUpperCase()),
|
|
330
216
|
task.source && sourceBadge(task.source),
|
|
331
217
|
task.chainId && h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 11, background: 'rgba(99,102,241,0.1)', color: '#6366f1', fontFamily: 'var(--font-mono)' } }, 'Chain #' + task.chainId.slice(0, 8)),
|
|
332
218
|
task.delegationType && tag(DELEGATION_COLORS[task.delegationType] || '#6b7394', task.delegationType)
|
|
333
219
|
),
|
|
334
220
|
|
|
335
|
-
// Customer
|
|
221
|
+
// Customer
|
|
336
222
|
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 } },
|
|
337
|
-
h('div', { style: { fontSize: 11, fontWeight: 600, color: 'var(--
|
|
338
|
-
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '
|
|
223
|
+
h('div', { style: { fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 6 } }, 'CUSTOMER'),
|
|
224
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '4px 16px', fontSize: 13 } },
|
|
339
225
|
task.customerContext.name && h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Name'), h('div', null, task.customerContext.name)),
|
|
340
226
|
task.customerContext.email && h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Email'), h('div', null, task.customerContext.email)),
|
|
341
|
-
task.customerContext.company && h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Company'), h('div', null, task.customerContext.company))
|
|
342
|
-
task.customerContext.channel && h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Channel'), h('div', null, task.customerContext.channel)),
|
|
343
|
-
h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Type'), h('div', null, task.customerContext.isNew ? 'New Customer' : 'Returning'))
|
|
227
|
+
task.customerContext.company && h(Fragment, null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Company'), h('div', null, task.customerContext.company))
|
|
344
228
|
)
|
|
345
229
|
),
|
|
346
230
|
|
|
@@ -348,13 +232,13 @@ function TaskDetail(props) {
|
|
|
348
232
|
|
|
349
233
|
// Progress
|
|
350
234
|
task.status === 'in_progress' && h('div', { style: { marginBottom: 16 } },
|
|
351
|
-
h('div', { style: { display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 } }, h('span', null, 'Progress'), h('span', null, task.progress + '%')),
|
|
235
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 } }, h('span', null, 'Progress'), h('span', null, (task.progress || 0) + '%')),
|
|
352
236
|
h('div', { style: { height: 6, background: 'var(--border)', borderRadius: 3, overflow: 'hidden' } },
|
|
353
|
-
h('div', { style: { height: '100%', width: task.progress + '%', background:
|
|
237
|
+
h('div', { style: { height: '100%', width: (task.progress || 0) + '%', background: '#06b6d4', borderRadius: 3, transition: 'width 0.3s' } })
|
|
354
238
|
)
|
|
355
239
|
),
|
|
356
240
|
|
|
357
|
-
//
|
|
241
|
+
// Details grid
|
|
358
242
|
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 24px', fontSize: 13, marginBottom: 16 } },
|
|
359
243
|
h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Assigned To'), h('div', null, task.assignedToName || task.assignedTo || '-')),
|
|
360
244
|
h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Created By'), h('div', null, task.createdByName || task.createdBy || '-')),
|
|
@@ -365,35 +249,13 @@ function TaskDetail(props) {
|
|
|
365
249
|
h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Source'), task.source ? sourceBadge(task.source) : h('div', null, '-'))
|
|
366
250
|
),
|
|
367
251
|
|
|
368
|
-
//
|
|
369
|
-
chain && chain.length > 1 && h(
|
|
370
|
-
h('div', { style: { fontSize: 12, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 8 } }, 'DELEGATION CHAIN'),
|
|
371
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 0, overflow: 'auto', padding: '8px 0' } },
|
|
372
|
-
chain.map(function(ct, i) {
|
|
373
|
-
var isMe = ct.id === task.id;
|
|
374
|
-
var sc = STATUS_COLORS[ct.status] || '#6b7394';
|
|
375
|
-
return h(Fragment, { key: ct.id },
|
|
376
|
-
i > 0 && h('div', { style: { display: 'flex', alignItems: 'center', flexShrink: 0 } },
|
|
377
|
-
h('div', { style: { width: 32, height: 2, background: (DELEGATION_COLORS[ct.delegationType] || '#6366f1') + '66' } }),
|
|
378
|
-
h('div', { style: { fontSize: 8, color: 'var(--tp-text-dim)', position: 'relative', top: -8 } }, ct.delegationType || '')
|
|
379
|
-
),
|
|
380
|
-
h('div', { style: {
|
|
381
|
-
padding: '6px 10px', borderRadius: 8, fontSize: 11, flexShrink: 0,
|
|
382
|
-
background: isMe ? sc + '22' : 'var(--tp-card)',
|
|
383
|
-
border: '1px solid ' + (isMe ? sc : 'var(--tp-border)'),
|
|
384
|
-
fontWeight: isMe ? 700 : 400, color: isMe ? sc : 'var(--tp-text-dim)',
|
|
385
|
-
} },
|
|
386
|
-
h('div', { style: { fontWeight: 600 } }, ct.assignedToName || ct.assignedTo),
|
|
387
|
-
h('div', { style: { fontSize: 9, marginTop: 2, opacity: 0.6 } }, ct.status.replace('_', ' '))
|
|
388
|
-
)
|
|
389
|
-
);
|
|
390
|
-
})
|
|
391
|
-
)
|
|
392
|
-
),
|
|
252
|
+
// Chain flow
|
|
253
|
+
chain && chain.length > 1 && h(ChainFlow, { chain: chain, currentId: task.id, agentMap: agentMap }),
|
|
393
254
|
|
|
394
|
-
// Activity log
|
|
255
|
+
// Activity log
|
|
395
256
|
task.activityLog && task.activityLog.length > 0 && h(ActivityLog, { entries: task.activityLog }),
|
|
396
257
|
|
|
258
|
+
// Error
|
|
397
259
|
task.error && h('div', { style: { padding: 12, background: 'rgba(239,68,68,0.1)', border: '1px solid rgba(239,68,68,0.3)', borderRadius: 'var(--radius)', marginBottom: 16, fontSize: 13, color: '#ef4444' } }, h('strong', null, 'Error: '), task.error),
|
|
398
260
|
|
|
399
261
|
// Actions
|
|
@@ -405,44 +267,6 @@ function TaskDetail(props) {
|
|
|
405
267
|
);
|
|
406
268
|
}
|
|
407
269
|
|
|
408
|
-
// ─── Metrics Bar ─────────────────────────────────────────
|
|
409
|
-
function MetricsBar(props) {
|
|
410
|
-
var s = props.stats;
|
|
411
|
-
function chip(label, value, color) {
|
|
412
|
-
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 4, padding: '3px 8px', background: 'var(--tp-card)', borderRadius: 6 } },
|
|
413
|
-
h('span', { style: { fontSize: 10, color: 'var(--tp-text-dim)' } }, label),
|
|
414
|
-
h('span', { style: { fontSize: 11, fontWeight: 700, color: color } }, value)
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
var hasActivity = s.total > 0;
|
|
418
|
-
|
|
419
|
-
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 } },
|
|
420
|
-
h('span', { style: { fontSize: 9, color: 'var(--tp-text-faint)', fontWeight: 600, letterSpacing: '0.06em', marginRight: 2 } }, 'TODAY'),
|
|
421
|
-
chip('Done', s.todayCompleted || 0, '#15803d'),
|
|
422
|
-
chip('Active', s.inProgress || 0, '#06b6d4'),
|
|
423
|
-
chip('New', s.todayCreated || 0, '#991b1b'),
|
|
424
|
-
s.todayFailed > 0 && chip('Failed', s.todayFailed, '#ef4444'),
|
|
425
|
-
hasActivity && h('div', { style: { width: 1, height: 14, background: 'var(--tp-border)' } }),
|
|
426
|
-
hasActivity && h('span', { style: { fontSize: 9, color: 'var(--tp-text-faint)', fontWeight: 600, letterSpacing: '0.06em' } }, 'ALL'),
|
|
427
|
-
hasActivity && chip('Total', s.total, 'rgba(255,255,255,0.6)'),
|
|
428
|
-
s.avgDurationMs > 0 && chip('Avg', formatDuration(s.avgDurationMs), '#fff'),
|
|
429
|
-
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'),
|
|
430
|
-
s.totalCost > 0 && chip('Cost', '$' + s.totalCost.toFixed(2), '#15803d'),
|
|
431
|
-
s.topAgents && s.topAgents.length > 0 && h(Fragment, null,
|
|
432
|
-
h('div', { style: { width: 1, height: 14, background: 'var(--tp-border)' } }),
|
|
433
|
-
s.topAgents.slice(0, 3).map(function(a) {
|
|
434
|
-
return h('div', { key: a.agent, style: { display: 'flex', alignItems: 'center', gap: 3, padding: '2px 6px', background: 'var(--tp-card)', borderRadius: 6 } },
|
|
435
|
-
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()),
|
|
436
|
-
h('span', { style: { fontSize: 10, color: 'var(--tp-text)', fontWeight: 600 } }, a.name),
|
|
437
|
-
h('span', { style: { fontSize: 9, color: 'var(--tp-text-dim)' } }, a.completed + '/' + a.active)
|
|
438
|
-
);
|
|
439
|
-
})
|
|
440
|
-
)
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// (ChainFlowInline removed — chain flow now renders inline on canvas)
|
|
445
|
-
|
|
446
270
|
// ─── Main Page ───────────────────────────────────────────
|
|
447
271
|
export function TaskPipelinePage() {
|
|
448
272
|
injectCSS();
|
|
@@ -450,89 +274,90 @@ export function TaskPipelinePage() {
|
|
|
450
274
|
var toast = app.toast;
|
|
451
275
|
var orgCtx = useOrgContext();
|
|
452
276
|
var effectiveOrgId = orgCtx.selectedOrgId || getOrgId();
|
|
453
|
-
|
|
454
|
-
var tasks = _tasks[0]; var setTasks = _tasks[1];
|
|
277
|
+
|
|
278
|
+
var _tasks = useState([]); var tasks = _tasks[0]; var setTasks = _tasks[1];
|
|
279
|
+
var _totalCount = useState(0); var totalCount = _totalCount[0]; var setTotalCount = _totalCount[1];
|
|
455
280
|
var _stats = useState({ created: 0, assigned: 0, inProgress: 0, completed: 0, failed: 0, cancelled: 0, total: 0, todayCompleted: 0, todayFailed: 0, todayCreated: 0, avgDurationMs: 0, totalCost: 0, totalTokens: 0, topAgents: [] });
|
|
456
281
|
var stats = _stats[0]; var setStats = _stats[1];
|
|
457
|
-
var
|
|
458
|
-
var
|
|
459
|
-
var
|
|
460
|
-
var
|
|
461
|
-
var
|
|
462
|
-
var
|
|
463
|
-
var
|
|
464
|
-
var
|
|
465
|
-
var
|
|
466
|
-
var
|
|
467
|
-
var
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
var dragStart = _dragStart[0]; var setDragStart = _dragStart[1];
|
|
475
|
-
var _filter = useState('active');
|
|
476
|
-
var filter = _filter[0]; var setFilter = _filter[1];
|
|
477
|
-
var _mousePos = useState({ x: 0, y: 0 });
|
|
478
|
-
var mousePos = _mousePos[0]; var setMousePos = _mousePos[1];
|
|
479
|
-
var containerRef = useRef(null);
|
|
480
|
-
|
|
481
|
-
var _agents = useState({});
|
|
482
|
-
var agentMap = _agents[0]; var setAgentMap = _agents[1];
|
|
483
|
-
|
|
484
|
-
var loadData = useCallback(function() {
|
|
485
|
-
setLoading(true);
|
|
486
|
-
Promise.all([
|
|
487
|
-
engineCall('/task-pipeline?limit=200'),
|
|
488
|
-
engineCall('/task-pipeline/stats'),
|
|
489
|
-
apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).catch(function() { return { agents: [] }; }),
|
|
490
|
-
]).then(function(res) {
|
|
491
|
-
var allTasks = res[0]?.tasks || [];
|
|
492
|
-
var orgAgents = res[2]?.agents || [];
|
|
493
|
-
// Build agent avatar/name map
|
|
282
|
+
var _loading = useState(true); var loading = _loading[0]; var setLoading = _loading[1];
|
|
283
|
+
var _tab = useState('active'); var tab = _tab[0]; var setTab = _tab[1];
|
|
284
|
+
var _page = useState(0); var page = _page[0]; var setPage = _page[1];
|
|
285
|
+
var _pageSize = useState(25); var pageSize = _pageSize[0]; var setPageSize = _pageSize[1];
|
|
286
|
+
var _search = useState(''); var search = _search[0]; var setSearch = _search[1];
|
|
287
|
+
var _sortBy = useState('createdAt'); var sortBy = _sortBy[0]; var setSortBy = _sortBy[1];
|
|
288
|
+
var _sortDir = useState('desc'); var sortDir = _sortDir[0]; var setSortDir = _sortDir[1];
|
|
289
|
+
var _selectedTask = useState(null); var selectedTask = _selectedTask[0]; var setSelectedTask = _selectedTask[1];
|
|
290
|
+
var _selectedChain = useState(null); var selectedChain = _selectedChain[0]; var setSelectedChain = _selectedChain[1];
|
|
291
|
+
var _agentMap = useState({}); var agentMap = _agentMap[0]; var setAgentMap = _agentMap[1];
|
|
292
|
+
var searchTimer = useRef(null);
|
|
293
|
+
|
|
294
|
+
// Load agents for avatar/name resolution
|
|
295
|
+
useEffect(function() {
|
|
296
|
+
apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).then(function(res) {
|
|
297
|
+
var agents = res?.agents || res || [];
|
|
298
|
+
if (!Array.isArray(agents)) agents = [];
|
|
494
299
|
var map = {};
|
|
495
|
-
|
|
300
|
+
agents.forEach(function(a) {
|
|
496
301
|
map[a.id] = { name: a.config?.name || a.name || a.id, avatar: a.config?.identity?.avatar || a.config?.avatar || a.config?.persona?.avatar || null };
|
|
497
302
|
});
|
|
498
303
|
setAgentMap(map);
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
304
|
+
}).catch(function() {});
|
|
305
|
+
}, [effectiveOrgId]);
|
|
306
|
+
|
|
307
|
+
// Load tasks
|
|
308
|
+
var loadTasks = useCallback(function() {
|
|
309
|
+
setLoading(true);
|
|
310
|
+
var limit = pageSize;
|
|
311
|
+
var offset = page * pageSize;
|
|
312
|
+
engineCall('/task-pipeline?limit=' + limit + '&offset=' + offset).then(function(res) {
|
|
313
|
+
var allTasks = res?.tasks || [];
|
|
314
|
+
// Client-side filtering (server should ideally do this)
|
|
315
|
+
var filtered = allTasks;
|
|
316
|
+
// Tab filter
|
|
317
|
+
if (tab === 'active') filtered = filtered.filter(function(t) { return t.status === 'created' || t.status === 'assigned' || t.status === 'in_progress'; });
|
|
318
|
+
else if (tab === 'completed') filtered = filtered.filter(function(t) { return t.status === 'completed'; });
|
|
319
|
+
else if (tab === 'failed') filtered = filtered.filter(function(t) { return t.status === 'failed' || t.status === 'cancelled'; });
|
|
320
|
+
// Search
|
|
321
|
+
if (search) {
|
|
322
|
+
var q = search.toLowerCase();
|
|
323
|
+
filtered = filtered.filter(function(t) {
|
|
324
|
+
return (t.title || '').toLowerCase().includes(q)
|
|
325
|
+
|| (t.assignedToName || t.assignedTo || '').toLowerCase().includes(q)
|
|
326
|
+
|| (t.createdByName || t.createdBy || '').toLowerCase().includes(q)
|
|
327
|
+
|| (t.description || '').toLowerCase().includes(q)
|
|
328
|
+
|| (t.category || '').toLowerCase().includes(q);
|
|
522
329
|
});
|
|
523
|
-
if (durCount > 0) cs.avgDurationMs = durSum / durCount;
|
|
524
|
-
cs.topAgents = Object.values(am).sort(function(a,b) { return (b.completed + b.active) - (a.completed + a.active); });
|
|
525
|
-
setStats(cs);
|
|
526
|
-
} else {
|
|
527
|
-
setStats(res[1] || stats);
|
|
528
330
|
}
|
|
331
|
+
// Sort
|
|
332
|
+
filtered.sort(function(a, b) {
|
|
333
|
+
var va = a[sortBy] || '';
|
|
334
|
+
var vb = b[sortBy] || '';
|
|
335
|
+
if (sortBy === 'createdAt' || sortBy === 'completedAt') {
|
|
336
|
+
va = new Date(va || 0).getTime();
|
|
337
|
+
vb = new Date(vb || 0).getTime();
|
|
338
|
+
}
|
|
339
|
+
if (typeof va === 'string') { va = va.toLowerCase(); vb = (vb || '').toLowerCase(); }
|
|
340
|
+
if (va < vb) return sortDir === 'asc' ? -1 : 1;
|
|
341
|
+
if (va > vb) return sortDir === 'asc' ? 1 : -1;
|
|
342
|
+
return 0;
|
|
343
|
+
});
|
|
344
|
+
setTasks(filtered);
|
|
345
|
+
setTotalCount(allTasks.length); // approximate
|
|
529
346
|
}).catch(function(err) { console.error('[TaskPipeline]', err); })
|
|
530
347
|
.finally(function() { setLoading(false); });
|
|
348
|
+
}, [effectiveOrgId, tab, page, pageSize, search, sortBy, sortDir]);
|
|
349
|
+
|
|
350
|
+
var loadStats = useCallback(function() {
|
|
351
|
+
engineCall('/task-pipeline/stats').then(function(s) { if (s) setStats(s); }).catch(function() {});
|
|
531
352
|
}, [effectiveOrgId]);
|
|
532
353
|
|
|
533
|
-
// SSE
|
|
534
354
|
useEffect(function() {
|
|
535
|
-
|
|
355
|
+
loadTasks();
|
|
356
|
+
loadStats();
|
|
357
|
+
}, [loadTasks, loadStats]);
|
|
358
|
+
|
|
359
|
+
// SSE for real-time updates
|
|
360
|
+
useEffect(function() {
|
|
536
361
|
var baseUrl = window.__ENGINE_BASE || '/api/engine';
|
|
537
362
|
var es;
|
|
538
363
|
try {
|
|
@@ -540,505 +365,238 @@ export function TaskPipelinePage() {
|
|
|
540
365
|
es.onmessage = function(e) {
|
|
541
366
|
try {
|
|
542
367
|
var event = JSON.parse(e.data);
|
|
543
|
-
if (event.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
} else if (event.task) {
|
|
368
|
+
if (event.task) {
|
|
369
|
+
var matchesTab = function(status) {
|
|
370
|
+
if (tab === 'all') return true;
|
|
371
|
+
if (tab === 'active') return status === 'created' || status === 'assigned' || status === 'in_progress';
|
|
372
|
+
if (tab === 'completed') return status === 'completed';
|
|
373
|
+
if (tab === 'failed') return status === 'failed' || status === 'cancelled';
|
|
374
|
+
return true;
|
|
375
|
+
};
|
|
552
376
|
setTasks(function(prev) {
|
|
553
377
|
var idx = prev.findIndex(function(t) { return t.id === event.task.id; });
|
|
554
|
-
if (idx >= 0) {
|
|
555
|
-
|
|
378
|
+
if (idx >= 0) {
|
|
379
|
+
// Task exists in list — update it, then remove if it no longer matches tab
|
|
380
|
+
if (!matchesTab(event.task.status)) {
|
|
381
|
+
// Status changed and no longer belongs in this tab — remove it
|
|
382
|
+
return prev.filter(function(t) { return t.id !== event.task.id; });
|
|
383
|
+
}
|
|
384
|
+
var next = prev.slice();
|
|
385
|
+
next[idx] = Object.assign({}, next[idx], event.task);
|
|
386
|
+
return next;
|
|
387
|
+
}
|
|
388
|
+
// New task — add if it matches current tab
|
|
389
|
+
if (matchesTab(event.task.status)) return [event.task].concat(prev);
|
|
390
|
+
return prev;
|
|
556
391
|
});
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
392
|
+
// Update selected task if it's open
|
|
393
|
+
setSelectedTask(function(prev) { return prev && prev.id === event.task.id ? Object.assign({}, prev, event.task) : prev; });
|
|
394
|
+
// Refresh stats
|
|
395
|
+
loadStats();
|
|
560
396
|
}
|
|
397
|
+
if (event.type === 'init' && event.stats) setStats(event.stats);
|
|
561
398
|
} catch (err) {}
|
|
562
399
|
};
|
|
563
400
|
} catch (err) {}
|
|
564
401
|
return function() { if (es) es.close(); };
|
|
565
|
-
}, []);
|
|
402
|
+
}, [tab]);
|
|
566
403
|
|
|
567
|
-
|
|
568
|
-
if (orgCtx.isLocked) return; // Client org stats computed locally from filtered tasks
|
|
569
|
-
var iv = setInterval(function() {
|
|
570
|
-
engineCall('/task-pipeline/stats').then(function(s) { if (s) setStats(s); }).catch(function() {});
|
|
571
|
-
}, 15000);
|
|
572
|
-
return function() { clearInterval(iv); };
|
|
573
|
-
}, []);
|
|
404
|
+
// (Tab filtering is handled inline in SSE handler + loadTasks)
|
|
574
405
|
|
|
575
406
|
var cancelTask = useCallback(function(taskId) {
|
|
576
407
|
engineCall('/task-pipeline/' + taskId + '/cancel', { method: 'POST' }).then(function() {
|
|
577
408
|
toast('Task cancelled', 'success');
|
|
578
409
|
setSelectedTask(null);
|
|
579
|
-
|
|
410
|
+
loadTasks();
|
|
580
411
|
}).catch(function(err) { toast(err.message || 'Failed', 'error'); });
|
|
581
|
-
}, []);
|
|
412
|
+
}, [loadTasks]);
|
|
582
413
|
|
|
583
|
-
function
|
|
414
|
+
function openTask(t) {
|
|
584
415
|
setSelectedTask(t);
|
|
585
416
|
if (t.chainId) {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
417
|
+
engineCall('/task-pipeline/chain/' + t.chainId).then(function(res) {
|
|
418
|
+
var chain = res?.chain || [];
|
|
419
|
+
chain.sort(function(a, b) { return (a.chainSeq || 0) - (b.chainSeq || 0); });
|
|
420
|
+
setSelectedChain(chain.length > 1 ? chain : null);
|
|
421
|
+
}).catch(function() { setSelectedChain(null); });
|
|
589
422
|
} else {
|
|
590
423
|
setSelectedChain(null);
|
|
591
424
|
}
|
|
592
425
|
}
|
|
593
426
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
setExpandedTaskId(null);
|
|
598
|
-
setSelectedChain(null);
|
|
599
|
-
} else {
|
|
600
|
-
setExpandedTaskId(t.id);
|
|
601
|
-
if (t.chainId) {
|
|
602
|
-
var chainTasks = tasks.filter(function(ct) { return ct.chainId === t.chainId; });
|
|
603
|
-
chainTasks.sort(function(a, b) { return (a.chainSeq || 0) - (b.chainSeq || 0); });
|
|
604
|
-
setSelectedChain(chainTasks.length > 0 ? chainTasks : [t]);
|
|
605
|
-
} else {
|
|
606
|
-
setSelectedChain([t]);
|
|
607
|
-
}
|
|
608
|
-
}
|
|
427
|
+
function handleSort(col) {
|
|
428
|
+
if (sortBy === col) setSortDir(sortDir === 'asc' ? 'desc' : 'asc');
|
|
429
|
+
else { setSortBy(col); setSortDir('desc'); }
|
|
609
430
|
}
|
|
610
431
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
if (filter === 'completed') return t.status === 'completed';
|
|
615
|
-
if (filter === 'failed') return t.status === 'failed' || t.status === 'cancelled';
|
|
616
|
-
return true;
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
// Layout
|
|
620
|
-
var layout = layoutChains(filtered);
|
|
621
|
-
var nodes = layout.nodes;
|
|
622
|
-
var edges = layout.edges;
|
|
623
|
-
var treeW = layout.width;
|
|
624
|
-
var treeH = layout.height;
|
|
625
|
-
var chainInfos = layout.chains;
|
|
626
|
-
|
|
627
|
-
// Zoom/Pan handlers
|
|
628
|
-
var handleWheel = useCallback(function(e) {
|
|
629
|
-
e.preventDefault();
|
|
630
|
-
setZoom(function(z) { return Math.min(3, Math.max(0.15, z + (e.deltaY > 0 ? -0.08 : 0.08))); });
|
|
631
|
-
}, []);
|
|
632
|
-
var handleMouseDown = useCallback(function(e) {
|
|
633
|
-
if (e.button !== 0 || e.target.closest('.tp-node')) return;
|
|
634
|
-
setDragging(true);
|
|
635
|
-
setDragStart({ x: e.clientX - pan.x, y: e.clientY - pan.y });
|
|
636
|
-
}, [pan]);
|
|
637
|
-
var handleMouseMove = useCallback(function(e) {
|
|
638
|
-
if (!dragging) return;
|
|
639
|
-
setPan({ x: e.clientX - dragStart.x, y: e.clientY - dragStart.y });
|
|
640
|
-
}, [dragging, dragStart]);
|
|
641
|
-
var handleMouseUp = useCallback(function() { setDragging(false); }, []);
|
|
642
|
-
useEffect(function() {
|
|
643
|
-
if (dragging) {
|
|
644
|
-
window.addEventListener('mousemove', handleMouseMove);
|
|
645
|
-
window.addEventListener('mouseup', handleMouseUp);
|
|
646
|
-
return function() { window.removeEventListener('mousemove', handleMouseMove); window.removeEventListener('mouseup', handleMouseUp); };
|
|
647
|
-
}
|
|
648
|
-
}, [dragging, handleMouseMove, handleMouseUp]);
|
|
649
|
-
|
|
650
|
-
var fitToView = useCallback(function() {
|
|
651
|
-
// No auto-zoom — keep nodes at full size, use scroll instead
|
|
652
|
-
setZoom(1);
|
|
653
|
-
setPan({ x: 0, y: 0 });
|
|
654
|
-
}, []);
|
|
655
|
-
useEffect(function() { if (nodes.length > 0) fitToView(); }, [nodes.length]);
|
|
656
|
-
|
|
657
|
-
var scrollLeft = useCallback(function() {
|
|
658
|
-
if (containerRef.current) containerRef.current.scrollBy({ left: -400, behavior: 'smooth' });
|
|
659
|
-
}, []);
|
|
660
|
-
var scrollRight = useCallback(function() {
|
|
661
|
-
if (containerRef.current) containerRef.current.scrollBy({ left: 400, behavior: 'smooth' });
|
|
662
|
-
}, []);
|
|
663
|
-
|
|
664
|
-
// Highlight connected chain on hover
|
|
665
|
-
var hoveredChainId = null;
|
|
666
|
-
if (hoveredId) {
|
|
667
|
-
var hn = nodes.find(function(n) { return n.id === hoveredId; });
|
|
668
|
-
if (hn) hoveredChainId = hn.chainId;
|
|
432
|
+
function sortIcon(col) {
|
|
433
|
+
if (sortBy !== col) return h('span', { style: { opacity: 0.2, fontSize: 10 } }, '\u2195');
|
|
434
|
+
return h('span', { style: { fontSize: 10 } }, sortDir === 'asc' ? '\u2191' : '\u2193');
|
|
669
435
|
}
|
|
670
436
|
|
|
671
|
-
var
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
437
|
+
var handleSearch = function(e) {
|
|
438
|
+
var val = e.target.value;
|
|
439
|
+
setSearch(val);
|
|
440
|
+
setPage(0);
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
var totalPages = Math.max(1, Math.ceil(totalCount / pageSize));
|
|
444
|
+
|
|
445
|
+
// Tab counts
|
|
446
|
+
var tabCounts = { active: (stats.inProgress || 0) + (stats.created || 0) + (stats.assigned || 0), completed: stats.completed || 0, failed: (stats.failed || 0) + (stats.cancelled || 0), all: stats.total || 0 };
|
|
447
|
+
|
|
448
|
+
return h(Fragment, null, h(orgCtx.Switcher),
|
|
449
|
+
h('div', { style: { padding: 0 } },
|
|
450
|
+
// Header
|
|
451
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16, flexWrap: 'wrap' } },
|
|
452
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
453
|
+
I.workflow(),
|
|
454
|
+
h('h1', { style: { fontSize: 20, fontWeight: 700, margin: 0 } }, 'Task Pipeline'),
|
|
455
|
+
h(KnowledgeLink, { page: 'task-pipeline' }),
|
|
456
|
+
h(HelpButton, { label: 'Task Pipeline' },
|
|
457
|
+
h('p', null, 'View and manage all agent tasks. Tasks update in real-time via SSE.'),
|
|
458
|
+
h('ul', { style: { paddingLeft: 20, margin: '8px 0' } },
|
|
459
|
+
h('li', null, 'Click any row to see full details, chain flow, and activity log'),
|
|
460
|
+
h('li', null, 'Use tabs to filter by status'),
|
|
461
|
+
h('li', null, 'Search by title, agent, or description'),
|
|
462
|
+
h('li', null, 'Sort by clicking column headers')
|
|
463
|
+
)
|
|
464
|
+
)
|
|
688
465
|
),
|
|
689
|
-
h('
|
|
690
|
-
|
|
691
|
-
h('
|
|
692
|
-
h('li', null, h('strong', null, 'Click'), ' \u2014 Opens detail modal with chain timeline, activity log, customer context'),
|
|
693
|
-
h('li', null, h('strong', null, 'Scroll'), ' \u2014 Zoom'),
|
|
694
|
-
h('li', null, h('strong', null, 'Drag'), ' \u2014 Pan')
|
|
466
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4, marginLeft: 8 } },
|
|
467
|
+
h('div', { style: { width: 8, height: 8, borderRadius: '50%', background: '#15803d', animation: 'flowPulse 2s infinite' } }),
|
|
468
|
+
h('span', { style: { color: 'var(--text-muted)', fontSize: 11 } }, 'Live')
|
|
695
469
|
),
|
|
696
|
-
h('div', { style:
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
|
|
700
|
-
h('div', { style: { width: 8, height: 8, borderRadius: '50%', background: '#15803d', animation: 'flowPulse 2s infinite' } }),
|
|
701
|
-
h('span', { style: { color: 'var(--tp-text-dim)', fontSize: 11 } }, 'Live')
|
|
702
|
-
),
|
|
703
|
-
h('div', { style: { color: 'var(--tp-text-dim)', fontSize: 11 } },
|
|
704
|
-
(stats.inProgress || 0) + ' active \u00B7 ' + (stats.completed || 0) + ' done \u00B7 ' + (stats.total || 0) + ' total'
|
|
705
|
-
),
|
|
706
|
-
h('div', { style: { flex: 1 } }),
|
|
707
|
-
// Filters
|
|
708
|
-
['active', 'all', 'completed', 'failed'].map(function(f) {
|
|
709
|
-
return h('button', { key: f, onClick: function() { setFilter(f); }, style: Object.assign({}, toolbarBtnStyle, { fontSize: 11, background: filter === f ? 'rgba(99,102,241,0.3)' : toolbarBtnStyle.background }) }, f.charAt(0).toUpperCase() + f.slice(1));
|
|
710
|
-
}),
|
|
711
|
-
h('div', { style: { width: 1, height: 14, background: 'rgba(255,255,255,0.12)' } }),
|
|
712
|
-
legendDot(STATUS_COLORS.in_progress, 'Active'),
|
|
713
|
-
legendDot(STATUS_COLORS.completed, 'Done'),
|
|
714
|
-
legendDot(STATUS_COLORS.failed, 'Failed'),
|
|
715
|
-
h('div', { style: { width: 1, height: 14, background: 'rgba(255,255,255,0.12)' } }),
|
|
716
|
-
h('button', { onClick: scrollLeft, style: toolbarBtnStyle, title: 'Scroll left' }, '\u2190'),
|
|
717
|
-
h('button', { onClick: scrollRight, style: toolbarBtnStyle, title: 'Scroll right' }, '\u2192'),
|
|
718
|
-
h('button', { onClick: loadData, style: toolbarBtnStyle }, 'Refresh'),
|
|
719
|
-
);
|
|
720
|
-
|
|
721
|
-
if (loading) return h(Fragment, null, h(orgCtx.Switcher), h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)' } }, 'Loading task pipeline...'));
|
|
722
|
-
|
|
723
|
-
if (nodes.length === 0) return h(Fragment, null, h(orgCtx.Switcher), h('div', { style: { height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--tp-bg)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' } },
|
|
724
|
-
toolbar,
|
|
725
|
-
h(MetricsBar, { stats: stats }),
|
|
726
|
-
h('div', { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column' } },
|
|
727
|
-
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()),
|
|
728
|
-
h('div', { style: { fontSize: 16, fontWeight: 600, marginBottom: 6, color: 'var(--tp-text)' } }, 'No Tasks in Pipeline'),
|
|
729
|
-
h('div', { style: { color: 'var(--tp-text-dim)', fontSize: 13 } }, 'Tasks will appear here as agents are assigned work.')
|
|
730
|
-
)
|
|
731
|
-
));
|
|
732
|
-
|
|
733
|
-
// Build expanded chain for inline flowchart
|
|
734
|
-
var expandedChain = null;
|
|
735
|
-
if (expandedTaskId) {
|
|
736
|
-
var et = tasks.find(function(t) { return t.id === expandedTaskId; });
|
|
737
|
-
if (et && et.chainId) {
|
|
738
|
-
expandedChain = tasks.filter(function(ct) { return ct.chainId === et.chainId; });
|
|
739
|
-
expandedChain.sort(function(a, b) { return (a.chainSeq || 0) - (b.chainSeq || 0); });
|
|
740
|
-
} else if (et) {
|
|
741
|
-
expandedChain = [et];
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
return h(Fragment, null, h(orgCtx.Switcher), h('div', { style: { height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--tp-bg)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' } },
|
|
746
|
-
toolbar,
|
|
747
|
-
// Metrics bar
|
|
748
|
-
h(MetricsBar, { stats: stats }),
|
|
749
|
-
// Canvas — native scroll, no zoom transform
|
|
750
|
-
h('div', {
|
|
751
|
-
ref: containerRef,
|
|
752
|
-
style: { flex: 1, overflow: 'auto', position: 'relative' },
|
|
753
|
-
},
|
|
754
|
-
h('div', { style: { position: 'relative', width: treeW + PAD * 2, minHeight: treeH + PAD * 2 } },
|
|
470
|
+
h('div', { style: { flex: 1 } }),
|
|
471
|
+
h('button', { className: 'btn btn-ghost btn-sm', onClick: function() { loadTasks(); loadStats(); } }, 'Refresh')
|
|
472
|
+
),
|
|
755
473
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
474
|
+
// Stats
|
|
475
|
+
h(StatsRow, { stats: stats }),
|
|
476
|
+
|
|
477
|
+
// Tabs + Search
|
|
478
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 0, borderBottom: '1px solid var(--border)', marginBottom: 0 } },
|
|
479
|
+
['active', 'completed', 'failed', 'all'].map(function(t) {
|
|
480
|
+
var label = t.charAt(0).toUpperCase() + t.slice(1);
|
|
481
|
+
var count = tabCounts[t] || 0;
|
|
482
|
+
return h('button', {
|
|
483
|
+
key: t,
|
|
484
|
+
className: 'tp-tab' + (tab === t ? ' tp-tab-active' : ''),
|
|
485
|
+
onClick: function() { setTab(t); setPage(0); }
|
|
486
|
+
}, label + ' (' + count + ')');
|
|
761
487
|
}),
|
|
488
|
+
h('div', { style: { flex: 1 } }),
|
|
489
|
+
h('input', {
|
|
490
|
+
type: 'text', placeholder: 'Search tasks...', value: search,
|
|
491
|
+
onChange: handleSearch,
|
|
492
|
+
style: { padding: '5px 10px', fontSize: 12, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: 'var(--text-primary)', width: 200, outline: 'none' }
|
|
493
|
+
})
|
|
494
|
+
),
|
|
762
495
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
h('feGaussianBlur', { stdDeviation: 2, result: 'blur' }),
|
|
775
|
-
h('feMerge', null, h('feMergeNode', { in: 'blur' }), h('feMergeNode', { in: 'SourceGraphic' }))
|
|
776
|
-
)
|
|
777
|
-
),
|
|
778
|
-
edges.map(function(e, i) {
|
|
779
|
-
var fromId = e.from.id;
|
|
780
|
-
var toId = e.to.id;
|
|
781
|
-
var isHl = hoveredChainId && e.from.chainId === hoveredChainId;
|
|
782
|
-
var dim = hoveredChainId && !isHl;
|
|
783
|
-
var dType = e.delegationType || 'delegation';
|
|
784
|
-
var edgeColor = isHl ? EDGE_HL : dim ? 'rgba(255,255,255,0.06)' : (DELEGATION_COLORS[dType] || EDGE_COLOR) + '88';
|
|
785
|
-
var d = e.isCircular ? circularPath(e.from, e.to) : horizontalPath(e.from, e.to);
|
|
786
|
-
|
|
787
|
-
return h(Fragment, { key: i },
|
|
788
|
-
// Base path
|
|
789
|
-
h('path', {
|
|
790
|
-
d: d, stroke: edgeColor, strokeWidth: isHl ? 2.5 : 1.5, fill: 'none',
|
|
791
|
-
markerEnd: isHl ? 'url(#tp-arr-hl)' : 'url(#tp-arr)',
|
|
792
|
-
style: { transition: 'stroke 0.2s, opacity 0.2s', opacity: dim ? 0.2 : 1 },
|
|
793
|
-
}),
|
|
794
|
-
// Animated flow dash overlay for active tasks
|
|
795
|
-
e.isActive && h('path', {
|
|
796
|
-
d: d, stroke: STATUS_COLORS.in_progress, strokeWidth: 2, fill: 'none',
|
|
797
|
-
strokeDasharray: '6 18',
|
|
798
|
-
className: 'tp-flow-active',
|
|
799
|
-
filter: 'url(#tp-glow)',
|
|
800
|
-
style: { opacity: dim ? 0.1 : 0.7 },
|
|
801
|
-
}),
|
|
802
|
-
// Delegation type label on edge
|
|
803
|
-
!dim && dType !== 'delegation' && h('text', {
|
|
804
|
-
x: (e.from.x + e.from.w + e.to.x) / 2,
|
|
805
|
-
y: (e.from.y + e.to.y) / 2 + (e.from.h / 2) - (e.isCircular ? 20 : 6),
|
|
806
|
-
fill: (DELEGATION_COLORS[dType] || 'rgba(255,255,255,0.3)') + (dim ? '33' : ''),
|
|
807
|
-
fontSize: 8, textAnchor: 'middle', fontWeight: 600,
|
|
808
|
-
}, dType)
|
|
809
|
-
);
|
|
810
|
-
})
|
|
496
|
+
// Table
|
|
497
|
+
h('div', { style: { border: '1px solid var(--border)', borderTop: 'none', borderRadius: '0 0 var(--radius) var(--radius)', overflow: 'hidden' } },
|
|
498
|
+
// Header
|
|
499
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '2fr 1fr 100px 80px 90px 80px 60px', gap: 0, padding: '8px 12px', background: 'var(--bg-secondary)', borderBottom: '1px solid var(--border)', fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', userSelect: 'none' } },
|
|
500
|
+
h('div', { style: { cursor: 'pointer' }, onClick: function() { handleSort('title'); } }, 'Task ', sortIcon('title')),
|
|
501
|
+
h('div', { style: { cursor: 'pointer' }, onClick: function() { handleSort('assignedToName'); } }, 'Agent ', sortIcon('assignedToName')),
|
|
502
|
+
h('div', { style: { cursor: 'pointer' }, onClick: function() { handleSort('status'); } }, 'Status ', sortIcon('status')),
|
|
503
|
+
h('div', null, 'Priority'),
|
|
504
|
+
h('div', { style: { cursor: 'pointer' }, onClick: function() { handleSort('createdAt'); } }, 'Created ', sortIcon('createdAt')),
|
|
505
|
+
h('div', null, 'Duration'),
|
|
506
|
+
h('div', null, 'Source')
|
|
811
507
|
),
|
|
812
508
|
|
|
813
|
-
//
|
|
814
|
-
|
|
815
|
-
var
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
},
|
|
841
|
-
// Agent + title row
|
|
842
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 5 } },
|
|
843
|
-
(agentMap[t.assignedTo] && agentMap[t.assignedTo].avatar)
|
|
844
|
-
? h('img', { src: agentMap[t.assignedTo].avatar, style: { width: 16, height: 16, borderRadius: '50%', border: '1px solid ' + sc + '66', objectFit: 'cover', flexShrink: 0 } })
|
|
845
|
-
: 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, border: '1px solid ' + sc + '44' } },
|
|
846
|
-
(t.assignedToName || t.assignedTo || '?').charAt(0).toUpperCase()
|
|
847
|
-
),
|
|
848
|
-
h('span', { style: { fontSize: 10, fontWeight: 600, color: 'var(--tp-text)', flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, t.title)
|
|
849
|
-
),
|
|
850
|
-
// Status + agent name + time
|
|
851
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4, flexWrap: 'nowrap', overflow: 'hidden' } },
|
|
852
|
-
tag(sc, t.status.replace('_', ' ')),
|
|
853
|
-
h('span', { style: { fontSize: 9, color: 'var(--tp-text-dim)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0 } }, t.assignedToName || t.assignedTo),
|
|
854
|
-
t.source && sourceBadge(t.source),
|
|
855
|
-
t.delegationType && tag(DELEGATION_COLORS[t.delegationType] || '#6b7394', t.delegationType),
|
|
856
|
-
h('span', { style: { fontSize: 9, color: 'var(--tp-text-dim)', marginLeft: 'auto' } }, timeAgo(t.createdAt))
|
|
857
|
-
),
|
|
858
|
-
// Progress bar
|
|
859
|
-
isActive && t.progress > 0 && h('div', { style: { height: 2, background: 'var(--tp-border)', borderRadius: 1, overflow: 'hidden', marginTop: 1 } },
|
|
860
|
-
h('div', { style: { height: '100%', width: t.progress + '%', background: sc, borderRadius: 1, transition: 'width 0.3s' } })
|
|
861
|
-
)
|
|
862
|
-
);
|
|
863
|
-
}),
|
|
864
|
-
|
|
865
|
-
// ── Expanded chain flow (rendered ON the canvas below clicked node) ──
|
|
866
|
-
expandedChain && expandedChain.length > 0 && (function() {
|
|
867
|
-
// Find the clicked node position to anchor below it
|
|
868
|
-
var anchor = nodes.find(function(n) { return n.id === expandedTaskId; });
|
|
869
|
-
if (!anchor) return null;
|
|
870
|
-
var flowY = anchor.y + anchor.h + 20;
|
|
871
|
-
var flowX = anchor.x;
|
|
872
|
-
var STEP_W = 100;
|
|
873
|
-
var STEP_H = 36;
|
|
874
|
-
var STEP_GAP = 32;
|
|
875
|
-
var ARROW_W = STEP_GAP;
|
|
876
|
-
|
|
877
|
-
// Build person-centric flow steps: createdBy → assignedTo for each chain task, then final status
|
|
878
|
-
var steps = [];
|
|
879
|
-
expandedChain.forEach(function(ct, i) {
|
|
880
|
-
if (i === 0 && ct.createdBy && ct.createdBy !== 'system') {
|
|
881
|
-
steps.push({ label: ct.createdByName || ct.createdBy, type: 'person', isHuman: ct.createdBy.indexOf('agent') === -1 && ct.createdBy !== 'system', status: null, arrow: ct.delegationType || 'assigned' });
|
|
882
|
-
} else if (i === 0 && ct.createdBy === 'system') {
|
|
883
|
-
steps.push({ label: 'System', type: 'system', isHuman: false, status: null, arrow: 'assigned' });
|
|
884
|
-
}
|
|
885
|
-
var nextArrow = i < expandedChain.length - 1 ? (expandedChain[i + 1].delegationType || 'delegation') : null;
|
|
886
|
-
steps.push({ label: ct.assignedToName || ct.assignedTo, type: 'agent', isHuman: false, status: ct.status, taskId: ct.id, arrow: nextArrow, duration: ct.actualDurationMs, progress: ct.progress });
|
|
887
|
-
});
|
|
888
|
-
// Add final status node + ensure arrow from last agent to terminal
|
|
889
|
-
var lastTask = expandedChain[expandedChain.length - 1];
|
|
890
|
-
var isDone = lastTask.status === 'completed' || lastTask.status === 'failed' || lastTask.status === 'cancelled';
|
|
891
|
-
if (isDone) {
|
|
892
|
-
// Set arrow on the last non-terminal step so the connector draws
|
|
893
|
-
if (steps.length > 0 && !steps[steps.length - 1].arrow) {
|
|
894
|
-
steps[steps.length - 1].arrow = lastTask.status;
|
|
895
|
-
}
|
|
896
|
-
steps.push({ label: lastTask.status === 'completed' ? 'Completed!' : lastTask.status === 'failed' ? 'Failed' : 'Cancelled', type: 'terminal', isHuman: false, status: lastTask.status, arrow: null });
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
var totalW = steps.length * STEP_W + (steps.length - 1) * STEP_GAP;
|
|
900
|
-
|
|
901
|
-
var maxFlowW = Math.max(totalW + 40, 400);
|
|
902
|
-
var containerW = (containerRef.current ? containerRef.current.getBoundingClientRect().width / zoom : 800) - flowX;
|
|
903
|
-
if (maxFlowW > containerW) maxFlowW = Math.max(containerW, 320);
|
|
904
|
-
|
|
905
|
-
return h('div', { style: { position: 'absolute', left: flowX, top: flowY, pointerEvents: 'auto', maxWidth: maxFlowW, zIndex: 20 } },
|
|
906
|
-
// Background card
|
|
907
|
-
h('div', { style: { background: 'var(--bg-primary, rgba(10,12,20,0.95))', border: '1px solid rgba(99,102,241,0.2)', borderRadius: 8, padding: '8px 10px 8px', backdropFilter: 'blur(8px)', overflowX: 'auto', overflowY: 'hidden' } },
|
|
908
|
-
// Header
|
|
909
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, marginBottom: 8 } },
|
|
910
|
-
h('span', { style: { fontSize: 9, fontWeight: 600, color: 'var(--tp-text-dim)', letterSpacing: '0.06em' } }, 'TASK FLOW'),
|
|
911
|
-
expandedChain[0].chainId && h('span', { style: { fontSize: 8, color: 'rgba(255,255,255,0.2)', fontFamily: 'var(--font-mono)' } }, '#' + expandedChain[0].chainId.slice(0, 8)),
|
|
912
|
-
h('div', { style: { flex: 1 } }),
|
|
913
|
-
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')
|
|
914
|
-
),
|
|
915
|
-
// Flow
|
|
916
|
-
h('div', { style: { position: 'relative', height: STEP_H + 8, minWidth: totalW } },
|
|
917
|
-
// SVG arrows
|
|
918
|
-
h('svg', { width: totalW, height: STEP_H + 8, style: { position: 'absolute', top: 0, left: 0, pointerEvents: 'none' } },
|
|
919
|
-
h('defs', null,
|
|
920
|
-
h('marker', { id: 'fc-arr', markerWidth: 8, markerHeight: 6, refX: 8, refY: 3, orient: 'auto' },
|
|
921
|
-
h('polygon', { points: '0 0, 8 3, 0 6', fill: 'var(--tp-text-dim, rgba(99,102,241,0.6))' })
|
|
922
|
-
),
|
|
923
|
-
h('marker', { id: 'fc-arr-active', markerWidth: 8, markerHeight: 6, refX: 8, refY: 3, orient: 'auto' },
|
|
924
|
-
h('polygon', { points: '0 0, 8 3, 0 6', fill: STATUS_COLORS.in_progress })
|
|
509
|
+
// Rows
|
|
510
|
+
loading && tasks.length === 0
|
|
511
|
+
? h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)', fontSize: 13 } }, 'Loading...')
|
|
512
|
+
: tasks.length === 0
|
|
513
|
+
? h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)' } },
|
|
514
|
+
h('div', { style: { fontSize: 14, fontWeight: 600, marginBottom: 4 } }, 'No tasks found'),
|
|
515
|
+
h('div', { style: { fontSize: 12 } }, search ? 'Try a different search term' : 'Tasks will appear here as agents are assigned work')
|
|
516
|
+
)
|
|
517
|
+
: tasks.map(function(t) {
|
|
518
|
+
var sc = STATUS_COLORS[t.status] || '#6b7394';
|
|
519
|
+
var agent = agentMap[t.assignedTo];
|
|
520
|
+
var isActive = t.status === 'in_progress';
|
|
521
|
+
return h('div', {
|
|
522
|
+
key: t.id,
|
|
523
|
+
className: 'tp-row' + (isActive ? ' tp-row-active' : ''),
|
|
524
|
+
onClick: function() { openTask(t); },
|
|
525
|
+
style: { display: 'grid', gridTemplateColumns: '2fr 1fr 100px 80px 90px 80px 60px', gap: 0, padding: '10px 12px', borderBottom: '1px solid var(--border)', cursor: 'pointer', alignItems: 'center', fontSize: 12 }
|
|
526
|
+
},
|
|
527
|
+
// Task title + chain indicator
|
|
528
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, overflow: 'hidden' } },
|
|
529
|
+
t.chainId && h('div', { style: { width: 3, height: 20, borderRadius: 2, background: '#6366f1', flexShrink: 0 } }),
|
|
530
|
+
h('div', { style: { overflow: 'hidden' } },
|
|
531
|
+
h('div', { style: { fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, t.title),
|
|
532
|
+
(t.category || t.delegationType) && h('div', { style: { fontSize: 10, color: 'var(--text-muted)', marginTop: 1, display: 'flex', gap: 4, alignItems: 'center' } },
|
|
533
|
+
t.category,
|
|
534
|
+
t.delegationType && tag(DELEGATION_COLORS[t.delegationType] || '#6b7394', t.delegationType)
|
|
535
|
+
)
|
|
925
536
|
)
|
|
926
537
|
),
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
);
|
|
942
|
-
})
|
|
943
|
-
),
|
|
944
|
-
// Step nodes
|
|
945
|
-
steps.map(function(step, i) {
|
|
946
|
-
var x = i * (STEP_W + STEP_GAP);
|
|
947
|
-
var sc = step.type === 'terminal'
|
|
948
|
-
? (STATUS_COLORS[step.status] || '#15803d')
|
|
949
|
-
: step.type === 'person' || step.isHuman
|
|
950
|
-
? '#991b1b'
|
|
951
|
-
: step.status ? (STATUS_COLORS[step.status] || '#6366f1') : '#6366f1';
|
|
952
|
-
var isTerminal = step.type === 'terminal';
|
|
953
|
-
var isMe = step.taskId === expandedTaskId;
|
|
954
|
-
|
|
955
|
-
return h('div', {
|
|
956
|
-
key: i,
|
|
957
|
-
className: 'tp-node',
|
|
958
|
-
onClick: function(e) { e.stopPropagation(); if (step.taskId) { var ct = expandedChain.find(function(c) { return c.id === step.taskId; }); if (ct) openTaskDetail(ct); } else if (expandedChain.length > 0) { openTaskDetail(expandedChain[0]); } },
|
|
959
|
-
style: {
|
|
960
|
-
position: 'absolute', left: x, top: 4, width: isTerminal ? 'auto' : STEP_W, minWidth: isTerminal ? 90 : undefined, height: STEP_H,
|
|
961
|
-
background: isTerminal ? sc + '15' : isMe ? 'rgba(255,255,255,0.06)' : 'rgba(255,255,255,0.02)',
|
|
962
|
-
border: '1px solid ' + (isTerminal ? sc + '44' : isMe ? sc : 'rgba(255,255,255,0.1)'),
|
|
963
|
-
borderRadius: isTerminal ? 18 : 6,
|
|
964
|
-
display: 'flex', alignItems: 'center', gap: 6, padding: '0 8px',
|
|
965
|
-
cursor: 'pointer',
|
|
966
|
-
},
|
|
967
|
-
},
|
|
968
|
-
// Avatar
|
|
969
|
-
(function() {
|
|
970
|
-
// Check if we have an agent avatar for this step
|
|
971
|
-
var stepAgent = step.taskId && expandedChain.find(function(c) { return c.id === step.taskId; });
|
|
972
|
-
var agentAvatar = stepAgent && agentMap[stepAgent.assignedTo] && agentMap[stepAgent.assignedTo].avatar;
|
|
973
|
-
if (!isTerminal && agentAvatar) {
|
|
974
|
-
return h('img', { src: agentAvatar, style: { width: 18, height: 18, borderRadius: '50%', border: '1px solid ' + sc + '44', objectFit: 'cover', flexShrink: 0 } });
|
|
975
|
-
}
|
|
976
|
-
return h('div', { style: {
|
|
977
|
-
width: 18, height: 18, borderRadius: '50%', flexShrink: 0,
|
|
978
|
-
background: isTerminal ? sc + '33' : step.isHuman || step.type === 'person' ? 'linear-gradient(135deg, #991b1b, #f97316)' : step.type === 'system' ? 'var(--tp-card)' : 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
|
979
|
-
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
980
|
-
fontSize: isTerminal ? 10 : 8, fontWeight: 700,
|
|
981
|
-
color: isTerminal ? sc : '#fff',
|
|
982
|
-
border: '1px solid ' + (isTerminal ? sc + '44' : 'transparent'),
|
|
983
|
-
} },
|
|
984
|
-
isTerminal ? (step.status === 'completed' ? '\u2714' : '\u2716') : step.label.charAt(0).toUpperCase()
|
|
985
|
-
);
|
|
986
|
-
})(),
|
|
987
|
-
// Info
|
|
988
|
-
h('div', { style: { overflow: 'hidden', flex: 1, minWidth: 0 } },
|
|
989
|
-
h('div', { style: { fontSize: 10, fontWeight: 600, color: isTerminal ? sc : 'var(--tp-text)', whiteSpace: 'nowrap', overflow: isTerminal ? 'visible' : 'hidden', textOverflow: isTerminal ? 'unset' : 'ellipsis' } }, step.label),
|
|
990
|
-
!isTerminal && h('div', { style: { fontSize: 8, color: 'var(--tp-text-dim)', marginTop: 1 } },
|
|
991
|
-
step.type === 'person' || step.isHuman ? 'Human' : step.type === 'system' ? 'System' : 'Agent',
|
|
992
|
-
step.duration ? ' \u00B7 ' + formatDuration(step.duration) : '',
|
|
993
|
-
step.status === 'in_progress' && step.progress > 0 ? ' \u00B7 ' + step.progress + '%' : ''
|
|
994
|
-
)
|
|
538
|
+
// Agent
|
|
539
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, overflow: 'hidden' } },
|
|
540
|
+
agent && agent.avatar
|
|
541
|
+
? h('img', { src: agent.avatar, style: { width: 20, height: 20, borderRadius: '50%', objectFit: 'cover', flexShrink: 0 } })
|
|
542
|
+
: h('div', { style: { width: 20, height: 20, borderRadius: '50%', background: sc + '22', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 8, fontWeight: 700, color: sc, flexShrink: 0 } },
|
|
543
|
+
(t.assignedToName || t.assignedTo || '?').charAt(0).toUpperCase()
|
|
544
|
+
),
|
|
545
|
+
h('span', { style: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: 11 } }, t.assignedToName || (agent && agent.name) || t.assignedTo || '-')
|
|
546
|
+
),
|
|
547
|
+
// Status
|
|
548
|
+
h('div', null,
|
|
549
|
+
h('span', { style: { padding: '2px 8px', borderRadius: 8, fontSize: 10, fontWeight: 600, background: sc + '22', color: sc } }, t.status.replace('_', ' ')),
|
|
550
|
+
isActive && t.progress > 0 && h('div', { style: { height: 3, background: 'var(--border)', borderRadius: 2, marginTop: 4, overflow: 'hidden' } },
|
|
551
|
+
h('div', { style: { height: '100%', width: t.progress + '%', background: '#06b6d4', borderRadius: 2 } })
|
|
995
552
|
)
|
|
996
|
-
)
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
border: '1px solid var(--tp-border)', borderRadius: 10, boxShadow: '0 8px 32px rgba(0,0,0,0.2)',
|
|
1010
|
-
padding: '10px 14px', pointerEvents: 'none', zIndex: 1000, minWidth: 180, maxWidth: 280,
|
|
1011
|
-
}},
|
|
1012
|
-
hoveredNode.task.customerContext && h(CustomerBadge, { customer: hoveredNode.task.customerContext }),
|
|
1013
|
-
h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 } },
|
|
1014
|
-
(agentMap[hoveredNode.task.assignedTo] && agentMap[hoveredNode.task.assignedTo].avatar)
|
|
1015
|
-
? h('img', { src: agentMap[hoveredNode.task.assignedTo].avatar, style: { width: 22, height: 22, borderRadius: '50%', border: '1.5px solid ' + (STATUS_COLORS[hoveredNode.task.status] || '#6366f1'), objectFit: 'cover', flexShrink: 0 } })
|
|
1016
|
-
: null,
|
|
1017
|
-
h('div', { style: { fontSize: 12, fontWeight: 600, color: 'var(--tp-text)' } }, hoveredNode.task.title)
|
|
553
|
+
),
|
|
554
|
+
// Priority
|
|
555
|
+
h('div', null,
|
|
556
|
+
h('span', { style: { fontSize: 10, fontWeight: 600, color: PRIORITY_COLORS[t.priority] || '#6366f1' } }, (t.priority || 'normal'))
|
|
557
|
+
),
|
|
558
|
+
// Created
|
|
559
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)' } }, timeAgo(t.createdAt)),
|
|
560
|
+
// Duration
|
|
561
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)' } }, formatDuration(t.actualDurationMs)),
|
|
562
|
+
// Source
|
|
563
|
+
h('div', null, t.source ? sourceBadge(t.source) : h('span', { style: { fontSize: 10, color: 'var(--text-muted)' } }, '-'))
|
|
564
|
+
);
|
|
565
|
+
})
|
|
1018
566
|
),
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
567
|
+
|
|
568
|
+
// Pagination
|
|
569
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 0', fontSize: 12 } },
|
|
570
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, color: 'var(--text-muted)' } },
|
|
571
|
+
h('span', null, 'Showing ' + tasks.length + ' of ' + (stats.total || totalCount) + ' tasks'),
|
|
572
|
+
h('select', {
|
|
573
|
+
value: pageSize,
|
|
574
|
+
onChange: function(e) { setPageSize(parseInt(e.target.value)); setPage(0); },
|
|
575
|
+
style: { padding: '3px 6px', fontSize: 11, borderRadius: 4, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: 'var(--text-primary)' }
|
|
576
|
+
},
|
|
577
|
+
PAGE_SIZES.map(function(s) { return h('option', { key: s, value: s }, s + ' per page'); })
|
|
578
|
+
)
|
|
579
|
+
),
|
|
580
|
+
h('div', { style: { display: 'flex', gap: 4, alignItems: 'center' } },
|
|
581
|
+
h('button', { className: 'btn btn-ghost btn-sm', disabled: page === 0, onClick: function() { setPage(0); } }, 'First'),
|
|
582
|
+
h('button', { className: 'btn btn-ghost btn-sm', disabled: page === 0, onClick: function() { setPage(page - 1); } }, 'Prev'),
|
|
583
|
+
h('span', { style: { padding: '0 8px', color: 'var(--text-muted)' } }, 'Page ' + (page + 1)),
|
|
584
|
+
h('button', { className: 'btn btn-ghost btn-sm', disabled: tasks.length < pageSize, onClick: function() { setPage(page + 1); } }, 'Next')
|
|
585
|
+
)
|
|
1025
586
|
)
|
|
1026
587
|
),
|
|
1027
588
|
|
|
1028
|
-
// Detail modal
|
|
1029
|
-
selectedTask && h(TaskDetail, { task: selectedTask, chain: selectedChain, onClose: function() { setSelectedTask(null); setSelectedChain(null); }, onCancel: cancelTask })
|
|
1030
|
-
)
|
|
589
|
+
// Detail modal
|
|
590
|
+
selectedTask && h(TaskDetail, { task: selectedTask, chain: selectedChain, onClose: function() { setSelectedTask(null); setSelectedChain(null); }, onCancel: cancelTask, agentMap: agentMap })
|
|
591
|
+
);
|
|
1031
592
|
}
|
|
1032
593
|
|
|
1033
594
|
// ─── Agent Task Pipeline (reusable mini for agent-detail workforce tab) ─
|
|
1034
595
|
export function AgentTaskPipeline(props) {
|
|
1035
596
|
var agentId = props.agentId;
|
|
1036
|
-
var _tasks = useState([]);
|
|
1037
|
-
var
|
|
1038
|
-
var
|
|
1039
|
-
var loading = _loading[0]; var setLoading = _loading[1];
|
|
1040
|
-
var _selectedTask = useState(null);
|
|
1041
|
-
var selectedTask = _selectedTask[0]; var setSelectedTask = _selectedTask[1];
|
|
597
|
+
var _tasks = useState([]); var tasks = _tasks[0]; var setTasks = _tasks[1];
|
|
598
|
+
var _loading = useState(true); var loading = _loading[0]; var setLoading = _loading[1];
|
|
599
|
+
var _selectedTask = useState(null); var selectedTask = _selectedTask[0]; var setSelectedTask = _selectedTask[1];
|
|
1042
600
|
var app = useApp();
|
|
1043
601
|
var toast = app.toast;
|
|
1044
602
|
|
|
@@ -1084,8 +642,7 @@ export function AgentTaskPipeline(props) {
|
|
|
1084
642
|
function renderTaskRow(t) {
|
|
1085
643
|
var sc = STATUS_COLORS[t.status] || '#6b7394';
|
|
1086
644
|
return h('div', {
|
|
1087
|
-
key: t.id,
|
|
1088
|
-
onClick: function() { setSelectedTask(t); },
|
|
645
|
+
key: t.id, onClick: function() { setSelectedTask(t); },
|
|
1089
646
|
style: { display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', borderBottom: '1px solid var(--border)', cursor: 'pointer', transition: 'background 0.15s' },
|
|
1090
647
|
onMouseEnter: function(e) { e.currentTarget.style.background = 'var(--bg-secondary)'; },
|
|
1091
648
|
onMouseLeave: function(e) { e.currentTarget.style.background = ''; },
|
|
@@ -1122,6 +679,6 @@ export function AgentTaskPipeline(props) {
|
|
|
1122
679
|
h('div', { style: { fontSize: 11, fontWeight: 600, color: STATUS_COLORS.failed, marginBottom: 6 } }, 'Failed (' + failed.length + ')'),
|
|
1123
680
|
h('div', { style: { border: '1px solid var(--border)', borderRadius: 'var(--radius)', overflow: 'hidden' } }, failed.slice(0, 5).map(renderTaskRow))
|
|
1124
681
|
),
|
|
1125
|
-
selectedTask && h(TaskDetail, { task: selectedTask, chain: null, onClose: function() { setSelectedTask(null); }, onCancel: cancelTask })
|
|
682
|
+
selectedTask && h(TaskDetail, { task: selectedTask, chain: null, onClose: function() { setSelectedTask(null); }, onCancel: cancelTask, agentMap: {} })
|
|
1126
683
|
);
|
|
1127
684
|
}
|