@sleep2agi/agent-network-dashboard 0.5.3 → 0.5.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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +2 -0
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +37 -37
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +29 -0
- package/.next/routes-manifest.json +12 -0
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +2 -2
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +3 -3
- package/.next/server/app/_not-found.rsc +14 -14
- package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +3 -3
- package/.next/server/app/admin.rsc +16 -16
- package/.next/server/app/admin.segments/_full.segment.rsc +16 -16
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/api/hub/upload/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/hub/upload/route/build-manifest.json +9 -0
- package/.next/server/app/api/hub/upload/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/hub/upload/route.js +7 -0
- package/.next/server/app/api/hub/upload/route.js.map +5 -0
- package/.next/server/app/api/hub/upload/route.js.nft.json +1 -0
- package/.next/server/app/api/hub/upload/route_client-reference-manifest.js +3 -0
- package/.next/server/app/index.html +3 -3
- package/.next/server/app/index.rsc +16 -16
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +16 -16
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +7 -7
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +16 -16
- package/.next/server/app/login.segments/_full.segment.rsc +16 -16
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +7 -7
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +3 -3
- package/.next/server/app/logs.rsc +16 -16
- package/.next/server/app/logs.segments/_full.segment.rsc +16 -16
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- package/.next/server/app/manifest.webmanifest/route/app-paths-manifest.json +3 -0
- package/.next/server/app/manifest.webmanifest/route/build-manifest.json +9 -0
- package/.next/server/app/manifest.webmanifest/route/server-reference-manifest.json +4 -0
- package/.next/server/app/manifest.webmanifest/route.js +8 -0
- package/.next/server/app/manifest.webmanifest/route.js.map +5 -0
- package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -0
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +3 -0
- package/.next/server/app/manifest.webmanifest.body +1 -0
- package/.next/server/app/manifest.webmanifest.meta +1 -0
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +3 -3
- package/.next/server/app/messages.rsc +16 -16
- package/.next/server/app/messages.segments/_full.segment.rsc +16 -16
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +3 -3
- package/.next/server/app/node.rsc +16 -16
- package/.next/server/app/node.segments/_full.segment.rsc +16 -16
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +7 -7
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +3 -3
- package/.next/server/app/nodes.rsc +16 -16
- package/.next/server/app/nodes.segments/_full.segment.rsc +16 -16
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +3 -3
- package/.next/server/app/server-logs.rsc +16 -16
- package/.next/server/app/server-logs.segments/_full.segment.rsc +16 -16
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +3 -3
- package/.next/server/app/settings/networks.rsc +16 -16
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +16 -16
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +3 -3
- package/.next/server/app/settings/tokens.rsc +16 -16
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +16 -16
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +3 -3
- package/.next/server/app/settings.rsc +16 -16
- package/.next/server/app/settings.segments/_full.segment.rsc +16 -16
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +3 -3
- package/.next/server/app/tasks.rsc +16 -16
- package/.next/server/app/tasks.segments/_full.segment.rsc +16 -16
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/app-paths-manifest.json +2 -0
- package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js +18 -0
- package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js.map +1 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_manifest_webmanifest_route_actions_0m16rb8.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_manifest_webmanifest_route_actions_0m16rb8.js.map +1 -0
- package/.next/server/chunks/{[externals]__11vad82._.js → [externals]__036g1.i._.js} +2 -2
- package/.next/server/chunks/[externals]__036g1.i._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js.map +1 -0
- package/.next/server/chunks/{[root-of-the-server]__08uyvdq._.js → [root-of-the-server]__0jndzts._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__08uyvdq._.js.map → [root-of-the-server]__0jndzts._.js.map} +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0..ddwm.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0..ddwm.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02bxi6j.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02bxi6j.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05oassd.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05oassd.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05vxtby.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05vxtby.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05~eml4.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05~eml4.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_-g_q2.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_-g_q2.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_ec0xu.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_ec0xu.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0czb6wz.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0czb6wz.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0e-cn.p.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0e-cn.p.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0k8_sr8.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0k8_sr8.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0lt_3bw.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0lt_3bw.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0uyh3yt.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0uyh3yt.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0v-a2ps.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0v-a2ps.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_12.4r9~.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_12.4r9~.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_13mqkay.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_13mqkay.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js +4 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +4 -4
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/middleware.js +2 -2
- package/.next/server/middleware.js.nft.json +1 -1
- package/.next/server/pages/404.html +3 -3
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/{07~8sx3_5uiox.js → 0csnc6nlttr5s.js} +4 -1
- package/.next/static/chunks/0grmy4z.ylqtd.css +2 -0
- package/.next/static/chunks/0k68tvhf0o-sb.js +1 -0
- package/.next/static/chunks/{0v4-5tng.uh.7.js → 0lc4e9o91uv.n.js} +2 -2
- package/.next/static/chunks/0prdn66k~zu45.js +1 -0
- package/.next/static/chunks/{0ph1in3421~o-.js → 0qvb.hq86qp2g.js} +1 -1
- package/.next/static/chunks/0wyjrc0bekhiz.js +1 -0
- package/.next/static/chunks/0~ykmap37nw9d.js +1 -0
- package/.next/static/chunks/17r9h6cx1w6q-.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/app/api/hub/send/route.ts +11 -2
- package/app/api/hub/servers/route.ts +3 -29
- package/app/api/hub/upload/route.ts +83 -0
- package/app/components/AppShell.tsx +4 -2
- package/app/components/CommandCenter.tsx +1 -1
- package/app/components/DispatchPanel.tsx +1 -1
- package/app/components/MobileNav.tsx +58 -0
- package/app/components/TaskChatPanel.tsx +209 -30
- package/app/components/TaskDrawer.tsx +1 -1
- package/app/components/TopoGraph.tsx +6686 -248
- package/app/globals.css +897 -7
- package/app/layout.tsx +8 -2
- package/app/lib/serverDedupe.ts +122 -0
- package/app/lib/vendorIdentity.ts +74 -56
- package/app/manifest.ts +23 -0
- package/app/nodes/page.tsx +21 -151
- package/package.json +4 -4
- package/public/vendors/claude.svg +7 -8
- package/public/vendors/minimax.svg +8 -9
- package/public/vendors/openai.svg +8 -10
- package/scripts/p157-rc2-dedup-test.mjs +110 -0
- package/scripts/topo-a11y-titles-catalog-test.mjs +132 -0
- package/scripts/topo-active-chrome-hover-text-test.mjs +107 -0
- package/scripts/topo-active-links-chip-halo-layers-test.mjs +81 -0
- package/scripts/topo-alias-chat-brightness-test.mjs +79 -0
- package/scripts/topo-alias-text-halo-layers-test.mjs +98 -0
- package/scripts/topo-animation-temporal-modes-catalog-test.mjs +144 -0
- package/scripts/topo-avatar-chat-gate-test.mjs +77 -0
- package/scripts/topo-avatar-drop-shadow-test.mjs +86 -0
- package/scripts/topo-avatar-fallback-hover-test.mjs +104 -0
- package/scripts/topo-avatar-fallback-rotate-test.mjs +92 -0
- package/scripts/topo-avatar-rotate-test.mjs +85 -0
- package/scripts/topo-avatar-scale-test.mjs +89 -0
- package/scripts/topo-badge-chat-gate-test.mjs +74 -0
- package/scripts/topo-brand-drop-shadow-test.mjs +71 -0
- package/scripts/topo-brand-logo-breath-test.mjs +102 -0
- package/scripts/topo-brand-logo-halo-layers-test.mjs +85 -0
- package/scripts/topo-brand-logo-hover-brightness-test.mjs +105 -0
- package/scripts/topo-brand-logo-hover-rotate-test.mjs +93 -0
- package/scripts/topo-brand-logo-hover-test.mjs +85 -0
- package/scripts/topo-canvas-desc-a11y-test.mjs +87 -0
- package/scripts/topo-canvas-entrance-animation-test.mjs +117 -0
- package/scripts/topo-canvas-scan-beam-diagonal-test.mjs +148 -0
- package/scripts/topo-canvas-scan-beam-test.mjs +109 -0
- package/scripts/topo-canvas-scan-beam-vertical-test.mjs +123 -0
- package/scripts/topo-card-chat-brightness-test.mjs +86 -0
- package/scripts/topo-chat-ring-breath-curve-test.mjs +114 -0
- package/scripts/topo-chat-ring-brightness-test.mjs +80 -0
- package/scripts/topo-chat-ring-halo-layers-test.mjs +100 -0
- package/scripts/topo-chat-ring-r-breath-test.mjs +121 -0
- package/scripts/topo-chat-ring-status-halo-test.mjs +106 -0
- package/scripts/topo-chat-ring-sw-breath-test.mjs +123 -0
- package/scripts/topo-chip-pin-halo-test.mjs +85 -0
- package/scripts/topo-chip-row-digit-ls-test.mjs +135 -0
- package/scripts/topo-chip-row-member-alias-lit-test.mjs +154 -0
- package/scripts/topo-chip-row-tier-glow-brightness-test.mjs +99 -0
- package/scripts/topo-chip-row-unit-hover-tracking-test.mjs +124 -0
- package/scripts/topo-chrome-control-halo-layers-test.mjs +22 -0
- package/scripts/topo-chrome-fullscreen-breath-test.mjs +121 -0
- package/scripts/topo-chrome-layout-trailer-breath-test.mjs +86 -0
- package/scripts/topo-chrome-nodesize-trailer-breath-test.mjs +86 -0
- package/scripts/topo-chrome-reset-breath-test.mjs +115 -0
- package/scripts/topo-chrome-strip-entrance-animation-test.mjs +115 -0
- package/scripts/topo-chrome-wrapper-halo-test.mjs +83 -0
- package/scripts/topo-chrome-zoom-wrapper-breath-test.mjs +85 -0
- package/scripts/topo-click-ripple-glow-test.mjs +86 -0
- package/scripts/topo-click-ripple-halo-layers-test.mjs +79 -0
- package/scripts/topo-click-ripple-sw-test.mjs +110 -0
- package/scripts/topo-cluster-count-attr-test.mjs +80 -0
- package/scripts/topo-crescent-breath-test.mjs +104 -0
- package/scripts/topo-crescent-envelope-breath-test.mjs +103 -0
- package/scripts/topo-crescent-recede-test.mjs +111 -0
- package/scripts/topo-dense-alias-chat-halo-test.mjs +73 -0
- package/scripts/topo-dense-alias-halo-layers-test.mjs +80 -0
- package/scripts/topo-dual-axis-surfaces-catalog-test.mjs +94 -0
- package/scripts/topo-edge-badge-circle-brightness-test.mjs +82 -0
- package/scripts/topo-edge-badge-circle-hot-pulse-test.mjs +100 -0
- package/scripts/topo-edge-badge-digit-halo-layers-test.mjs +107 -0
- package/scripts/topo-edge-badge-endpoint-gate-test.mjs +94 -0
- package/scripts/topo-edge-badge-halo-layers-test.mjs +85 -0
- package/scripts/topo-edge-badge-hot-pulse-test.mjs +92 -0
- package/scripts/topo-edge-badge-hover-glow-test.mjs +90 -0
- package/scripts/topo-edge-badge-text-brightness-test.mjs +83 -0
- package/scripts/topo-edge-chat-gate-test.mjs +71 -0
- package/scripts/topo-edge-flow-rail-halo-layers-test.mjs +89 -0
- package/scripts/topo-edge-particle-brightness-test.mjs +82 -0
- package/scripts/topo-edge-particle-halo-layers-test.mjs +91 -0
- package/scripts/topo-edge-pill-glow-test.mjs +67 -0
- package/scripts/topo-edge-pin-halo-test.mjs +99 -0
- package/scripts/topo-edge-visible-brightness-test.mjs +84 -0
- package/scripts/topo-edge-visible-halo-layers-test.mjs +87 -0
- package/scripts/topo-endpoint-ring-brightness-test.mjs +83 -0
- package/scripts/topo-endpoint-ring-flow-halo-test.mjs +107 -0
- package/scripts/topo-endpoint-ring-halo-layers-test.mjs +100 -0
- package/scripts/topo-filter-pill-glow-test.mjs +90 -0
- package/scripts/topo-filter-pill-halo-layers-test.mjs +27 -0
- package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
- package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
- package/scripts/topo-fullscreen-attr-test.mjs +73 -0
- package/scripts/topo-fullscreen-brightness-test.mjs +84 -0
- package/scripts/topo-fullscreen-icon-rotate-test.mjs +93 -0
- package/scripts/topo-grid-content-bottom-attr-test.mjs +72 -0
- package/scripts/topo-group-box-brightness-test.mjs +84 -0
- package/scripts/topo-group-box-halo-layers-test.mjs +91 -0
- package/scripts/topo-group-chat-gate-test.mjs +77 -0
- package/scripts/topo-group-label-brightness-test.mjs +84 -0
- package/scripts/topo-group-label-halo-layers-test.mjs +78 -0
- package/scripts/topo-group-label-hover-glow-test.mjs +86 -0
- package/scripts/topo-group-label-member-alias-hover-test.mjs +125 -0
- package/scripts/topo-group-pill-glow-test.mjs +76 -0
- package/scripts/topo-group-tint-brightness-test.mjs +82 -0
- package/scripts/topo-h2-dual-axis-breath-test.mjs +92 -0
- package/scripts/topo-h2-triple-axis-breath-test.mjs +142 -0
- package/scripts/topo-halo-chat-gate-test.mjs +72 -0
- package/scripts/topo-hover-detail-halo-test.mjs +76 -0
- package/scripts/topo-hub-a11y-title-test.mjs +95 -0
- package/scripts/topo-hub-core-brightness-test.mjs +82 -0
- package/scripts/topo-hub-core-halo-layers-test.mjs +81 -0
- package/scripts/topo-hub-digit-brightness-test.mjs +79 -0
- package/scripts/topo-hub-digit-halo-layers-test.mjs +76 -0
- package/scripts/topo-hub-digit-ls-test.mjs +119 -0
- package/scripts/topo-hub-halo-brightness-test.mjs +80 -0
- package/scripts/topo-hub-halo-glow-test.mjs +96 -0
- package/scripts/topo-hub-halo-halo-layers-test.mjs +76 -0
- package/scripts/topo-hub-highlight-brightness-test.mjs +84 -0
- package/scripts/topo-hub-highlight-glow-test.mjs +99 -0
- package/scripts/topo-hub-highlight-halo-layers-test.mjs +78 -0
- package/scripts/topo-hub-highlight-r-test.mjs +112 -0
- package/scripts/topo-hub-hover-ring-brightness-test.mjs +79 -0
- package/scripts/topo-hub-hover-ring-glow-test.mjs +97 -0
- package/scripts/topo-hub-hover-ring-halo-layers-test.mjs +71 -0
- package/scripts/topo-hub-spoke-brightness-test.mjs +77 -0
- package/scripts/topo-hub-spoke-glow-test.mjs +112 -0
- package/scripts/topo-hub-spoke-halo-layers-test.mjs +97 -0
- package/scripts/topo-hub-spoke-self-filter-test.mjs +119 -0
- package/scripts/topo-kicker-breath-test.mjs +100 -0
- package/scripts/topo-kicker-dual-axis-breath-test.mjs +81 -0
- package/scripts/topo-kicker-halo-layers-test.mjs +82 -0
- package/scripts/topo-kicker-triple-axis-breath-test.mjs +124 -0
- package/scripts/topo-label-card-brightness-test.mjs +81 -0
- package/scripts/topo-layout-hover-fw-test.mjs +98 -0
- package/scripts/topo-layout-toggle-brightness-test.mjs +94 -0
- package/scripts/topo-layout-toggle-halo-layers-test.mjs +95 -0
- package/scripts/topo-legend-count-brightness-test.mjs +80 -0
- package/scripts/topo-legend-count-halo-layers-test.mjs +79 -0
- package/scripts/topo-legend-count-letter-spacing-test.mjs +108 -0
- package/scripts/topo-legend-label-fw-test.mjs +107 -0
- package/scripts/topo-legend-panel-title-breath-test.mjs +86 -0
- package/scripts/topo-legend-pin-ring-brightness-test.mjs +82 -0
- package/scripts/topo-legend-pin-ring-halo-layers-test.mjs +71 -0
- package/scripts/topo-legend-row-count-brightness-test.mjs +85 -0
- package/scripts/topo-legend-row-label-glow-test.mjs +102 -0
- package/scripts/topo-legend-swatch-glow-test.mjs +109 -0
- package/scripts/topo-legend-swatch-member-alias-match-test.mjs +139 -0
- package/scripts/topo-legend-tint-brightness-test.mjs +83 -0
- package/scripts/topo-legend-trio-halo-layers-test.mjs +22 -0
- package/scripts/topo-live-lanes.mjs +48 -0
- package/scripts/topo-minimap-container-halo-test.mjs +82 -0
- package/scripts/topo-minimap-dot-chat-gate-test.mjs +81 -0
- package/scripts/topo-minimap-hover-glow-test.mjs +109 -0
- package/scripts/topo-minimap-viewport-brightness-test.mjs +84 -0
- package/scripts/topo-minimap-viewport-halo-layers-test.mjs +24 -0
- package/scripts/topo-more-footer-brightness-test.mjs +94 -0
- package/scripts/topo-node-alias-brightness-test.mjs +84 -0
- package/scripts/topo-node-avatar-halo-layers-test.mjs +25 -0
- package/scripts/topo-node-hover-ring-halo-layers-test.mjs +70 -0
- package/scripts/topo-node-label-card-halo-test.mjs +76 -0
- package/scripts/topo-node-sub-text-brightness-test.mjs +88 -0
- package/scripts/topo-nodesize-brightness-test.mjs +82 -0
- package/scripts/topo-nodesize-halo-layers-test.mjs +89 -0
- package/scripts/topo-nodesize-hover-fw-test.mjs +99 -0
- package/scripts/topo-orphan-label-opacity-test.mjs +98 -0
- package/scripts/topo-overlap-test.mjs +22 -8
- package/scripts/topo-panel-count-halo-layers-test.mjs +91 -0
- package/scripts/topo-panel-count-hover-ls-test.mjs +87 -0
- package/scripts/topo-panel-rect-halo-test.mjs +90 -0
- package/scripts/topo-panel-row-brightness-test.mjs +116 -0
- package/scripts/topo-panel-title-brightness-test.mjs +98 -0
- package/scripts/topo-panel-title-glow-test.mjs +111 -0
- package/scripts/topo-panel-titles-dual-axis-breath-test.mjs +94 -0
- package/scripts/topo-panel-titles-halo-layers-test.mjs +23 -0
- package/scripts/topo-panel-titles-triple-axis-breath-test.mjs +161 -0
- package/scripts/topo-pill-x-rotate-test.mjs +96 -0
- package/scripts/topo-pip-brightness-test.mjs +85 -0
- package/scripts/topo-pressure-bar-halo-layers-test.mjs +19 -0
- package/scripts/topo-pressure-seg-glow-test.mjs +92 -0
- package/scripts/topo-pressure-seg-member-alias-match-test.mjs +133 -0
- package/scripts/topo-pressure-seg-motion-test.mjs +101 -0
- package/scripts/topo-r717-scan-beam-pair-pattern-test.mjs +100 -0
- package/scripts/topo-r717-triple-axis-pair-pattern-test.mjs +113 -0
- package/scripts/topo-r717-triple-axis-tier-pattern-test.mjs +117 -0
- package/scripts/topo-recent-count-brightness-test.mjs +84 -0
- package/scripts/topo-recent-more-fw-test.mjs +126 -0
- package/scripts/topo-recent-more-halo-layers-test.mjs +90 -0
- package/scripts/topo-recent-panel-hot-pulse-test.mjs +105 -0
- package/scripts/topo-recent-panel-title-breath-test.mjs +91 -0
- package/scripts/topo-recent-pip-halo-layers-test.mjs +82 -0
- package/scripts/topo-recent-row-chat-gate-test.mjs +75 -0
- package/scripts/topo-recent-row-content-lift-test.mjs +140 -0
- package/scripts/topo-recent-row-fw-test.mjs +115 -0
- package/scripts/topo-recent-row-text-glow-test.mjs +86 -0
- package/scripts/topo-recent-row-text-halo-layers-test.mjs +67 -0
- package/scripts/topo-recent-tint-brightness-test.mjs +80 -0
- package/scripts/topo-recent-ts-brightness-test.mjs +86 -0
- package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
- package/scripts/topo-reset-brightness-test.mjs +83 -0
- package/scripts/topo-reset-icon-hover-scale-test.mjs +102 -0
- package/scripts/topo-respiratory-axis-count-stats-test.mjs +154 -0
- package/scripts/topo-respiratory-patterns-catalog-test.mjs +112 -0
- package/scripts/topo-respiratory-rolodex-test.mjs +83 -0
- package/scripts/topo-respiratory-tiers-catalog-test.mjs +119 -0
- package/scripts/topo-respiratory-triple-axis-surfaces-catalog-test.mjs +127 -0
- package/scripts/topo-runtime-badge-brightness-test.mjs +78 -0
- package/scripts/topo-runtime-badge-glow-test.mjs +108 -0
- package/scripts/topo-runtime-badge-halo-layers-test.mjs +87 -0
- package/scripts/topo-runtime-badge-rotate-test.mjs +85 -0
- package/scripts/topo-section-title-breath-test.mjs +83 -0
- package/scripts/topo-section-title-halo-layers-test.mjs +88 -0
- package/scripts/topo-spoke-chat-gate-test.mjs +72 -0
- package/scripts/topo-starfield-hue-test.mjs +109 -0
- package/scripts/topo-status-pin-pill-halo-layers-test.mjs +17 -0
- package/scripts/topo-status-ring-brightness-test.mjs +84 -0
- package/scripts/topo-status-ring-chat-gate-test.mjs +72 -0
- package/scripts/topo-status-ring-halo-layers-test.mjs +105 -0
- package/scripts/topo-status-ring-status-halo-test.mjs +110 -0
- package/scripts/topo-sub-text-chat-brightness-test.mjs +81 -0
- package/scripts/topo-svg-title-a11y-r731-test.mjs +93 -0
- package/scripts/topo-svg-title-a11y-test.mjs +88 -0
- package/scripts/topo-title-block-entrance-animation-test.mjs +127 -0
- package/scripts/topo-title-block-envelope-breath-test.mjs +87 -0
- package/scripts/topo-titleblock-h2-hover-fw-test.mjs +109 -0
- package/scripts/topo-titleblock-h2-hover-tracking-test.mjs +128 -0
- package/scripts/topo-titleblock-kicker-hover-test.mjs +134 -0
- package/scripts/topo-tree-diag.mjs +95 -0
- package/scripts/topo-vendor-chip-glow-test.mjs +97 -0
- package/scripts/topo-vendor-chip-halo-layers-test.mjs +18 -0
- package/scripts/topo-vendor-chip-pin-halo-test.mjs +88 -0
- package/scripts/topo-vendor-count-suffix-halo-layers-test.mjs +79 -0
- package/scripts/topo-vendor-distribution-wrapper-halo-test.mjs +93 -0
- package/scripts/topo-vendor-letter-halo-layers-test.mjs +93 -0
- package/scripts/topo-vendor-pill-glow-test.mjs +98 -0
- package/scripts/topo-watermark-breath-test.mjs +100 -0
- package/scripts/topo-watermark-dual-axis-breath-test.mjs +88 -0
- package/scripts/topo-watermark-envelope-breath-test.mjs +88 -0
- package/scripts/topo-watermark-recede-test.mjs +114 -0
- package/scripts/topo-watermark-triple-axis-breath-test.mjs +129 -0
- package/scripts/topo-working-online-chip-halo-layers-test.mjs +94 -0
- package/scripts/topo-zoom-buttons-brightness-test.mjs +94 -0
- package/scripts/topo-zoom-in-out-halo-layers-test.mjs +97 -0
- package/scripts/topo-zoom-level-breath-test.mjs +87 -0
- package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
- package/scripts/topo-zoom-level-color-test.mjs +105 -0
- package/scripts/topo-zoom-level-dual-axis-breath-test.mjs +83 -0
- package/scripts/topo-zoom-level-halo-layers-test.mjs +78 -0
- package/scripts/topo-zoom-level-triple-axis-breath-test.mjs +148 -0
- package/.next/static/chunks/01lmbsd37fybu.js +0 -1
- package/.next/static/chunks/03o.h6kvmw4l_.js +0 -1
- package/.next/static/chunks/0fuba20p57-zo.js +0 -1
- package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
- package/.next/static/chunks/10cj-86disers.js +0 -1
- package/.next/static/chunks/158h2g7f-nxbt.js +0 -4
- /package/.next/server/chunks/{[externals]__11vad82._.js.map → 0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js.map} +0 -0
- /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_buildManifest.js +0 -0
- /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_ssgManifest.js +0 -0
|
@@ -13,6 +13,82 @@ interface ChatTask {
|
|
|
13
13
|
content: string;
|
|
14
14
|
result: string;
|
|
15
15
|
created_at: string;
|
|
16
|
+
completed_at?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type ChatEvent =
|
|
20
|
+
| { kind: 'task'; task: ChatTask; at: string }
|
|
21
|
+
| { kind: 'reply'; task: ChatTask; at: string };
|
|
22
|
+
|
|
23
|
+
function eventTime(value?: string) {
|
|
24
|
+
if (!value) return 0;
|
|
25
|
+
return new Date(value.replace(' ', 'T') + (value.includes('T') ? '' : 'Z')).getTime() || 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function formatTimestamp(value?: string) {
|
|
29
|
+
if (!value) return '--';
|
|
30
|
+
const d = new Date(value.replace(' ', 'T') + (value.includes('T') ? '' : 'Z'));
|
|
31
|
+
if (Number.isNaN(d.getTime())) return value;
|
|
32
|
+
return d.toLocaleString(undefined, { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function quotePreview(text: string, max = 140) {
|
|
36
|
+
const compact = (text || '')
|
|
37
|
+
.replace(/\[Dashboard 附件[\s\S]*$/m, '[附件]')
|
|
38
|
+
.replace(/\s+/g, ' ')
|
|
39
|
+
.trim();
|
|
40
|
+
return compact.length > max ? `${compact.slice(0, max)}…` : compact;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function extractAttachmentPreviews(text: string): string[] {
|
|
44
|
+
const urls: string[] = [];
|
|
45
|
+
for (const line of (text || '').split('\n')) {
|
|
46
|
+
const match = line.match(/^\s*-\s*预览:\s*(\S+)\s*$/);
|
|
47
|
+
if (match?.[1]) urls.push(match[1]);
|
|
48
|
+
}
|
|
49
|
+
return Array.from(new Set(urls));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function AttachmentPreviews({ text }: { text: string }) {
|
|
53
|
+
const urls = extractAttachmentPreviews(text);
|
|
54
|
+
if (urls.length === 0) return null;
|
|
55
|
+
return (
|
|
56
|
+
<div className="mt-2 grid grid-cols-2 gap-2">
|
|
57
|
+
{urls.map((url) => (
|
|
58
|
+
<a key={url} href={url} target="_blank" rel="noreferrer" className="group block overflow-hidden rounded-lg border border-cyan-500/20 bg-black/20">
|
|
59
|
+
<img
|
|
60
|
+
src={url}
|
|
61
|
+
alt="Dashboard attachment preview"
|
|
62
|
+
className="h-28 w-full object-cover transition-transform duration-200 group-hover:scale-[1.02]"
|
|
63
|
+
loading="lazy"
|
|
64
|
+
/>
|
|
65
|
+
</a>
|
|
66
|
+
))}
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function LocalImagePreview({ file, onRemove }: { file: File; onRemove: () => void }) {
|
|
72
|
+
const [url, setUrl] = useState('');
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
const objectUrl = URL.createObjectURL(file);
|
|
75
|
+
setUrl(objectUrl);
|
|
76
|
+
return () => URL.revokeObjectURL(objectUrl);
|
|
77
|
+
}, [file]);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div className="relative h-16 w-16 overflow-hidden rounded-lg border border-cyan-500/25 bg-black/20">
|
|
81
|
+
{url && <img src={url} alt={file.name} className="h-full w-full object-cover" />}
|
|
82
|
+
<button
|
|
83
|
+
type="button"
|
|
84
|
+
onClick={onRemove}
|
|
85
|
+
className="absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-black/70 text-xs text-white hover:bg-red-500"
|
|
86
|
+
aria-label={`Remove ${file.name}`}
|
|
87
|
+
>
|
|
88
|
+
×
|
|
89
|
+
</button>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
16
92
|
}
|
|
17
93
|
|
|
18
94
|
const STATUS_STEPS = ['created', 'delivered', 'running', 'replied'];
|
|
@@ -123,6 +199,7 @@ interface TaskChatPanelProps {
|
|
|
123
199
|
export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskChatPanelProps) {
|
|
124
200
|
const [messages, setMessages] = useState<ChatTask[]>([]);
|
|
125
201
|
const [input, setInput] = useState('');
|
|
202
|
+
const [attachedFiles, setAttachedFiles] = useState<File[]>([]);
|
|
126
203
|
const [priority, setPriority] = useState('normal');
|
|
127
204
|
const [sending, setSending] = useState(false);
|
|
128
205
|
const [pollingIds, setPollingIds] = useState<Set<string>>(new Set());
|
|
@@ -228,8 +305,21 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
228
305
|
return () => clearInterval(interval);
|
|
229
306
|
}, [pollingIds]);
|
|
230
307
|
|
|
308
|
+
const uploadAttachments = async () => {
|
|
309
|
+
const uploaded = [];
|
|
310
|
+
for (const file of attachedFiles) {
|
|
311
|
+
const form = new FormData();
|
|
312
|
+
form.append('file', file);
|
|
313
|
+
const res = await fetch('/api/hub/upload', { method: 'POST', body: form });
|
|
314
|
+
const data = await res.json().catch(() => ({ ok: false, error: `HTTP ${res.status}` }));
|
|
315
|
+
if (!res.ok || !data.ok) throw new Error(data.error || data.detail || `upload failed: ${file.name}`);
|
|
316
|
+
uploaded.push({ type: 'image', name: file.name, path: data.path, url: data.url, mime: data.mime, size: data.size });
|
|
317
|
+
}
|
|
318
|
+
return uploaded;
|
|
319
|
+
};
|
|
320
|
+
|
|
231
321
|
const send = async () => {
|
|
232
|
-
if (!input.trim() || sending) return;
|
|
322
|
+
if ((!input.trim() && attachedFiles.length === 0) || sending) return;
|
|
233
323
|
let taskContent = input.trim();
|
|
234
324
|
let sendTo = targetAlias;
|
|
235
325
|
|
|
@@ -245,9 +335,14 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
245
335
|
|
|
246
336
|
setSending(true);
|
|
247
337
|
setInput('');
|
|
338
|
+
setAttachedFiles([]);
|
|
248
339
|
setShowMentions(false);
|
|
249
340
|
if (textareaRef.current) textareaRef.current.style.height = 'auto';
|
|
250
341
|
|
|
342
|
+
const pendingAttachmentText = attachedFiles.length > 0
|
|
343
|
+
? `\n\n[Dashboard 附件待上传]\n${attachedFiles.map(f => `- 图片: ${f.name}`).join('\n')}`
|
|
344
|
+
: '';
|
|
345
|
+
|
|
251
346
|
// Optimistic echo first so the user always sees their message in history
|
|
252
347
|
// even if the network call fails or the server returns ok:false. Earlier
|
|
253
348
|
// version only added on data.ok=true → silent failures looked like
|
|
@@ -259,17 +354,31 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
259
354
|
to_name: sendTo,
|
|
260
355
|
status: 'created',
|
|
261
356
|
priority,
|
|
262
|
-
content: taskContent,
|
|
357
|
+
content: `${taskContent}${pendingAttachmentText}`.trim(),
|
|
263
358
|
result: '',
|
|
264
359
|
created_at: new Date().toISOString(),
|
|
265
360
|
};
|
|
266
361
|
setMessages(prev => [...prev, optimistic]);
|
|
267
362
|
|
|
268
363
|
try {
|
|
364
|
+
const uploaded = await uploadAttachments();
|
|
365
|
+
if (uploaded.length > 0) {
|
|
366
|
+
const attachmentText = [
|
|
367
|
+
'',
|
|
368
|
+
'',
|
|
369
|
+
'[Dashboard 附件]',
|
|
370
|
+
...uploaded.map(f => `- 图片: ${f.path}`),
|
|
371
|
+
...uploaded.map(f => `- 预览: ${f.url}`),
|
|
372
|
+
].join('\n');
|
|
373
|
+
taskContent = `${taskContent}${attachmentText}`.trim();
|
|
374
|
+
setMessages(prev => prev.map(m =>
|
|
375
|
+
m.task_id === localTaskId ? { ...m, content: taskContent } : m,
|
|
376
|
+
));
|
|
377
|
+
}
|
|
269
378
|
const res = await fetch('/api/hub/send', {
|
|
270
379
|
method: 'POST',
|
|
271
380
|
headers: { 'Content-Type': 'application/json' },
|
|
272
|
-
body: JSON.stringify({ alias: sendTo, task: taskContent, priority }),
|
|
381
|
+
body: JSON.stringify({ alias: sendTo, task: taskContent, priority, attachments: uploaded }),
|
|
273
382
|
});
|
|
274
383
|
const data = await res.json().catch(() => ({ ok: false, error: `HTTP ${res.status}` }));
|
|
275
384
|
if (data.ok && data.message_id) {
|
|
@@ -318,6 +427,20 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
318
427
|
setShowMentions(false);
|
|
319
428
|
};
|
|
320
429
|
|
|
430
|
+
const addImageFiles = (files: FileList | File[]) => {
|
|
431
|
+
const images = Array.from(files).filter(file => file.type.startsWith('image/'));
|
|
432
|
+
if (images.length === 0) return;
|
|
433
|
+
setAttachedFiles(prev => [...prev, ...images].slice(0, 6));
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
|
|
437
|
+
const files = Array.from(e.clipboardData.files || []);
|
|
438
|
+
if (files.some(file => file.type.startsWith('image/'))) {
|
|
439
|
+
addImageFiles(files);
|
|
440
|
+
e.preventDefault();
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
|
|
321
444
|
const insertMention = (nodeName: string) => {
|
|
322
445
|
const lastAt = input.lastIndexOf('@');
|
|
323
446
|
const before = input.slice(0, lastAt);
|
|
@@ -335,11 +458,24 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
335
458
|
el.style.height = Math.min(el.scrollHeight, 150) + 'px';
|
|
336
459
|
};
|
|
337
460
|
|
|
461
|
+
const chatEvents: ChatEvent[] = messages
|
|
462
|
+
.flatMap((task): ChatEvent[] => {
|
|
463
|
+
const events: ChatEvent[] = [{ kind: 'task', task, at: task.created_at }];
|
|
464
|
+
if (task.result) events.push({ kind: 'reply', task, at: task.completed_at || task.created_at });
|
|
465
|
+
return events;
|
|
466
|
+
})
|
|
467
|
+
.sort((a, b) => {
|
|
468
|
+
const delta = eventTime(a.at) - eventTime(b.at);
|
|
469
|
+
if (delta !== 0) return delta;
|
|
470
|
+
if (a.task.task_id !== b.task.task_id) return a.task.task_id.localeCompare(b.task.task_id);
|
|
471
|
+
return a.kind === 'task' ? -1 : 1;
|
|
472
|
+
});
|
|
473
|
+
|
|
338
474
|
// Inline mode: just the chat content, no panel chrome
|
|
339
475
|
const chatContent = (
|
|
340
476
|
<>
|
|
341
477
|
{/* Messages area */}
|
|
342
|
-
<div className="flex-1 overflow-y-auto px-4 py-4 space-y-4">
|
|
478
|
+
<div className="flex-1 overflow-y-auto px-3 py-3 sm:px-4 sm:py-4 space-y-3 sm:space-y-4">
|
|
343
479
|
{!historyLoaded && (
|
|
344
480
|
<div className="flex justify-center py-8">
|
|
345
481
|
<div className="w-5 h-5 border-2 border-cyan-500/30 border-t-cyan-500 rounded-full animate-spin" />
|
|
@@ -353,7 +489,8 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
353
489
|
</div>
|
|
354
490
|
)}
|
|
355
491
|
|
|
356
|
-
{
|
|
492
|
+
{chatEvents.map((event) => {
|
|
493
|
+
const m = event.task;
|
|
357
494
|
// Distinguish task source so users can tell when a peer agent
|
|
358
495
|
// forwarded a task vs when they themselves sent it from Dashboard.
|
|
359
496
|
const fromUser = !m.from_name || m.from_name === 'Dashboard' || m.from_name === 'api' || m.from_name === 'hub';
|
|
@@ -361,43 +498,61 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
361
498
|
const senderBadge = fromUser
|
|
362
499
|
? null
|
|
363
500
|
: <span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-purple-500/15 border border-purple-500/30 text-[9px] text-purple-300 font-medium">↳ {m.from_name}</span>;
|
|
501
|
+
if (event.kind === 'reply') {
|
|
502
|
+
return (
|
|
503
|
+
<div key={`${m.task_id}:reply`} className="flex justify-start">
|
|
504
|
+
<div className="max-w-[92%] sm:max-w-[85%] bg-green-500/8 border border-green-500/15 rounded-2xl rounded-bl-md px-3 py-2.5 sm:px-4 shadow-sm">
|
|
505
|
+
<div className="flex items-center justify-between gap-2 mb-2">
|
|
506
|
+
<div className="flex items-center gap-1.5 min-w-0">
|
|
507
|
+
{m.to_name && <AliasAvatar alias={m.to_name} size={14} />}
|
|
508
|
+
<span className="text-[10px] text-[var(--fg)] font-medium truncate">{m.to_name}</span>
|
|
509
|
+
<span className="text-[9px] text-green-300/70">replied</span>
|
|
510
|
+
</div>
|
|
511
|
+
<span className="shrink-0 rounded-md bg-black/20 px-1.5 py-0.5 text-[9px] text-[var(--fg-dim)]" title={event.at}>
|
|
512
|
+
{timeAgo(event.at)} · {formatTimestamp(event.at)}
|
|
513
|
+
</span>
|
|
514
|
+
</div>
|
|
515
|
+
<div className="mb-2 rounded-lg border-l-2 border-cyan-400/40 bg-black/20 px-2.5 py-1.5">
|
|
516
|
+
<div className="text-[9px] text-cyan-300/80">
|
|
517
|
+
引用 {senderLabel} 的任务 · {formatTimestamp(m.created_at)}
|
|
518
|
+
</div>
|
|
519
|
+
<div className="mt-0.5 max-h-10 overflow-hidden text-[11px] leading-5 text-[var(--fg-muted)]">
|
|
520
|
+
{quotePreview(m.content) || 'No content'}
|
|
521
|
+
</div>
|
|
522
|
+
</div>
|
|
523
|
+
<div className="text-[13px] text-[var(--fg)]">
|
|
524
|
+
<MarkdownContent text={m.result} />
|
|
525
|
+
<AttachmentPreviews text={m.result} />
|
|
526
|
+
</div>
|
|
527
|
+
</div>
|
|
528
|
+
</div>
|
|
529
|
+
);
|
|
530
|
+
}
|
|
364
531
|
return (
|
|
365
|
-
<div key={m.task_id} className="space-y-2">
|
|
532
|
+
<div key={`${m.task_id}:task`} className="space-y-2">
|
|
366
533
|
{/* Outgoing task — labeled with origin so peer-forwarded tasks are obvious */}
|
|
367
534
|
<div className="flex justify-end">
|
|
368
|
-
<div className="max-w-[85%] bg-cyan-500/8 border border-cyan-500/15 rounded-2xl rounded-br-md px-
|
|
535
|
+
<div className="max-w-[92%] sm:max-w-[85%] bg-cyan-500/8 border border-cyan-500/15 rounded-2xl rounded-br-md px-3 py-2.5 sm:px-4 shadow-sm">
|
|
369
536
|
<div className="flex items-center gap-2 mb-1">
|
|
370
537
|
<span className={`text-[10px] font-medium ${fromUser ? 'text-cyan-400' : 'text-purple-300'}`}>{senderLabel}</span>
|
|
371
538
|
{!fromUser && <span className="text-[9px] text-[var(--fg-dim)]">forwarded to {m.to_name}</span>}
|
|
372
539
|
</div>
|
|
373
540
|
<div className="text-[13px] text-[var(--fg)]">
|
|
374
541
|
<MarkdownContent text={m.content} />
|
|
542
|
+
<AttachmentPreviews text={m.content} />
|
|
375
543
|
</div>
|
|
376
|
-
<div className="flex items-center justify-between mt-1.5 gap-3">
|
|
544
|
+
<div className="flex flex-wrap items-center justify-between mt-1.5 gap-2 sm:gap-3">
|
|
377
545
|
<StatusBar status={m.status} />
|
|
378
546
|
<div className="flex items-center gap-2 shrink-0">
|
|
379
547
|
{senderBadge}
|
|
380
|
-
<span className="text-[9px] text-[var(--fg-dim)]"
|
|
548
|
+
<span className="rounded-md bg-black/15 px-1.5 py-0.5 text-[9px] text-[var(--fg-dim)]" title={m.created_at}>
|
|
549
|
+
{timeAgo(m.created_at)} · {formatTimestamp(m.created_at)}
|
|
550
|
+
</span>
|
|
381
551
|
</div>
|
|
382
552
|
</div>
|
|
383
553
|
</div>
|
|
384
554
|
</div>
|
|
385
555
|
|
|
386
|
-
{/* Incoming reply */}
|
|
387
|
-
{m.result && (
|
|
388
|
-
<div className="flex justify-start">
|
|
389
|
-
<div className="max-w-[85%] bg-green-500/8 border border-green-500/15 rounded-2xl rounded-bl-md px-4 py-2.5 shadow-sm">
|
|
390
|
-
<div className="flex items-center gap-1.5 mb-1.5">
|
|
391
|
-
{m.to_name && <AliasAvatar alias={m.to_name} size={14} />}
|
|
392
|
-
<span className="text-[10px] text-[var(--fg)] font-medium">{m.to_name}</span>
|
|
393
|
-
</div>
|
|
394
|
-
<div className="text-[13px] text-[var(--fg)]">
|
|
395
|
-
<MarkdownContent text={m.result} />
|
|
396
|
-
</div>
|
|
397
|
-
</div>
|
|
398
|
-
</div>
|
|
399
|
-
)}
|
|
400
|
-
|
|
401
556
|
{/* Typing indicator when running */}
|
|
402
557
|
{m.status === 'running' && !m.result && (
|
|
403
558
|
<div className="flex justify-start">
|
|
@@ -417,7 +572,7 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
417
572
|
</div>
|
|
418
573
|
|
|
419
574
|
{/* Input area */}
|
|
420
|
-
<div className="border-t border-[var(--border)] bg-[var(--bg-secondary)] px-
|
|
575
|
+
<div className="border-t border-[var(--border)] bg-[var(--bg-secondary)] px-3 py-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] sm:px-4">
|
|
421
576
|
<div className="flex items-end gap-2">
|
|
422
577
|
<div className="flex-1 relative">
|
|
423
578
|
{/* @ mention dropdown */}
|
|
@@ -437,11 +592,24 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
437
592
|
value={input}
|
|
438
593
|
onChange={e => { handleInputChange(e.target.value); autoResize(e.target); }}
|
|
439
594
|
onKeyDown={handleKeyDown}
|
|
595
|
+
onPaste={handlePaste}
|
|
440
596
|
placeholder={`Message ${alias}...`}
|
|
441
597
|
rows={1}
|
|
442
|
-
className="w-full bg-[var(--bg-secondary)] border border-[var(--border)] rounded-xl px-
|
|
598
|
+
className="w-full bg-[var(--bg-secondary)] border border-[var(--border)] rounded-xl px-3 py-2.5 pr-24 text-base sm:px-4 sm:text-sm text-[var(--fg)] placeholder-[var(--fg-dim)] focus:border-cyan-500/40 focus:outline-none resize-none transition-colors"
|
|
443
599
|
/>
|
|
444
600
|
<div className="absolute right-2 bottom-1.5 flex items-center gap-1">
|
|
601
|
+
<label className="p-1 text-[var(--fg-dim)] hover:text-cyan-300 cursor-pointer rounded hover:bg-cyan-500/10" title="Attach image">
|
|
602
|
+
<input
|
|
603
|
+
type="file"
|
|
604
|
+
accept="image/*"
|
|
605
|
+
multiple
|
|
606
|
+
className="hidden"
|
|
607
|
+
onChange={e => { if (e.target.files) addImageFiles(e.target.files); e.currentTarget.value = ''; }}
|
|
608
|
+
/>
|
|
609
|
+
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
610
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M16.5 6.5l-7.78 7.78a3 3 0 104.24 4.24l8.49-8.49a5 5 0 00-7.07-7.07L5.89 11.45a7 7 0 109.9 9.9l7.07-7.07" />
|
|
611
|
+
</svg>
|
|
612
|
+
</label>
|
|
445
613
|
<select value={priority} onChange={e => setPriority(e.target.value)}
|
|
446
614
|
className="bg-transparent text-[9px] text-[var(--fg-dim)] focus:outline-none cursor-pointer">
|
|
447
615
|
<option value="normal">N</option>
|
|
@@ -450,7 +618,7 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
450
618
|
</select>
|
|
451
619
|
</div>
|
|
452
620
|
</div>
|
|
453
|
-
<button onClick={send} disabled={sending || !input.trim()}
|
|
621
|
+
<button onClick={send} disabled={sending || (!input.trim() && attachedFiles.length === 0)}
|
|
454
622
|
className="p-2.5 bg-cyan-600 hover:bg-cyan-500 disabled:bg-[var(--border)] disabled:text-[var(--fg-dim)] text-[var(--fg)] rounded-xl transition-all shrink-0 active:scale-95">
|
|
455
623
|
{sending ? (
|
|
456
624
|
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
|
@@ -461,9 +629,20 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
461
629
|
)}
|
|
462
630
|
</button>
|
|
463
631
|
</div>
|
|
464
|
-
|
|
632
|
+
{attachedFiles.length > 0 && (
|
|
633
|
+
<div className="mt-2 flex flex-wrap gap-2">
|
|
634
|
+
{attachedFiles.map((file, index) => (
|
|
635
|
+
<LocalImagePreview
|
|
636
|
+
key={`${file.name}-${file.size}-${index}`}
|
|
637
|
+
file={file}
|
|
638
|
+
onRemove={() => setAttachedFiles(prev => prev.filter((_, i) => i !== index))}
|
|
639
|
+
/>
|
|
640
|
+
))}
|
|
641
|
+
</div>
|
|
642
|
+
)}
|
|
643
|
+
<div className="hidden sm:flex justify-between text-[9px] text-[var(--fg-dim)] mt-1.5">
|
|
465
644
|
<span>{input.includes('@') ? `Sending to: ${targetAlias}` : `Type @ to mention another node`}</span>
|
|
466
|
-
<span>Enter to send ·
|
|
645
|
+
<span>Enter to send · paste image</span>
|
|
467
646
|
</div>
|
|
468
647
|
</div>
|
|
469
648
|
</>
|
|
@@ -476,7 +655,7 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
476
655
|
return (
|
|
477
656
|
<>
|
|
478
657
|
<div className="fixed inset-0 bg-black/30 z-40 lg:hidden anet-fade-in" onClick={onClose} />
|
|
479
|
-
<div className="fixed top-0 right-0 h-
|
|
658
|
+
<div className="fixed top-0 right-0 h-[100dvh] w-full lg:w-[500px] bg-[var(--bg)] border-l border-[var(--border)] z-50 flex flex-col shadow-2xl shadow-black/60 animate-slide-in">
|
|
480
659
|
{/* Header */}
|
|
481
660
|
<div className="flex items-center justify-between px-4 py-3 border-b border-[var(--border)] bg-[var(--bg-secondary)]">
|
|
482
661
|
<div className="flex items-center gap-3">
|
|
@@ -81,7 +81,7 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
|
|
|
81
81
|
return (
|
|
82
82
|
<>
|
|
83
83
|
<div className="fixed inset-0 bg-black/30 z-40 anet-fade-in" onClick={onClose} />
|
|
84
|
-
<div className="fixed top-0 right-0 h-
|
|
84
|
+
<div className="fixed top-0 right-0 h-[100dvh] 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">
|
|
85
85
|
{/* Header */}
|
|
86
86
|
<div className="flex items-center justify-between px-5 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a] sticky top-0">
|
|
87
87
|
<div>
|