@geminilight/mindos 0.6.58 → 0.6.60
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 +3 -3
- 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/react-loadable-manifest.json +1 -1
- 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 +2 -2
- 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_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 +18 -7
- 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_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 +3 -3
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -8
- 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 +2 -2
- 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.js.nft.json +1 -1
- package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/view/[...path]/page.js +3 -3
- 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 +2 -2
- 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/3484.js +1 -1
- package/_standalone/.next/server/chunks/530.js +70 -71
- package/_standalone/.next/server/chunks/{6793.js → 9753.js} +2 -2
- package/_standalone/.next/server/chunks/9787.js +2 -0
- package/_standalone/.next/server/middleware-build-manifest.js +1 -1
- package/_standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- 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/K3wZNf5bj_AFYwtqcRXIf/_buildManifest.js +1 -0
- package/_standalone/.next/static/chunks/1369-7d0ac5d1564eed1e.js +1 -0
- package/_standalone/.next/static/chunks/{1814.a7c127b2c73d1f70.js → 1814.a79b84d37df75c43.js} +1 -1
- package/_standalone/.next/static/chunks/3427-2e61a5df1f5e55fb.js +1 -0
- package/_standalone/.next/static/chunks/{1053-fe009233cff06e72.js → 5581-974dfb26d1d1b38f.js} +3 -3
- package/_standalone/.next/static/chunks/6297-085daa21037d5f81.js +1 -0
- 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/9905-a19d379cb225246e.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-66858acbcd1d4bf8.js +1 -0
- 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-bf5c290fa3ccff09.js +11 -0
- package/_standalone/.next/static/chunks/app/echo/page-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/explore/{page-d3d99308146c2240.js → page-d9f58000bc445360.js} +2 -2
- package/_standalone/.next/static/chunks/app/help/{page-222df603080b5fab.js → page-f8cb806371b3175f.js} +1 -1
- package/_standalone/.next/static/chunks/app/inbox/history/{page-07819cf95cb0805f.js → page-3279585360df132c.js} +1 -1
- package/_standalone/.next/static/chunks/app/layout-6a0169582db11a08.js +164 -0
- package/_standalone/.next/static/chunks/app/loading-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/login/{page-0eeef685052869a6.js → page-18fb00d568cd1f0e.js} +1 -1
- package/_standalone/.next/static/chunks/app/page-6a1f8d21c12b829e.js +1 -0
- package/_standalone/.next/static/chunks/app/setup/{page-99fcfc460fa29733.js → page-821714e7477be46c.js} +1 -1
- package/_standalone/.next/static/chunks/app/trash/page-ed7ba3b0b50223a6.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/{not-found-fc04c2bd4f35bc6f.js → not-found-6e0c75ad26ce8572.js} +1 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/page-678139779971cfcb.js +12 -0
- package/_standalone/.next/static/chunks/app/wiki/page-194ae9af2d461481.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/chunks/{webpack-2c19436659aa657b.js → webpack-72e8d9e9073fd1f9.js} +1 -1
- package/_standalone/.next/static/css/9c558c42831fae58.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 +4 -2
- package/_standalone/app/globals.css +2 -1
- package/_standalone/components/AskFab.tsx +11 -5
- package/_standalone/components/AskModal.tsx +1 -1
- package/_standalone/components/FileTree.tsx +83 -1
- package/_standalone/components/GuideCard.tsx +101 -152
- package/_standalone/components/Panel.tsx +6 -1
- package/_standalone/components/RightAskPanel.tsx +2 -2
- package/_standalone/components/agents/AgentsOverviewSection.tsx +13 -11
- package/_standalone/components/agents/CustomAgentModal.tsx +72 -18
- package/_standalone/components/ask/AskContent.tsx +109 -54
- package/_standalone/components/ask/AskHeader.tsx +218 -18
- package/_standalone/components/ask/FileChip.tsx +93 -12
- package/_standalone/components/ask/MessageList.tsx +66 -47
- package/_standalone/components/ask/SessionHistory.tsx +86 -60
- package/_standalone/components/ask/SessionTabBar.tsx +29 -21
- package/_standalone/components/ask/ThinkingBlock.tsx +6 -5
- package/_standalone/components/ask/ToolCallBlock.tsx +10 -9
- package/_standalone/components/changes/ChangesBanner.tsx +1 -1
- package/_standalone/components/settings/SettingsContent.tsx +1 -1
- package/_standalone/components/walkthrough/WalkthroughTooltip.tsx +3 -1
- package/_standalone/components/walkthrough/steps.ts +1 -1
- package/_standalone/data/skills/mindos/SKILL.md +67 -15
- package/_standalone/data/skills/mindos-zh/SKILL.md +67 -11
- package/_standalone/hooks/useAskChat.ts +10 -8
- package/_standalone/hooks/useAskSession.ts +23 -1
- package/_standalone/hooks/useFileUpload.ts +97 -43
- package/_standalone/hooks/useImageUpload.ts +1 -1
- package/_standalone/lib/inbox-upload.ts +86 -0
- package/_standalone/lib/stores/locale-store.ts +20 -6
- 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 +7 -1
- package/app/app/api/extract-pdf/route.ts +12 -5
- package/app/app/api/mcp/agents/route.ts +64 -2
- package/app/app/globals.css +2 -1
- package/app/app/layout.tsx +16 -4
- package/app/components/AskFab.tsx +11 -5
- package/app/components/AskModal.tsx +1 -1
- package/app/components/FileTree.tsx +83 -1
- package/app/components/GuideCard.tsx +101 -152
- package/app/components/HomeContent.tsx +123 -574
- package/app/components/Panel.tsx +6 -1
- package/app/components/RightAskPanel.tsx +2 -2
- package/app/components/WikiHomeContent.tsx +151 -3
- 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 +109 -54
- package/app/components/ask/AskHeader.tsx +218 -18
- package/app/components/ask/FileChip.tsx +93 -12
- package/app/components/ask/MessageList.tsx +66 -47
- package/app/components/ask/SessionHistory.tsx +86 -60
- package/app/components/ask/SessionTabBar.tsx +29 -21
- package/app/components/ask/ThinkingBlock.tsx +6 -5
- package/app/components/ask/ToolCallBlock.tsx +10 -9
- package/app/components/changes/ChangesBanner.tsx +1 -1
- package/app/components/changes/ChangesContentPage.tsx +368 -168
- package/app/components/settings/SettingsContent.tsx +1 -1
- package/app/components/walkthrough/WalkthroughTooltip.tsx +3 -1
- package/app/components/walkthrough/steps.ts +1 -1
- package/app/data/skills/mindos/SKILL.md +67 -15
- package/app/data/skills/mindos-zh/SKILL.md +67 -11
- package/app/hooks/useAskChat.ts +10 -8
- package/app/hooks/useAskSession.ts +23 -1
- package/app/hooks/useFileUpload.ts +97 -43
- package/app/hooks/useImageUpload.ts +1 -1
- 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 +134 -10
- package/app/lib/i18n/modules/knowledge.ts +2 -0
- package/app/lib/i18n/modules/onboarding.ts +12 -12
- package/app/lib/inbox-upload.ts +86 -0
- package/app/lib/mcp-agents.ts +21 -1
- package/app/lib/stores/LocaleStoreInit.tsx +24 -1
- package/app/lib/stores/locale-store.ts +20 -6
- package/app/lib/types.ts +13 -0
- package/app/package.json +1 -1
- package/app/scripts/extract-pdf.cjs +110 -3
- package/package.json +1 -1
- package/skills/mindos/SKILL.md +67 -15
- package/skills/mindos/references/knowledge-health.md +120 -0
- package/skills/mindos-max/SKILL.md +52 -5
- package/skills/mindos-max-zh/SKILL.md +55 -6
- package/skills/mindos-zh/SKILL.md +67 -11
- package/_standalone/.next/server/chunks/2364.js +0 -2
- package/_standalone/.next/server/chunks/357.js +0 -1
- package/_standalone/.next/static/2ksXveDzEcnCMRIElDkLq/_buildManifest.js +0 -1
- package/_standalone/.next/static/chunks/178-105779afb62d36d9.js +0 -1
- package/_standalone/.next/static/chunks/2218-d54538000574ffef.js +0 -1
- package/_standalone/.next/static/chunks/2549-e63cf57fa927a41d.js +0 -1
- 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-fa98ca10e9a10f39.js +0 -11
- package/_standalone/.next/static/chunks/9274-296ab35f9f09e42e.js +0 -1
- package/_standalone/.next/static/chunks/9286-5b09baa5200318c2.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-7bdeab5af8e4f5f2.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/page-5d1446665ddb3801.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-5a72144d1080a699.js +0 -1
- package/_standalone/.next/static/chunks/app/echo/[segment]/page-b0103509ce34444b.js +0 -11
- package/_standalone/.next/static/chunks/app/echo/page-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/layout-7e02ddf4144b01f1.js +0 -186
- package/_standalone/.next/static/chunks/app/loading-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/page-6a6a12bd6d6812d0.js +0 -7
- package/_standalone/.next/static/chunks/app/trash/page-54cbd5c98d9de69b.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/page-ca7bdcbf27f88a46.js +0 -12
- package/_standalone/.next/static/chunks/app/wiki/page-d492256a93f0b8bc.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/fd84c8316ead16eb.css +0 -1
- /package/_standalone/.next/static/{2ksXveDzEcnCMRIElDkLq → K3wZNf5bj_AFYwtqcRXIf}/_ssgManifest.js +0 -0
|
@@ -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
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useRef, useEffect, memo, useState, useCallback } from 'react';
|
|
4
|
-
import { Sparkles, Loader2, AlertCircle, Wrench, WifiOff, Zap, Copy, Check, ArrowDown } from 'lucide-react';
|
|
4
|
+
import { Sparkles, Loader2, AlertCircle, Wrench, WifiOff, Zap, Copy, Check, ArrowDown, FolderInput, Search, PenLine, Lightbulb } from 'lucide-react';
|
|
5
5
|
import ReactMarkdown from 'react-markdown';
|
|
6
6
|
import remarkGfm from 'remark-gfm';
|
|
7
7
|
import type { Message, ImagePart } from '@/lib/types';
|
|
@@ -12,7 +12,7 @@ import ThinkingBlock from './ThinkingBlock';
|
|
|
12
12
|
|
|
13
13
|
const SKILL_PREFIX_RE = /^Use the skill ([^:]+):\s*/;
|
|
14
14
|
|
|
15
|
-
function CopyMessageButton({ text }: { text: string }) {
|
|
15
|
+
function CopyMessageButton({ text, label }: { text: string; label?: string }) {
|
|
16
16
|
const [copied, setCopied] = useState(false);
|
|
17
17
|
const handleCopy = useCallback(() => {
|
|
18
18
|
copyToClipboard(text).then(ok => {
|
|
@@ -27,8 +27,8 @@ function CopyMessageButton({ text }: { text: string }) {
|
|
|
27
27
|
<button
|
|
28
28
|
type="button"
|
|
29
29
|
onClick={handleCopy}
|
|
30
|
-
className="absolute -bottom-1 right-1 p-1 rounded-md bg-card border border-border/60 shadow-sm text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity"
|
|
31
|
-
title=
|
|
30
|
+
className="absolute -bottom-1 right-1 p-1 rounded-md bg-card border border-border/60 shadow-sm text-muted-foreground hover:text-foreground opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity"
|
|
31
|
+
title={label ?? 'Copy'}
|
|
32
32
|
>
|
|
33
33
|
{copied ? <Check size={11} className="text-success" /> : <Copy size={11} />}
|
|
34
34
|
</button>
|
|
@@ -62,7 +62,7 @@ function UserMessageContent({ content, skillName, images }: { content: string; s
|
|
|
62
62
|
)}
|
|
63
63
|
{/* Skill capsule + text */}
|
|
64
64
|
{resolved && (
|
|
65
|
-
<span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium bg-
|
|
65
|
+
<span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[11px] font-medium bg-white/20 text-white/90 mr-1 align-middle">
|
|
66
66
|
<Zap size={10} className="shrink-0" />
|
|
67
67
|
{resolved}
|
|
68
68
|
</span>
|
|
@@ -82,16 +82,16 @@ function AssistantMessage({ content, isStreaming }: { content: string; isStreami
|
|
|
82
82
|
prose-h1:text-base prose-h2:text-[15px] prose-h3:text-sm
|
|
83
83
|
prose-ul:my-1.5 prose-li:my-0.5
|
|
84
84
|
prose-ol:my-1.5
|
|
85
|
-
prose-code:text-[0.8em] prose-code:bg-
|
|
86
|
-
prose-pre:bg-
|
|
87
|
-
prose-blockquote:border-l-[var(--amber)] prose-blockquote:text-muted-foreground
|
|
85
|
+
prose-code:text-[0.8em] prose-code:bg-muted/80 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded-md prose-code:before:content-none prose-code:after:content-none prose-code:font-mono
|
|
86
|
+
prose-pre:bg-muted/60 prose-pre:text-foreground prose-pre:text-xs prose-pre:rounded-lg
|
|
87
|
+
prose-blockquote:border-l-[var(--amber)] prose-blockquote:text-muted-foreground prose-blockquote:not-italic
|
|
88
88
|
prose-a:text-[var(--amber)] prose-a:no-underline hover:prose-a:underline
|
|
89
89
|
prose-strong:text-foreground prose-strong:font-semibold
|
|
90
|
-
prose-table:text-xs prose-th:py-1 prose-td:py-1
|
|
90
|
+
prose-table:text-xs prose-th:py-1.5 prose-td:py-1
|
|
91
91
|
">
|
|
92
92
|
<ReactMarkdown remarkPlugins={[remarkGfm]}>{cleaned}</ReactMarkdown>
|
|
93
93
|
{isStreaming && (
|
|
94
|
-
<span className="inline-block w-1.5 h-3.5 bg-[var(--amber)] ml-0.5 align-middle animate-pulse rounded-
|
|
94
|
+
<span className="inline-block w-1.5 h-3.5 bg-[var(--amber)] ml-0.5 align-middle animate-pulse rounded-full" />
|
|
95
95
|
)}
|
|
96
96
|
</div>
|
|
97
97
|
);
|
|
@@ -129,7 +129,7 @@ function AssistantMessageWithParts({ message, isStreaming }: { message: Message;
|
|
|
129
129
|
return null;
|
|
130
130
|
})}
|
|
131
131
|
{showTrailingSpinner && (
|
|
132
|
-
<div className="flex items-center gap-2 py-1 mt-1">
|
|
132
|
+
<div className="flex items-center gap-2 py-1.5 mt-1.5">
|
|
133
133
|
<Loader2 size={12} className="animate-spin text-[var(--amber)]" />
|
|
134
134
|
<span className="text-xs text-muted-foreground animate-pulse">Executing tool…</span>
|
|
135
135
|
</div>
|
|
@@ -145,9 +145,9 @@ function StepCounter({ parts }: { parts: Message['parts'] }) {
|
|
|
145
145
|
const lastToolCall = toolCalls[toolCalls.length - 1];
|
|
146
146
|
const toolLabel = lastToolCall.type === 'tool-call' ? lastToolCall.toolName : '';
|
|
147
147
|
return (
|
|
148
|
-
<div className="flex items-center gap-1.5 mt-1.5 text-xs text-muted-foreground/
|
|
148
|
+
<div className="flex items-center gap-1.5 mt-2 pt-1.5 border-t border-border/15 text-xs text-muted-foreground/60">
|
|
149
149
|
<Wrench size={10} />
|
|
150
|
-
<span>Step {toolCalls.length}{toolLabel ? ` — ${toolLabel}` : ''}</span>
|
|
150
|
+
<span className="font-medium">Step {toolCalls.length}{toolLabel ? ` — ${toolLabel}` : ''}</span>
|
|
151
151
|
</div>
|
|
152
152
|
);
|
|
153
153
|
}
|
|
@@ -158,13 +158,14 @@ interface MessageListProps {
|
|
|
158
158
|
loadingPhase: 'connecting' | 'thinking' | 'streaming' | 'reconnecting';
|
|
159
159
|
emptyPrompt: string;
|
|
160
160
|
emptyHint?: string;
|
|
161
|
-
suggestions: readonly string[];
|
|
161
|
+
suggestions: readonly { label: string; prompt: string }[];
|
|
162
162
|
onSuggestionClick: (text: string) => void;
|
|
163
163
|
labels: {
|
|
164
164
|
connecting: string;
|
|
165
165
|
thinking: string;
|
|
166
166
|
generating: string;
|
|
167
167
|
reconnecting?: string;
|
|
168
|
+
copyMessage?: string;
|
|
168
169
|
};
|
|
169
170
|
}
|
|
170
171
|
|
|
@@ -183,7 +184,9 @@ export default memo(function MessageList({
|
|
|
183
184
|
const [showScrollDown, setShowScrollDown] = useState(false);
|
|
184
185
|
|
|
185
186
|
const scrollToBottom = useCallback(() => {
|
|
186
|
-
|
|
187
|
+
const container = scrollContainerRef.current;
|
|
188
|
+
if (!container) return;
|
|
189
|
+
container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' });
|
|
187
190
|
}, []);
|
|
188
191
|
|
|
189
192
|
useEffect(() => {
|
|
@@ -202,56 +205,65 @@ export default memo(function MessageList({
|
|
|
202
205
|
}, []);
|
|
203
206
|
|
|
204
207
|
return (
|
|
205
|
-
<div ref={scrollContainerRef} className="relative flex-1 overflow-y-auto overflow-x-hidden px-4 py-
|
|
208
|
+
<div ref={scrollContainerRef} role="log" aria-live="polite" className="relative flex-1 overflow-y-auto overflow-x-hidden px-4 py-5 space-y-5 min-h-0">
|
|
206
209
|
{messages.length === 0 && (
|
|
207
|
-
<div className="flex flex-col items-center justify-center flex-1 min-h-[
|
|
208
|
-
{/* Brand anchor */}
|
|
209
|
-
<div className="w-
|
|
210
|
-
<
|
|
210
|
+
<div className="flex flex-col items-center justify-center flex-1 min-h-[260px] px-6 pt-10 pb-4">
|
|
211
|
+
{/* Brand anchor — refined presence */}
|
|
212
|
+
<div className="relative w-12 h-12 rounded-2xl bg-[var(--amber)]/10 flex items-center justify-center mb-6">
|
|
213
|
+
<div className="absolute inset-0 rounded-2xl bg-[var(--amber)]/5 scale-[1.4]" />
|
|
214
|
+
<Sparkles size={22} className="text-[var(--amber)] relative z-10" />
|
|
211
215
|
</div>
|
|
212
|
-
<p className="text-center text-
|
|
216
|
+
<p className="text-center text-[15px] font-semibold text-foreground tracking-tight mb-2">{emptyPrompt}</p>
|
|
213
217
|
{emptyHint && (
|
|
214
|
-
<p className="text-center text-
|
|
218
|
+
<p className="text-center text-xs text-muted-foreground/80 mb-10 tracking-wide">{emptyHint}</p>
|
|
215
219
|
)}
|
|
216
|
-
{/* Suggestion chips —
|
|
217
|
-
<div className="
|
|
218
|
-
{suggestions.map((s, i) =>
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
220
|
+
{/* Suggestion chips — refined single column */}
|
|
221
|
+
<div className="flex flex-col gap-2.5 max-w-[280px] w-full">
|
|
222
|
+
{suggestions.map((s, i) => {
|
|
223
|
+
const icons = [FolderInput, Search, PenLine, Lightbulb];
|
|
224
|
+
const SugIcon = icons[i % icons.length];
|
|
225
|
+
return (
|
|
226
|
+
<button
|
|
227
|
+
key={i}
|
|
228
|
+
type="button"
|
|
229
|
+
onClick={() => onSuggestionClick(s.prompt)}
|
|
230
|
+
className="group/sug flex items-center gap-3 text-left text-[13px] px-3.5 py-3 rounded-xl border border-border/40 bg-transparent text-muted-foreground hover:text-foreground hover:border-[var(--amber)]/30 hover:bg-[var(--amber)]/5 transition-all leading-snug"
|
|
231
|
+
aria-label={s.prompt}
|
|
232
|
+
>
|
|
233
|
+
<span className="shrink-0 w-8 h-8 rounded-lg bg-muted/60 flex items-center justify-center group-hover/sug:bg-[var(--amber)]/10 transition-colors">
|
|
234
|
+
<SugIcon size={15} className="text-muted-foreground/70 group-hover/sug:text-[var(--amber)] transition-colors" />
|
|
235
|
+
</span>
|
|
236
|
+
<span className="flex-1">{s.label}</span>
|
|
237
|
+
</button>
|
|
238
|
+
);
|
|
239
|
+
})}
|
|
228
240
|
</div>
|
|
229
241
|
</div>
|
|
230
242
|
)}
|
|
231
243
|
{messages.map((m, i) => (
|
|
232
|
-
<div key={i} className={`flex gap-3 ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
|
|
244
|
+
<div key={i} className={`flex gap-3 animate-[fadeSlideUp_0.22s_ease_both] ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
|
|
233
245
|
{m.role === 'assistant' && (
|
|
234
246
|
<div
|
|
235
|
-
className="w-
|
|
247
|
+
className="w-7 h-7 rounded-lg flex items-center justify-center shrink-0 mt-0.5 bg-[var(--amber)]/8"
|
|
236
248
|
>
|
|
237
|
-
<Sparkles size={
|
|
249
|
+
<Sparkles size={13} className="text-[var(--amber)]" />
|
|
238
250
|
</div>
|
|
239
251
|
)}
|
|
240
252
|
{m.role === 'user' ? (
|
|
241
253
|
<div
|
|
242
|
-
className="max-w-[85%] px-3 py-2 rounded-
|
|
254
|
+
className="max-w-[85%] px-3.5 py-2.5 rounded-2xl rounded-br-lg text-sm leading-relaxed whitespace-pre-wrap bg-[var(--amber)] text-[var(--amber-foreground)] shadow-sm shadow-[var(--amber)]/10"
|
|
243
255
|
>
|
|
244
256
|
<UserMessageContent content={m.content} skillName={m.skillName} images={m.images} />
|
|
245
257
|
</div>
|
|
246
258
|
) : m.content.startsWith('__error__') ? (
|
|
247
|
-
<div className="max-w-[85%] px-3 py-
|
|
248
|
-
<div className="flex items-start gap-2 text-error">
|
|
249
|
-
<AlertCircle size={
|
|
250
|
-
<span className="leading-relaxed">{m.content.slice(9)}</span>
|
|
259
|
+
<div className="max-w-[85%] px-3.5 py-3 rounded-2xl rounded-bl-md border border-error/30 bg-error/10 text-sm shadow-sm">
|
|
260
|
+
<div className="flex items-start gap-2.5 text-error">
|
|
261
|
+
<AlertCircle size={15} className="shrink-0 mt-0.5" />
|
|
262
|
+
<span className="leading-relaxed font-medium">{m.content.slice(9)}</span>
|
|
251
263
|
</div>
|
|
252
264
|
</div>
|
|
253
265
|
) : (
|
|
254
|
-
<div className="group relative max-w-[85%] px-3 py-2 rounded-
|
|
266
|
+
<div className="group relative max-w-[85%] px-3.5 py-2.5 rounded-2xl rounded-bl-lg bg-card border border-border/30 shadow-sm text-foreground text-sm">
|
|
255
267
|
{(m.parts && m.parts.length > 0) || stripThinkingTags(m.content) ? (
|
|
256
268
|
<>
|
|
257
269
|
<AssistantMessageWithParts message={m} isStreaming={isLoading && i === messages.length - 1} />
|
|
@@ -259,17 +271,18 @@ export default memo(function MessageList({
|
|
|
259
271
|
<StepCounter parts={m.parts} />
|
|
260
272
|
)}
|
|
261
273
|
{!(isLoading && i === messages.length - 1) && stripThinkingTags(m.content) && (
|
|
262
|
-
<CopyMessageButton text={stripThinkingTags(m.content)} />
|
|
274
|
+
<CopyMessageButton text={stripThinkingTags(m.content)} label={labels.copyMessage} />
|
|
263
275
|
)}
|
|
264
276
|
</>
|
|
265
277
|
) : isLoading && i === messages.length - 1 ? (
|
|
266
|
-
<div className="flex items-center gap-2 py-1">
|
|
278
|
+
<div className="flex items-center gap-2.5 py-1">
|
|
267
279
|
{loadingPhase === 'reconnecting' ? (
|
|
268
280
|
<WifiOff size={14} className="text-[var(--amber)] animate-pulse" />
|
|
269
281
|
) : (
|
|
270
282
|
<Loader2 size={14} className="animate-spin text-[var(--amber)]" />
|
|
271
283
|
)}
|
|
272
|
-
<span className="text-xs text-muted-foreground
|
|
284
|
+
<span className="text-xs text-muted-foreground">
|
|
285
|
+
<span className="inline-flex items-center gap-1">
|
|
273
286
|
{loadingPhase === 'reconnecting'
|
|
274
287
|
? (labels.reconnecting ?? 'Reconnecting...')
|
|
275
288
|
: loadingPhase === 'connecting'
|
|
@@ -277,6 +290,12 @@ export default memo(function MessageList({
|
|
|
277
290
|
: loadingPhase === 'thinking'
|
|
278
291
|
? labels.thinking
|
|
279
292
|
: labels.generating}
|
|
293
|
+
<span className="inline-flex gap-0.5">
|
|
294
|
+
<span className="w-1 h-1 rounded-full bg-[var(--amber)] animate-bounce [animation-delay:0ms]"></span>
|
|
295
|
+
<span className="w-1 h-1 rounded-full bg-[var(--amber)] animate-bounce [animation-delay:150ms]"></span>
|
|
296
|
+
<span className="w-1 h-1 rounded-full bg-[var(--amber)] animate-bounce [animation-delay:300ms]"></span>
|
|
297
|
+
</span>
|
|
298
|
+
</span>
|
|
280
299
|
</span>
|
|
281
300
|
</div>
|
|
282
301
|
) : null}
|
|
@@ -291,7 +310,7 @@ export default memo(function MessageList({
|
|
|
291
310
|
<button
|
|
292
311
|
type="button"
|
|
293
312
|
onClick={scrollToBottom}
|
|
294
|
-
className="sticky bottom-2 left-1/2 -translate-x-1/2 z-10 p-
|
|
313
|
+
className="sticky bottom-2 left-1/2 -translate-x-1/2 z-10 p-2 rounded-full border border-border/60 bg-card shadow-md text-muted-foreground hover:text-foreground hover:bg-muted transition-all hover:shadow-lg"
|
|
295
314
|
title="Scroll to bottom"
|
|
296
315
|
>
|
|
297
316
|
<ArrowDown size={14} />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
4
|
-
import { Trash2, Pencil } from 'lucide-react';
|
|
4
|
+
import { Trash2, Pencil, Pin, PinOff } from 'lucide-react';
|
|
5
5
|
import type { ChatSession } from '@/lib/types';
|
|
6
6
|
import { sessionTitle } from '@/hooks/useAskSession';
|
|
7
7
|
|
|
@@ -11,11 +11,25 @@ interface SessionHistoryProps {
|
|
|
11
11
|
onLoad: (id: string) => void;
|
|
12
12
|
onDelete: (id: string) => void;
|
|
13
13
|
onRename: (id: string, title: string) => void;
|
|
14
|
+
onTogglePin: (id: string) => void;
|
|
14
15
|
onClearAll: () => void;
|
|
15
16
|
labels: { title: string; clearAll: string; confirmClear: string; noSessions: string; rename: string };
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
function formatRelativeTime(date: Date): string {
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const diff = now - date.getTime();
|
|
22
|
+
const mins = Math.floor(diff / 60000);
|
|
23
|
+
if (mins < 1) return 'just now';
|
|
24
|
+
if (mins < 60) return `${mins}m ago`;
|
|
25
|
+
const hours = Math.floor(mins / 60);
|
|
26
|
+
if (hours < 24) return `${hours}h ago`;
|
|
27
|
+
const days = Math.floor(hours / 24);
|
|
28
|
+
if (days < 7) return `${days}d ago`;
|
|
29
|
+
return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default function SessionHistory({ sessions, activeSessionId, onLoad, onDelete, onRename, onTogglePin, onClearAll, labels }: SessionHistoryProps) {
|
|
19
33
|
const [confirmClearAll, setConfirmClearAll] = useState(false);
|
|
20
34
|
const clearTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
21
35
|
const [editingId, setEditingId] = useState<string | null>(null);
|
|
@@ -60,78 +74,90 @@ export default function SessionHistory({ sessions, activeSessionId, onLoad, onDe
|
|
|
60
74
|
}, []);
|
|
61
75
|
|
|
62
76
|
return (
|
|
63
|
-
<div className="border-b border-border px-4 py-
|
|
64
|
-
<div className="flex items-center justify-between mb-2">
|
|
65
|
-
<span className="text-xs text-muted-foreground">{labels.title}</span>
|
|
77
|
+
<div className="border-b border-border/40 px-4 py-3 max-h-[220px] overflow-y-auto">
|
|
78
|
+
<div className="flex items-center justify-between mb-2.5">
|
|
79
|
+
<span className="text-xs font-medium text-muted-foreground">{labels.title}</span>
|
|
66
80
|
{sessions.length > 1 && (
|
|
67
81
|
<button
|
|
68
82
|
type="button"
|
|
69
83
|
onClick={handleClearAll}
|
|
70
|
-
className={`text-2xs px-
|
|
84
|
+
className={`text-2xs px-2 py-0.5 rounded-md transition-colors ${
|
|
71
85
|
confirmClearAll
|
|
72
86
|
? 'bg-error/10 text-error font-medium'
|
|
73
|
-
: 'text-muted-foreground hover:text-error hover:bg-muted'
|
|
87
|
+
: 'text-muted-foreground/60 hover:text-error hover:bg-muted'
|
|
74
88
|
}`}
|
|
75
89
|
>
|
|
76
90
|
{confirmClearAll ? labels.confirmClear : labels.clearAll}
|
|
77
91
|
</button>
|
|
78
92
|
)}
|
|
79
93
|
</div>
|
|
80
|
-
<div className="flex flex-col gap-1
|
|
94
|
+
<div className="flex flex-col gap-1">
|
|
81
95
|
{sessions.length === 0 && (
|
|
82
|
-
<div className="text-xs text-muted-foreground/
|
|
96
|
+
<div className="text-xs text-muted-foreground/50 py-2 text-center">{labels.noSessions}</div>
|
|
83
97
|
)}
|
|
84
|
-
{sessions.map((s) =>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
98
|
+
{sessions.map((s) => {
|
|
99
|
+
const isActive = activeSessionId === s.id;
|
|
100
|
+
return (
|
|
101
|
+
<div key={s.id} className="group flex items-center gap-0.5">
|
|
102
|
+
{s.pinned && <Pin size={10} className="shrink-0 text-[var(--amber)]/50 -rotate-45 ml-1" />}
|
|
103
|
+
<button
|
|
104
|
+
type="button"
|
|
105
|
+
onClick={() => onLoad(s.id)}
|
|
106
|
+
onDoubleClick={() => startRename(s)}
|
|
107
|
+
className={`flex-1 text-left px-2.5 py-2 rounded-lg text-xs transition-colors min-w-0 ${
|
|
108
|
+
isActive
|
|
109
|
+
? 'bg-[var(--amber)]/8 text-foreground border border-[var(--amber)]/15'
|
|
110
|
+
: 'text-muted-foreground hover:bg-muted hover:text-foreground border border-transparent'
|
|
111
|
+
}`}
|
|
112
|
+
>
|
|
113
|
+
{editingId === s.id ? (
|
|
114
|
+
<input
|
|
115
|
+
ref={inputRef}
|
|
116
|
+
type="text"
|
|
117
|
+
value={editValue}
|
|
118
|
+
onChange={(e) => setEditValue(e.target.value)}
|
|
119
|
+
onBlur={commitRename}
|
|
120
|
+
onKeyDown={(e) => {
|
|
121
|
+
if (e.key === 'Enter') { e.preventDefault(); commitRename(); }
|
|
122
|
+
if (e.key === 'Escape') { e.preventDefault(); cancelRename(); }
|
|
123
|
+
}}
|
|
124
|
+
onClick={(e) => e.stopPropagation()}
|
|
125
|
+
className="w-full bg-transparent border-b border-[var(--amber)] outline-none text-xs text-foreground"
|
|
126
|
+
/>
|
|
127
|
+
) : (
|
|
128
|
+
<div className="truncate font-medium">{sessionTitle(s)}</div>
|
|
129
|
+
)}
|
|
130
|
+
{editingId !== s.id && (
|
|
131
|
+
<div className="text-2xs text-muted-foreground/50 mt-0.5">{formatRelativeTime(new Date(s.updatedAt))}</div>
|
|
132
|
+
)}
|
|
133
|
+
</button>
|
|
134
|
+
<button
|
|
135
|
+
type="button"
|
|
136
|
+
onClick={() => onTogglePin(s.id)}
|
|
137
|
+
className={`p-1.5 rounded-lg transition-opacity opacity-0 group-hover:opacity-100 ${s.pinned ? 'text-[var(--amber)] hover:text-muted-foreground' : 'text-muted-foreground hover:text-[var(--amber)]'}`}
|
|
138
|
+
title={s.pinned ? 'Unpin' : 'Pin'}
|
|
139
|
+
>
|
|
140
|
+
{s.pinned ? <PinOff size={11} /> : <Pin size={11} />}
|
|
141
|
+
</button>
|
|
142
|
+
<button
|
|
143
|
+
type="button"
|
|
144
|
+
onClick={() => startRename(s)}
|
|
145
|
+
className="p-1.5 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted opacity-0 group-hover:opacity-100 transition-opacity"
|
|
146
|
+
title={labels.rename}
|
|
147
|
+
>
|
|
148
|
+
<Pencil size={11} />
|
|
149
|
+
</button>
|
|
150
|
+
<button
|
|
151
|
+
type="button"
|
|
152
|
+
onClick={() => onDelete(s.id)}
|
|
153
|
+
className="p-1.5 rounded-lg text-muted-foreground hover:text-error hover:bg-error/5 opacity-0 group-hover:opacity-100 transition-opacity"
|
|
154
|
+
title="Delete session"
|
|
155
|
+
>
|
|
156
|
+
<Trash2 size={11} />
|
|
157
|
+
</button>
|
|
158
|
+
</div>
|
|
159
|
+
);
|
|
160
|
+
})}
|
|
135
161
|
</div>
|
|
136
162
|
</div>
|
|
137
163
|
);
|