@geminilight/mindos 0.6.59 → 0.6.61
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/_standalone/.mindos-build-version +1 -1
- package/_standalone/.next/BUILD_ID +1 -1
- package/_standalone/.next/app-path-routes-manifest.json +23 -22
- package/_standalone/.next/build-manifest.json +2 -2
- package/_standalone/.next/cache/.previewinfo +1 -1
- package/_standalone/.next/cache/.rscinfo +1 -1
- package/_standalone/.next/cache/config.json +3 -3
- package/_standalone/.next/prerender-manifest.json +3 -3
- package/_standalone/.next/routes-manifest.json +6 -0
- package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error.html +2 -2
- package/_standalone/.next/server/app/_global-error.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/_standalone/.next/server/app/_not-found/page.js +1 -1
- package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/page.js +1 -1
- package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/registry/route.js +1 -1
- package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/session/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/agents/copy-skill/route.js +1 -0
- package/_standalone/.next/server/app/api/agents/copy-skill/route.js.nft.json +1 -0
- package/_standalone/.next/server/app/api/agents/copy-skill/route_client-reference-manifest.js +1 -0
- package/_standalone/.next/server/app/api/agents/custom/detect/route.js +1 -1
- package/_standalone/.next/server/app/api/agents/custom/detect/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/agents/custom/route.js +1 -1
- package/_standalone/.next/server/app/api/agents/custom/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask/route.js +20 -9
- package/_standalone/.next/server/app/api/ask/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask-sessions/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/auth/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/extract-pdf/route.js +2 -2
- package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/raw/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/graph/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/agents/route.js +1 -1
- package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install/route.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install-skill/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/restart/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/uninstall/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/monitoring/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/recent-files/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/list-models/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/reset-token/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/test-key/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/check-path/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/check-port/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/generate-token/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/ls/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/tree-version/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/uninstall/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update-check/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update-status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/changes/page.js +2 -2
- package/_standalone/.next/server/app/changes/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/changes/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page.js +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/echo/page.js +1 -1
- package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/explore/page.js +1 -1
- package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/help/page.js +1 -1
- package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/inbox/history/page.js +1 -1
- package/_standalone/.next/server/app/inbox/history/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/inbox/history/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/login/page.js +1 -1
- package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/page.js +1 -1
- package/_standalone/.next/server/app/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/setup/page.js +1 -1
- package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/trash/page.js +3 -3
- package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/view/[...path]/page.js +2 -2
- package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/wiki/page.js +1 -1
- package/_standalone/.next/server/app/wiki/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/wiki/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app-paths-manifest.json +23 -22
- package/_standalone/.next/server/chunks/1550.js +1 -1
- package/_standalone/.next/server/chunks/1750.js +1 -1
- package/_standalone/.next/server/chunks/3484.js +1 -1
- package/_standalone/.next/server/chunks/530.js +33 -33
- package/_standalone/.next/server/chunks/6539.js +1 -1
- package/_standalone/.next/server/chunks/{8343.js → 8955.js} +3 -3
- package/_standalone/.next/server/pages/500.html +2 -2
- package/_standalone/.next/server/server-reference-manifest.js +1 -1
- package/_standalone/.next/server/server-reference-manifest.json +1 -1
- package/_standalone/.next/static/5GmVArEG8OX03azKICsGq/_buildManifest.js +1 -0
- package/_standalone/.next/static/chunks/1369-7d0ac5d1564eed1e.js +1 -0
- package/_standalone/.next/static/chunks/{5581-dac72e9f16e5ea29.js → 5581-0c700c20718bd916.js} +4 -4
- package/_standalone/.next/static/chunks/7249-b0a9c77b9a84b11c.js +11 -0
- package/_standalone/.next/static/chunks/7637-904b0a381dc3ec02.js +1 -0
- package/_standalone/.next/static/chunks/8520-76d1b05072178b43.js +22 -0
- package/_standalone/.next/static/chunks/9186-ead47513192f658b.js +1 -0
- package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/_global-error/{page-2f4705aa66819b86.js → page-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-0ea3571c8fbae823.js +1 -0
- package/_standalone/.next/static/chunks/app/agents/{page-b172ea3743adb047.js → page-66858acbcd1d4bf8.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/agents/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/delegations/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/a2a/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/config/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/install/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/session/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/copy-skill/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/custom/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/auth/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/backlinks/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/changes/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/export/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/import/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/raw/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/files/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/git/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/graph/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/health/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/inbox/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/init/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/monitoring/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/recent-files/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/restart/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/search/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/skills/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/sync/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/tree-version/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/uninstall/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-check/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-status/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/workflows/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/changes/page-dd0b00a7b81f74e2.js +1 -0
- package/_standalone/.next/static/chunks/app/echo/[segment]/{page-84b95256f6e38aae.js → page-bf5c290fa3ccff09.js} +1 -1
- package/_standalone/.next/static/chunks/app/echo/page-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/inbox/history/{page-26e71fb6f716a4c4.js → page-3279585360df132c.js} +1 -1
- package/_standalone/.next/static/chunks/app/{layout-b89b0d955f39a753.js → layout-a5d5925b47e87cc3.js} +24 -24
- package/_standalone/.next/static/chunks/app/loading-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/{page-a8e6f085f38388bf.js → page-6a1f8d21c12b829e.js} +1 -1
- package/_standalone/.next/static/chunks/app/trash/page-40bc7316806acd62.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/{page-f87f4901b5e1a88f.js → page-6fbb14b8f322d0f0.js} +1 -1
- package/_standalone/.next/static/chunks/app/wiki/page-ba36eccf4fe62cfe.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/css/b57c4eb3cc88308b.css +1 -0
- package/_standalone/.next/trace +65 -64
- package/_standalone/.next/types/routes.d.ts +2 -1
- package/_standalone/.next/types/validator.ts +9 -0
- package/_standalone/__tests__/api/mcp-install.test.ts +5 -2
- package/_standalone/components/AskFab.tsx +7 -1
- package/_standalone/components/FileTree.tsx +83 -1
- package/_standalone/components/Panel.tsx +20 -1
- package/_standalone/components/agents/AgentsOverviewSection.tsx +13 -11
- package/_standalone/components/agents/CustomAgentModal.tsx +72 -18
- package/_standalone/components/ask/AskContent.tsx +19 -3
- package/_standalone/components/ask/FileChip.tsx +93 -12
- package/_standalone/components/changes/ChangesBanner.tsx +1 -1
- package/_standalone/components/home/InboxSection.tsx +148 -32
- package/_standalone/components/walkthrough/WalkthroughTooltip.tsx +3 -1
- package/_standalone/components/walkthrough/steps.ts +1 -1
- package/_standalone/hooks/useAskChat.ts +10 -8
- package/_standalone/hooks/useFileUpload.ts +97 -43
- package/_standalone/hooks/useImageUpload.ts +1 -1
- package/_standalone/lib/inbox-upload.ts +86 -0
- package/_standalone/package-lock.json +2 -2
- package/_standalone/package.json +1 -1
- package/_standalone/scripts/extract-pdf.cjs +110 -3
- package/_standalone/tsconfig.tsbuildinfo +1 -1
- package/app/app/api/agents/copy-skill/route.ts +110 -0
- package/app/app/api/agents/custom/detect/route.ts +16 -1
- package/app/app/api/ask/route.ts +9 -3
- package/app/app/api/extract-pdf/route.ts +12 -5
- package/app/app/api/mcp/agents/route.ts +64 -2
- package/app/app/api/mcp/install/route.ts +17 -1
- package/app/components/AskFab.tsx +7 -1
- package/app/components/FileTree.tsx +83 -1
- package/app/components/HomeContent.tsx +14 -6
- package/app/components/Panel.tsx +20 -1
- package/app/components/agents/AgentDetailContent.tsx +58 -1
- package/app/components/agents/AgentsOverviewSection.tsx +13 -11
- package/app/components/agents/CustomAgentModal.tsx +72 -18
- package/app/components/ask/AskContent.tsx +19 -3
- package/app/components/ask/FileChip.tsx +93 -12
- package/app/components/changes/ChangesBanner.tsx +1 -1
- package/app/components/changes/ChangesContentPage.tsx +368 -168
- package/app/components/home/InboxSection.tsx +148 -32
- package/app/components/walkthrough/WalkthroughTooltip.tsx +3 -1
- package/app/components/walkthrough/steps.ts +1 -1
- package/app/hooks/useAskChat.ts +10 -8
- package/app/hooks/useFileUpload.ts +97 -43
- package/app/hooks/useImageUpload.ts +1 -1
- package/app/lib/acp/agent-descriptors.ts +3 -0
- package/app/lib/acp/subprocess.ts +56 -8
- package/app/lib/agent/prompt.ts +15 -4
- package/app/lib/custom-agents.ts +109 -1
- package/app/lib/file-ops.ts +58 -0
- package/app/lib/i18n/modules/ai-chat.ts +37 -0
- package/app/lib/i18n/modules/knowledge.ts +12 -0
- package/app/lib/inbox-upload.ts +86 -0
- package/app/lib/mcp-agents.ts +30 -1
- package/app/lib/types.ts +12 -0
- package/app/package.json +1 -1
- package/app/scripts/extract-pdf.cjs +110 -3
- package/bin/lib/mcp-agents.js +34 -1
- package/bin/lib/mcp-install.js +94 -20
- package/bin/lib/toml.js +125 -0
- package/package.json +1 -1
- package/scripts/build-runtime-archive.sh +5 -1
- package/scripts/setup.js +19 -0
- package/_standalone/.next/static/chunks/4237-ffc6e7c15d4007b6.js +0 -1
- package/_standalone/.next/static/chunks/6878-e2c5459e1c608f89.js +0 -1
- package/_standalone/.next/static/chunks/7249-6cf8f2b78718c59e.js +0 -11
- package/_standalone/.next/static/chunks/8520-56ec9ff087c15204.js +0 -22
- package/_standalone/.next/static/chunks/9286-5b09baa5200318c2.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-35ea6de1af2be3b5.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/config/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/install/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/session/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agents/custom/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/auth/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/backlinks/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/changes/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/export/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/import/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/raw/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/files/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/git/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/graph/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/health/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/inbox/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/init/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/monitoring/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/recent-files/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/restart/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/search/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/skills/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/sync/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/tree-version/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/uninstall/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-check/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-status/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/workflows/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/changes/page-6d2f49651c0061f7.js +0 -1
- package/_standalone/.next/static/chunks/app/echo/page-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/loading-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/trash/page-f92b728b78ac0f7e.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/wiki/page-641edb1f3cff2f93.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/css/6c104b118d3bc9b7.css +0 -1
- package/_standalone/.next/static/u8p6oIRTcr_ns-ElNZ9rl/_buildManifest.js +0 -1
- /package/_standalone/.next/static/{u8p6oIRTcr_ns-ElNZ9rl → 5GmVArEG8OX03azKICsGq}/_ssgManifest.js +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Do not edit this file manually
|
|
3
3
|
|
|
4
4
|
type AppRoutes = "/" | "/agents" | "/agents/[agentKey]" | "/changes" | "/echo" | "/echo/[segment]" | "/explore" | "/help" | "/inbox/history" | "/login" | "/setup" | "/trash" | "/view/[...path]" | "/wiki"
|
|
5
|
-
type AppRouteHandlerRoutes = "/.well-known/agent-card.json" | "/api/a2a" | "/api/a2a/agents" | "/api/a2a/delegations" | "/api/a2a/discover" | "/api/acp/config" | "/api/acp/detect" | "/api/acp/install" | "/api/acp/registry" | "/api/acp/session" | "/api/agent-activity" | "/api/agents/custom" | "/api/agents/custom/detect" | "/api/ask" | "/api/ask-sessions" | "/api/auth" | "/api/backlinks" | "/api/bootstrap" | "/api/changes" | "/api/export" | "/api/extract-pdf" | "/api/file" | "/api/file/import" | "/api/file/raw" | "/api/files" | "/api/git" | "/api/graph" | "/api/health" | "/api/inbox" | "/api/init" | "/api/mcp/agents" | "/api/mcp/install" | "/api/mcp/install-skill" | "/api/mcp/restart" | "/api/mcp/status" | "/api/mcp/uninstall" | "/api/monitoring" | "/api/recent-files" | "/api/restart" | "/api/search" | "/api/settings" | "/api/settings/list-models" | "/api/settings/reset-token" | "/api/settings/test-key" | "/api/setup" | "/api/setup/check-path" | "/api/setup/check-port" | "/api/setup/generate-token" | "/api/setup/ls" | "/api/skills" | "/api/sync" | "/api/tree-version" | "/api/uninstall" | "/api/update" | "/api/update-check" | "/api/update-status" | "/api/workflows"
|
|
5
|
+
type AppRouteHandlerRoutes = "/.well-known/agent-card.json" | "/api/a2a" | "/api/a2a/agents" | "/api/a2a/delegations" | "/api/a2a/discover" | "/api/acp/config" | "/api/acp/detect" | "/api/acp/install" | "/api/acp/registry" | "/api/acp/session" | "/api/agent-activity" | "/api/agents/copy-skill" | "/api/agents/custom" | "/api/agents/custom/detect" | "/api/ask" | "/api/ask-sessions" | "/api/auth" | "/api/backlinks" | "/api/bootstrap" | "/api/changes" | "/api/export" | "/api/extract-pdf" | "/api/file" | "/api/file/import" | "/api/file/raw" | "/api/files" | "/api/git" | "/api/graph" | "/api/health" | "/api/inbox" | "/api/init" | "/api/mcp/agents" | "/api/mcp/install" | "/api/mcp/install-skill" | "/api/mcp/restart" | "/api/mcp/status" | "/api/mcp/uninstall" | "/api/monitoring" | "/api/recent-files" | "/api/restart" | "/api/search" | "/api/settings" | "/api/settings/list-models" | "/api/settings/reset-token" | "/api/settings/test-key" | "/api/setup" | "/api/setup/check-path" | "/api/setup/check-port" | "/api/setup/generate-token" | "/api/setup/ls" | "/api/skills" | "/api/sync" | "/api/tree-version" | "/api/uninstall" | "/api/update" | "/api/update-check" | "/api/update-status" | "/api/workflows"
|
|
6
6
|
type PageRoutes = never
|
|
7
7
|
type LayoutRoutes = "/"
|
|
8
8
|
type RedirectRoutes = never
|
|
@@ -25,6 +25,7 @@ interface ParamMap {
|
|
|
25
25
|
"/api/acp/registry": {}
|
|
26
26
|
"/api/acp/session": {}
|
|
27
27
|
"/api/agent-activity": {}
|
|
28
|
+
"/api/agents/copy-skill": {}
|
|
28
29
|
"/api/agents/custom": {}
|
|
29
30
|
"/api/agents/custom/detect": {}
|
|
30
31
|
"/api/ask": {}
|
|
@@ -272,6 +272,15 @@ type RouteHandlerConfig<Route extends AppRouteHandlerRoutes = AppRouteHandlerRou
|
|
|
272
272
|
type __Unused = __Check
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
+
// Validate ../../app/api/agents/copy-skill/route.ts
|
|
276
|
+
{
|
|
277
|
+
type __IsExpected<Specific extends RouteHandlerConfig<"/api/agents/copy-skill">> = Specific
|
|
278
|
+
const handler = {} as typeof import("../../app/api/agents/copy-skill/route.js")
|
|
279
|
+
type __Check = __IsExpected<typeof handler>
|
|
280
|
+
// @ts-ignore
|
|
281
|
+
type __Unused = __Check
|
|
282
|
+
}
|
|
283
|
+
|
|
275
284
|
// Validate ../../app/api/agents/custom/detect/route.ts
|
|
276
285
|
{
|
|
277
286
|
type __IsExpected<Specific extends RouteHandlerConfig<"/api/agents/custom/detect">> = Specific
|
|
@@ -254,11 +254,11 @@ describe('POST /api/mcp/install', () => {
|
|
|
254
254
|
});
|
|
255
255
|
|
|
256
256
|
describe('GET /api/mcp/agents', () => {
|
|
257
|
-
it('returns all
|
|
257
|
+
it('returns all 24 agents (1 builtin + 21 registry + 2 new)', async () => {
|
|
258
258
|
const { GET } = await importAgentsRoute();
|
|
259
259
|
const res = await GET();
|
|
260
260
|
const body = await res.json();
|
|
261
|
-
expect(body.agents).toHaveLength(
|
|
261
|
+
expect(body.agents).toHaveLength(24);
|
|
262
262
|
const keys = body.agents.map((a: { key: string }) => a.key);
|
|
263
263
|
expect(keys).toContain('mindos');
|
|
264
264
|
expect(keys).toContain('claude-code');
|
|
@@ -276,6 +276,9 @@ describe('GET /api/mcp/agents', () => {
|
|
|
276
276
|
expect(keys).toContain('github-copilot');
|
|
277
277
|
expect(keys).toContain('codex');
|
|
278
278
|
expect(keys).toContain('antigravity');
|
|
279
|
+
expect(keys).toContain('qclaw');
|
|
280
|
+
expect(keys).toContain('workbuddy');
|
|
281
|
+
expect(keys).toContain('lingma');
|
|
279
282
|
});
|
|
280
283
|
|
|
281
284
|
it('detects installed agent from config file', async () => {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { Sparkles } from 'lucide-react';
|
|
4
4
|
import { useLocale } from '@/lib/stores/locale-store';
|
|
5
|
+
import { usePathname } from 'next/navigation';
|
|
5
6
|
|
|
6
7
|
interface AskFabProps {
|
|
7
8
|
/** Toggle the right-side Ask AI panel */
|
|
@@ -12,8 +13,13 @@ interface AskFabProps {
|
|
|
12
13
|
|
|
13
14
|
export default function AskFab({ onToggle, askPanelOpen }: AskFabProps) {
|
|
14
15
|
const { t } = useLocale();
|
|
16
|
+
const pathname = usePathname();
|
|
15
17
|
const label = `${t.ask?.fabLabel ?? 'Ask AI'} (⌘/)`;
|
|
16
18
|
|
|
19
|
+
// Hide on home page — it already has an inline chatbot
|
|
20
|
+
const isHome = pathname === '/' || pathname === '';
|
|
21
|
+
const hidden = askPanelOpen || isHome;
|
|
22
|
+
|
|
17
23
|
return (
|
|
18
24
|
<button
|
|
19
25
|
onClick={onToggle}
|
|
@@ -28,7 +34,7 @@ export default function AskFab({ onToggle, askPanelOpen }: AskFabProps) {
|
|
|
28
34
|
transition-all duration-200 ease-out
|
|
29
35
|
hover:shadow-lg hover:shadow-[var(--amber)]/20
|
|
30
36
|
active:scale-95 cursor-pointer overflow-hidden
|
|
31
|
-
${
|
|
37
|
+
${hidden ? 'opacity-0 pointer-events-none translate-y-2' : 'opacity-100 translate-y-0'}
|
|
32
38
|
`}
|
|
33
39
|
style={{
|
|
34
40
|
background: 'var(--amber)',
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { createFileAction, deleteFileAction, renameFileAction, renameSpaceAction, deleteSpaceAction, convertToSpaceAction, deleteFolderAction, undoDeleteAction } from '@/lib/actions';
|
|
13
13
|
import { toast } from '@/lib/toast';
|
|
14
14
|
import { useLocale } from '@/lib/stores/locale-store';
|
|
15
|
+
import { quickDropToDirectory } from '@/lib/inbox-upload';
|
|
15
16
|
import { ConfirmDialog } from '@/components/agents/AgentsPrimitives';
|
|
16
17
|
import { usePinnedFiles } from '@/lib/hooks/usePinnedFiles';
|
|
17
18
|
import { checkAiAvailable, triggerSpaceAiInit } from '@/lib/space-ai-init';
|
|
@@ -318,6 +319,81 @@ function DirectoryNode({ node, depth, currentPath, onNavigate, maxOpenDepth, onI
|
|
|
318
319
|
const [deleteConfirm, setDeleteConfirm] = useState<null | 'space' | 'folder'>(null);
|
|
319
320
|
const [isPendingDelete, startDeleteTransition] = useTransition();
|
|
320
321
|
|
|
322
|
+
// ── External file drop target ──
|
|
323
|
+
const [isDragTarget, setIsDragTarget] = useState(false);
|
|
324
|
+
const autoExpandTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
325
|
+
const dragLeaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
326
|
+
|
|
327
|
+
const clearAutoExpand = useCallback(() => {
|
|
328
|
+
if (autoExpandTimerRef.current) {
|
|
329
|
+
clearTimeout(autoExpandTimerRef.current);
|
|
330
|
+
autoExpandTimerRef.current = null;
|
|
331
|
+
}
|
|
332
|
+
}, []);
|
|
333
|
+
|
|
334
|
+
// Use dragOver (fires continuously while hovering) for highlight.
|
|
335
|
+
// Clear highlight with a short delay on dragLeave — if dragOver fires again
|
|
336
|
+
// within the delay, the highlight stays. This avoids flicker from nested elements.
|
|
337
|
+
const handleRowDragOver = useCallback((e: React.DragEvent) => {
|
|
338
|
+
if (!e.dataTransfer.types.includes('Files')) return;
|
|
339
|
+
e.preventDefault();
|
|
340
|
+
e.stopPropagation();
|
|
341
|
+
e.dataTransfer.dropEffect = 'copy';
|
|
342
|
+
if (dragLeaveTimerRef.current) {
|
|
343
|
+
clearTimeout(dragLeaveTimerRef.current);
|
|
344
|
+
dragLeaveTimerRef.current = null;
|
|
345
|
+
}
|
|
346
|
+
if (!isDragTarget) setIsDragTarget(true);
|
|
347
|
+
}, [isDragTarget]);
|
|
348
|
+
|
|
349
|
+
const handleRowDragEnter = useCallback((e: React.DragEvent) => {
|
|
350
|
+
if (!e.dataTransfer.types.includes('Files')) return;
|
|
351
|
+
e.preventDefault();
|
|
352
|
+
e.stopPropagation();
|
|
353
|
+
setIsDragTarget(true);
|
|
354
|
+
// Auto-expand collapsed directory after 500ms hover
|
|
355
|
+
clearAutoExpand();
|
|
356
|
+
if (!open) {
|
|
357
|
+
autoExpandTimerRef.current = setTimeout(() => {
|
|
358
|
+
setOpen(true);
|
|
359
|
+
autoExpandTimerRef.current = null;
|
|
360
|
+
}, 500);
|
|
361
|
+
}
|
|
362
|
+
}, [open, clearAutoExpand]);
|
|
363
|
+
|
|
364
|
+
const handleRowDragLeave = useCallback((e: React.DragEvent) => {
|
|
365
|
+
if (!e.dataTransfer.types.includes('Files')) return;
|
|
366
|
+
e.stopPropagation();
|
|
367
|
+
// Delay clearing so dragOver on the same row can cancel it
|
|
368
|
+
dragLeaveTimerRef.current = setTimeout(() => {
|
|
369
|
+
setIsDragTarget(false);
|
|
370
|
+
clearAutoExpand();
|
|
371
|
+
dragLeaveTimerRef.current = null;
|
|
372
|
+
}, 50);
|
|
373
|
+
}, [clearAutoExpand]);
|
|
374
|
+
|
|
375
|
+
const handleRowDrop = useCallback((e: React.DragEvent) => {
|
|
376
|
+
e.preventDefault();
|
|
377
|
+
e.stopPropagation();
|
|
378
|
+
setIsDragTarget(false);
|
|
379
|
+
clearAutoExpand();
|
|
380
|
+
if (dragLeaveTimerRef.current) {
|
|
381
|
+
clearTimeout(dragLeaveTimerRef.current);
|
|
382
|
+
dragLeaveTimerRef.current = null;
|
|
383
|
+
}
|
|
384
|
+
const files = e.dataTransfer.files;
|
|
385
|
+
if (files.length > 0) {
|
|
386
|
+
void quickDropToDirectory(Array.from(files), node.path, t);
|
|
387
|
+
}
|
|
388
|
+
}, [node.path, t, clearAutoExpand]);
|
|
389
|
+
|
|
390
|
+
useEffect(() => {
|
|
391
|
+
return () => {
|
|
392
|
+
clearAutoExpand();
|
|
393
|
+
if (dragLeaveTimerRef.current) clearTimeout(dragLeaveTimerRef.current);
|
|
394
|
+
};
|
|
395
|
+
}, [clearAutoExpand]);
|
|
396
|
+
|
|
321
397
|
const toggle = useCallback(() => setOpen(v => !v), []);
|
|
322
398
|
|
|
323
399
|
const prevMaxOpenDepth = useRef<number | null | undefined>(undefined);
|
|
@@ -421,8 +497,14 @@ function DirectoryNode({ node, depth, currentPath, onNavigate, maxOpenDepth, onI
|
|
|
421
497
|
return (
|
|
422
498
|
<div>
|
|
423
499
|
<div
|
|
424
|
-
className=
|
|
500
|
+
className={`relative group/dir flex items-center transition-colors duration-100 ${
|
|
501
|
+
isDragTarget ? 'bg-[var(--amber)]/10 rounded-md' : ''
|
|
502
|
+
}`}
|
|
425
503
|
onContextMenu={handleContextMenu}
|
|
504
|
+
onDragEnter={handleRowDragEnter}
|
|
505
|
+
onDragOver={handleRowDragOver}
|
|
506
|
+
onDragLeave={handleRowDragLeave}
|
|
507
|
+
onDrop={handleRowDrop}
|
|
426
508
|
>
|
|
427
509
|
<button
|
|
428
510
|
onClick={toggle}
|
|
@@ -316,9 +316,28 @@ export default function Panel({
|
|
|
316
316
|
</div>
|
|
317
317
|
</div>
|
|
318
318
|
</PanelHeader>
|
|
319
|
-
<div
|
|
319
|
+
<div
|
|
320
|
+
className="flex-1 overflow-y-auto min-h-0 px-2 py-2"
|
|
321
|
+
onDragEnter={(e) => { if (e.dataTransfer.types.includes('Files')) e.stopPropagation(); }}
|
|
322
|
+
onDragOver={(e) => { if (e.dataTransfer.types.includes('Files')) { e.preventDefault(); e.stopPropagation(); } }}
|
|
323
|
+
onDrop={(e) => { if (e.dataTransfer.types.includes('Files')) { e.preventDefault(); e.stopPropagation(); } }}
|
|
324
|
+
>
|
|
320
325
|
<FileTree nodes={fileTree} onNavigate={onNavigate} maxOpenDepth={maxOpenDepth} onImport={onImport} />
|
|
321
326
|
</div>
|
|
327
|
+
{/* Inbox quick entry — always visible above sync bar */}
|
|
328
|
+
<button
|
|
329
|
+
type="button"
|
|
330
|
+
onClick={() => router.push('/view/Inbox/')}
|
|
331
|
+
className="flex items-center gap-2 mx-2 px-2 py-1.5 text-sm rounded-md transition-colors hover:bg-muted group border-t border-border/40 shrink-0"
|
|
332
|
+
>
|
|
333
|
+
<Inbox size={14} className="shrink-0 text-[var(--amber)]" />
|
|
334
|
+
<span className="flex-1 text-left text-muted-foreground group-hover:text-foreground transition-colors text-xs">
|
|
335
|
+
{t.sidebar.capture}
|
|
336
|
+
</span>
|
|
337
|
+
{inboxCount > 0 && (
|
|
338
|
+
<span className="text-xs font-medium text-[var(--amber)] tabular-nums">{inboxCount}</span>
|
|
339
|
+
)}
|
|
340
|
+
</button>
|
|
322
341
|
<SyncStatusBar collapsed={false} onOpenSyncSettings={onOpenSyncSettings} />
|
|
323
342
|
</div>
|
|
324
343
|
|
|
@@ -223,17 +223,7 @@ export default function AgentsOverviewSection({
|
|
|
223
223
|
</span>
|
|
224
224
|
</div>
|
|
225
225
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
226
|
-
{
|
|
227
|
-
<AgentCard
|
|
228
|
-
key={agent.key}
|
|
229
|
-
agent={agent}
|
|
230
|
-
copy={copy}
|
|
231
|
-
index={i}
|
|
232
|
-
mcpEnabled={mcpEnabled}
|
|
233
|
-
onEdit={agent.isCustom ? onEditCustomAgent : undefined}
|
|
234
|
-
onRemove={agent.isCustom ? onRemoveCustomAgent : undefined}
|
|
235
|
-
/>
|
|
236
|
-
))}
|
|
226
|
+
{/* Add Custom Agent Button — Always First */}
|
|
237
227
|
{onAddCustomAgent && (
|
|
238
228
|
<button
|
|
239
229
|
type="button"
|
|
@@ -254,6 +244,18 @@ export default function AgentsOverviewSection({
|
|
|
254
244
|
</span>
|
|
255
245
|
</button>
|
|
256
246
|
)}
|
|
247
|
+
{/* Agent Cards */}
|
|
248
|
+
{sortedAgents.map((agent, i) => (
|
|
249
|
+
<AgentCard
|
|
250
|
+
key={agent.key}
|
|
251
|
+
agent={agent}
|
|
252
|
+
copy={copy}
|
|
253
|
+
index={i}
|
|
254
|
+
mcpEnabled={mcpEnabled}
|
|
255
|
+
onEdit={agent.isCustom ? onEditCustomAgent : undefined}
|
|
256
|
+
onRemove={agent.isCustom ? onRemoveCustomAgent : undefined}
|
|
257
|
+
/>
|
|
258
|
+
))}
|
|
257
259
|
</div>
|
|
258
260
|
</section>
|
|
259
261
|
) : (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
|
4
|
-
import { X, Loader2, ChevronRight, ChevronDown, CheckCircle2, Info, AlertCircle } from 'lucide-react';
|
|
4
|
+
import { X, Loader2, ChevronRight, ChevronDown, CheckCircle2, Info, AlertCircle, Server, Zap } from 'lucide-react';
|
|
5
5
|
import { useLocale } from '@/lib/stores/locale-store';
|
|
6
6
|
import { useFocusTrap } from '@/lib/hooks/useFocusTrap';
|
|
7
7
|
import { toast } from '@/lib/toast';
|
|
@@ -19,6 +19,8 @@ interface DetectResult {
|
|
|
19
19
|
detectedSkillDir?: string;
|
|
20
20
|
skillCount?: number;
|
|
21
21
|
skillNames?: string[];
|
|
22
|
+
mcpServers?: string[];
|
|
23
|
+
mcpParseError?: string;
|
|
22
24
|
suggestedName?: string;
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -406,7 +408,7 @@ export default function CustomAgentModal({
|
|
|
406
408
|
{phase === 'result' && (
|
|
407
409
|
<>
|
|
408
410
|
{/* Result Card */}
|
|
409
|
-
<div className={`rounded-lg p-4 space-y-
|
|
411
|
+
<div className={`rounded-lg p-4 space-y-3 ${
|
|
410
412
|
detectResult?.exists
|
|
411
413
|
? 'border border-[var(--success)]/20 bg-[var(--success)]/5'
|
|
412
414
|
: 'border border-border bg-muted/30'
|
|
@@ -414,22 +416,74 @@ export default function CustomAgentModal({
|
|
|
414
416
|
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
|
415
417
|
{detectResult?.exists ? p.customAgentDetectedTitle : p.customAgentDefaultTitle}
|
|
416
418
|
</p>
|
|
417
|
-
<div className="
|
|
418
|
-
|
|
419
|
-
<
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
419
|
+
<div className="space-y-2.5">
|
|
420
|
+
{/* Config Path */}
|
|
421
|
+
<div>
|
|
422
|
+
<p className="text-xs text-muted-foreground mb-1">{p.customAgentConfigLabel}</p>
|
|
423
|
+
<span className="text-sm text-foreground font-mono truncate block">{form.global}</span>
|
|
424
|
+
{detectResult?.mcpParseError && (
|
|
425
|
+
<p className="text-xs text-[var(--error)] mt-1 flex items-center gap-1">
|
|
426
|
+
<AlertCircle size={12} className="shrink-0" />
|
|
427
|
+
{detectResult.mcpParseError}
|
|
428
|
+
</p>
|
|
429
|
+
)}
|
|
430
|
+
</div>
|
|
431
|
+
|
|
432
|
+
{/* Format & Key */}
|
|
433
|
+
<div className="grid grid-cols-2 gap-2">
|
|
434
|
+
<div>
|
|
435
|
+
<p className="text-xs text-muted-foreground mb-1">{p.customAgentFormatLabel}</p>
|
|
436
|
+
<span className="text-sm text-foreground">{form.format.toUpperCase()}</span>
|
|
437
|
+
</div>
|
|
438
|
+
<div>
|
|
439
|
+
<p className="text-xs text-muted-foreground mb-1">Config Key</p>
|
|
440
|
+
<span className="text-sm text-foreground font-mono">{form.configKey}</span>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
|
|
444
|
+
{/* Transport */}
|
|
445
|
+
<div>
|
|
446
|
+
<p className="text-xs text-muted-foreground mb-1">{p.customAgentTransportLabel}</p>
|
|
447
|
+
<span className="text-sm text-foreground">{form.preferredTransport}</span>
|
|
448
|
+
</div>
|
|
449
|
+
|
|
450
|
+
{/* MCP Servers */}
|
|
451
|
+
<div>
|
|
452
|
+
<p className="text-xs text-muted-foreground mb-1 flex items-center gap-1">
|
|
453
|
+
<Server size={11} className="shrink-0" aria-hidden="true" />
|
|
454
|
+
MCP Servers
|
|
455
|
+
</p>
|
|
456
|
+
{detectResult?.mcpServers && detectResult.mcpServers.length > 0 ? (
|
|
457
|
+
<div className="flex flex-wrap gap-1">
|
|
458
|
+
{detectResult.mcpServers.map(name => (
|
|
459
|
+
<span key={name} className="text-xs bg-muted/60 text-foreground px-2 py-0.5 rounded font-mono">
|
|
460
|
+
{name}
|
|
461
|
+
</span>
|
|
462
|
+
))}
|
|
463
|
+
</div>
|
|
464
|
+
) : (
|
|
465
|
+
<span className="text-sm text-muted-foreground">—</span>
|
|
466
|
+
)}
|
|
467
|
+
</div>
|
|
468
|
+
|
|
469
|
+
{/* Skills */}
|
|
470
|
+
<div>
|
|
471
|
+
<p className="text-xs text-muted-foreground mb-1 flex items-center gap-1">
|
|
472
|
+
<Zap size={11} className="shrink-0" aria-hidden="true" />
|
|
473
|
+
{p.customAgentSkillsLabel}
|
|
474
|
+
</p>
|
|
475
|
+
{detectResult?.skillNames && detectResult.skillNames.length > 0 ? (
|
|
476
|
+
<div className="flex flex-wrap gap-1">
|
|
477
|
+
{detectResult.skillNames.map(name => (
|
|
478
|
+
<span key={name} className="text-xs bg-[var(--amber-dim)] text-[var(--amber-text,var(--foreground))] px-2 py-0.5 rounded font-mono">
|
|
479
|
+
{name}
|
|
480
|
+
</span>
|
|
481
|
+
))}
|
|
482
|
+
</div>
|
|
483
|
+
) : (
|
|
484
|
+
<span className="text-sm text-muted-foreground">—</span>
|
|
485
|
+
)}
|
|
486
|
+
</div>
|
|
433
487
|
</div>
|
|
434
488
|
</div>
|
|
435
489
|
|
|
@@ -403,6 +403,7 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
|
|
|
403
403
|
// Accept mindos file paths and image drops
|
|
404
404
|
if (e.dataTransfer.types.includes('text/mindos-path') || e.dataTransfer.types.includes('Files')) {
|
|
405
405
|
e.preventDefault();
|
|
406
|
+
e.stopPropagation();
|
|
406
407
|
e.dataTransfer.dropEffect = 'copy';
|
|
407
408
|
setIsDragOver(true);
|
|
408
409
|
}
|
|
@@ -412,6 +413,7 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
|
|
|
412
413
|
|
|
413
414
|
const handleDrop = useCallback(async (e: React.DragEvent) => {
|
|
414
415
|
e.preventDefault();
|
|
416
|
+
e.stopPropagation();
|
|
415
417
|
setIsDragOver(false);
|
|
416
418
|
const filePath = e.dataTransfer.getData('text/mindos-path');
|
|
417
419
|
if (filePath) {
|
|
@@ -422,7 +424,21 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
|
|
|
422
424
|
}
|
|
423
425
|
return;
|
|
424
426
|
}
|
|
425
|
-
|
|
427
|
+
// Try image upload first, then fall back to general file upload
|
|
428
|
+
const files = e.dataTransfer.files;
|
|
429
|
+
if (files.length > 0) {
|
|
430
|
+
const hasImages = Array.from(files).some(f => f.type.startsWith('image/'));
|
|
431
|
+
if (hasImages) {
|
|
432
|
+
await imageUploadRef.current.handleDrop(e);
|
|
433
|
+
}
|
|
434
|
+
// Upload non-image files as attachments
|
|
435
|
+
const nonImageFiles = Array.from(files).filter(f => !f.type.startsWith('image/'));
|
|
436
|
+
if (nonImageFiles.length > 0) {
|
|
437
|
+
const dt = new DataTransfer();
|
|
438
|
+
nonImageFiles.forEach(f => dt.items.add(f));
|
|
439
|
+
await uploadRef.current.pickFiles(dt.files);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
426
442
|
}, []);
|
|
427
443
|
|
|
428
444
|
const handlePaste = useCallback((e: React.ClipboardEvent) => {
|
|
@@ -571,12 +587,12 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
|
|
|
571
587
|
<FileChip key={f} path={f} variant="kb" onRemove={() => setAttachedFiles(prev => prev.filter(x => x !== f))} />
|
|
572
588
|
))}
|
|
573
589
|
{upload.localAttachments.map((f, idx) => (
|
|
574
|
-
<FileChip key={`up-${f.name}-${idx}`} path={f.name} variant="upload" onRemove={() => upload.removeAttachment(idx)} />
|
|
590
|
+
<FileChip key={`up-${f.name}-${idx}`} path={f.name} variant="upload" status={f.status} error={f.error} truncatedInfo={f.truncatedInfo} onRemove={() => upload.removeAttachment(idx)} />
|
|
575
591
|
))}
|
|
576
592
|
{imageUpload.images.map((img, idx) => (
|
|
577
593
|
<FileChip
|
|
578
594
|
key={`img-${idx}`}
|
|
579
|
-
path={`Image ${idx + 1}`}
|
|
595
|
+
path={img.fileName || `Image ${idx + 1}`}
|
|
580
596
|
variant="image"
|
|
581
597
|
imageData={img.data}
|
|
582
598
|
imageMime={img.mimeType}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
|
-
import { X, FileText, Table, Paperclip, ImageIcon, Zap, Bot, Folder } from 'lucide-react';
|
|
5
|
+
import { X, FileText, Table, Paperclip, ImageIcon, Zap, Bot, Folder, Loader2, CheckCircle2, AlertCircle, AlertTriangle } from 'lucide-react';
|
|
6
6
|
|
|
7
7
|
interface FileChipProps {
|
|
8
8
|
path: string;
|
|
@@ -12,6 +12,16 @@ interface FileChipProps {
|
|
|
12
12
|
imageData?: string;
|
|
13
13
|
/** MIME type for image preview */
|
|
14
14
|
imageMime?: string;
|
|
15
|
+
/** Extraction status for uploaded files (e.g. PDF). */
|
|
16
|
+
status?: 'loading' | 'success' | 'error';
|
|
17
|
+
/** Human-readable error message shown on hover when status='error'. */
|
|
18
|
+
error?: string;
|
|
19
|
+
/** Present when the PDF text was truncated due to length. */
|
|
20
|
+
truncatedInfo?: {
|
|
21
|
+
totalChars: number;
|
|
22
|
+
includedChars: number;
|
|
23
|
+
totalPages: number;
|
|
24
|
+
};
|
|
15
25
|
}
|
|
16
26
|
|
|
17
27
|
const VARIANT_ICON = {
|
|
@@ -30,11 +40,13 @@ const VARIANT_STYLE = {
|
|
|
30
40
|
agent: 'border-[var(--amber)]/25 bg-[var(--amber)]/10 text-foreground',
|
|
31
41
|
} as const;
|
|
32
42
|
|
|
33
|
-
export default function FileChip({ path, onRemove, variant = 'kb', imageData, imageMime }: FileChipProps) {
|
|
43
|
+
export default function FileChip({ path, onRemove, variant = 'kb', imageData, imageMime, status, error, truncatedInfo }: FileChipProps) {
|
|
34
44
|
const [showPreview, setShowPreview] = useState(false);
|
|
45
|
+
const [showTooltip, setShowTooltip] = useState(false);
|
|
35
46
|
const [mounted, setMounted] = useState(false);
|
|
36
47
|
const chipRef = useRef<HTMLSpanElement>(null);
|
|
37
48
|
const [previewPos, setPreviewPos] = useState<{ top: number; left: number } | null>(null);
|
|
49
|
+
const [tooltipPos, setTooltipPos] = useState<{ top: number; left: number } | null>(null);
|
|
38
50
|
|
|
39
51
|
useEffect(() => setMounted(true), []);
|
|
40
52
|
|
|
@@ -42,23 +54,63 @@ export default function FileChip({ path, onRemove, variant = 'kb', imageData, im
|
|
|
42
54
|
const cleanPath = isDir ? path.slice(0, -1) : path;
|
|
43
55
|
const name = cleanPath.split('/').pop() ?? cleanPath;
|
|
44
56
|
const isCsv = variant === 'kb' && !isDir && name.endsWith('.csv');
|
|
45
|
-
|
|
57
|
+
|
|
58
|
+
// Determine the base icon from variant / file type
|
|
59
|
+
const { icon: BaseIcon, cls: baseIconCls } = isDir
|
|
46
60
|
? { icon: Folder, cls: 'text-yellow-400' }
|
|
47
61
|
: isCsv
|
|
48
62
|
? { icon: Table, cls: 'text-success' }
|
|
49
63
|
: VARIANT_ICON[variant];
|
|
50
|
-
const style = VARIANT_STYLE[variant];
|
|
51
64
|
|
|
52
|
-
//
|
|
65
|
+
// Determine status trailing indicator
|
|
66
|
+
const isTruncated = !!truncatedInfo;
|
|
67
|
+
let StatusIndicator: React.ComponentType<{ size: number; className?: string }> | null = null;
|
|
68
|
+
let statusIndicatorCls = '';
|
|
69
|
+
if (status === 'loading') {
|
|
70
|
+
StatusIndicator = Loader2;
|
|
71
|
+
statusIndicatorCls = 'text-muted-foreground animate-spin';
|
|
72
|
+
} else if (status === 'error') {
|
|
73
|
+
StatusIndicator = AlertCircle;
|
|
74
|
+
statusIndicatorCls = 'text-destructive';
|
|
75
|
+
} else if (isTruncated) {
|
|
76
|
+
StatusIndicator = AlertTriangle;
|
|
77
|
+
statusIndicatorCls = 'text-amber-500';
|
|
78
|
+
} else if (status === 'success') {
|
|
79
|
+
StatusIndicator = CheckCircle2;
|
|
80
|
+
statusIndicatorCls = 'text-emerald-500';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const style = status === 'error'
|
|
84
|
+
? 'border-destructive/30 bg-destructive/5 text-foreground'
|
|
85
|
+
: isTruncated
|
|
86
|
+
? 'border-amber-500/30 bg-amber-500/5 text-foreground'
|
|
87
|
+
: VARIANT_STYLE[variant];
|
|
88
|
+
|
|
89
|
+
// Build tooltip text
|
|
90
|
+
let tooltipText: string | null = null;
|
|
91
|
+
if (status === 'error' && error) {
|
|
92
|
+
tooltipText = error;
|
|
93
|
+
} else if (isTruncated) {
|
|
94
|
+
const pct = truncatedInfo.totalChars > 0
|
|
95
|
+
? Math.round((truncatedInfo.includedChars / truncatedInfo.totalChars) * 100)
|
|
96
|
+
: 0;
|
|
97
|
+
tooltipText = `Document truncated — only ${pct}% included (${Math.round(truncatedInfo.includedChars / 1000)}K / ${Math.round(truncatedInfo.totalChars / 1000)}K chars, ${truncatedInfo.totalPages} pages total)`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Position image preview above the chip
|
|
53
101
|
useEffect(() => {
|
|
54
102
|
if (!showPreview || !chipRef.current) { setPreviewPos(null); return; }
|
|
55
103
|
const rect = chipRef.current.getBoundingClientRect();
|
|
56
|
-
setPreviewPos({
|
|
57
|
-
top: rect.top - 8, // 8px gap above chip
|
|
58
|
-
left: rect.left,
|
|
59
|
-
});
|
|
104
|
+
setPreviewPos({ top: rect.top - 8, left: rect.left });
|
|
60
105
|
}, [showPreview]);
|
|
61
106
|
|
|
107
|
+
// Position tooltip above the chip
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (!showTooltip || !chipRef.current) { setTooltipPos(null); return; }
|
|
110
|
+
const rect = chipRef.current.getBoundingClientRect();
|
|
111
|
+
setTooltipPos({ top: rect.top - 8, left: rect.left });
|
|
112
|
+
}, [showTooltip]);
|
|
113
|
+
|
|
62
114
|
const preview = showPreview && previewPos && imageData && imageMime ? (
|
|
63
115
|
<div
|
|
64
116
|
className="fixed z-50 p-1 rounded-lg border border-border bg-card shadow-lg pointer-events-none"
|
|
@@ -75,16 +127,44 @@ export default function FileChip({ path, onRemove, variant = 'kb', imageData, im
|
|
|
75
127
|
</div>
|
|
76
128
|
) : null;
|
|
77
129
|
|
|
130
|
+
const tooltipBorderCls = status === 'error'
|
|
131
|
+
? 'border-destructive/20 text-destructive'
|
|
132
|
+
: 'border-amber-500/20 text-amber-600 dark:text-amber-400';
|
|
133
|
+
|
|
134
|
+
const tooltip = showTooltip && tooltipPos && tooltipText ? (
|
|
135
|
+
<div
|
|
136
|
+
className={`fixed z-50 px-2.5 py-1.5 rounded-lg border bg-card text-xs shadow-lg pointer-events-none max-w-[280px] ${tooltipBorderCls}`}
|
|
137
|
+
style={{
|
|
138
|
+
left: tooltipPos.left,
|
|
139
|
+
bottom: window.innerHeight - tooltipPos.top,
|
|
140
|
+
}}
|
|
141
|
+
>
|
|
142
|
+
{tooltipText}
|
|
143
|
+
</div>
|
|
144
|
+
) : null;
|
|
145
|
+
|
|
146
|
+
const handleMouseEnter = () => {
|
|
147
|
+
if (imageData) setShowPreview(true);
|
|
148
|
+
if (tooltipText) setShowTooltip(true);
|
|
149
|
+
};
|
|
150
|
+
const handleMouseLeave = () => {
|
|
151
|
+
setShowPreview(false);
|
|
152
|
+
setShowTooltip(false);
|
|
153
|
+
};
|
|
154
|
+
|
|
78
155
|
return (
|
|
79
156
|
<>
|
|
80
157
|
<span
|
|
81
158
|
ref={chipRef}
|
|
82
159
|
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs border max-w-[220px] ${style}`}
|
|
83
|
-
onMouseEnter={
|
|
84
|
-
onMouseLeave={
|
|
160
|
+
onMouseEnter={handleMouseEnter}
|
|
161
|
+
onMouseLeave={handleMouseLeave}
|
|
85
162
|
>
|
|
86
|
-
<
|
|
163
|
+
<BaseIcon size={11} className={`${baseIconCls} shrink-0`} />
|
|
87
164
|
<span className="truncate" title={isDir ? cleanPath : path}>{name}</span>
|
|
165
|
+
{StatusIndicator && (
|
|
166
|
+
<StatusIndicator size={10} className={`${statusIndicatorCls} shrink-0`} />
|
|
167
|
+
)}
|
|
88
168
|
<button
|
|
89
169
|
type="button"
|
|
90
170
|
onClick={onRemove}
|
|
@@ -95,6 +175,7 @@ export default function FileChip({ path, onRemove, variant = 'kb', imageData, im
|
|
|
95
175
|
</button>
|
|
96
176
|
</span>
|
|
97
177
|
{mounted && preview && createPortal(preview, document.body)}
|
|
178
|
+
{mounted && tooltip && createPortal(tooltip, document.body)}
|
|
98
179
|
</>
|
|
99
180
|
);
|
|
100
181
|
}
|
|
@@ -111,7 +111,7 @@ export default function ChangesBanner() {
|
|
|
111
111
|
<History size={14} />
|
|
112
112
|
</span>
|
|
113
113
|
<div className="min-w-0 flex-1">
|
|
114
|
-
<p className="text-xs text-foreground font-
|
|
114
|
+
<p className="text-xs text-foreground font-medium whitespace-nowrap">
|
|
115
115
|
{t.changes.unreadBanner(unreadCount)}
|
|
116
116
|
</p>
|
|
117
117
|
<div className="mt-1 flex items-center gap-1.5">
|