@sleep2agi/agent-network-dashboard 0.4.3-preview.1 → 0.4.5-preview.0

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.
Files changed (272) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +6 -6
  3. package/.next/diagnostics/route-bundle-stats.json +106 -92
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/prerender-manifest.json +3 -3
  6. package/.next/server/app/_global-error/page/build-manifest.json +3 -3
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found/page/build-manifest.json +3 -3
  15. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  16. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  17. package/.next/server/app/_not-found.html +2 -2
  18. package/.next/server/app/_not-found.rsc +12 -12
  19. package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
  20. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  21. package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
  22. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  23. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  24. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  25. package/.next/server/app/admin/page/build-manifest.json +3 -3
  26. package/.next/server/app/admin/page.js.nft.json +1 -1
  27. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  28. package/.next/server/app/admin.html +2 -2
  29. package/.next/server/app/admin.rsc +14 -14
  30. package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
  31. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  32. package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
  33. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  34. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  35. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  36. package/.next/server/app/index.html +2 -2
  37. package/.next/server/app/index.rsc +14 -14
  38. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  39. package/.next/server/app/index.segments/_full.segment.rsc +14 -14
  40. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  41. package/.next/server/app/index.segments/_index.segment.rsc +7 -7
  42. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  43. package/.next/server/app/login/page/build-manifest.json +3 -3
  44. package/.next/server/app/login/page.js.nft.json +1 -1
  45. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  46. package/.next/server/app/login.html +2 -2
  47. package/.next/server/app/login.rsc +14 -14
  48. package/.next/server/app/login.segments/_full.segment.rsc +14 -14
  49. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  50. package/.next/server/app/login.segments/_index.segment.rsc +7 -7
  51. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  52. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  53. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  54. package/.next/server/app/logs/page/build-manifest.json +3 -3
  55. package/.next/server/app/logs/page.js.nft.json +1 -1
  56. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  57. package/.next/server/app/logs.html +2 -2
  58. package/.next/server/app/logs.rsc +14 -14
  59. package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
  60. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  61. package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
  62. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  63. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  64. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  65. package/.next/server/app/messages/page/build-manifest.json +3 -3
  66. package/.next/server/app/messages/page.js.nft.json +1 -1
  67. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  68. package/.next/server/app/messages.html +2 -2
  69. package/.next/server/app/messages.rsc +14 -14
  70. package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
  71. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  72. package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
  73. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  74. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  75. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  76. package/.next/server/app/node/page/build-manifest.json +3 -3
  77. package/.next/server/app/node/page.js.nft.json +1 -1
  78. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  79. package/.next/server/app/node.html +2 -2
  80. package/.next/server/app/node.rsc +14 -14
  81. package/.next/server/app/node.segments/_full.segment.rsc +14 -14
  82. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  83. package/.next/server/app/node.segments/_index.segment.rsc +7 -7
  84. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  85. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  86. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  87. package/.next/server/app/nodes/page/build-manifest.json +3 -3
  88. package/.next/server/app/nodes/page.js.nft.json +1 -1
  89. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  90. package/.next/server/app/nodes.html +2 -2
  91. package/.next/server/app/nodes.rsc +14 -14
  92. package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
  93. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  94. package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
  95. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  96. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  97. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  98. package/.next/server/app/page/build-manifest.json +3 -3
  99. package/.next/server/app/page.js.nft.json +1 -1
  100. package/.next/server/app/page_client-reference-manifest.js +1 -1
  101. package/.next/server/app/server-logs/page/build-manifest.json +3 -3
  102. package/.next/server/app/server-logs/page.js.nft.json +1 -1
  103. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/server-logs.html +2 -2
  105. package/.next/server/app/server-logs.rsc +14 -14
  106. package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
  107. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  108. package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
  109. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  110. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  111. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  112. package/.next/server/app/settings/networks/page/build-manifest.json +3 -3
  113. package/.next/server/app/settings/networks/page.js.nft.json +1 -1
  114. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  115. package/.next/server/app/settings/networks.html +2 -2
  116. package/.next/server/app/settings/networks.rsc +14 -14
  117. package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
  118. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  119. package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
  120. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  121. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  122. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  123. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  124. package/.next/server/app/settings/page/build-manifest.json +3 -3
  125. package/.next/server/app/settings/page.js.nft.json +1 -1
  126. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  127. package/.next/server/app/settings/tokens/page/build-manifest.json +3 -3
  128. package/.next/server/app/settings/tokens/page.js.nft.json +1 -1
  129. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  130. package/.next/server/app/settings/tokens.html +2 -2
  131. package/.next/server/app/settings/tokens.rsc +14 -14
  132. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
  133. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  134. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
  135. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  136. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  137. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  138. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  139. package/.next/server/app/settings.html +2 -2
  140. package/.next/server/app/settings.rsc +14 -14
  141. package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
  142. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  143. package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
  144. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  145. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  146. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  147. package/.next/server/app/tasks/[id]/page/build-manifest.json +3 -3
  148. package/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  149. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  150. package/.next/server/app/tasks/page/build-manifest.json +3 -3
  151. package/.next/server/app/tasks/page.js.nft.json +1 -1
  152. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  153. package/.next/server/app/tasks.html +2 -2
  154. package/.next/server/app/tasks.rsc +14 -14
  155. package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
  156. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  157. package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
  158. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  159. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  160. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  161. package/.next/server/chunks/ssr/[root-of-the-server]__013i9e9._.js +9 -0
  162. package/.next/server/chunks/ssr/[root-of-the-server]__013i9e9._.js.map +1 -0
  163. package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js +3 -0
  164. package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js.map +1 -0
  165. package/.next/server/chunks/ssr/[root-of-the-server]__12mpoig._.js +3 -0
  166. package/.next/server/chunks/ssr/[root-of-the-server]__12mpoig._.js.map +1 -0
  167. package/.next/server/chunks/ssr/_0d-fuox._.js +3 -0
  168. package/.next/server/chunks/ssr/_0d-fuox._.js.map +1 -0
  169. package/.next/server/chunks/ssr/app_0.0wpa~._.js +3 -0
  170. package/.next/server/chunks/ssr/app_0.0wpa~._.js.map +1 -0
  171. package/.next/server/chunks/ssr/app_0dk5wao._.js +1 -1
  172. package/.next/server/chunks/ssr/app_0dk5wao._.js.map +1 -1
  173. package/.next/server/chunks/ssr/app_0et5yua._.js +3 -0
  174. package/.next/server/chunks/ssr/app_0et5yua._.js.map +1 -0
  175. package/.next/server/chunks/ssr/app_0ff~kjj._.js +9 -0
  176. package/.next/server/chunks/ssr/app_0ff~kjj._.js.map +1 -0
  177. package/.next/server/chunks/ssr/app_0izi28j._.js +3 -0
  178. package/.next/server/chunks/ssr/app_0izi28j._.js.map +1 -0
  179. package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js +1 -1
  180. package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js.map +1 -1
  181. package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js +1 -1
  182. package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js.map +1 -1
  183. package/.next/server/chunks/ssr/app_server-logs_page_tsx_0_kpp1p._.js +1 -1
  184. package/.next/server/chunks/ssr/app_server-logs_page_tsx_0_kpp1p._.js.map +1 -1
  185. package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js +1 -1
  186. package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js.map +1 -1
  187. package/.next/server/chunks/ssr/node_modules_0ck2~9g._.js +3 -0
  188. package/.next/server/chunks/ssr/node_modules_0ck2~9g._.js.map +1 -0
  189. package/.next/server/middleware-build-manifest.js +6 -6
  190. package/.next/server/pages/404.html +2 -2
  191. package/.next/server/pages/500.html +1 -1
  192. package/.next/server/server-reference-manifest.js +1 -1
  193. package/.next/server/server-reference-manifest.json +1 -1
  194. package/.next/static/chunks/0257pdz1-imal.js +2 -0
  195. package/.next/static/chunks/02flrewxlf_m_.js +1 -0
  196. package/.next/static/chunks/051gslfjka1kj.js +1 -0
  197. package/.next/static/chunks/06t_vzei8s9_h.js +1 -0
  198. package/.next/static/chunks/0e-.zgw81gela.js +31 -0
  199. package/.next/static/chunks/0e7c40p~wq665.js +1 -0
  200. package/.next/static/chunks/0g7m7zk.v7g6h.js +1 -0
  201. package/.next/static/chunks/0hyhubmh-__wg.js +1 -0
  202. package/.next/static/chunks/0khpyxpdrp~ty.js +1 -0
  203. package/.next/static/chunks/0lo_g.q1fm-hr.js +7 -0
  204. package/.next/static/chunks/0snd~q2ucn.h1.css +2 -0
  205. package/.next/static/chunks/0w1zwt8kq_7nb.js +1 -0
  206. package/.next/static/chunks/0xn9.0ejo1s_a.js +7 -0
  207. package/.next/static/chunks/0y0lo-~k2c~00.js +1 -0
  208. package/.next/static/chunks/10njj7kn9ylkf.js +1 -0
  209. package/.next/static/chunks/13.dst7liziwo.js +1 -0
  210. package/.next/static/chunks/{turbopack-0vsvjs02l449s.js → turbopack-01f1xs~cq_~si.js} +1 -1
  211. package/.next/trace +2 -2
  212. package/.next/trace-build +1 -1
  213. package/app/components/EmptyState.tsx +189 -0
  214. package/app/components/LoadingSkeleton.tsx +3 -18
  215. package/app/components/Sidebar.tsx +72 -11
  216. package/app/components/StatsBar.tsx +7 -1
  217. package/app/components/TopoGraph.tsx +151 -62
  218. package/app/globals.css +108 -8
  219. package/app/login/page.tsx +26 -13
  220. package/app/logs/page.tsx +24 -11
  221. package/app/messages/page.tsx +2 -5
  222. package/app/nodes/page.tsx +6 -1
  223. package/app/page.tsx +36 -12
  224. package/app/server-logs/page.tsx +22 -11
  225. package/app/settings/networks/page.tsx +6 -1
  226. package/app/settings/page.tsx +56 -29
  227. package/app/settings/tokens/page.tsx +6 -1
  228. package/app/tasks/page.tsx +7 -9
  229. package/docs/loop-design-rounds.md +502 -0
  230. package/docs/oss-readiness-report.md +189 -0
  231. package/package.json +1 -1
  232. package/.mcp.json +0 -11
  233. package/.next/server/chunks/ssr/[root-of-the-server]__093ymui._.js +0 -3
  234. package/.next/server/chunks/ssr/[root-of-the-server]__093ymui._.js.map +0 -1
  235. package/.next/server/chunks/ssr/[root-of-the-server]__0i1gizm._.js +0 -9
  236. package/.next/server/chunks/ssr/[root-of-the-server]__0i1gizm._.js.map +0 -1
  237. package/.next/server/chunks/ssr/[root-of-the-server]__0~yad5w._.js +0 -3
  238. package/.next/server/chunks/ssr/[root-of-the-server]__0~yad5w._.js.map +0 -1
  239. package/.next/server/chunks/ssr/_06_xh1~._.js +0 -3
  240. package/.next/server/chunks/ssr/_06_xh1~._.js.map +0 -1
  241. package/.next/server/chunks/ssr/app_01vhyfx._.js +0 -9
  242. package/.next/server/chunks/ssr/app_01vhyfx._.js.map +0 -1
  243. package/.next/server/chunks/ssr/app_023a94i._.js +0 -3
  244. package/.next/server/chunks/ssr/app_023a94i._.js.map +0 -1
  245. package/.next/server/chunks/ssr/app_0basiqb._.js +0 -3
  246. package/.next/server/chunks/ssr/app_0basiqb._.js.map +0 -1
  247. package/.next/server/chunks/ssr/app_0pljk5o._.js +0 -3
  248. package/.next/server/chunks/ssr/app_0pljk5o._.js.map +0 -1
  249. package/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js +0 -3
  250. package/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js.map +0 -1
  251. package/.next/static/chunks/0.z~9klrgd.t-.js +0 -1
  252. package/.next/static/chunks/08aj9~75raaah.js +0 -7
  253. package/.next/static/chunks/08iom_z8w-wmz.js +0 -7
  254. package/.next/static/chunks/08v0-ki6vwpxf.js +0 -1
  255. package/.next/static/chunks/0agna31q2fjq1.css +0 -2
  256. package/.next/static/chunks/0dkkv90do9a4r.js +0 -1
  257. package/.next/static/chunks/0e-wrhqh4h3r5.js +0 -2
  258. package/.next/static/chunks/0ejz4zwhu3a3y.js +0 -1
  259. package/.next/static/chunks/0o5zj~5vjeks3.js +0 -1
  260. package/.next/static/chunks/0ttvcv6~g0f6i.js +0 -1
  261. package/.next/static/chunks/0uqfv6rc-xdru.js +0 -1
  262. package/.next/static/chunks/0xrnwfefpke-g.js +0 -31
  263. package/.next/static/chunks/0y_po~f~fk~ap.js +0 -1
  264. package/.next/static/chunks/0~93h~zb55yh9.js +0 -1
  265. package/.next/static/chunks/140l7~i5q9wrv.js +0 -1
  266. package/AGENTS.md +0 -5
  267. package/DASHBOARD_OPTIMIZATION_PLAN.md +0 -414
  268. package/docs/iteration-plan.md +0 -62
  269. package/docs/v4-plan.md +0 -38
  270. /package/.next/static/{7dwKlhAm5uyghPmkAubQK → 2m1yIfZCIYDWMYrrJEKSC}/_buildManifest.js +0 -0
  271. /package/.next/static/{7dwKlhAm5uyghPmkAubQK → 2m1yIfZCIYDWMYrrJEKSC}/_clientMiddlewareManifest.js +0 -0
  272. /package/.next/static/{7dwKlhAm5uyghPmkAubQK → 2m1yIfZCIYDWMYrrJEKSC}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../app/server-logs/page.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\n\ninterface LogLine {\n ts: string;\n level: 'log' | 'info' | 'warn' | 'error';\n line: string;\n}\n\nconst LEVEL_COLOR: Record<LogLine['level'], string> = {\n log: 'text-gray-300',\n info: 'text-cyan-300',\n warn: 'text-amber-400',\n error: 'text-red-400',\n};\n\nconst LEVEL_BADGE: Record<LogLine['level'], string> = {\n log: 'bg-gray-500/10 text-gray-400 border-gray-500/20',\n info: 'bg-cyan-500/10 text-cyan-300 border-cyan-500/30',\n warn: 'bg-amber-500/10 text-amber-300 border-amber-500/30',\n error: 'bg-red-500/10 text-red-300 border-red-500/30',\n};\n\nfunction shortTime(iso: string) {\n try {\n const d = new Date(iso);\n return d.toTimeString().slice(0, 8) + '.' + String(d.getMilliseconds()).padStart(3, '0');\n } catch {\n return iso;\n }\n}\n\nexport default function ServerLogsPage() {\n const [logs, setLogs] = useState<LogLine[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [paused, setPaused] = useState(false);\n const [filterLevel, setFilterLevel] = useState<'all' | LogLine['level']>('all');\n const [search, setSearch] = useState('');\n const [autoRefresh, setAutoRefresh] = useState(true);\n const lastTsRef = useRef<string>('');\n\n const fetchLogs = useCallback(async (initial = false) => {\n try {\n const params = new URLSearchParams({ limit: '500' });\n if (!initial && lastTsRef.current) params.set('since', lastTsRef.current);\n const res = await fetch(`/api/hub/server-logs?${params.toString()}`);\n const data = await res.json();\n if (!res.ok || !data.ok) {\n setError(data.error || `HTTP ${res.status}`);\n return;\n }\n setError(null);\n const newLogs: LogLine[] = data.logs || [];\n if (newLogs.length === 0) return;\n // server returns newest-first; track most recent ts for incremental fetches\n lastTsRef.current = newLogs[0].ts;\n if (initial) {\n setLogs(newLogs);\n } else {\n // merge: prepend new entries (which are newer than lastTs)\n setLogs(prev => {\n // de-dup by ts+line\n const seen = new Set(prev.map(l => l.ts + l.line));\n const fresh = newLogs.filter(l => !seen.has(l.ts + l.line));\n return [...fresh, ...prev].slice(0, 1000);\n });\n }\n } catch (e: unknown) {\n setError(e instanceof Error ? e.message : 'fetch failed');\n }\n }, []);\n\n useEffect(() => {\n fetchLogs(true);\n }, [fetchLogs]);\n\n useEffect(() => {\n if (!autoRefresh || paused) return;\n const interval = setInterval(() => fetchLogs(false), 2000);\n return () => clearInterval(interval);\n }, [autoRefresh, paused, fetchLogs]);\n\n const filtered = logs.filter(l => {\n if (filterLevel !== 'all' && l.level !== filterLevel) return false;\n if (search && !l.line.toLowerCase().includes(search.toLowerCase())) return false;\n return true;\n });\n\n const counts = { log: 0, info: 0, warn: 0, error: 0 };\n for (const l of logs) counts[l.level]++;\n\n return (\n <div className=\"p-6 max-w-[1600px] mx-auto\">\n <div className=\"flex items-baseline justify-between mb-4\">\n <div className=\"flex items-baseline gap-3\">\n <h1 className=\"text-2xl font-bold text-white\">Server Logs</h1>\n <span className=\"text-xs text-gray-500\">CommHub stdout/stderr · 最新在上</span>\n </div>\n <div className=\"flex items-center gap-2 text-xs\">\n <button\n onClick={() => setPaused(p => !p)}\n className={`px-3 py-1 rounded border ${paused ? 'bg-amber-500/10 text-amber-300 border-amber-500/30' : 'bg-cyan-500/10 text-cyan-300 border-cyan-500/30'}`}\n >\n {paused ? '▶ Resume' : '⏸ Pause'}\n </button>\n <label className=\"flex items-center gap-1 text-gray-400 select-none\">\n <input type=\"checkbox\" checked={autoRefresh} onChange={e => setAutoRefresh(e.target.checked)} className=\"accent-cyan-500\" />\n auto-refresh\n </label>\n <button onClick={() => fetchLogs(true)} className=\"px-3 py-1 rounded border bg-gray-500/10 text-gray-300 border-gray-500/20 hover:bg-gray-500/20\">\n ↻ Reload\n </button>\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 mb-3\">\n <div className=\"flex items-center gap-1 text-xs\">\n {(['all', 'log', 'info', 'warn', 'error'] as const).map(lv => (\n <button\n key={lv}\n onClick={() => setFilterLevel(lv)}\n className={`px-2.5 py-1 rounded border ${\n filterLevel === lv\n ? 'bg-cyan-500/15 text-cyan-200 border-cyan-500/40'\n : 'bg-[#11111c] text-gray-400 border-[#2a2a4a] hover:bg-[#1a1a2a]'\n }`}\n >\n {lv}{lv !== 'all' && counts[lv as LogLine['level']] > 0 ? ` (${counts[lv as LogLine['level']]})` : ''}\n </button>\n ))}\n </div>\n <input\n value={search}\n onChange={e => setSearch(e.target.value)}\n placeholder=\"搜索关键字 (alias / task_id / error message)\"\n className=\"flex-1 px-3 py-1.5 text-xs bg-[#11111c] border border-[#2a2a4a] rounded text-gray-200 focus:outline-none focus:border-cyan-500/40\"\n />\n <span className=\"text-[10px] text-gray-600\">\n {filtered.length} / {logs.length}\n </span>\n </div>\n\n {error && (() => {\n // Translate server error to user-friendly copy. Keep the raw error\n // available as a tooltip for debugging, but the user-visible message\n // stays human.\n const isAuth = /401|unauthor|forbidden|403|admin/i.test(error);\n const human = isAuth\n ? '需要 admin 角色才能查看服务器日志'\n : '服务器日志暂时无法加载';\n const sub = isAuth\n ? '请用 admin 账号登录后查看。当前账号没有这个权限。'\n : '请检查 CommHub 是否在线,或稍后重试。';\n return (\n <div className=\"anet-error-chip mb-3 p-3 rounded border border-red-500/30 bg-red-500/10 text-red-300 text-sm flex items-start gap-3\" role=\"alert\">\n <span aria-hidden className=\"text-base leading-none\">⛔</span>\n <div className=\"flex-1\">\n <div className=\"font-medium\">{human}</div>\n <div className=\"text-xs opacity-70 mt-0.5\" title={error}>{sub}</div>\n </div>\n </div>\n );\n })()}\n\n <div className=\"rounded border border-[#1a1a2a] bg-[#050510] font-mono text-[11px] leading-relaxed overflow-hidden\">\n {filtered.length === 0 ? (\n <div className=\"p-8 text-center text-gray-600\">\n {error ? '加载失败' : logs.length === 0 ? '加载中...' : '没有匹配的日志'}\n </div>\n ) : (\n <div className=\"divide-y divide-[#0d0d18] max-h-[calc(100vh-260px)] overflow-y-auto\">\n {filtered.map((l, i) => (\n <div key={`${l.ts}-${i}`} className=\"px-3 py-1 hover:bg-[#0a0a14] flex gap-3\">\n <span className=\"text-gray-600 shrink-0 w-[110px] text-[10px]\">{shortTime(l.ts)}</span>\n <span className={`shrink-0 px-1.5 rounded border text-[9px] uppercase ${LEVEL_BADGE[l.level]}`}>\n {l.level}\n </span>\n <span className={`break-all whitespace-pre-wrap ${LEVEL_COLOR[l.level]}`}>{l.line}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"names":["LEVEL_COLOR","log","info","warn","error","LEVEL_BADGE","shortTime","iso","d","Date","toTimeString","slice","String","getMilliseconds","padStart","ServerLogsPage","logs","setLogs","setError","paused","setPaused","filterLevel","setFilterLevel","search","setSearch","autoRefresh","setAutoRefresh","lastTsRef","fetchLogs","initial","params","URLSearchParams","limit","current","set","res","fetch","toString","data","json","ok","status","newLogs","length","ts","prev","seen","Set","map","l","line","fresh","filter","has","e","Error","message","interval","setInterval","clearInterval","filtered","level","toLowerCase","includes","counts","className","onClick","p","type","checked","onChange","target","lv","value","placeholder","isAuth","test","human","sub","role","title","i"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../app/server-logs/page.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport Link from 'next/link';\n\ninterface LogLine {\n ts: string;\n level: 'log' | 'info' | 'warn' | 'error';\n line: string;\n}\n\nconst LEVEL_COLOR: Record<LogLine['level'], string> = {\n log: 'text-gray-300',\n info: 'text-cyan-300',\n warn: 'text-amber-400',\n error: 'text-red-400',\n};\n\nconst LEVEL_BADGE: Record<LogLine['level'], string> = {\n log: 'bg-gray-500/10 text-gray-400 border-gray-500/20',\n info: 'bg-cyan-500/10 text-cyan-300 border-cyan-500/30',\n warn: 'bg-amber-500/10 text-amber-300 border-amber-500/30',\n error: 'bg-red-500/10 text-red-300 border-red-500/30',\n};\n\nfunction shortTime(iso: string) {\n try {\n const d = new Date(iso);\n return d.toTimeString().slice(0, 8) + '.' + String(d.getMilliseconds()).padStart(3, '0');\n } catch {\n return iso;\n }\n}\n\nexport default function ServerLogsPage() {\n const [logs, setLogs] = useState<LogLine[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [paused, setPaused] = useState(false);\n const [filterLevel, setFilterLevel] = useState<'all' | LogLine['level']>('all');\n const [search, setSearch] = useState('');\n const [autoRefresh, setAutoRefresh] = useState(true);\n const lastTsRef = useRef<string>('');\n\n const fetchLogs = useCallback(async (initial = false) => {\n try {\n const params = new URLSearchParams({ limit: '500' });\n if (!initial && lastTsRef.current) params.set('since', lastTsRef.current);\n const res = await fetch(`/api/hub/server-logs?${params.toString()}`);\n const data = await res.json();\n if (!res.ok || !data.ok) {\n setError(data.error || `HTTP ${res.status}`);\n return;\n }\n setError(null);\n const newLogs: LogLine[] = data.logs || [];\n if (newLogs.length === 0) return;\n // server returns newest-first; track most recent ts for incremental fetches\n lastTsRef.current = newLogs[0].ts;\n if (initial) {\n setLogs(newLogs);\n } else {\n // merge: prepend new entries (which are newer than lastTs)\n setLogs(prev => {\n // de-dup by ts+line\n const seen = new Set(prev.map(l => l.ts + l.line));\n const fresh = newLogs.filter(l => !seen.has(l.ts + l.line));\n return [...fresh, ...prev].slice(0, 1000);\n });\n }\n } catch (e: unknown) {\n setError(e instanceof Error ? e.message : 'fetch failed');\n }\n }, []);\n\n useEffect(() => {\n fetchLogs(true);\n }, [fetchLogs]);\n\n useEffect(() => {\n if (!autoRefresh || paused) return;\n const interval = setInterval(() => fetchLogs(false), 2000);\n return () => clearInterval(interval);\n }, [autoRefresh, paused, fetchLogs]);\n\n const filtered = logs.filter(l => {\n if (filterLevel !== 'all' && l.level !== filterLevel) return false;\n if (search && !l.line.toLowerCase().includes(search.toLowerCase())) return false;\n return true;\n });\n\n const counts = { log: 0, info: 0, warn: 0, error: 0 };\n for (const l of logs) counts[l.level]++;\n\n return (\n <div className=\"p-6 max-w-[1600px] mx-auto\">\n <div className=\"flex items-baseline justify-between mb-4\">\n <div className=\"flex items-baseline gap-3\">\n <h1 className=\"text-2xl font-bold text-white\">Server Logs</h1>\n <span className=\"text-xs text-gray-500\">CommHub stdout/stderr · 最新在上</span>\n </div>\n <div className=\"flex items-center gap-2 text-xs\">\n <button\n onClick={() => setPaused(p => !p)}\n className={`px-3 py-1 rounded border ${paused ? 'bg-amber-500/10 text-amber-300 border-amber-500/30' : 'bg-cyan-500/10 text-cyan-300 border-cyan-500/30'}`}\n >\n {paused ? '▶ Resume' : '⏸ Pause'}\n </button>\n <label className=\"flex items-center gap-1 text-gray-400 select-none\">\n <input type=\"checkbox\" checked={autoRefresh} onChange={e => setAutoRefresh(e.target.checked)} className=\"accent-cyan-500\" />\n auto-refresh\n </label>\n <button onClick={() => fetchLogs(true)} className=\"px-3 py-1 rounded border bg-gray-500/10 text-gray-300 border-gray-500/20 hover:bg-gray-500/20\">\n ↻ Reload\n </button>\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 mb-3\">\n <div className=\"flex items-center gap-1 text-xs\">\n {(['all', 'log', 'info', 'warn', 'error'] as const).map(lv => (\n <button\n key={lv}\n onClick={() => setFilterLevel(lv)}\n className={`px-2.5 py-1 rounded border ${\n filterLevel === lv\n ? 'bg-cyan-500/15 text-cyan-200 border-cyan-500/40'\n : 'bg-[#11111c] text-gray-400 border-[#2a2a4a] hover:bg-[#1a1a2a]'\n }`}\n >\n {lv}{lv !== 'all' && counts[lv as LogLine['level']] > 0 ? ` (${counts[lv as LogLine['level']]})` : ''}\n </button>\n ))}\n </div>\n <input\n value={search}\n onChange={e => setSearch(e.target.value)}\n placeholder=\"搜索关键字 (alias / task_id / error message)\"\n className=\"flex-1 px-3 py-1.5 text-xs bg-[#11111c] border border-[#2a2a4a] rounded text-gray-200 focus:outline-none focus:border-cyan-500/40\"\n />\n <span className=\"text-[10px] text-gray-600\">\n {filtered.length} / {logs.length}\n </span>\n </div>\n\n {error && (() => {\n // Translate server error to user-friendly copy + actionable recovery.\n // Raw error stays in title tooltip for debugging.\n const isAuth = /401|unauthor|forbidden|403|admin/i.test(error);\n return (\n <div className=\"anet-error-chip mb-3 p-3 rounded border border-red-500/30 bg-red-500/10 text-red-300 text-sm flex items-start gap-3\" role=\"alert\">\n <span aria-hidden className=\"text-base leading-none\">⛔</span>\n <div className=\"flex-1\">\n {isAuth ? (\n <>\n <div className=\"font-medium\">需要 admin 角色才能查看服务器日志</div>\n <div className=\"text-xs opacity-80 mt-0.5\" title={error}>\n 服务器日志包含运行时 stdout/stderr,仅 admin 角色可读。\n </div>\n <Link href=\"/login\" className=\"inline-block mt-2 text-xs font-medium underline underline-offset-4 hover:opacity-80\">\n 切到 admin 账号 →\n </Link>\n </>\n ) : (\n <>\n <div className=\"font-medium\">服务器日志暂时无法加载</div>\n <div className=\"text-xs opacity-80 mt-0.5\" title={error}>请检查 CommHub 是否在线,或稍后重试。</div>\n <button onClick={() => window.location.reload()} className=\"inline-block mt-2 text-xs font-medium underline underline-offset-4 hover:opacity-80\">\n 重新加载 →\n </button>\n </>\n )}\n </div>\n </div>\n );\n })()}\n\n <div className=\"rounded border border-[#1a1a2a] bg-[#050510] font-mono text-[11px] leading-relaxed overflow-hidden\">\n {filtered.length === 0 ? (\n <div className=\"p-8 text-center text-gray-600\">\n {error ? '加载失败' : logs.length === 0 ? '加载中...' : '没有匹配的日志'}\n </div>\n ) : (\n <div className=\"divide-y divide-[#0d0d18] max-h-[calc(100vh-260px)] overflow-y-auto\">\n {filtered.map((l, i) => (\n <div key={`${l.ts}-${i}`} className=\"px-3 py-1 hover:bg-[#0a0a14] flex gap-3\">\n <span className=\"text-gray-600 shrink-0 w-[110px] text-[10px]\">{shortTime(l.ts)}</span>\n <span className={`shrink-0 px-1.5 rounded border text-[9px] uppercase ${LEVEL_BADGE[l.level]}`}>\n {l.level}\n </span>\n <span className={`break-all whitespace-pre-wrap ${LEVEL_COLOR[l.level]}`}>{l.line}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"names":["LEVEL_COLOR","log","info","warn","error","LEVEL_BADGE","shortTime","iso","d","Date","toTimeString","slice","String","getMilliseconds","padStart","ServerLogsPage","logs","setLogs","setError","paused","setPaused","filterLevel","setFilterLevel","search","setSearch","autoRefresh","setAutoRefresh","lastTsRef","fetchLogs","initial","params","URLSearchParams","limit","current","set","res","fetch","toString","data","json","ok","status","newLogs","length","ts","prev","seen","Set","map","l","line","fresh","filter","has","e","Error","message","interval","setInterval","clearInterval","filtered","level","toLowerCase","includes","counts","className","onClick","p","type","checked","onChange","target","lv","value","placeholder","isAuth","test","role","title","href","window","location","reload","i"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- module.exports=[69474,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(50944),e=a.i(22397),f=a.i(31626),g=a.i(43515);let h={created:"text-gray-400",delivered:"text-blue-400",running:"text-green-400",replied:"text-purple-400",failed:"text-red-400",closed:"text-gray-500"};function i({taskId:a,onClose:d}){let[e,j]=(0,c.useState)(null),[k,l]=(0,c.useState)([]),[m,n]=(0,c.useState)(!0);(0,c.useEffect)(()=>{(async()=>{try{let[b,c]=await Promise.all([fetch(`/api/hub/tasks?task_id=${encodeURIComponent(a)}`),fetch(`/api/hub/task-events?task_id=${encodeURIComponent(a)}&limit=50`)]),d=await b.json(),e=await c.json();d.tasks?.[0]&&j(d.tasks[0]),l(e.events||[])}catch{}finally{n(!1)}})()},[a]);let o=e?[{label:"Created",time:e.created_at,color:"bg-gray-400"},{label:"Delivered",time:e.delivered_at,color:"bg-blue-400"},{label:"Started",time:e.started_at,color:"bg-green-400"},{label:"Completed",time:e.completed_at,color:"bg-purple-400"}]:[],p=e?.started_at&&e?.completed_at?Math.round((new Date(e.completed_at).getTime()-new Date(e.started_at).getTime())/1e3):null;return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("div",{onClick:d,className:"jsx-c3e56cbc81656d9 fixed inset-0 bg-black/30 z-40"}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 overflow-y-auto animate-slide-in",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center justify-between px-5 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a] sticky top-0",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-sm font-semibold text-white",children:"Task Detail"}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 text-[10px] text-gray-500 mt-0.5",children:[a.slice(0,16),"..."]})]}),(0,b.jsx)("button",{onClick:d,className:"jsx-c3e56cbc81656d9 text-gray-500 hover:text-white p-1.5 rounded-lg hover:bg-[#1a1a2a]",children:(0,b.jsx)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,className:"jsx-c3e56cbc81656d9 w-5 h-5",children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12",className:"jsx-c3e56cbc81656d9"})})})]}),m?(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 flex justify-center py-16",children:(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 w-6 h-6 border-2 border-cyan-500/30 border-t-cyan-500 rounded-full animate-spin"})}):e?(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 px-5 py-5 space-y-5",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-3",children:[(0,b.jsx)("span",{className:`jsx-c3e56cbc81656d9 text-lg font-bold ${h[e.status]||"text-gray-400"}`,children:e.status}),"normal"!==e.priority&&(0,b.jsx)("span",{className:`jsx-c3e56cbc81656d9 text-xs px-2 py-0.5 rounded border ${"high"===e.priority?"text-red-300 border-red-500/20":"text-gray-400 border-gray-600/20"}`,children:e.priority}),null!==p&&(0,b.jsxs)("span",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500",children:["⏱ ",p<60?`${p}s`:`${Math.floor(p/60)}m ${p%60}s`]})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-2 text-sm",children:[(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-blue-400 font-medium",children:e.from_name||"--"}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-gray-600",children:"→"}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-cyan-400 font-medium",children:e.to_name||"--"})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-3",children:"Timeline"}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 space-y-3",children:o.map((a,c)=>(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-3",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex flex-col items-center",children:[(0,b.jsx)("div",{className:`jsx-c3e56cbc81656d9 w-3 h-3 rounded-full ${a.time?a.color:"bg-gray-700"}`}),c<o.length-1&&(0,b.jsx)("div",{className:`jsx-c3e56cbc81656d9 w-0.5 h-4 mt-1 ${a.time&&o[c+1]?.time?"bg-gray-600":"bg-gray-800"}`})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex-1",children:[(0,b.jsx)("div",{className:`jsx-c3e56cbc81656d9 text-xs font-medium ${a.time?"text-gray-300":"text-gray-600"}`,children:a.label}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-[10px] text-gray-500",children:a.time||"Pending"})]})]},a.label))})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-2",children:"Input"}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-sm text-gray-300 whitespace-pre-wrap",children:e.content||"--"})]}),e.result&&(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-2",children:"Output"}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-sm text-gray-300 whitespace-pre-wrap max-h-64 overflow-y-auto",children:e.result})]}),k.length>0&&(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-2",children:["Events (",k.length,")"]}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 space-y-1.5 max-h-40 overflow-y-auto",children:k.map(a=>(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-2 text-[11px]",children:[(0,b.jsx)("span",{className:`jsx-c3e56cbc81656d9 w-1.5 h-1.5 rounded-full shrink-0 ${"running"===a.to_status?"bg-green-400":"replied"===a.to_status?"bg-purple-400":"failed"===a.to_status?"bg-red-400":"bg-blue-400"}`}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-gray-400",children:a.event_type}),a.from_status&&(0,b.jsxs)("span",{className:"jsx-c3e56cbc81656d9 text-gray-600",children:[a.from_status,"→",a.to_status]}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-gray-600 ml-auto",children:(0,g.timeAgo)(a.created_at)})]},a.id))})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 text-[10px] text-gray-600 space-y-1",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9",children:["Task ID: ",e.task_id]}),e.expires_at&&(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9",children:["Expires: ",e.expires_at]})]})]}):(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-center py-16 text-gray-500",children:"Task not found"})]}),(0,b.jsx)(f.default,{id:"c3e56cbc81656d9",children:"@keyframes slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}.animate-slide-in{animation:.2s ease-out slide-in}"})]})}let j=["","created","delivered","acked","running","replied","closed","failed","cancelled","expired"],k={created:"bg-gray-500/10 text-gray-400 border-gray-500/20",delivered:"bg-blue-500/10 text-blue-300 border-blue-500/20",acked:"bg-cyan-500/10 text-cyan-300 border-cyan-500/20",running:"bg-green-500/10 text-green-300 border-green-500/20",replied:"bg-purple-500/10 text-purple-300 border-purple-500/20",closed:"bg-gray-500/10 text-gray-500 border-gray-500/20",failed:"bg-red-500/10 text-red-300 border-red-500/20",cancelled:"bg-yellow-500/10 text-yellow-300 border-yellow-500/20",expired:"bg-orange-500/10 text-orange-300 border-orange-500/20"};function l(a){let b=k[a]||"bg-gray-500/10 text-gray-400 border-gray-500/20";return`text-xs px-2 py-0.5 rounded-md border ${b}`}function m(a){return"high"===a?"text-red-400":"low"===a?"text-gray-600":"text-gray-400"}function n(a){if(!a)return"--";let b=Math.floor((Date.now()-new Date(a.replace(" ","T")+"Z").getTime())/1e3);return b<60?`${b}s ago`:b<3600?`${Math.floor(b/60)}m ago`:b<86400?`${Math.floor(b/3600)}h ago`:`${Math.floor(b/86400)}d ago`}function o(){let a,f,g,h=(0,d.useSearchParams)(),{networkId:o}=(0,e.useNetworkId)(),[p,q]=(0,c.useState)([]),[r,s]=(0,c.useState)(0),[t,u]=(0,c.useState)(!0),[v,w]=(0,c.useState)(""),[x,y]=(0,c.useState)(new Set),[z,A]=(0,c.useState)(h.get("status")||""),[B,C]=(0,c.useState)(""),[D,E]=(0,c.useState)(""),[F,G]=(0,c.useState)(null),H=(0,c.useCallback)(async()=>{try{let a=new URLSearchParams;o&&a.set("network_id",o),z&&a.set("status",z),B&&a.set("from_name",B),D&&a.set("to_name",D),a.set("limit","100");let b=await fetch(`/api/hub/tasks?${a.toString()}`);if(401===b.status)return void window.location.assign("/login");let c=await b.json();q(c.tasks||[]),s(c.count??(c.tasks?.length||0)),w("")}catch(a){w(a instanceof Error?a.message:"fetch failed")}finally{u(!1)}},[z,B,D,o]);return(0,c.useEffect)(()=>{u(!0),H();let a=setInterval(H,5e3);return()=>clearInterval(a)},[H]),(0,b.jsxs)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono",children:[(0,b.jsxs)("div",{className:"flex items-center gap-4 mb-6",children:[(0,b.jsx)("h1",{className:"text-2xl font-bold text-white lg:ml-0 ml-10",children:"Tasks"}),(0,b.jsx)("span",{className:"text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30",children:r})]}),(0,b.jsx)("div",{className:"flex flex-wrap gap-1 mb-4 bg-[#111128] rounded-lg border border-[#2a2a4a] p-1",children:["",...j.filter(Boolean)].map(a=>(0,b.jsx)("button",{onClick:()=>A(a),className:`px-3 py-1.5 rounded-md text-xs transition-colors ${z===a?`${k[a]||"bg-cyan-500/10 text-cyan-300 border-cyan-500/20"} border`:"text-gray-500 hover:text-gray-300"}`,children:a||"All"},a))}),(0,b.jsxs)("div",{className:"flex flex-wrap gap-3 mb-6",children:[(0,b.jsx)("input",{type:"text",value:B,onChange:a=>C(a.target.value),placeholder:"From node...",className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40"}),(0,b.jsx)("input",{type:"text",value:D,onChange:a=>E(a.target.value),placeholder:"To node...",className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40"})]}),p.length>0&&!z&&(a={},p.forEach(b=>{a[b.status]=(a[b.status]||0)+1}),f=p.length||1,(g=[{key:"running",color:"bg-green-500",text:"text-green-400"},{key:"delivered",color:"bg-blue-500",text:"text-blue-400"},{key:"replied",color:"bg-purple-500",text:"text-purple-400"},{key:"failed",color:"bg-red-500",text:"text-red-400"},{key:"expired",color:"bg-orange-500",text:"text-orange-400"}].filter(b=>a[b.key])).length?(0,b.jsxs)("div",{className:"mb-6",children:[(0,b.jsx)("div",{className:"flex h-2 rounded-full overflow-hidden bg-gray-800",children:g.map(c=>(0,b.jsx)("div",{className:c.color,style:{width:`${a[c.key]/f*100}%`}},c.key))}),(0,b.jsx)("div",{className:"flex flex-wrap gap-3 mt-1.5 text-[10px] text-gray-500",children:g.map(c=>(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:`inline-block w-2 h-2 rounded-full ${c.color} mr-1`}),a[c.key]," ",c.key]},c.key))})]}):null),v&&(0,b.jsx)("div",{className:"bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-2 rounded-lg mb-6 text-sm",children:v}),t?(0,b.jsx)("div",{className:"animate-pulse space-y-3",children:[1,2,3,4,5].map(a=>(0,b.jsx)("div",{className:"h-20 bg-gray-800/20 rounded-lg border border-gray-800/40"},a))}):0===p.length?(0,b.jsxs)("div",{className:"text-center py-16",children:[(0,b.jsx)("div",{className:"text-gray-600 text-4xl mb-4",children:"--"}),(0,b.jsx)("h3",{className:"text-gray-400 text-lg font-medium mb-2",children:"No tasks found"}),(0,b.jsx)("p",{className:"text-gray-600 text-sm",children:z||B||D?"Try adjusting your filters.":"Tasks will appear here when agents send them via CommHub."})]}):(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsxs)("div",{className:"hidden sm:grid sm:grid-cols-12 gap-2 px-4 py-2 text-xs text-gray-600 uppercase",children:[(0,b.jsx)("div",{className:"col-span-1",children:"Status"}),(0,b.jsx)("div",{className:"col-span-2",children:"From"}),(0,b.jsx)("div",{className:"col-span-2",children:"To"}),(0,b.jsx)("div",{className:"col-span-4",children:"Content"}),(0,b.jsx)("div",{className:"col-span-1",children:"Priority"}),(0,b.jsx)("div",{className:"col-span-2",children:"Time"})]}),p.map(a=>(0,b.jsxs)("div",{className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-3 hover:border-[#3a3a5a] transition-colors cursor-pointer",onClick:()=>{var b;return b=a.task_id,void y(a=>{let c=new Set(a);return c.has(b)?c.delete(b):c.add(b),c})},children:[(0,b.jsxs)("div",{className:"hidden sm:grid sm:grid-cols-12 gap-2 items-center",children:[(0,b.jsx)("div",{className:"col-span-1",children:(0,b.jsx)("span",{className:l(a.status),children:a.status})}),(0,b.jsx)("div",{className:"col-span-2 text-sm text-blue-400 truncate",title:a.from_name,children:a.from_name||"--"}),(0,b.jsx)("div",{className:"col-span-2 text-sm text-cyan-400 truncate",title:a.to_name,children:a.to_name||"--"}),(0,b.jsx)("div",{className:"col-span-4 text-xs text-gray-400 truncate",title:a.content,children:a.content||"--"}),(0,b.jsx)("div",{className:"col-span-1",children:(0,b.jsx)("span",{className:`text-xs ${m(a.priority)}`,children:a.priority||"normal"})}),(0,b.jsx)("div",{className:"col-span-2 text-xs text-gray-500",title:a.created_at,children:n(a.created_at)})]}),(0,b.jsxs)("div",{className:"sm:hidden space-y-2",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:l(a.status),children:a.status}),(0,b.jsx)("span",{className:`text-xs ${m(a.priority)}`,children:a.priority||"normal"})]}),(0,b.jsxs)("div",{className:"text-xs text-gray-500",children:[(0,b.jsx)("span",{className:"text-blue-400",children:a.from_name||"--"}),(0,b.jsx)("span",{className:"text-gray-600 mx-1",children:"→"}),(0,b.jsx)("span",{className:"text-cyan-400",children:a.to_name||"--"})]}),(0,b.jsx)("div",{className:"text-xs text-gray-400 truncate",children:a.content||"--"}),(0,b.jsx)("div",{className:"text-xs text-gray-600",children:n(a.created_at)})]}),x.has(a.task_id)&&(0,b.jsxs)("div",{className:"mt-3 pt-3 border-t border-[#2a2a4a] space-y-3",children:[a.content&&(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{className:"text-xs text-gray-600 mb-1",children:"Content"}),(0,b.jsx)("div",{className:"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a]",children:a.content})]}),a.result&&(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{className:"text-xs text-gray-600 mb-1",children:"Result"}),(0,b.jsx)("div",{className:"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a] max-h-48 overflow-y-auto",children:a.result})]}),(0,b.jsx)("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2 text-xs",children:[["Created",a.created_at],["Delivered",a.delivered_at],["Started",a.started_at],["Completed",a.completed_at]].map(([a,c])=>(0,b.jsxs)("div",{children:[(0,b.jsxs)("span",{className:"text-gray-600",children:[a,": "]}),(0,b.jsx)("span",{className:"text-gray-400",children:c?n(c):"--"})]},a))}),a.expires_at&&(0,b.jsxs)("div",{className:"text-xs",children:[(0,b.jsx)("span",{className:"text-gray-600",children:"Expires: "}),(0,b.jsx)("span",{className:"text-orange-400",children:a.expires_at})]}),(0,b.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,b.jsxs)("div",{className:"text-xs text-gray-600 truncate",title:a.task_id,children:["ID: ",a.task_id]}),(0,b.jsxs)("div",{className:"flex gap-2 shrink-0",children:[("failed"===a.status||"expired"===a.status)&&(0,b.jsx)("button",{onClick:async b=>{b.stopPropagation(),await fetch("/api/hub/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({alias:a.to_name,task:a.content,priority:a.priority})}),H()},className:"text-xs text-orange-400 hover:text-orange-300 px-2 py-0.5 rounded border border-orange-500/20 hover:bg-orange-500/10",children:"Retry"}),(0,b.jsx)("button",{onClick:b=>{b.stopPropagation(),G(a.task_id)},className:"text-xs text-cyan-400 hover:text-cyan-300",children:"Detail →"})]})]})]})]},a.task_id))]}),F&&(0,b.jsx)(i,{taskId:F,onClose:()=>G(null)})]})}a.s(["default",0,function(){return(0,b.jsx)(c.Suspense,{fallback:(0,b.jsx)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-6 font-mono",children:"Loading tasks..."}),children:(0,b.jsx)(o,{})})}],69474)}];
1
+ module.exports=[69474,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(50944),e=a.i(22397),f=a.i(31626),g=a.i(43515);let h={created:"text-gray-400",delivered:"text-blue-400",running:"text-green-400",replied:"text-purple-400",failed:"text-red-400",closed:"text-gray-500"};function i({taskId:a,onClose:d}){let[e,j]=(0,c.useState)(null),[k,l]=(0,c.useState)([]),[m,n]=(0,c.useState)(!0);(0,c.useEffect)(()=>{(async()=>{try{let[b,c]=await Promise.all([fetch(`/api/hub/tasks?task_id=${encodeURIComponent(a)}`),fetch(`/api/hub/task-events?task_id=${encodeURIComponent(a)}&limit=50`)]),d=await b.json(),e=await c.json();d.tasks?.[0]&&j(d.tasks[0]),l(e.events||[])}catch{}finally{n(!1)}})()},[a]);let o=e?[{label:"Created",time:e.created_at,color:"bg-gray-400"},{label:"Delivered",time:e.delivered_at,color:"bg-blue-400"},{label:"Started",time:e.started_at,color:"bg-green-400"},{label:"Completed",time:e.completed_at,color:"bg-purple-400"}]:[],p=e?.started_at&&e?.completed_at?Math.round((new Date(e.completed_at).getTime()-new Date(e.started_at).getTime())/1e3):null;return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("div",{onClick:d,className:"jsx-c3e56cbc81656d9 fixed inset-0 bg-black/30 z-40"}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 overflow-y-auto animate-slide-in",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center justify-between px-5 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a] sticky top-0",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-sm font-semibold text-white",children:"Task Detail"}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 text-[10px] text-gray-500 mt-0.5",children:[a.slice(0,16),"..."]})]}),(0,b.jsx)("button",{onClick:d,className:"jsx-c3e56cbc81656d9 text-gray-500 hover:text-white p-1.5 rounded-lg hover:bg-[#1a1a2a]",children:(0,b.jsx)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,className:"jsx-c3e56cbc81656d9 w-5 h-5",children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12",className:"jsx-c3e56cbc81656d9"})})})]}),m?(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 flex justify-center py-16",children:(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 w-6 h-6 border-2 border-cyan-500/30 border-t-cyan-500 rounded-full animate-spin"})}):e?(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 px-5 py-5 space-y-5",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-3",children:[(0,b.jsx)("span",{className:`jsx-c3e56cbc81656d9 text-lg font-bold ${h[e.status]||"text-gray-400"}`,children:e.status}),"normal"!==e.priority&&(0,b.jsx)("span",{className:`jsx-c3e56cbc81656d9 text-xs px-2 py-0.5 rounded border ${"high"===e.priority?"text-red-300 border-red-500/20":"text-gray-400 border-gray-600/20"}`,children:e.priority}),null!==p&&(0,b.jsxs)("span",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500",children:["⏱ ",p<60?`${p}s`:`${Math.floor(p/60)}m ${p%60}s`]})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-2 text-sm",children:[(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-blue-400 font-medium",children:e.from_name||"--"}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-gray-600",children:"→"}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-cyan-400 font-medium",children:e.to_name||"--"})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-3",children:"Timeline"}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 space-y-3",children:o.map((a,c)=>(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-3",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex flex-col items-center",children:[(0,b.jsx)("div",{className:`jsx-c3e56cbc81656d9 w-3 h-3 rounded-full ${a.time?a.color:"bg-gray-700"}`}),c<o.length-1&&(0,b.jsx)("div",{className:`jsx-c3e56cbc81656d9 w-0.5 h-4 mt-1 ${a.time&&o[c+1]?.time?"bg-gray-600":"bg-gray-800"}`})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex-1",children:[(0,b.jsx)("div",{className:`jsx-c3e56cbc81656d9 text-xs font-medium ${a.time?"text-gray-300":"text-gray-600"}`,children:a.label}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-[10px] text-gray-500",children:a.time||"Pending"})]})]},a.label))})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-2",children:"Input"}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-sm text-gray-300 whitespace-pre-wrap",children:e.content||"--"})]}),e.result&&(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-2",children:"Output"}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-sm text-gray-300 whitespace-pre-wrap max-h-64 overflow-y-auto",children:e.result})]}),k.length>0&&(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 text-xs text-gray-500 uppercase mb-2",children:["Events (",k.length,")"]}),(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 space-y-1.5 max-h-40 overflow-y-auto",children:k.map(a=>(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 flex items-center gap-2 text-[11px]",children:[(0,b.jsx)("span",{className:`jsx-c3e56cbc81656d9 w-1.5 h-1.5 rounded-full shrink-0 ${"running"===a.to_status?"bg-green-400":"replied"===a.to_status?"bg-purple-400":"failed"===a.to_status?"bg-red-400":"bg-blue-400"}`}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-gray-400",children:a.event_type}),a.from_status&&(0,b.jsxs)("span",{className:"jsx-c3e56cbc81656d9 text-gray-600",children:[a.from_status,"→",a.to_status]}),(0,b.jsx)("span",{className:"jsx-c3e56cbc81656d9 text-gray-600 ml-auto",children:(0,g.timeAgo)(a.created_at)})]},a.id))})]}),(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9 text-[10px] text-gray-600 space-y-1",children:[(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9",children:["Task ID: ",e.task_id]}),e.expires_at&&(0,b.jsxs)("div",{className:"jsx-c3e56cbc81656d9",children:["Expires: ",e.expires_at]})]})]}):(0,b.jsx)("div",{className:"jsx-c3e56cbc81656d9 text-center py-16 text-gray-500",children:"Task not found"})]}),(0,b.jsx)(f.default,{id:"c3e56cbc81656d9",children:"@keyframes slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}.animate-slide-in{animation:.2s ease-out slide-in}"})]})}var j=a.i(53142);let k=["","created","delivered","acked","running","replied","closed","failed","cancelled","expired"],l={created:"bg-gray-500/10 text-gray-400 border-gray-500/20",delivered:"bg-blue-500/10 text-blue-300 border-blue-500/20",acked:"bg-cyan-500/10 text-cyan-300 border-cyan-500/20",running:"bg-green-500/10 text-green-300 border-green-500/20",replied:"bg-purple-500/10 text-purple-300 border-purple-500/20",closed:"bg-gray-500/10 text-gray-500 border-gray-500/20",failed:"bg-red-500/10 text-red-300 border-red-500/20",cancelled:"bg-yellow-500/10 text-yellow-300 border-yellow-500/20",expired:"bg-orange-500/10 text-orange-300 border-orange-500/20"};function m(a){let b=l[a]||"bg-gray-500/10 text-gray-400 border-gray-500/20";return`text-xs px-2 py-0.5 rounded-md border ${b}`}function n(a){return"high"===a?"text-red-400":"low"===a?"text-gray-600":"text-gray-400"}function o(a){if(!a)return"--";let b=Math.floor((Date.now()-new Date(a.replace(" ","T")+"Z").getTime())/1e3);return b<60?`${b}s ago`:b<3600?`${Math.floor(b/60)}m ago`:b<86400?`${Math.floor(b/3600)}h ago`:`${Math.floor(b/86400)}d ago`}function p(){let a,f,g,h=(0,d.useSearchParams)(),{networkId:p}=(0,e.useNetworkId)(),[q,r]=(0,c.useState)([]),[s,t]=(0,c.useState)(0),[u,v]=(0,c.useState)(!0),[w,x]=(0,c.useState)(""),[y,z]=(0,c.useState)(new Set),[A,B]=(0,c.useState)(h.get("status")||""),[C,D]=(0,c.useState)(""),[E,F]=(0,c.useState)(""),[G,H]=(0,c.useState)(null),I=(0,c.useCallback)(async()=>{try{let a=new URLSearchParams;p&&a.set("network_id",p),A&&a.set("status",A),C&&a.set("from_name",C),E&&a.set("to_name",E),a.set("limit","100");let b=await fetch(`/api/hub/tasks?${a.toString()}`);if(401===b.status)return void window.location.assign("/login");let c=await b.json();r(c.tasks||[]),t(c.count??(c.tasks?.length||0)),x("")}catch(a){x(a instanceof Error?a.message:"fetch failed")}finally{v(!1)}},[A,C,E,p]);return(0,c.useEffect)(()=>{v(!0),I();let a=setInterval(I,5e3);return()=>clearInterval(a)},[I]),(0,b.jsxs)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono",children:[(0,b.jsxs)("div",{className:"flex items-center gap-4 mb-6",children:[(0,b.jsx)("h1",{className:"text-2xl font-bold text-white lg:ml-0 ml-10",children:"Tasks"}),(0,b.jsx)("span",{className:"text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30",children:s})]}),(0,b.jsx)("div",{className:"flex flex-wrap gap-1 mb-4 bg-[#111128] rounded-lg border border-[#2a2a4a] p-1",children:["",...k.filter(Boolean)].map(a=>(0,b.jsx)("button",{onClick:()=>B(a),className:`px-3 py-1.5 rounded-md text-xs transition-colors ${A===a?`${l[a]||"bg-cyan-500/10 text-cyan-300 border-cyan-500/20"} border`:"text-gray-500 hover:text-gray-300"}`,children:a||"All"},a))}),(0,b.jsxs)("div",{className:"flex flex-wrap gap-3 mb-6",children:[(0,b.jsx)("input",{type:"text",value:C,onChange:a=>D(a.target.value),placeholder:"From node...",className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40"}),(0,b.jsx)("input",{type:"text",value:E,onChange:a=>F(a.target.value),placeholder:"To node...",className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40"})]}),q.length>0&&!A&&(a={},q.forEach(b=>{a[b.status]=(a[b.status]||0)+1}),f=q.length||1,(g=[{key:"running",color:"bg-green-500",text:"text-green-400"},{key:"delivered",color:"bg-blue-500",text:"text-blue-400"},{key:"replied",color:"bg-purple-500",text:"text-purple-400"},{key:"failed",color:"bg-red-500",text:"text-red-400"},{key:"expired",color:"bg-orange-500",text:"text-orange-400"}].filter(b=>a[b.key])).length?(0,b.jsxs)("div",{className:"mb-6",children:[(0,b.jsx)("div",{className:"flex h-2 rounded-full overflow-hidden bg-gray-800",children:g.map(c=>(0,b.jsx)("div",{className:c.color,style:{width:`${a[c.key]/f*100}%`}},c.key))}),(0,b.jsx)("div",{className:"flex flex-wrap gap-3 mt-1.5 text-[10px] text-gray-500",children:g.map(c=>(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:`inline-block w-2 h-2 rounded-full ${c.color} mr-1`}),a[c.key]," ",c.key]},c.key))})]}):null),w&&(0,b.jsx)("div",{className:"bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-2 rounded-lg mb-6 text-sm",children:w}),u?(0,b.jsx)("div",{className:"animate-pulse space-y-3",children:[1,2,3,4,5].map(a=>(0,b.jsx)("div",{className:"h-20 bg-gray-800/20 rounded-lg border border-gray-800/40"},a))}):0===q.length?(0,b.jsx)(j.EmptyState,{variant:"tasks",sub:A||C||E?"No tasks match the current filters. Try clearing them.":"Tasks will appear here when agents send them via CommHub."}):(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsxs)("div",{className:"hidden sm:grid sm:grid-cols-12 gap-2 px-4 py-2 text-xs text-gray-600 uppercase",children:[(0,b.jsx)("div",{className:"col-span-1",children:"Status"}),(0,b.jsx)("div",{className:"col-span-2",children:"From"}),(0,b.jsx)("div",{className:"col-span-2",children:"To"}),(0,b.jsx)("div",{className:"col-span-4",children:"Content"}),(0,b.jsx)("div",{className:"col-span-1",children:"Priority"}),(0,b.jsx)("div",{className:"col-span-2",children:"Time"})]}),q.map(a=>(0,b.jsxs)("div",{className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-3 hover:border-[#3a3a5a] transition-colors cursor-pointer",onClick:()=>{var b;return b=a.task_id,void z(a=>{let c=new Set(a);return c.has(b)?c.delete(b):c.add(b),c})},children:[(0,b.jsxs)("div",{className:"hidden sm:grid sm:grid-cols-12 gap-2 items-center",children:[(0,b.jsx)("div",{className:"col-span-1",children:(0,b.jsx)("span",{className:m(a.status),children:a.status})}),(0,b.jsx)("div",{className:"col-span-2 text-sm text-blue-400 truncate",title:a.from_name,children:a.from_name||"--"}),(0,b.jsx)("div",{className:"col-span-2 text-sm text-cyan-400 truncate",title:a.to_name,children:a.to_name||"--"}),(0,b.jsx)("div",{className:"col-span-4 text-xs text-gray-400 truncate",title:a.content,children:a.content||"--"}),(0,b.jsx)("div",{className:"col-span-1",children:(0,b.jsx)("span",{className:`text-xs ${n(a.priority)}`,children:a.priority||"normal"})}),(0,b.jsx)("div",{className:"col-span-2 text-xs text-gray-500",title:a.created_at,children:o(a.created_at)})]}),(0,b.jsxs)("div",{className:"sm:hidden space-y-2",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:m(a.status),children:a.status}),(0,b.jsx)("span",{className:`text-xs ${n(a.priority)}`,children:a.priority||"normal"})]}),(0,b.jsxs)("div",{className:"text-xs text-gray-500",children:[(0,b.jsx)("span",{className:"text-blue-400",children:a.from_name||"--"}),(0,b.jsx)("span",{className:"text-gray-600 mx-1",children:"→"}),(0,b.jsx)("span",{className:"text-cyan-400",children:a.to_name||"--"})]}),(0,b.jsx)("div",{className:"text-xs text-gray-400 truncate",children:a.content||"--"}),(0,b.jsx)("div",{className:"text-xs text-gray-600",children:o(a.created_at)})]}),y.has(a.task_id)&&(0,b.jsxs)("div",{className:"mt-3 pt-3 border-t border-[#2a2a4a] space-y-3",children:[a.content&&(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{className:"text-xs text-gray-600 mb-1",children:"Content"}),(0,b.jsx)("div",{className:"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a]",children:a.content})]}),a.result&&(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{className:"text-xs text-gray-600 mb-1",children:"Result"}),(0,b.jsx)("div",{className:"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a] max-h-48 overflow-y-auto",children:a.result})]}),(0,b.jsx)("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2 text-xs",children:[["Created",a.created_at],["Delivered",a.delivered_at],["Started",a.started_at],["Completed",a.completed_at]].map(([a,c])=>(0,b.jsxs)("div",{children:[(0,b.jsxs)("span",{className:"text-gray-600",children:[a,": "]}),(0,b.jsx)("span",{className:"text-gray-400",children:c?o(c):"--"})]},a))}),a.expires_at&&(0,b.jsxs)("div",{className:"text-xs",children:[(0,b.jsx)("span",{className:"text-gray-600",children:"Expires: "}),(0,b.jsx)("span",{className:"text-orange-400",children:a.expires_at})]}),(0,b.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,b.jsxs)("div",{className:"text-xs text-gray-600 truncate",title:a.task_id,children:["ID: ",a.task_id]}),(0,b.jsxs)("div",{className:"flex gap-2 shrink-0",children:[("failed"===a.status||"expired"===a.status)&&(0,b.jsx)("button",{onClick:async b=>{b.stopPropagation(),await fetch("/api/hub/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({alias:a.to_name,task:a.content,priority:a.priority})}),I()},className:"text-xs text-orange-400 hover:text-orange-300 px-2 py-0.5 rounded border border-orange-500/20 hover:bg-orange-500/10",children:"Retry"}),(0,b.jsx)("button",{onClick:b=>{b.stopPropagation(),H(a.task_id)},className:"text-xs text-cyan-400 hover:text-cyan-300",children:"Detail →"})]})]})]})]},a.task_id))]}),G&&(0,b.jsx)(i,{taskId:G,onClose:()=>H(null)})]})}a.s(["default",0,function(){return(0,b.jsx)(c.Suspense,{fallback:(0,b.jsx)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-6 font-mono",children:"Loading tasks..."}),children:(0,b.jsx)(p,{})})}],69474)}];
2
2
 
3
3
  //# sourceMappingURL=app_tasks_page_tsx_0z-d6mp._.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../app/tasks/page.tsx","../../../../app/components/TaskDrawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, useCallback, Suspense } from 'react';\nimport { useSearchParams } from 'next/navigation';\nimport Link from 'next/link';\nimport { useNetworkId } from '../lib/network-context';\nimport { TaskDrawer } from '../components/TaskDrawer';\n\ninterface Task {\n task_id: string;\n from_name: string;\n to_name: string;\n status: string;\n priority: string;\n content: string;\n result: string;\n created_at: string;\n updated_at: string;\n delivered_at: string;\n started_at: string;\n completed_at: string;\n expires_at: string;\n}\n\nconst STATUS_OPTIONS = [\n '',\n 'created',\n 'delivered',\n 'acked',\n 'running',\n 'replied',\n 'closed',\n 'failed',\n 'cancelled',\n 'expired',\n];\n\nconst STATUS_COLORS: Record<string, string> = {\n created: 'bg-gray-500/10 text-gray-400 border-gray-500/20',\n delivered: 'bg-blue-500/10 text-blue-300 border-blue-500/20',\n acked: 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20',\n running: 'bg-green-500/10 text-green-300 border-green-500/20',\n replied: 'bg-purple-500/10 text-purple-300 border-purple-500/20',\n closed: 'bg-gray-500/10 text-gray-500 border-gray-500/20',\n failed: 'bg-red-500/10 text-red-300 border-red-500/20',\n cancelled: 'bg-yellow-500/10 text-yellow-300 border-yellow-500/20',\n expired: 'bg-orange-500/10 text-orange-300 border-orange-500/20',\n};\n\nfunction statusBadge(status: string) {\n const color = STATUS_COLORS[status] || 'bg-gray-500/10 text-gray-400 border-gray-500/20';\n return `text-xs px-2 py-0.5 rounded-md border ${color}`;\n}\n\nfunction priorityBadge(priority: string) {\n if (priority === 'high') return 'text-red-400';\n if (priority === 'low') return 'text-gray-600';\n return 'text-gray-400';\n}\n\nfunction timeAgo(dateStr: string): string {\n if (!dateStr) return '--';\n const diff = Date.now() - new Date(dateStr.replace(' ', 'T') + 'Z').getTime();\n const s = Math.floor(diff / 1000);\n if (s < 60) return `${s}s ago`;\n if (s < 3600) return `${Math.floor(s / 60)}m ago`;\n if (s < 86400) return `${Math.floor(s / 3600)}h ago`;\n return `${Math.floor(s / 86400)}d ago`;\n}\n\nfunction TasksContent() {\n const searchParams = useSearchParams();\n const { networkId } = useNetworkId();\n const [tasks, setTasks] = useState<Task[]>([]);\n const [count, setCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState('');\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n\n const [filterStatus, setFilterStatus] = useState(searchParams.get('status') || '');\n const [filterFrom, setFilterFrom] = useState('');\n const [filterTo, setFilterTo] = useState('');\n const [drawerTaskId, setDrawerTaskId] = useState<string | null>(null);\n\n const toggleExpand = (taskId: string) => {\n setExpanded(prev => {\n const next = new Set(prev);\n if (next.has(taskId)) next.delete(taskId);\n else next.add(taskId);\n return next;\n });\n };\n\n const fetchTasks = useCallback(async () => {\n try {\n const params = new URLSearchParams();\n if (networkId) params.set('network_id', networkId);\n if (filterStatus) params.set('status', filterStatus);\n if (filterFrom) params.set('from_name', filterFrom);\n if (filterTo) params.set('to_name', filterTo);\n params.set('limit', '100');\n\n const res = await fetch(`/api/hub/tasks?${params.toString()}`);\n if (res.status === 401) {\n window.location.assign('/login');\n return;\n }\n const data = await res.json();\n setTasks(data.tasks || []);\n setCount(data.count ?? (data.tasks?.length || 0));\n setError('');\n } catch (e: unknown) {\n setError(e instanceof Error ? e.message : 'fetch failed');\n } finally {\n setLoading(false);\n }\n }, [filterStatus, filterFrom, filterTo, networkId]);\n\n useEffect(() => {\n setLoading(true);\n fetchTasks();\n const interval = setInterval(fetchTasks, 5000);\n return () => clearInterval(interval);\n }, [fetchTasks]);\n\n return (\n <div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono\">\n {/* Header */}\n <div className=\"flex items-center gap-4 mb-6\">\n <h1 className=\"text-2xl font-bold text-white lg:ml-0 ml-10\">Tasks</h1>\n <span className=\"text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30\">\n {count}\n </span>\n </div>\n\n {/* Status Tabs */}\n <div className=\"flex flex-wrap gap-1 mb-4 bg-[#111128] rounded-lg border border-[#2a2a4a] p-1\">\n {['', ...STATUS_OPTIONS.filter(Boolean)].map(s => (\n <button key={s} onClick={() => setFilterStatus(s)}\n className={`px-3 py-1.5 rounded-md text-xs transition-colors ${\n filterStatus === s\n ? `${STATUS_COLORS[s] || 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20'} border`\n : 'text-gray-500 hover:text-gray-300'\n }`}>\n {s || 'All'}\n </button>\n ))}\n </div>\n\n {/* From/To Filters */}\n <div className=\"flex flex-wrap gap-3 mb-6\">\n <input\n type=\"text\"\n value={filterFrom}\n onChange={e => setFilterFrom(e.target.value)}\n placeholder=\"From node...\"\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40\"\n />\n <input\n type=\"text\"\n value={filterTo}\n onChange={e => setFilterTo(e.target.value)}\n placeholder=\"To node...\"\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40\"\n />\n </div>\n\n {/* Status distribution */}\n {tasks.length > 0 && !filterStatus && (() => {\n const stats: Record<string, number> = {};\n tasks.forEach(t => { stats[t.status] = (stats[t.status] || 0) + 1; });\n const total = tasks.length || 1;\n const bars = [\n { key: 'running', color: 'bg-green-500', text: 'text-green-400' },\n { key: 'delivered', color: 'bg-blue-500', text: 'text-blue-400' },\n { key: 'replied', color: 'bg-purple-500', text: 'text-purple-400' },\n { key: 'failed', color: 'bg-red-500', text: 'text-red-400' },\n { key: 'expired', color: 'bg-orange-500', text: 'text-orange-400' },\n ].filter(b => stats[b.key]);\n if (!bars.length) return null;\n return (\n <div className=\"mb-6\">\n <div className=\"flex h-2 rounded-full overflow-hidden bg-gray-800\">\n {bars.map(b => <div key={b.key} className={b.color} style={{ width: `${(stats[b.key]/total)*100}%` }} />)}\n </div>\n <div className=\"flex flex-wrap gap-3 mt-1.5 text-[10px] text-gray-500\">\n {bars.map(b => <span key={b.key}><span className={`inline-block w-2 h-2 rounded-full ${b.color} mr-1`} />{stats[b.key]} {b.key}</span>)}\n </div>\n </div>\n );\n })()}\n\n {error && (\n <div className=\"bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-2 rounded-lg mb-6 text-sm\">{error}</div>\n )}\n\n {loading ? (\n <div className=\"animate-pulse space-y-3\">\n {[1, 2, 3, 4, 5].map(i => (\n <div key={i} className=\"h-20 bg-gray-800/20 rounded-lg border border-gray-800/40\" />\n ))}\n </div>\n ) : tasks.length === 0 ? (\n <div className=\"text-center py-16\">\n <div className=\"text-gray-600 text-4xl mb-4\">--</div>\n <h3 className=\"text-gray-400 text-lg font-medium mb-2\">No tasks found</h3>\n <p className=\"text-gray-600 text-sm\">\n {filterStatus || filterFrom || filterTo\n ? 'Try adjusting your filters.'\n : 'Tasks will appear here when agents send them via CommHub.'}\n </p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {/* Table header */}\n <div className=\"hidden sm:grid sm:grid-cols-12 gap-2 px-4 py-2 text-xs text-gray-600 uppercase\">\n <div className=\"col-span-1\">Status</div>\n <div className=\"col-span-2\">From</div>\n <div className=\"col-span-2\">To</div>\n <div className=\"col-span-4\">Content</div>\n <div className=\"col-span-1\">Priority</div>\n <div className=\"col-span-2\">Time</div>\n </div>\n\n {tasks.map(t => (\n <div\n key={t.task_id}\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-3 hover:border-[#3a3a5a] transition-colors cursor-pointer\"\n onClick={() => toggleExpand(t.task_id)}\n >\n {/* Desktop row */}\n <div className=\"hidden sm:grid sm:grid-cols-12 gap-2 items-center\">\n <div className=\"col-span-1\">\n <span className={statusBadge(t.status)}>{t.status}</span>\n </div>\n <div className=\"col-span-2 text-sm text-blue-400 truncate\" title={t.from_name}>\n {t.from_name || '--'}\n </div>\n <div className=\"col-span-2 text-sm text-cyan-400 truncate\" title={t.to_name}>\n {t.to_name || '--'}\n </div>\n <div className=\"col-span-4 text-xs text-gray-400 truncate\" title={t.content}>\n {t.content || '--'}\n </div>\n <div className=\"col-span-1\">\n <span className={`text-xs ${priorityBadge(t.priority)}`}>{t.priority || 'normal'}</span>\n </div>\n <div className=\"col-span-2 text-xs text-gray-500\" title={t.created_at}>\n {timeAgo(t.created_at)}\n </div>\n </div>\n\n {/* Mobile layout */}\n <div className=\"sm:hidden space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className={statusBadge(t.status)}>{t.status}</span>\n <span className={`text-xs ${priorityBadge(t.priority)}`}>{t.priority || 'normal'}</span>\n </div>\n <div className=\"text-xs text-gray-500\">\n <span className=\"text-blue-400\">{t.from_name || '--'}</span>\n <span className=\"text-gray-600 mx-1\">&rarr;</span>\n <span className=\"text-cyan-400\">{t.to_name || '--'}</span>\n </div>\n <div className=\"text-xs text-gray-400 truncate\">{t.content || '--'}</div>\n <div className=\"text-xs text-gray-600\">{timeAgo(t.created_at)}</div>\n </div>\n\n {/* Expanded detail */}\n {expanded.has(t.task_id) && (\n <div className=\"mt-3 pt-3 border-t border-[#2a2a4a] space-y-3\">\n {t.content && (\n <div>\n <div className=\"text-xs text-gray-600 mb-1\">Content</div>\n <div className=\"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a]\">{t.content}</div>\n </div>\n )}\n {t.result && (\n <div>\n <div className=\"text-xs text-gray-600 mb-1\">Result</div>\n <div className=\"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a] max-h-48 overflow-y-auto\">{t.result}</div>\n </div>\n )}\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-2 text-xs\">\n {[\n ['Created', t.created_at],\n ['Delivered', t.delivered_at],\n ['Started', t.started_at],\n ['Completed', t.completed_at],\n ].map(([label, val]) => (\n <div key={label as string}>\n <span className=\"text-gray-600\">{label}: </span>\n <span className=\"text-gray-400\">{val ? timeAgo(val as string) : '--'}</span>\n </div>\n ))}\n </div>\n {t.expires_at && (\n <div className=\"text-xs\">\n <span className=\"text-gray-600\">Expires: </span>\n <span className=\"text-orange-400\">{t.expires_at}</span>\n </div>\n )}\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-xs text-gray-600 truncate\" title={t.task_id}>\n ID: {t.task_id}\n </div>\n <div className=\"flex gap-2 shrink-0\">\n {(t.status === 'failed' || t.status === 'expired') && (\n <button\n onClick={async (e) => {\n e.stopPropagation();\n await fetch('/api/hub/send', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ alias: t.to_name, task: t.content, priority: t.priority }),\n });\n fetchTasks();\n }}\n className=\"text-xs text-orange-400 hover:text-orange-300 px-2 py-0.5 rounded border border-orange-500/20 hover:bg-orange-500/10\"\n >\n Retry\n </button>\n )}\n <button\n onClick={e => { e.stopPropagation(); setDrawerTaskId(t.task_id); }}\n className=\"text-xs text-cyan-400 hover:text-cyan-300\"\n >\n Detail &rarr;\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {drawerTaskId && <TaskDrawer taskId={drawerTaskId} onClose={() => setDrawerTaskId(null)} />}\n </div>\n );\n}\n\nexport default function TasksPage() {\n return (\n <Suspense fallback={<div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-6 font-mono\">Loading tasks...</div>}>\n <TasksContent />\n </Suspense>\n );\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { timeAgo } from './utils';\nimport Link from 'next/link';\n\ninterface TaskDetail {\n task_id: string;\n from_name: string;\n to_name: string;\n status: string;\n priority: string;\n content: string;\n result: string;\n created_at: string;\n delivered_at: string;\n started_at: string;\n completed_at: string;\n expires_at: string;\n}\n\ninterface TaskEvent {\n id: number;\n event_type: string;\n from_status: string;\n to_status: string;\n detail: string;\n created_at: string;\n}\n\nconst STATUS_COLORS: Record<string, string> = {\n created: 'text-gray-400', delivered: 'text-blue-400', running: 'text-green-400',\n replied: 'text-purple-400', failed: 'text-red-400', closed: 'text-gray-500',\n};\n\ninterface TaskDrawerProps {\n taskId: string;\n onClose: () => void;\n}\n\nexport function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {\n const [task, setTask] = useState<TaskDetail | null>(null);\n const [events, setEvents] = useState<TaskEvent[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n (async () => {\n try {\n const [taskRes, eventsRes] = await Promise.all([\n fetch(`/api/hub/tasks?task_id=${encodeURIComponent(taskId)}`),\n fetch(`/api/hub/task-events?task_id=${encodeURIComponent(taskId)}&limit=50`),\n ]);\n const taskData = await taskRes.json();\n const eventsData = await eventsRes.json();\n if (taskData.tasks?.[0]) setTask(taskData.tasks[0]);\n setEvents(eventsData.events || []);\n } catch {} finally { setLoading(false); }\n })();\n }, [taskId]);\n\n const timeline = task ? [\n { label: 'Created', time: task.created_at, color: 'bg-gray-400' },\n { label: 'Delivered', time: task.delivered_at, color: 'bg-blue-400' },\n { label: 'Started', time: task.started_at, color: 'bg-green-400' },\n { label: 'Completed', time: task.completed_at, color: 'bg-purple-400' },\n ] : [];\n\n const duration = task?.started_at && task?.completed_at\n ? Math.round((new Date(task.completed_at).getTime() - new Date(task.started_at).getTime()) / 1000)\n : null;\n\n return (\n <>\n <div className=\"fixed inset-0 bg-black/30 z-40\" onClick={onClose} />\n <div className=\"fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 overflow-y-auto animate-slide-in\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a] sticky top-0\">\n <div>\n <div className=\"text-sm font-semibold text-white\">Task Detail</div>\n <div className=\"text-[10px] text-gray-500 mt-0.5\">{taskId.slice(0, 16)}...</div>\n </div>\n <button onClick={onClose} className=\"text-gray-500 hover:text-white p-1.5 rounded-lg hover:bg-[#1a1a2a]\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {loading ? (\n <div className=\"flex justify-center py-16\">\n <div className=\"w-6 h-6 border-2 border-cyan-500/30 border-t-cyan-500 rounded-full animate-spin\" />\n </div>\n ) : !task ? (\n <div className=\"text-center py-16 text-gray-500\">Task not found</div>\n ) : (\n <div className=\"px-5 py-5 space-y-5\">\n {/* Status + Priority */}\n <div className=\"flex items-center gap-3\">\n <span className={`text-lg font-bold ${STATUS_COLORS[task.status] || 'text-gray-400'}`}>{task.status}</span>\n {task.priority !== 'normal' && (\n <span className={`text-xs px-2 py-0.5 rounded border ${task.priority === 'high' ? 'text-red-300 border-red-500/20' : 'text-gray-400 border-gray-600/20'}`}>{task.priority}</span>\n )}\n {duration !== null && (\n <span className=\"text-xs text-gray-500\">⏱ {duration < 60 ? `${duration}s` : `${Math.floor(duration/60)}m ${duration%60}s`}</span>\n )}\n </div>\n\n {/* From → To */}\n <div className=\"flex items-center gap-2 text-sm\">\n <span className=\"text-blue-400 font-medium\">{task.from_name || '--'}</span>\n <span className=\"text-gray-600\">→</span>\n <span className=\"text-cyan-400 font-medium\">{task.to_name || '--'}</span>\n </div>\n\n {/* Timeline */}\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-3\">Timeline</div>\n <div className=\"space-y-3\">\n {timeline.map((step, i) => (\n <div key={step.label} className=\"flex items-center gap-3\">\n <div className=\"flex flex-col items-center\">\n <div className={`w-3 h-3 rounded-full ${step.time ? step.color : 'bg-gray-700'}`} />\n {i < timeline.length - 1 && <div className={`w-0.5 h-4 mt-1 ${step.time && timeline[i+1]?.time ? 'bg-gray-600' : 'bg-gray-800'}`} />}\n </div>\n <div className=\"flex-1\">\n <div className={`text-xs font-medium ${step.time ? 'text-gray-300' : 'text-gray-600'}`}>{step.label}</div>\n <div className=\"text-[10px] text-gray-500\">{step.time || 'Pending'}</div>\n </div>\n </div>\n ))}\n </div>\n </div>\n\n {/* Content */}\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-2\">Input</div>\n <div className=\"text-sm text-gray-300 whitespace-pre-wrap\">{task.content || '--'}</div>\n </div>\n\n {/* Result */}\n {task.result && (\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-2\">Output</div>\n <div className=\"text-sm text-gray-300 whitespace-pre-wrap max-h-64 overflow-y-auto\">{task.result}</div>\n </div>\n )}\n\n {/* Events */}\n {events.length > 0 && (\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-2\">Events ({events.length})</div>\n <div className=\"space-y-1.5 max-h-40 overflow-y-auto\">\n {events.map(e => (\n <div key={e.id} className=\"flex items-center gap-2 text-[11px]\">\n <span className={`w-1.5 h-1.5 rounded-full shrink-0 ${\n e.to_status === 'running' ? 'bg-green-400' : e.to_status === 'replied' ? 'bg-purple-400' : e.to_status === 'failed' ? 'bg-red-400' : 'bg-blue-400'\n }`} />\n <span className=\"text-gray-400\">{e.event_type}</span>\n {e.from_status && <span className=\"text-gray-600\">{e.from_status}→{e.to_status}</span>}\n <span className=\"text-gray-600 ml-auto\">{timeAgo(e.created_at)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Metadata */}\n <div className=\"text-[10px] text-gray-600 space-y-1\">\n <div>Task ID: {task.task_id}</div>\n {task.expires_at && <div>Expires: {task.expires_at}</div>}\n </div>\n </div>\n )}\n </div>\n <style jsx global>{`\n @keyframes slide-in { from { transform: translateX(100%); } to { transform: translateX(0); } }\n .animate-slide-in { animation: slide-in 0.2s ease-out; }\n `}</style>\n </>\n );\n}\n"],"names":["STATUS_COLORS","created","delivered","running","replied","failed","closed","TaskDrawer","taskId","onClose","task","setTask","events","setEvents","loading","setLoading","taskRes","eventsRes","Promise","all","fetch","encodeURIComponent","taskData","json","eventsData","tasks","timeline","label","time","created_at","color","delivered_at","started_at","completed_at","duration","Math","round","Date","getTime","onClick","slice","fill","viewBox","stroke","strokeWidth","strokeLinecap","strokeLinejoin","d","status","priority","floor","from_name","to_name","map","step","i","length","content","result","e","to_status","event_type","from_status","id","task_id","expires_at"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../app/tasks/page.tsx","../../../../app/components/TaskDrawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, useCallback, Suspense } from 'react';\nimport { useSearchParams } from 'next/navigation';\nimport Link from 'next/link';\nimport { useNetworkId } from '../lib/network-context';\nimport { TaskDrawer } from '../components/TaskDrawer';\nimport { EmptyState } from '../components/EmptyState';\n\ninterface Task {\n task_id: string;\n from_name: string;\n to_name: string;\n status: string;\n priority: string;\n content: string;\n result: string;\n created_at: string;\n updated_at: string;\n delivered_at: string;\n started_at: string;\n completed_at: string;\n expires_at: string;\n}\n\nconst STATUS_OPTIONS = [\n '',\n 'created',\n 'delivered',\n 'acked',\n 'running',\n 'replied',\n 'closed',\n 'failed',\n 'cancelled',\n 'expired',\n];\n\nconst STATUS_COLORS: Record<string, string> = {\n created: 'bg-gray-500/10 text-gray-400 border-gray-500/20',\n delivered: 'bg-blue-500/10 text-blue-300 border-blue-500/20',\n acked: 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20',\n running: 'bg-green-500/10 text-green-300 border-green-500/20',\n replied: 'bg-purple-500/10 text-purple-300 border-purple-500/20',\n closed: 'bg-gray-500/10 text-gray-500 border-gray-500/20',\n failed: 'bg-red-500/10 text-red-300 border-red-500/20',\n cancelled: 'bg-yellow-500/10 text-yellow-300 border-yellow-500/20',\n expired: 'bg-orange-500/10 text-orange-300 border-orange-500/20',\n};\n\nfunction statusBadge(status: string) {\n const color = STATUS_COLORS[status] || 'bg-gray-500/10 text-gray-400 border-gray-500/20';\n return `text-xs px-2 py-0.5 rounded-md border ${color}`;\n}\n\nfunction priorityBadge(priority: string) {\n if (priority === 'high') return 'text-red-400';\n if (priority === 'low') return 'text-gray-600';\n return 'text-gray-400';\n}\n\nfunction timeAgo(dateStr: string): string {\n if (!dateStr) return '--';\n const diff = Date.now() - new Date(dateStr.replace(' ', 'T') + 'Z').getTime();\n const s = Math.floor(diff / 1000);\n if (s < 60) return `${s}s ago`;\n if (s < 3600) return `${Math.floor(s / 60)}m ago`;\n if (s < 86400) return `${Math.floor(s / 3600)}h ago`;\n return `${Math.floor(s / 86400)}d ago`;\n}\n\nfunction TasksContent() {\n const searchParams = useSearchParams();\n const { networkId } = useNetworkId();\n const [tasks, setTasks] = useState<Task[]>([]);\n const [count, setCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState('');\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n\n const [filterStatus, setFilterStatus] = useState(searchParams.get('status') || '');\n const [filterFrom, setFilterFrom] = useState('');\n const [filterTo, setFilterTo] = useState('');\n const [drawerTaskId, setDrawerTaskId] = useState<string | null>(null);\n\n const toggleExpand = (taskId: string) => {\n setExpanded(prev => {\n const next = new Set(prev);\n if (next.has(taskId)) next.delete(taskId);\n else next.add(taskId);\n return next;\n });\n };\n\n const fetchTasks = useCallback(async () => {\n try {\n const params = new URLSearchParams();\n if (networkId) params.set('network_id', networkId);\n if (filterStatus) params.set('status', filterStatus);\n if (filterFrom) params.set('from_name', filterFrom);\n if (filterTo) params.set('to_name', filterTo);\n params.set('limit', '100');\n\n const res = await fetch(`/api/hub/tasks?${params.toString()}`);\n if (res.status === 401) {\n window.location.assign('/login');\n return;\n }\n const data = await res.json();\n setTasks(data.tasks || []);\n setCount(data.count ?? (data.tasks?.length || 0));\n setError('');\n } catch (e: unknown) {\n setError(e instanceof Error ? e.message : 'fetch failed');\n } finally {\n setLoading(false);\n }\n }, [filterStatus, filterFrom, filterTo, networkId]);\n\n useEffect(() => {\n setLoading(true);\n fetchTasks();\n const interval = setInterval(fetchTasks, 5000);\n return () => clearInterval(interval);\n }, [fetchTasks]);\n\n return (\n <div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono\">\n {/* Header */}\n <div className=\"flex items-center gap-4 mb-6\">\n <h1 className=\"text-2xl font-bold text-white lg:ml-0 ml-10\">Tasks</h1>\n <span className=\"text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30\">\n {count}\n </span>\n </div>\n\n {/* Status Tabs */}\n <div className=\"flex flex-wrap gap-1 mb-4 bg-[#111128] rounded-lg border border-[#2a2a4a] p-1\">\n {['', ...STATUS_OPTIONS.filter(Boolean)].map(s => (\n <button key={s} onClick={() => setFilterStatus(s)}\n className={`px-3 py-1.5 rounded-md text-xs transition-colors ${\n filterStatus === s\n ? `${STATUS_COLORS[s] || 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20'} border`\n : 'text-gray-500 hover:text-gray-300'\n }`}>\n {s || 'All'}\n </button>\n ))}\n </div>\n\n {/* From/To Filters */}\n <div className=\"flex flex-wrap gap-3 mb-6\">\n <input\n type=\"text\"\n value={filterFrom}\n onChange={e => setFilterFrom(e.target.value)}\n placeholder=\"From node...\"\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40\"\n />\n <input\n type=\"text\"\n value={filterTo}\n onChange={e => setFilterTo(e.target.value)}\n placeholder=\"To node...\"\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-40\"\n />\n </div>\n\n {/* Status distribution */}\n {tasks.length > 0 && !filterStatus && (() => {\n const stats: Record<string, number> = {};\n tasks.forEach(t => { stats[t.status] = (stats[t.status] || 0) + 1; });\n const total = tasks.length || 1;\n const bars = [\n { key: 'running', color: 'bg-green-500', text: 'text-green-400' },\n { key: 'delivered', color: 'bg-blue-500', text: 'text-blue-400' },\n { key: 'replied', color: 'bg-purple-500', text: 'text-purple-400' },\n { key: 'failed', color: 'bg-red-500', text: 'text-red-400' },\n { key: 'expired', color: 'bg-orange-500', text: 'text-orange-400' },\n ].filter(b => stats[b.key]);\n if (!bars.length) return null;\n return (\n <div className=\"mb-6\">\n <div className=\"flex h-2 rounded-full overflow-hidden bg-gray-800\">\n {bars.map(b => <div key={b.key} className={b.color} style={{ width: `${(stats[b.key]/total)*100}%` }} />)}\n </div>\n <div className=\"flex flex-wrap gap-3 mt-1.5 text-[10px] text-gray-500\">\n {bars.map(b => <span key={b.key}><span className={`inline-block w-2 h-2 rounded-full ${b.color} mr-1`} />{stats[b.key]} {b.key}</span>)}\n </div>\n </div>\n );\n })()}\n\n {error && (\n <div className=\"bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-2 rounded-lg mb-6 text-sm\">{error}</div>\n )}\n\n {loading ? (\n <div className=\"animate-pulse space-y-3\">\n {[1, 2, 3, 4, 5].map(i => (\n <div key={i} className=\"h-20 bg-gray-800/20 rounded-lg border border-gray-800/40\" />\n ))}\n </div>\n ) : tasks.length === 0 ? (\n <EmptyState\n variant=\"tasks\"\n sub={(filterStatus || filterFrom || filterTo)\n ? 'No tasks match the current filters. Try clearing them.'\n : 'Tasks will appear here when agents send them via CommHub.'}\n />\n ) : (\n <div className=\"space-y-2\">\n {/* Table header */}\n <div className=\"hidden sm:grid sm:grid-cols-12 gap-2 px-4 py-2 text-xs text-gray-600 uppercase\">\n <div className=\"col-span-1\">Status</div>\n <div className=\"col-span-2\">From</div>\n <div className=\"col-span-2\">To</div>\n <div className=\"col-span-4\">Content</div>\n <div className=\"col-span-1\">Priority</div>\n <div className=\"col-span-2\">Time</div>\n </div>\n\n {tasks.map(t => (\n <div\n key={t.task_id}\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-3 hover:border-[#3a3a5a] transition-colors cursor-pointer\"\n onClick={() => toggleExpand(t.task_id)}\n >\n {/* Desktop row */}\n <div className=\"hidden sm:grid sm:grid-cols-12 gap-2 items-center\">\n <div className=\"col-span-1\">\n <span className={statusBadge(t.status)}>{t.status}</span>\n </div>\n <div className=\"col-span-2 text-sm text-blue-400 truncate\" title={t.from_name}>\n {t.from_name || '--'}\n </div>\n <div className=\"col-span-2 text-sm text-cyan-400 truncate\" title={t.to_name}>\n {t.to_name || '--'}\n </div>\n <div className=\"col-span-4 text-xs text-gray-400 truncate\" title={t.content}>\n {t.content || '--'}\n </div>\n <div className=\"col-span-1\">\n <span className={`text-xs ${priorityBadge(t.priority)}`}>{t.priority || 'normal'}</span>\n </div>\n <div className=\"col-span-2 text-xs text-gray-500\" title={t.created_at}>\n {timeAgo(t.created_at)}\n </div>\n </div>\n\n {/* Mobile layout */}\n <div className=\"sm:hidden space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className={statusBadge(t.status)}>{t.status}</span>\n <span className={`text-xs ${priorityBadge(t.priority)}`}>{t.priority || 'normal'}</span>\n </div>\n <div className=\"text-xs text-gray-500\">\n <span className=\"text-blue-400\">{t.from_name || '--'}</span>\n <span className=\"text-gray-600 mx-1\">&rarr;</span>\n <span className=\"text-cyan-400\">{t.to_name || '--'}</span>\n </div>\n <div className=\"text-xs text-gray-400 truncate\">{t.content || '--'}</div>\n <div className=\"text-xs text-gray-600\">{timeAgo(t.created_at)}</div>\n </div>\n\n {/* Expanded detail */}\n {expanded.has(t.task_id) && (\n <div className=\"mt-3 pt-3 border-t border-[#2a2a4a] space-y-3\">\n {t.content && (\n <div>\n <div className=\"text-xs text-gray-600 mb-1\">Content</div>\n <div className=\"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a]\">{t.content}</div>\n </div>\n )}\n {t.result && (\n <div>\n <div className=\"text-xs text-gray-600 mb-1\">Result</div>\n <div className=\"text-xs text-gray-300 whitespace-pre-wrap bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a] max-h-48 overflow-y-auto\">{t.result}</div>\n </div>\n )}\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-2 text-xs\">\n {[\n ['Created', t.created_at],\n ['Delivered', t.delivered_at],\n ['Started', t.started_at],\n ['Completed', t.completed_at],\n ].map(([label, val]) => (\n <div key={label as string}>\n <span className=\"text-gray-600\">{label}: </span>\n <span className=\"text-gray-400\">{val ? timeAgo(val as string) : '--'}</span>\n </div>\n ))}\n </div>\n {t.expires_at && (\n <div className=\"text-xs\">\n <span className=\"text-gray-600\">Expires: </span>\n <span className=\"text-orange-400\">{t.expires_at}</span>\n </div>\n )}\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-xs text-gray-600 truncate\" title={t.task_id}>\n ID: {t.task_id}\n </div>\n <div className=\"flex gap-2 shrink-0\">\n {(t.status === 'failed' || t.status === 'expired') && (\n <button\n onClick={async (e) => {\n e.stopPropagation();\n await fetch('/api/hub/send', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ alias: t.to_name, task: t.content, priority: t.priority }),\n });\n fetchTasks();\n }}\n className=\"text-xs text-orange-400 hover:text-orange-300 px-2 py-0.5 rounded border border-orange-500/20 hover:bg-orange-500/10\"\n >\n Retry\n </button>\n )}\n <button\n onClick={e => { e.stopPropagation(); setDrawerTaskId(t.task_id); }}\n className=\"text-xs text-cyan-400 hover:text-cyan-300\"\n >\n Detail &rarr;\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {drawerTaskId && <TaskDrawer taskId={drawerTaskId} onClose={() => setDrawerTaskId(null)} />}\n </div>\n );\n}\n\nexport default function TasksPage() {\n return (\n <Suspense fallback={<div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-6 font-mono\">Loading tasks...</div>}>\n <TasksContent />\n </Suspense>\n );\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { timeAgo } from './utils';\nimport Link from 'next/link';\n\ninterface TaskDetail {\n task_id: string;\n from_name: string;\n to_name: string;\n status: string;\n priority: string;\n content: string;\n result: string;\n created_at: string;\n delivered_at: string;\n started_at: string;\n completed_at: string;\n expires_at: string;\n}\n\ninterface TaskEvent {\n id: number;\n event_type: string;\n from_status: string;\n to_status: string;\n detail: string;\n created_at: string;\n}\n\nconst STATUS_COLORS: Record<string, string> = {\n created: 'text-gray-400', delivered: 'text-blue-400', running: 'text-green-400',\n replied: 'text-purple-400', failed: 'text-red-400', closed: 'text-gray-500',\n};\n\ninterface TaskDrawerProps {\n taskId: string;\n onClose: () => void;\n}\n\nexport function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {\n const [task, setTask] = useState<TaskDetail | null>(null);\n const [events, setEvents] = useState<TaskEvent[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n (async () => {\n try {\n const [taskRes, eventsRes] = await Promise.all([\n fetch(`/api/hub/tasks?task_id=${encodeURIComponent(taskId)}`),\n fetch(`/api/hub/task-events?task_id=${encodeURIComponent(taskId)}&limit=50`),\n ]);\n const taskData = await taskRes.json();\n const eventsData = await eventsRes.json();\n if (taskData.tasks?.[0]) setTask(taskData.tasks[0]);\n setEvents(eventsData.events || []);\n } catch {} finally { setLoading(false); }\n })();\n }, [taskId]);\n\n const timeline = task ? [\n { label: 'Created', time: task.created_at, color: 'bg-gray-400' },\n { label: 'Delivered', time: task.delivered_at, color: 'bg-blue-400' },\n { label: 'Started', time: task.started_at, color: 'bg-green-400' },\n { label: 'Completed', time: task.completed_at, color: 'bg-purple-400' },\n ] : [];\n\n const duration = task?.started_at && task?.completed_at\n ? Math.round((new Date(task.completed_at).getTime() - new Date(task.started_at).getTime()) / 1000)\n : null;\n\n return (\n <>\n <div className=\"fixed inset-0 bg-black/30 z-40\" onClick={onClose} />\n <div className=\"fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 overflow-y-auto animate-slide-in\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a] sticky top-0\">\n <div>\n <div className=\"text-sm font-semibold text-white\">Task Detail</div>\n <div className=\"text-[10px] text-gray-500 mt-0.5\">{taskId.slice(0, 16)}...</div>\n </div>\n <button onClick={onClose} className=\"text-gray-500 hover:text-white p-1.5 rounded-lg hover:bg-[#1a1a2a]\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {loading ? (\n <div className=\"flex justify-center py-16\">\n <div className=\"w-6 h-6 border-2 border-cyan-500/30 border-t-cyan-500 rounded-full animate-spin\" />\n </div>\n ) : !task ? (\n <div className=\"text-center py-16 text-gray-500\">Task not found</div>\n ) : (\n <div className=\"px-5 py-5 space-y-5\">\n {/* Status + Priority */}\n <div className=\"flex items-center gap-3\">\n <span className={`text-lg font-bold ${STATUS_COLORS[task.status] || 'text-gray-400'}`}>{task.status}</span>\n {task.priority !== 'normal' && (\n <span className={`text-xs px-2 py-0.5 rounded border ${task.priority === 'high' ? 'text-red-300 border-red-500/20' : 'text-gray-400 border-gray-600/20'}`}>{task.priority}</span>\n )}\n {duration !== null && (\n <span className=\"text-xs text-gray-500\">⏱ {duration < 60 ? `${duration}s` : `${Math.floor(duration/60)}m ${duration%60}s`}</span>\n )}\n </div>\n\n {/* From → To */}\n <div className=\"flex items-center gap-2 text-sm\">\n <span className=\"text-blue-400 font-medium\">{task.from_name || '--'}</span>\n <span className=\"text-gray-600\">→</span>\n <span className=\"text-cyan-400 font-medium\">{task.to_name || '--'}</span>\n </div>\n\n {/* Timeline */}\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-3\">Timeline</div>\n <div className=\"space-y-3\">\n {timeline.map((step, i) => (\n <div key={step.label} className=\"flex items-center gap-3\">\n <div className=\"flex flex-col items-center\">\n <div className={`w-3 h-3 rounded-full ${step.time ? step.color : 'bg-gray-700'}`} />\n {i < timeline.length - 1 && <div className={`w-0.5 h-4 mt-1 ${step.time && timeline[i+1]?.time ? 'bg-gray-600' : 'bg-gray-800'}`} />}\n </div>\n <div className=\"flex-1\">\n <div className={`text-xs font-medium ${step.time ? 'text-gray-300' : 'text-gray-600'}`}>{step.label}</div>\n <div className=\"text-[10px] text-gray-500\">{step.time || 'Pending'}</div>\n </div>\n </div>\n ))}\n </div>\n </div>\n\n {/* Content */}\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-2\">Input</div>\n <div className=\"text-sm text-gray-300 whitespace-pre-wrap\">{task.content || '--'}</div>\n </div>\n\n {/* Result */}\n {task.result && (\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-2\">Output</div>\n <div className=\"text-sm text-gray-300 whitespace-pre-wrap max-h-64 overflow-y-auto\">{task.result}</div>\n </div>\n )}\n\n {/* Events */}\n {events.length > 0 && (\n <div className=\"bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"text-xs text-gray-500 uppercase mb-2\">Events ({events.length})</div>\n <div className=\"space-y-1.5 max-h-40 overflow-y-auto\">\n {events.map(e => (\n <div key={e.id} className=\"flex items-center gap-2 text-[11px]\">\n <span className={`w-1.5 h-1.5 rounded-full shrink-0 ${\n e.to_status === 'running' ? 'bg-green-400' : e.to_status === 'replied' ? 'bg-purple-400' : e.to_status === 'failed' ? 'bg-red-400' : 'bg-blue-400'\n }`} />\n <span className=\"text-gray-400\">{e.event_type}</span>\n {e.from_status && <span className=\"text-gray-600\">{e.from_status}→{e.to_status}</span>}\n <span className=\"text-gray-600 ml-auto\">{timeAgo(e.created_at)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Metadata */}\n <div className=\"text-[10px] text-gray-600 space-y-1\">\n <div>Task ID: {task.task_id}</div>\n {task.expires_at && <div>Expires: {task.expires_at}</div>}\n </div>\n </div>\n )}\n </div>\n <style jsx global>{`\n @keyframes slide-in { from { transform: translateX(100%); } to { transform: translateX(0); } }\n .animate-slide-in { animation: slide-in 0.2s ease-out; }\n `}</style>\n </>\n );\n}\n"],"names":["STATUS_COLORS","created","delivered","running","replied","failed","closed","TaskDrawer","taskId","onClose","task","setTask","events","setEvents","loading","setLoading","taskRes","eventsRes","Promise","all","fetch","encodeURIComponent","taskData","json","eventsData","tasks","timeline","label","time","created_at","color","delivered_at","started_at","completed_at","duration","Math","round","Date","getTime","onClick","slice","fill","viewBox","stroke","strokeWidth","strokeLinecap","strokeLinejoin","d","status","priority","floor","from_name","to_name","map","step","i","length","content","result","e","to_status","event_type","from_status","id","task_id","expires_at"],"mappings":"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"}