@geminilight/mindos 0.6.38 → 0.6.40
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/README.md +37 -9
- package/README_zh.md +37 -9
- package/_standalone/.mindos-build-version +1 -1
- package/_standalone/.next/BUILD_ID +1 -1
- package/_standalone/.next/app-path-routes-manifest.json +21 -20
- 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 +68 -6
- 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 +2 -2
- 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 +2 -2
- 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 +3 -3
- 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.js +1 -1
- package/_standalone/.next/server/app/api/acp/config/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/acp/detect/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/acp/session/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/agent-activity/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask/route.js +133 -95
- package/_standalone/.next/server/app/api/ask/route.js.nft.json +1 -1
- 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.js +1 -1
- package/_standalone/.next/server/app/api/backlinks/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/bootstrap/route.js +1 -1
- package/_standalone/.next/server/app/api/bootstrap/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/changes/route.js +1 -1
- package/_standalone/.next/server/app/api/changes/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/export/route.js +3 -3
- package/_standalone/.next/server/app/api/export/route.js.nft.json +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_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/import/route.js +2 -19
- package/_standalone/.next/server/app/api/file/import/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/route.js +1 -18
- package/_standalone/.next/server/app/api/file/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/files/route.js +1 -1
- package/_standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/git/route.js +1 -1
- package/_standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/graph/route.js +1 -1
- package/_standalone/.next/server/app/api/graph/route.js.nft.json +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.js +1 -0
- package/_standalone/.next/server/app/api/inbox/route.js.nft.json +1 -0
- package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.js +1 -0
- package/_standalone/.next/server/app/api/init/route.js +1 -1
- package/_standalone/.next/server/app/api/init/route.js.nft.json +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.js.nft.json +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.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/mcp/status/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/monitoring/route.js +1 -1
- package/_standalone/.next/server/app/api/monitoring/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/recent-files/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/search/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/settings/list-models/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/settings/reset-token/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/settings/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/settings/test-key/route.js.nft.json +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.js +1 -1
- package/_standalone/.next/server/app/api/setup/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/skills/route.js +2 -2
- package/_standalone/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/sync/route.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.js +1 -1
- package/_standalone/.next/server/app/api/tree-version/route.js.nft.json +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.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.js +2 -2
- package/_standalone/.next/server/app/api/workflows/route.js.nft.json +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 +6 -6
- 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 +2 -2
- 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 +3 -3
- 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/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 +3 -3
- 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 +4 -4
- 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-paths-manifest.json +21 -20
- package/_standalone/.next/server/chunks/1550.js +1 -1
- package/_standalone/.next/server/chunks/1750.js +1 -0
- package/_standalone/.next/server/chunks/1955.js +11 -0
- package/_standalone/.next/server/chunks/3680.js +1 -0
- package/_standalone/.next/server/chunks/4497.js +219 -0
- package/_standalone/.next/server/chunks/5560.js +2 -0
- package/_standalone/.next/server/chunks/6365.js +52 -0
- package/_standalone/.next/server/chunks/6539.js +1 -1
- package/_standalone/.next/server/chunks/8388.js +15 -0
- package/_standalone/.next/server/chunks/953.js +42 -2
- package/_standalone/.next/server/functions-config-manifest.json +2 -1
- package/_standalone/.next/server/instrumentation.js +1 -1
- 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/next-font-manifest.js +1 -1
- package/_standalone/.next/server/next-font-manifest.json +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/chunks/1053-0adaccc98a752a58.js +29 -0
- package/_standalone/.next/static/chunks/1239.10a0710c2772ab34.js +1 -0
- package/_standalone/.next/static/chunks/{1814.e2da5460ded71d71.js → 1814.2ee1d03297c0bccd.js} +1 -1
- package/_standalone/.next/static/chunks/{1a258343-030e4d6735874dd4.js → 1a258343-9803591e4aaee1f6.js} +1 -1
- package/_standalone/.next/static/chunks/2631.dc56e83472bde281.js +1 -0
- package/_standalone/.next/static/chunks/2872.045858d00bd8307f.js +8 -0
- package/_standalone/.next/static/chunks/2968.f10ccee9e7e2324d.js +2 -0
- package/_standalone/.next/static/chunks/3160-83a7e0b94414b3ac.js +1 -0
- package/_standalone/.next/static/chunks/{3637.4bcd01a4db78b894.js → 3637.f9a42cca59fd5bb5.js} +1 -1
- package/_standalone/.next/static/chunks/4033.6666700547b20141.js +1 -0
- package/_standalone/.next/static/chunks/4563-c2afaeacb241d1d0.js +6 -0
- package/_standalone/.next/static/chunks/516.24ee058b1d4b1fed.js +8 -0
- package/_standalone/.next/static/chunks/5627.c4337d7289acb31f.js +1 -0
- package/_standalone/.next/static/chunks/5956.b445072b35915129.js +1 -0
- package/_standalone/.next/static/chunks/6090-c98268ca726a68d3.js +1 -0
- package/_standalone/.next/static/chunks/6357-c645842834c0d4cd.js +1 -0
- package/_standalone/.next/static/chunks/6826.7b7d94dd0fd83812.js +1 -0
- package/_standalone/.next/static/chunks/{8409-de5726a4a278d28f.js → 6926-4af497b83952fa87.js} +1 -1
- package/_standalone/.next/static/chunks/7266-bb7be1128eccd48e.js +13 -0
- package/_standalone/.next/static/chunks/7753.63831cfc54a55fbb.js +1 -0
- package/_standalone/.next/static/chunks/862.9f526e964489e2e5.js +1 -0
- package/_standalone/.next/static/chunks/{1384-55276d40a9da4e88.js → 8663-de911d2d395622be.js} +2 -2
- package/_standalone/.next/static/chunks/9300.118b8c840634383f.js +28 -0
- package/_standalone/.next/static/chunks/9371-575600301da5d6bb.js +1 -0
- package/_standalone/.next/static/chunks/95247769.3b5caae1c1a76ce1.js +4 -0
- package/_standalone/.next/static/chunks/9602-423291fdb36396d1.js +1 -0
- package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/_global-error/page-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-3e08abb495ecd5fd.js +1 -0
- package/_standalone/.next/static/chunks/app/agents/page-e7e0f87ad3d765ac.js +5 -0
- package/_standalone/.next/static/chunks/app/api/a2a/agents/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/a2a/delegations/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/a2a/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/config/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/install/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/session/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/auth/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/backlinks/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/changes/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/export/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/import/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/files/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/git/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/graph/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/health/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/inbox/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/init/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/monitoring/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/recent-files/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/restart/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/search/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/skills/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/sync/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/tree-version/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/uninstall/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-check/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-status/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/api/workflows/route-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/changes/page-350992cf5091bc5b.js +1 -0
- package/_standalone/.next/static/chunks/app/echo/[segment]/page-addf014fcf23fad5.js +11 -0
- package/_standalone/.next/static/chunks/app/echo/page-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/explore/page-5eb2835e9e3ab4bb.js +4 -0
- package/_standalone/.next/static/chunks/app/help/page-3d0e1ceaa4abc243.js +1 -0
- package/_standalone/.next/static/chunks/app/layout-9378c1c8d3e5761b.js +186 -0
- package/_standalone/.next/static/chunks/app/login/page-24236460fa7c11d0.js +1 -0
- package/_standalone/.next/static/chunks/app/page-9bae420fbbdc5fff.js +7 -0
- package/_standalone/.next/static/chunks/app/setup/page-99ed3d1bb6b8f4ef.js +1 -0
- package/_standalone/.next/static/chunks/app/trash/page-b61ef2d5cd4f8d73.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/not-found-61474670d6bb6116.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/page-44fa78cbea613a78.js +12 -0
- package/_standalone/.next/static/chunks/e71f6c19-4df85185bf989b49.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-400c3c09b1540c14.js +1 -0
- package/_standalone/.next/static/chunks/webpack-c28c55d0a6021a6b.js +1 -0
- package/_standalone/.next/static/css/d300701f384db50d.css +1 -0
- package/_standalone/.next/static/rZLs1krFuduixvcVNe6q3/_buildManifest.js +1 -0
- package/_standalone/.next/trace +63 -53
- package/_standalone/.next/types/routes.d.ts +2 -1
- package/_standalone/.next/types/validator.ts +9 -0
- package/_standalone/__tests__/agent/chat-mode.test.ts +103 -0
- package/_standalone/__tests__/agents/agents-content-dashboard.test.tsx +4 -3
- package/_standalone/__tests__/api/bootstrap.test.ts +0 -2
- package/_standalone/__tests__/api/file.test.ts +22 -1
- package/_standalone/__tests__/api/install-skill.test.ts +2 -2
- package/_standalone/__tests__/api/mcp-install.test.ts +9 -10
- package/_standalone/__tests__/api/setup.test.ts +2 -2
- package/_standalone/__tests__/api/test-key.test.ts +73 -147
- package/_standalone/__tests__/ask/ask-content-input-during-run.test.tsx +1 -1
- package/_standalone/__tests__/ask/mode-capsule.test.ts +95 -0
- package/_standalone/__tests__/core/inbox.test.ts +250 -0
- package/_standalone/__tests__/core/skill-install-logic.test.ts +3 -3
- package/_standalone/__tests__/core/sync-status.test.ts +1 -1
- package/_standalone/__tests__/core/tools.test.ts +11 -6
- package/_standalone/__tests__/lib/echo-pages-visual-i18n.test.ts +2 -2
- package/_standalone/__tests__/lib/i18n-new-keys.test.ts +2 -2
- package/_standalone/__tests__/panels/agents-panel-hub.test.tsx +2 -2
- package/_standalone/__tests__/settings/activity-bar-update-badge.test.tsx +1 -1
- package/_standalone/__tests__/settings/settings-update-badge.test.tsx +1 -1
- package/_standalone/__tests__/settings/update-tab-availability-sync.test.tsx +1 -1
- package/_standalone/__tests__/settings/update-tab-browser.test.tsx +1 -1
- package/_standalone/__tests__/settings/update-tab-desktop.test.tsx +1 -1
- package/_standalone/__tests__/setup.ts +3 -5
- package/_standalone/app/globals.css +11 -1
- package/_standalone/components/ActivityBar.tsx +26 -10
- package/_standalone/components/AskFab.tsx +1 -1
- package/_standalone/components/AskModal.tsx +1 -1
- package/_standalone/components/Backlinks.tsx +1 -1
- package/_standalone/components/CreateSpaceModal.tsx +7 -55
- package/_standalone/components/EchoSpotlight.tsx +1 -1
- package/_standalone/components/ExportModal.tsx +1 -1
- package/_standalone/components/FileTree.tsx +64 -79
- package/_standalone/components/FindInPage.tsx +1 -1
- package/_standalone/components/GuideCard.tsx +1 -1
- package/_standalone/components/ImportModal.tsx +1 -1
- package/_standalone/components/KeyboardShortcuts.tsx +1 -1
- package/_standalone/components/MarkdownView.tsx +11 -1
- package/_standalone/components/OnboardingView.tsx +1 -1
- package/_standalone/components/OrganizeToast.tsx +1 -1
- package/_standalone/components/Panel.tsx +82 -4
- package/_standalone/components/QuickSuggestion.tsx +1 -1
- package/_standalone/components/RightAgentDetailPanel.tsx +2 -2
- package/_standalone/components/RightAskPanel.tsx +58 -22
- package/_standalone/components/SearchModal.tsx +1 -1
- package/_standalone/components/Sidebar.tsx +1 -1
- package/_standalone/components/SidebarLayout.tsx +52 -16
- package/_standalone/components/SpaceInitToast.tsx +1 -1
- package/_standalone/components/SyncStatusBar.tsx +2 -2
- package/_standalone/components/SystemPulse.tsx +12 -6
- package/_standalone/components/TableOfContents.tsx +86 -39
- package/_standalone/components/agents/AgentActivitySection.tsx +225 -0
- package/_standalone/components/agents/AgentsMcpSection.tsx +7 -16
- package/_standalone/components/agents/AgentsOverviewSection.tsx +28 -27
- package/_standalone/components/agents/AgentsPanelA2aTab.tsx +1 -1
- package/_standalone/components/agents/AgentsPanelSessionsTab.tsx +6 -1
- package/_standalone/components/agents/AgentsSkillsSection.tsx +1 -1
- package/_standalone/components/agents/DiscoverAgentModal.tsx +1 -1
- package/_standalone/components/agents/RecentActivityFeed.tsx +49 -88
- package/_standalone/components/agents/agent-activity-shared.tsx +110 -0
- package/_standalone/components/ask/AgentSelectorCapsule.tsx +1 -1
- package/_standalone/components/ask/AskContent.tsx +332 -486
- package/_standalone/components/ask/AskHeader.tsx +61 -0
- package/_standalone/components/ask/FileChip.tsx +9 -5
- package/_standalone/components/ask/MessageList.tsx +88 -21
- package/_standalone/components/ask/ModeCapsule.tsx +180 -0
- package/_standalone/components/ask/ProviderModelCapsule.tsx +284 -0
- package/_standalone/components/ask/SessionHistory.tsx +63 -10
- package/_standalone/components/ask/SessionTabBar.tsx +1 -1
- package/_standalone/components/ask/ThinkingBlock.tsx +1 -1
- package/_standalone/components/ask/ToolCallBlock.tsx +28 -24
- package/_standalone/components/changes/ChangesBanner.tsx +1 -1
- package/_standalone/components/echo/EchoInsightCollapsible.tsx +1 -1
- package/_standalone/components/echo/EchoSegmentNav.tsx +1 -1
- package/_standalone/components/home/InboxSection.tsx +268 -0
- package/_standalone/components/panels/AgentsPanel.tsx +3 -2
- package/_standalone/components/panels/AgentsPanelHubNav.tsx +2 -6
- package/_standalone/components/panels/DiscoverPanel.tsx +1 -1
- package/_standalone/components/panels/EchoPanel.tsx +1 -1
- package/_standalone/components/panels/EchoSidebarStats.tsx +1 -1
- package/_standalone/components/panels/ImportHistoryPanel.tsx +1 -1
- package/_standalone/components/panels/PanelHeader.tsx +1 -1
- package/_standalone/components/panels/PluginsPanel.tsx +1 -1
- package/_standalone/components/panels/SearchPanel.tsx +5 -2
- package/_standalone/components/panels/SyncPopover.tsx +1 -1
- package/_standalone/components/panels/WorkflowsPanel.tsx +1 -1
- package/_standalone/components/renderers/agent-inspector/AgentInspectorRenderer.tsx +18 -0
- package/_standalone/components/renderers/agent-inspector/manifest.ts +16 -0
- package/_standalone/components/renderers/todo/TodoRenderer.tsx +489 -75
- package/_standalone/components/settings/AiTab.tsx +198 -127
- package/_standalone/components/settings/AppearanceTab.tsx +48 -50
- package/_standalone/components/settings/KnowledgeTab.tsx +92 -27
- package/_standalone/components/settings/McpAgentInstall.tsx +1 -1
- package/_standalone/components/settings/McpSkillsSection.tsx +1 -1
- package/_standalone/components/settings/McpTab.tsx +145 -7
- package/_standalone/components/settings/PluginsTab.tsx +1 -1
- package/_standalone/components/settings/SettingsContent.tsx +5 -2
- package/_standalone/components/settings/SyncTab.tsx +615 -230
- package/_standalone/components/settings/UninstallTab.tsx +1 -1
- package/_standalone/components/settings/UpdateTab.tsx +373 -109
- package/_standalone/components/settings/types.ts +4 -5
- package/_standalone/components/setup/StepAI.tsx +70 -49
- package/_standalone/components/setup/StepDots.tsx +1 -1
- package/_standalone/components/setup/StepReview.tsx +176 -8
- package/_standalone/components/setup/types.ts +11 -8
- package/_standalone/components/shared/ProviderSelect.tsx +134 -0
- package/_standalone/components/walkthrough/WalkthroughOverlay.tsx +2 -2
- package/_standalone/components/walkthrough/WalkthroughTooltip.tsx +2 -2
- package/_standalone/components/walkthrough/index.ts +1 -1
- package/_standalone/data/skills/mindos/SKILL.md +27 -12
- package/_standalone/data/skills/mindos-zh/SKILL.md +27 -12
- package/_standalone/hooks/useAcpDetection.ts +1 -1
- package/_standalone/hooks/useAskChat.ts +248 -0
- package/_standalone/hooks/useAskPanel.ts +24 -4
- package/_standalone/hooks/useAskSession.ts +15 -0
- package/_standalone/lib/acp/types.ts +1 -1
- package/_standalone/lib/api.ts +3 -1
- package/_standalone/lib/core/types.ts +2 -0
- package/_standalone/lib/i18n/modules/ai-chat.ts +35 -13
- package/_standalone/lib/i18n/modules/features.ts +2 -2
- package/_standalone/lib/i18n/modules/knowledge.ts +82 -2
- package/_standalone/lib/i18n/modules/navigation.ts +6 -2
- package/_standalone/lib/i18n/modules/onboarding.ts +39 -9
- package/_standalone/lib/i18n/modules/panels.ts +78 -29
- package/_standalone/lib/i18n/modules/settings.ts +236 -20
- package/_standalone/lib/inbox-upload.ts +93 -0
- package/_standalone/lib/settings-ai-client.ts +13 -12
- package/_standalone/lib/space-ai-init.ts +66 -0
- package/_standalone/lib/stores/McpStoreInit.tsx +18 -0
- package/_standalone/lib/stores/WalkthroughInit.tsx +20 -0
- package/_standalone/lib/stores/locale-store.ts +55 -0
- package/_standalone/lib/stores/mcp-store.ts +156 -0
- package/_standalone/lib/stores/walkthrough-store.ts +118 -0
- package/_standalone/package-lock.json +40 -8
- package/_standalone/package.json +3 -1
- package/_standalone/tsconfig.json +1 -1
- package/_standalone/tsconfig.tsbuildinfo +1 -1
- package/app/app/api/acp/detect/route.ts +29 -20
- package/app/app/api/agent-activity/route.ts +1 -1
- package/app/app/api/ask/route.ts +115 -31
- package/app/app/api/ask-sessions/route.ts +1 -0
- package/app/app/api/bootstrap/route.ts +1 -3
- package/app/app/api/file/route.ts +34 -4
- package/app/app/api/inbox/route.ts +61 -0
- package/app/app/api/settings/list-models/route.ts +73 -53
- package/app/app/api/settings/route.ts +46 -55
- package/app/app/api/settings/test-key/route.ts +57 -114
- package/app/app/api/setup/route.ts +31 -21
- package/app/app/api/sync/route.ts +122 -12
- package/app/app/api/update-check/route.ts +2 -2
- package/app/app/globals.css +11 -1
- package/app/app/layout.tsx +2 -3
- package/app/app/login/page.tsx +1 -1
- package/app/app/view/[...path]/ViewPageClient.tsx +10 -10
- package/app/app/view/[...path]/not-found.tsx +1 -1
- package/app/components/ActivityBar.tsx +26 -10
- package/app/components/AskFab.tsx +1 -1
- package/app/components/AskModal.tsx +1 -1
- package/app/components/Backlinks.tsx +1 -1
- package/app/components/CreateSpaceModal.tsx +7 -55
- package/app/components/DirView.tsx +93 -11
- package/app/components/EchoSpotlight.tsx +1 -1
- package/app/components/ExportModal.tsx +1 -1
- package/app/components/FileTree.tsx +64 -79
- package/app/components/FindInPage.tsx +1 -1
- package/app/components/GuideCard.tsx +1 -1
- package/app/components/HomeContent.tsx +21 -14
- package/app/components/ImportModal.tsx +1 -1
- package/app/components/KeyboardShortcuts.tsx +1 -1
- package/app/components/MarkdownView.tsx +11 -1
- package/app/components/OnboardingView.tsx +1 -1
- package/app/components/OrganizeToast.tsx +1 -1
- package/app/components/Panel.tsx +82 -4
- package/app/components/QuickSuggestion.tsx +1 -1
- package/app/components/RightAgentDetailPanel.tsx +2 -2
- package/app/components/RightAskPanel.tsx +58 -22
- package/app/components/SearchModal.tsx +1 -1
- package/app/components/Sidebar.tsx +1 -1
- package/app/components/SidebarLayout.tsx +52 -16
- package/app/components/SpaceInitToast.tsx +1 -1
- package/app/components/SyncStatusBar.tsx +2 -2
- package/app/components/SystemPulse.tsx +12 -6
- package/app/components/TableOfContents.tsx +86 -39
- package/app/components/TrashPageClient.tsx +1 -1
- package/app/components/UpdateOverlay.tsx +2 -2
- package/app/components/agents/AgentActivitySection.tsx +225 -0
- package/app/components/agents/AgentDetailContent.tsx +234 -3
- package/app/components/agents/AgentsContentPage.tsx +13 -2
- package/app/components/agents/AgentsMcpSection.tsx +7 -16
- package/app/components/agents/AgentsOverviewSection.tsx +28 -27
- package/app/components/agents/AgentsPanelA2aTab.tsx +1 -1
- package/app/components/agents/AgentsPanelSessionsTab.tsx +6 -1
- package/app/components/agents/AgentsSkillsSection.tsx +1 -1
- package/app/components/agents/DiscoverAgentModal.tsx +1 -1
- package/app/components/agents/RecentActivityFeed.tsx +49 -88
- package/app/components/agents/agent-activity-shared.tsx +110 -0
- package/app/components/agents/agents-content-model.ts +2 -2
- package/app/components/ask/AgentSelectorCapsule.tsx +1 -1
- package/app/components/ask/AskContent.tsx +332 -486
- package/app/components/ask/AskHeader.tsx +61 -0
- package/app/components/ask/FileChip.tsx +9 -5
- package/app/components/ask/MessageList.tsx +88 -21
- package/app/components/ask/ModeCapsule.tsx +180 -0
- package/app/components/ask/ProviderModelCapsule.tsx +284 -0
- package/app/components/ask/SessionHistory.tsx +63 -10
- package/app/components/ask/SessionTabBar.tsx +1 -1
- package/app/components/ask/ThinkingBlock.tsx +1 -1
- package/app/components/ask/ToolCallBlock.tsx +28 -24
- package/app/components/changes/ChangesBanner.tsx +1 -1
- package/app/components/changes/ChangesContentPage.tsx +1 -1
- package/app/components/echo/EchoInsightCollapsible.tsx +1 -1
- package/app/components/echo/EchoSegmentNav.tsx +1 -1
- package/app/components/echo/EchoSegmentPageClient.tsx +1 -1
- package/app/components/explore/ExploreContent.tsx +1 -1
- package/app/components/help/HelpContent.tsx +1 -1
- package/app/components/home/InboxSection.tsx +268 -0
- package/app/components/panels/AgentsPanel.tsx +3 -2
- package/app/components/panels/AgentsPanelHubNav.tsx +2 -6
- package/app/components/panels/DiscoverPanel.tsx +1 -1
- package/app/components/panels/EchoPanel.tsx +1 -1
- package/app/components/panels/EchoSidebarStats.tsx +1 -1
- package/app/components/panels/ImportHistoryPanel.tsx +1 -1
- package/app/components/panels/PanelHeader.tsx +1 -1
- package/app/components/panels/PluginsPanel.tsx +1 -1
- package/app/components/panels/SearchPanel.tsx +5 -2
- package/app/components/panels/SyncPopover.tsx +1 -1
- package/app/components/panels/WorkflowsPanel.tsx +1 -1
- package/app/components/renderers/agent-inspector/AgentInspectorRenderer.tsx +18 -0
- package/app/components/renderers/todo/TodoRenderer.tsx +489 -75
- package/app/components/settings/AiTab.tsx +198 -127
- package/app/components/settings/AppearanceTab.tsx +48 -50
- package/app/components/settings/KnowledgeTab.tsx +92 -27
- package/app/components/settings/McpAgentInstall.tsx +1 -1
- package/app/components/settings/McpSkillsSection.tsx +1 -1
- package/app/components/settings/McpTab.tsx +145 -7
- package/app/components/settings/PluginsTab.tsx +1 -1
- package/app/components/settings/SettingsContent.tsx +5 -2
- package/app/components/settings/SyncTab.tsx +615 -230
- package/app/components/settings/UninstallTab.tsx +1 -1
- package/app/components/settings/UpdateTab.tsx +373 -109
- package/app/components/settings/types.ts +4 -5
- package/app/components/setup/StepAI.tsx +70 -49
- package/app/components/setup/StepDots.tsx +1 -1
- package/app/components/setup/StepReview.tsx +176 -8
- package/app/components/setup/index.tsx +73 -39
- package/app/components/setup/types.ts +11 -8
- package/app/components/shared/ProviderSelect.tsx +134 -0
- package/app/components/walkthrough/WalkthroughOverlay.tsx +2 -2
- package/app/components/walkthrough/WalkthroughTooltip.tsx +2 -2
- package/app/components/walkthrough/index.ts +1 -1
- package/app/data/skills/mindos/SKILL.md +27 -12
- package/app/data/skills/mindos-zh/SKILL.md +27 -12
- package/app/hooks/useAcpDetection.ts +1 -1
- package/app/hooks/useAskChat.ts +248 -0
- package/app/hooks/useAskPanel.ts +24 -4
- package/app/hooks/useAskSession.ts +15 -0
- package/app/lib/acp/types.ts +1 -1
- package/app/lib/actions.ts +13 -0
- package/app/lib/agent/log.ts +2 -0
- package/app/lib/agent/model.ts +69 -81
- package/app/lib/agent/prompt.ts +27 -0
- package/app/lib/agent/providers.ts +299 -0
- package/app/lib/agent/tools.ts +26 -4
- package/app/lib/api.ts +3 -1
- package/app/lib/core/agent-audit-log.ts +7 -0
- package/app/lib/core/fs-ops.ts +9 -4
- package/app/lib/core/inbox.ts +181 -0
- package/app/lib/core/index.ts +4 -0
- package/app/lib/core/tree.ts +3 -0
- package/app/lib/core/types.ts +2 -0
- package/app/lib/fs.ts +26 -2
- package/app/lib/i18n/modules/ai-chat.ts +35 -13
- package/app/lib/i18n/modules/features.ts +2 -2
- package/app/lib/i18n/modules/knowledge.ts +82 -2
- package/app/lib/i18n/modules/navigation.ts +6 -2
- package/app/lib/i18n/modules/onboarding.ts +39 -9
- package/app/lib/i18n/modules/panels.ts +78 -29
- package/app/lib/i18n/modules/settings.ts +236 -20
- package/app/lib/inbox-upload.ts +93 -0
- package/app/lib/mcp-agents.ts +6 -7
- package/app/lib/renderers/index.ts +1 -2
- package/app/lib/settings-ai-client.ts +13 -12
- package/app/lib/settings.ts +48 -33
- package/app/lib/space-ai-init.ts +66 -0
- package/app/lib/stores/LocaleStoreInit.tsx +18 -0
- package/app/lib/stores/McpStoreInit.tsx +18 -0
- package/app/lib/stores/WalkthroughInit.tsx +20 -0
- package/app/lib/stores/locale-store.ts +55 -0
- package/app/lib/stores/mcp-store.ts +156 -0
- package/app/lib/stores/walkthrough-store.ts +118 -0
- package/app/lib/types.ts +20 -0
- package/app/package.json +3 -1
- package/app/tsconfig.json +1 -1
- package/bin/cli.js +46 -27
- package/bin/commands/file.js +7 -4
- package/bin/commands/space.js +4 -0
- package/bin/lib/mcp-agents.js +26 -2
- package/bin/lib/mcp-install.js +11 -3
- package/bin/lib/sync.js +140 -34
- package/mcp/README.md +2 -2
- package/mcp/dist/index.cjs +43 -43
- package/mcp/package.json +1 -1
- package/mcp/src/index.ts +77 -61
- package/package.json +1 -1
- package/scripts/build-runtime-archive.sh +113 -0
- package/scripts/setup.js +1 -1
- package/skills/mindos/SKILL.md +27 -12
- package/skills/mindos/references/preference-capture.md +4 -4
- package/skills/mindos/references/write-supplement.md +46 -4
- package/skills/mindos-zh/SKILL.md +27 -12
- package/skills/mindos-zh/references/preference-capture.md +4 -4
- package/skills/mindos-zh/references/write-supplement.md +47 -5
- package/templates/empty/INSTRUCTION.md +0 -1
- package/templates/en/INSTRUCTION.md +0 -1
- package/templates/template-generation-skill.md +0 -1
- package/templates/zh/INSTRUCTION.md +0 -1
- package/_standalone/.next/server/chunks/248.js +0 -15
- package/_standalone/.next/server/chunks/359.js +0 -2
- package/_standalone/.next/server/chunks/4931.js +0 -202
- package/_standalone/.next/server/chunks/7670.js +0 -1
- package/_standalone/.next/server/chunks/8407.js +0 -52
- package/_standalone/.next/server/chunks/9414.js +0 -11
- package/_standalone/.next/static/VAb8MoUUpoXjVJalRJogO/_buildManifest.js +0 -1
- package/_standalone/.next/static/chunks/1038-ed04d6651ec92312.js +0 -1
- package/_standalone/.next/static/chunks/1263-79beb8734dee7bbd.js +0 -25
- package/_standalone/.next/static/chunks/275-ebcaaedabe706903.js +0 -1
- package/_standalone/.next/static/chunks/5637-b97c869adf70c82e.js +0 -1
- package/_standalone/.next/static/chunks/5681-a53362a1cd629dc6.js +0 -1
- package/_standalone/.next/static/chunks/9602-35ca17b688f1a4fe.js +0 -1
- package/_standalone/.next/static/chunks/9670-d59e4d45ed705f58.js +0 -6
- package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/_global-error/page-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-519d4da1142db5ef.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/page-b709cf3103321609.js +0 -5
- package/_standalone/.next/static/chunks/app/api/a2a/agents/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/delegations/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/config/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/install/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/session/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/auth/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/backlinks/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/changes/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/export/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/import/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/files/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/git/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/graph/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/health/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/init/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/monitoring/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/recent-files/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/restart/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/search/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/skills/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/sync/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/tree-version/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/uninstall/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-check/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-status/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/api/workflows/route-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/changes/page-def5210095f8698d.js +0 -1
- package/_standalone/.next/static/chunks/app/echo/[segment]/page-be28eff31b1a186e.js +0 -11
- package/_standalone/.next/static/chunks/app/echo/page-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/explore/page-e4b8098dca200389.js +0 -4
- package/_standalone/.next/static/chunks/app/help/page-d5e57d73d94bad19.js +0 -1
- package/_standalone/.next/static/chunks/app/layout-aab90c2b4faf8d57.js +0 -173
- package/_standalone/.next/static/chunks/app/login/page-321875768b70938a.js +0 -1
- package/_standalone/.next/static/chunks/app/page-9a15cf85f0962c59.js +0 -7
- package/_standalone/.next/static/chunks/app/setup/page-01ab1f549d636057.js +0 -1
- package/_standalone/.next/static/chunks/app/trash/page-7df0139c6b0f87e0.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/not-found-f22c513bbc348cc8.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/page-35811d7e49e08157.js +0 -12
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d4762cc48529e566.js +0 -1
- package/_standalone/.next/static/chunks/webpack-3489a2b6c2882b0c.js +0 -1
- package/_standalone/.next/static/css/f16595bc58a16d5d.css +0 -1
- package/_standalone/components/walkthrough/WalkthroughProvider.tsx +0 -133
- package/_standalone/hooks/useMcpData.tsx +0 -169
- package/_standalone/lib/i18n-en.ts +0 -2
- package/_standalone/lib/i18n-zh.ts +0 -2
- package/_standalone/lib/types.ts +0 -70
- package/app/components/walkthrough/WalkthroughProvider.tsx +0 -133
- package/app/hooks/useMcpData.tsx +0 -169
- package/app/lib/LocaleContext.tsx +0 -60
- package/app/lib/i18n-en.ts +0 -2
- package/app/lib/i18n-zh.ts +0 -2
- /package/_standalone/.next/static/{VAb8MoUUpoXjVJalRJogO → rZLs1krFuduixvcVNe6q3}/_ssgManifest.js +0 -0
|
@@ -1,21 +1,263 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
4
|
-
import { RefreshCw, AlertCircle, CheckCircle2, Loader2, GitBranch, ExternalLink, Eye, EyeOff } from 'lucide-react';
|
|
5
|
-
import { SectionLabel, PrimaryButton, Input } from './Primitives';
|
|
3
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
4
|
+
import { RefreshCw, AlertCircle, CheckCircle2, Loader2, GitBranch, ExternalLink, Eye, EyeOff, Check, ChevronRight, FileX2 } from 'lucide-react';
|
|
5
|
+
import { SectionLabel, PrimaryButton, Input, Field, SettingCard } from './Primitives';
|
|
6
6
|
import { apiFetch } from '@/lib/api';
|
|
7
7
|
import type { SyncStatus, SyncTabProps } from './types';
|
|
8
8
|
import type { Messages } from '@/lib/i18n';
|
|
9
9
|
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
export function timeAgo(iso: string | null | undefined): string {
|
|
13
|
-
if (!iso) return 'never';
|
|
10
|
+
export function timeAgo(iso: string | null | undefined, syncT?: Record<string, unknown>): string {
|
|
11
|
+
if (!iso) return (syncT?.timeNever as string) ?? 'never';
|
|
14
12
|
const diff = Date.now() - new Date(iso).getTime();
|
|
15
|
-
if (diff < 60000) return 'just now';
|
|
16
|
-
|
|
17
|
-
if (diff <
|
|
18
|
-
|
|
13
|
+
if (diff < 60000) return (syncT?.timeJustNow as string) ?? 'just now';
|
|
14
|
+
const m = Math.floor(diff / 60000);
|
|
15
|
+
if (diff < 3600000) return (syncT?.timeMinAgo as ((n: number) => string))?.(m) ?? `${m}m ago`;
|
|
16
|
+
const h = Math.floor(diff / 3600000);
|
|
17
|
+
if (diff < 86400000) return (syncT?.timeHourAgo as ((n: number) => string))?.(h) ?? `${h}h ago`;
|
|
18
|
+
const d = Math.floor(diff / 86400000);
|
|
19
|
+
return (syncT?.timeDayAgo as ((n: number) => string))?.(d) ?? `${d}d ago`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Classify a raw sync error and return a user-friendly message with action hint. */
|
|
23
|
+
function formatSyncError(raw: string, syncT?: Record<string, unknown>): string {
|
|
24
|
+
const hint = getSyncErrorHint(raw, undefined, syncT);
|
|
25
|
+
return hint ? `${raw}\n${hint}` : raw;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Return an actionable hint for common sync errors. */
|
|
29
|
+
function getSyncErrorHint(error: string, remote?: string | null, syncT?: Record<string, unknown>): string {
|
|
30
|
+
const lower = error.toLowerCase();
|
|
31
|
+
|
|
32
|
+
// SSH authentication failures
|
|
33
|
+
if (lower.includes('permission denied') || lower.includes('publickey')) {
|
|
34
|
+
return (syncT?.hintSshAuth as string) ?? 'SSH key may not be configured. Run: ssh-keygen -t ed25519 && ssh -T git@github.com';
|
|
35
|
+
}
|
|
36
|
+
// SSH host key / connection
|
|
37
|
+
if (lower.includes('host key') || lower.includes('known_hosts') || lower.includes('fingerprint')) {
|
|
38
|
+
return (syncT?.hintSshHost as string) ?? 'Run: ssh-keyscan github.com >> ~/.ssh/known_hosts';
|
|
39
|
+
}
|
|
40
|
+
// HTTPS auth failures
|
|
41
|
+
if (lower.includes('authentication failed') || lower.includes('invalid credentials') || lower.includes('401') || lower.includes('403')) {
|
|
42
|
+
return (syncT?.hintHttpsAuth as string) ?? 'Access token may be expired or missing. Check Settings → Developer settings → Personal access tokens.';
|
|
43
|
+
}
|
|
44
|
+
// Network / timeout
|
|
45
|
+
if (lower.includes('timed out') || lower.includes('timeout') || lower.includes('could not resolve')) {
|
|
46
|
+
return (syncT?.hintNetwork as string) ?? 'Check your network connection and try again.';
|
|
47
|
+
}
|
|
48
|
+
// Remote not found
|
|
49
|
+
if (lower.includes('not found') || lower.includes('does not exist') || lower.includes('repository not found')) {
|
|
50
|
+
return (syncT?.hintNotFound as string) ?? 'Repository not found. Check the URL and ensure the repo exists.';
|
|
51
|
+
}
|
|
52
|
+
// Push rejected (non-fast-forward)
|
|
53
|
+
if (lower.includes('non-fast-forward') || lower.includes('rejected') || lower.includes('fetch first')) {
|
|
54
|
+
return (syncT?.hintPushRejected as string) ?? 'Remote has changes. Click "Sync Now" to pull and retry.';
|
|
55
|
+
}
|
|
56
|
+
// Merge conflicts
|
|
57
|
+
if (lower.includes('conflict') || lower.includes('merge')) {
|
|
58
|
+
return (syncT?.hintConflict as string) ?? 'Merge conflict detected. Check the Conflicts section below.';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* ── Conflict Row ──────────────────────────────────────────────── */
|
|
65
|
+
|
|
66
|
+
function ConflictRow({ file, time, syncT, onResolved }: {
|
|
67
|
+
file: string; time: string; syncT?: Record<string, unknown>; onResolved: () => void;
|
|
68
|
+
}) {
|
|
69
|
+
const [resolving, setResolving] = useState<string | null>(null);
|
|
70
|
+
const [expanded, setExpanded] = useState(false);
|
|
71
|
+
const [preview, setPreview] = useState<{ local: string; remote: string } | null>(null);
|
|
72
|
+
const [loadingPreview, setLoadingPreview] = useState(false);
|
|
73
|
+
|
|
74
|
+
const togglePreview = async () => {
|
|
75
|
+
if (expanded) { setExpanded(false); return; }
|
|
76
|
+
if (!preview) {
|
|
77
|
+
setLoadingPreview(true);
|
|
78
|
+
try {
|
|
79
|
+
const data = await apiFetch<{ local: string; remote: string }>('/api/sync', {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: { 'Content-Type': 'application/json' },
|
|
82
|
+
body: JSON.stringify({ action: 'conflict-preview', remote: file }),
|
|
83
|
+
});
|
|
84
|
+
setPreview(data);
|
|
85
|
+
} catch { /* ignore */ }
|
|
86
|
+
setLoadingPreview(false);
|
|
87
|
+
}
|
|
88
|
+
setExpanded(true);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const handleResolve = async (strategy: 'keep-local' | 'keep-remote') => {
|
|
92
|
+
setResolving(strategy === 'keep-local' ? 'local' : 'remote');
|
|
93
|
+
try {
|
|
94
|
+
await apiFetch('/api/sync', {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
headers: { 'Content-Type': 'application/json' },
|
|
97
|
+
body: JSON.stringify({ action: 'resolve-conflict', remote: file, branch: strategy }),
|
|
98
|
+
});
|
|
99
|
+
onResolved();
|
|
100
|
+
} catch {
|
|
101
|
+
setResolving(null);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<div className="rounded-lg border border-border/50 overflow-hidden">
|
|
107
|
+
{/* Header row */}
|
|
108
|
+
<div className="flex items-center gap-2 p-2 text-xs bg-muted/20">
|
|
109
|
+
<AlertCircle size={12} className="text-error shrink-0" />
|
|
110
|
+
<button
|
|
111
|
+
type="button"
|
|
112
|
+
onClick={togglePreview}
|
|
113
|
+
className="font-mono truncate hover:text-foreground hover:underline transition-colors flex-1 min-w-0 text-left"
|
|
114
|
+
title={(syncT?.viewDiff as string) ?? 'View differences'}
|
|
115
|
+
>
|
|
116
|
+
<ChevronRight size={11} className={`inline mr-1 transition-transform ${expanded ? 'rotate-90' : ''}`} />
|
|
117
|
+
{file}
|
|
118
|
+
</button>
|
|
119
|
+
<span className="text-muted-foreground shrink-0">{timeAgo(time, syncT)}</span>
|
|
120
|
+
<div className="flex items-center gap-1 shrink-0">
|
|
121
|
+
<button
|
|
122
|
+
type="button"
|
|
123
|
+
onClick={() => handleResolve('keep-local')}
|
|
124
|
+
disabled={!!resolving}
|
|
125
|
+
className="px-2 py-0.5 rounded border border-border text-2xs hover:bg-muted transition-colors disabled:opacity-40"
|
|
126
|
+
title={(syncT?.keepLocalHint as string) ?? 'Keep this device\'s version'}
|
|
127
|
+
>
|
|
128
|
+
{resolving === 'local' ? <Loader2 size={10} className="animate-spin" /> : ((syncT?.keepLocal as string) ?? 'Keep local')}
|
|
129
|
+
</button>
|
|
130
|
+
<button
|
|
131
|
+
type="button"
|
|
132
|
+
onClick={() => handleResolve('keep-remote')}
|
|
133
|
+
disabled={!!resolving}
|
|
134
|
+
className="px-2 py-0.5 rounded border border-border text-2xs hover:bg-muted transition-colors disabled:opacity-40"
|
|
135
|
+
title={(syncT?.keepRemoteHint as string) ?? 'Replace with remote version'}
|
|
136
|
+
>
|
|
137
|
+
{resolving === 'remote' ? <Loader2 size={10} className="animate-spin" /> : ((syncT?.keepRemote as string) ?? 'Keep remote')}
|
|
138
|
+
</button>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
{/* Diff preview */}
|
|
143
|
+
{expanded && (
|
|
144
|
+
<div className="border-t border-border/50">
|
|
145
|
+
{loadingPreview ? (
|
|
146
|
+
<div className="flex justify-center py-3">
|
|
147
|
+
<Loader2 size={13} className="animate-spin text-muted-foreground" />
|
|
148
|
+
</div>
|
|
149
|
+
) : preview ? (
|
|
150
|
+
<div className="grid grid-cols-2 divide-x divide-border/50 text-2xs font-mono max-h-60 overflow-auto">
|
|
151
|
+
<div className="p-2">
|
|
152
|
+
<div className="text-muted-foreground mb-1 font-sans text-xs font-medium">
|
|
153
|
+
{(syncT?.localVersion as string) ?? 'Local (this device)'}
|
|
154
|
+
</div>
|
|
155
|
+
<pre className="whitespace-pre-wrap text-foreground/80 leading-relaxed">{preview.local || ((syncT?.emptyFile as string) ?? '(empty)')}</pre>
|
|
156
|
+
</div>
|
|
157
|
+
<div className="p-2">
|
|
158
|
+
<div className="text-muted-foreground mb-1 font-sans text-xs font-medium">
|
|
159
|
+
{(syncT?.remoteVersion as string) ?? 'Remote'}
|
|
160
|
+
</div>
|
|
161
|
+
<pre className="whitespace-pre-wrap text-foreground/80 leading-relaxed">{preview.remote || ((syncT?.emptyFile as string) ?? '(empty)')}</pre>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
) : null}
|
|
165
|
+
</div>
|
|
166
|
+
)}
|
|
167
|
+
</div>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* ── Gitignore Editor ──────────────────────────────────────────── */
|
|
172
|
+
|
|
173
|
+
function GitignoreEditor({ syncT }: { syncT?: Record<string, unknown> }) {
|
|
174
|
+
const [open, setOpen] = useState(false);
|
|
175
|
+
const [content, setContent] = useState('');
|
|
176
|
+
const [saved, setSaved] = useState('');
|
|
177
|
+
const [loading, setLoading] = useState(false);
|
|
178
|
+
const [saveOk, setSaveOk] = useState(false);
|
|
179
|
+
const loaded = useRef(false);
|
|
180
|
+
|
|
181
|
+
const dirty = content !== saved;
|
|
182
|
+
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
if (!open || loaded.current) return;
|
|
185
|
+
loaded.current = true;
|
|
186
|
+
setLoading(true);
|
|
187
|
+
apiFetch<{ content: string }>('/api/sync', {
|
|
188
|
+
method: 'POST',
|
|
189
|
+
headers: { 'Content-Type': 'application/json' },
|
|
190
|
+
body: JSON.stringify({ action: 'gitignore-get' }),
|
|
191
|
+
}).then(data => {
|
|
192
|
+
setContent(data.content);
|
|
193
|
+
setSaved(data.content);
|
|
194
|
+
}).catch(() => {}).finally(() => setLoading(false));
|
|
195
|
+
}, [open]);
|
|
196
|
+
|
|
197
|
+
const handleSave = async () => {
|
|
198
|
+
try {
|
|
199
|
+
await apiFetch('/api/sync', {
|
|
200
|
+
method: 'POST',
|
|
201
|
+
headers: { 'Content-Type': 'application/json' },
|
|
202
|
+
body: JSON.stringify({ action: 'gitignore-save', content }),
|
|
203
|
+
});
|
|
204
|
+
setSaved(content);
|
|
205
|
+
setSaveOk(true);
|
|
206
|
+
setTimeout(() => setSaveOk(false), 2000);
|
|
207
|
+
} catch {}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<div className="pt-2 border-t border-border/50">
|
|
212
|
+
<button
|
|
213
|
+
type="button"
|
|
214
|
+
onClick={() => setOpen(!open)}
|
|
215
|
+
className="flex items-center gap-2 w-full text-left text-sm text-muted-foreground hover:text-foreground transition-colors py-1"
|
|
216
|
+
>
|
|
217
|
+
<ChevronRight size={14} className={`shrink-0 transition-transform ${open ? 'rotate-90' : ''}`} />
|
|
218
|
+
<FileX2 size={13} className="shrink-0" />
|
|
219
|
+
<span>{(syncT?.gitignoreTitle as string) ?? 'Excluded files'}</span>
|
|
220
|
+
<span className="text-2xs opacity-50">.gitignore</span>
|
|
221
|
+
</button>
|
|
222
|
+
|
|
223
|
+
{open && (
|
|
224
|
+
<div className="mt-2 space-y-2">
|
|
225
|
+
{loading ? (
|
|
226
|
+
<div className="flex justify-center py-4">
|
|
227
|
+
<Loader2 size={14} className="animate-spin text-muted-foreground" />
|
|
228
|
+
</div>
|
|
229
|
+
) : (
|
|
230
|
+
<>
|
|
231
|
+
<textarea
|
|
232
|
+
value={content}
|
|
233
|
+
onChange={e => setContent(e.target.value)}
|
|
234
|
+
rows={8}
|
|
235
|
+
className="w-full rounded-lg border border-border bg-background px-3 py-2 text-xs font-mono leading-relaxed text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring resize-y"
|
|
236
|
+
placeholder={(syncT?.gitignorePlaceholder as string) ?? '# Files to exclude from sync\n*.tmp\nsecret/'}
|
|
237
|
+
spellCheck={false}
|
|
238
|
+
/>
|
|
239
|
+
<div className="flex items-center gap-2">
|
|
240
|
+
{dirty && (
|
|
241
|
+
<button
|
|
242
|
+
type="button"
|
|
243
|
+
onClick={handleSave}
|
|
244
|
+
className="flex items-center gap-1.5 px-3 py-1 text-xs rounded-lg bg-[var(--amber)] text-[var(--amber-foreground)] hover:opacity-90 transition-opacity"
|
|
245
|
+
>
|
|
246
|
+
{(syncT?.gitignoreSave as string) ?? 'Save'}
|
|
247
|
+
</button>
|
|
248
|
+
)}
|
|
249
|
+
{saveOk && (
|
|
250
|
+
<span className="flex items-center gap-1 text-xs text-success">
|
|
251
|
+
<Check size={12} /> {(syncT?.gitignoreSaved as string) ?? 'Saved'}
|
|
252
|
+
</span>
|
|
253
|
+
)}
|
|
254
|
+
</div>
|
|
255
|
+
</>
|
|
256
|
+
)}
|
|
257
|
+
</div>
|
|
258
|
+
)}
|
|
259
|
+
</div>
|
|
260
|
+
);
|
|
19
261
|
}
|
|
20
262
|
|
|
21
263
|
/* ── Empty state — GUI sync init form ─────────────────────────── */
|
|
@@ -27,22 +269,32 @@ function isValidGitUrl(url: string): 'https' | 'ssh' | false {
|
|
|
27
269
|
}
|
|
28
270
|
|
|
29
271
|
function SyncEmptyState({ t, onInitComplete }: { t: Messages; onInitComplete: () => void }) {
|
|
30
|
-
const syncT = t.settings?.sync;
|
|
272
|
+
const syncT = t.settings?.sync as Record<string, unknown> | undefined;
|
|
31
273
|
|
|
32
274
|
const [remoteUrl, setRemoteUrl] = useState('');
|
|
33
275
|
const [token, setToken] = useState('');
|
|
34
276
|
const [branch, setBranch] = useState('main');
|
|
35
277
|
const [showToken, setShowToken] = useState(false);
|
|
36
|
-
const [
|
|
278
|
+
const [connectStep, setConnectStep] = useState<number>(-1); // -1=idle, 0..3=steps, 4=done
|
|
37
279
|
const [error, setError] = useState('');
|
|
280
|
+
const stepTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
281
|
+
|
|
282
|
+
const connecting = connectStep >= 0 && connectStep < 4;
|
|
38
283
|
|
|
39
284
|
const urlType = remoteUrl.trim() ? isValidGitUrl(remoteUrl.trim()) : null;
|
|
40
285
|
const isValid = urlType === 'https' || urlType === 'ssh';
|
|
41
286
|
const showTokenField = urlType === 'https';
|
|
42
287
|
|
|
43
288
|
const handleConnect = async () => {
|
|
44
|
-
|
|
289
|
+
setConnectStep(0);
|
|
45
290
|
setError('');
|
|
291
|
+
|
|
292
|
+
// Progress steps on a timer (visual only — actual work is one API call)
|
|
293
|
+
const advanceStep = (step: number, delayMs: number) =>
|
|
294
|
+
setTimeout(() => setConnectStep(s => s >= 0 && s < 4 ? step : s), delayMs);
|
|
295
|
+
stepTimerRef.current = advanceStep(1, 2000); // "Authenticating..." → "Syncing data..."
|
|
296
|
+
const t2 = advanceStep(2, 5000); // → "Almost done..."
|
|
297
|
+
|
|
46
298
|
try {
|
|
47
299
|
await apiFetch('/api/sync', {
|
|
48
300
|
method: 'POST',
|
|
@@ -53,128 +305,171 @@ function SyncEmptyState({ t, onInitComplete }: { t: Messages; onInitComplete: ()
|
|
|
53
305
|
token: token.trim() || undefined,
|
|
54
306
|
branch: branch.trim() || 'main',
|
|
55
307
|
}),
|
|
308
|
+
timeout: 120_000,
|
|
56
309
|
});
|
|
57
|
-
|
|
310
|
+
setConnectStep(4); // success
|
|
311
|
+
setTimeout(() => onInitComplete(), 600);
|
|
58
312
|
} catch (err: unknown) {
|
|
59
|
-
|
|
60
|
-
|
|
313
|
+
let msg = err instanceof Error ? err.message : 'Connection failed';
|
|
314
|
+
if (msg.includes('timed out')) {
|
|
315
|
+
msg = (syncT?.timeoutError as string) ?? 'Connection timed out. The remote repository may be large or the network is slow. Please try again.';
|
|
316
|
+
}
|
|
317
|
+
const hint = getSyncErrorHint(msg, remoteUrl, syncT);
|
|
318
|
+
setError(hint ? `${msg}\n${hint}` : msg);
|
|
319
|
+
setConnectStep(-1);
|
|
61
320
|
} finally {
|
|
62
|
-
|
|
321
|
+
if (stepTimerRef.current) clearTimeout(stepTimerRef.current);
|
|
322
|
+
clearTimeout(t2);
|
|
63
323
|
}
|
|
64
324
|
};
|
|
65
325
|
|
|
326
|
+
const connectSteps = [
|
|
327
|
+
(syncT?.stepConnecting as string) ?? 'Connecting to remote...',
|
|
328
|
+
(syncT?.stepAuthenticating as string) ?? 'Authenticating...',
|
|
329
|
+
(syncT?.stepSyncing as string) ?? 'Syncing data...',
|
|
330
|
+
(syncT?.stepAlmostDone as string) ?? 'Almost done...',
|
|
331
|
+
];
|
|
332
|
+
|
|
66
333
|
return (
|
|
67
|
-
<div className="space-y-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
334
|
+
<div className="space-y-4">
|
|
335
|
+
<SettingCard
|
|
336
|
+
icon={<GitBranch size={15} />}
|
|
337
|
+
title={(syncT?.emptyTitle as string) ?? 'Cross-device Sync'}
|
|
338
|
+
description={(syncT?.emptyDesc as string) ?? 'Automatically sync your knowledge base across devices via Git.'}
|
|
339
|
+
>
|
|
340
|
+
{/* Git Remote URL */}
|
|
341
|
+
<Field
|
|
342
|
+
label={(syncT?.remoteUrl as string) ?? 'Git Remote URL'}
|
|
343
|
+
hint={urlType === 'ssh'
|
|
344
|
+
? ((syncT?.sshHint as string) ?? 'Requires SSH key on this machine. Verify with: ssh -T git@github.com')
|
|
345
|
+
: undefined
|
|
346
|
+
}
|
|
347
|
+
>
|
|
348
|
+
<Input
|
|
349
|
+
type="text"
|
|
350
|
+
value={remoteUrl}
|
|
351
|
+
onChange={e => { setRemoteUrl(e.target.value); setError(''); }}
|
|
352
|
+
placeholder="git@github.com:user/repo.git"
|
|
353
|
+
className={`font-mono ${remoteUrl.trim() && !isValid ? 'border-destructive' : ''}`}
|
|
354
|
+
/>
|
|
355
|
+
{!remoteUrl.trim() && (
|
|
356
|
+
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground mt-1.5">
|
|
357
|
+
<span><code className="text-foreground/60 bg-muted/60 px-1 py-0.5 rounded text-2xs">SSH</code> {(syncT?.sshBrief as string) ?? 'one-time key setup, no token needed'}</span>
|
|
358
|
+
<span><code className="text-foreground/60 bg-muted/60 px-1 py-0.5 rounded text-2xs">HTTPS</code> {(syncT?.httpsBrief as string) ?? 'works anywhere, token recommended'}</span>
|
|
359
|
+
</div>
|
|
360
|
+
)}
|
|
361
|
+
{remoteUrl.trim() && !isValid && (
|
|
362
|
+
<p className="text-xs text-destructive mt-1">
|
|
363
|
+
{(syncT?.invalidUrl as string) ?? 'Invalid Git URL — use HTTPS (https://...) or SSH (git@...)'}
|
|
364
|
+
</p>
|
|
365
|
+
)}
|
|
366
|
+
</Field>
|
|
82
367
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
368
|
+
{/* Access Token (HTTPS only) */}
|
|
369
|
+
{showTokenField && (
|
|
370
|
+
<Field
|
|
371
|
+
label={<>{(syncT?.accessToken as string) ?? 'Access Token'} <span className="text-muted-foreground font-normal">{(syncT?.optional as string) ?? '(optional, for private repos)'}</span></>}
|
|
372
|
+
hint={undefined}
|
|
373
|
+
>
|
|
374
|
+
<div className="relative">
|
|
375
|
+
<Input
|
|
376
|
+
type={showToken ? 'text' : 'password'}
|
|
377
|
+
value={token}
|
|
378
|
+
onChange={e => setToken(e.target.value)}
|
|
379
|
+
placeholder="ghp_xxxxxxxxxxxx"
|
|
380
|
+
className="pr-9 font-mono"
|
|
381
|
+
/>
|
|
382
|
+
<button
|
|
383
|
+
type="button"
|
|
384
|
+
onClick={() => setShowToken(!showToken)}
|
|
385
|
+
className="absolute right-2 top-1/2 -translate-y-1/2 p-0.5 rounded hover:bg-muted text-muted-foreground transition-colors"
|
|
386
|
+
>
|
|
387
|
+
{showToken ? <EyeOff size={14} /> : <Eye size={14} />}
|
|
388
|
+
</button>
|
|
389
|
+
</div>
|
|
390
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
391
|
+
{(syncT?.tokenHint as string) ?? 'GitHub:'}{' '}
|
|
392
|
+
<a
|
|
393
|
+
href="https://github.com/settings/tokens/new?scopes=repo&description=MindOS+Sync"
|
|
394
|
+
target="_blank"
|
|
395
|
+
rel="noopener noreferrer"
|
|
396
|
+
className="underline hover:text-foreground transition-colors"
|
|
397
|
+
>
|
|
398
|
+
{(syncT?.tokenLink as string) ?? 'Create a token (repo scope)'}
|
|
399
|
+
</a>
|
|
400
|
+
</p>
|
|
401
|
+
</Field>
|
|
99
402
|
)}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
403
|
+
|
|
404
|
+
{/* Branch */}
|
|
405
|
+
<Field label={(syncT?.branchLabel as string) ?? 'Branch'}>
|
|
406
|
+
<Input
|
|
407
|
+
type="text"
|
|
408
|
+
value={branch}
|
|
409
|
+
onChange={e => setBranch(e.target.value)}
|
|
410
|
+
placeholder="main"
|
|
411
|
+
className="max-w-[200px] font-mono"
|
|
412
|
+
/>
|
|
413
|
+
</Field>
|
|
414
|
+
|
|
415
|
+
{/* Connect button + progress */}
|
|
416
|
+
{!connecting && connectStep !== 4 && (
|
|
417
|
+
<PrimaryButton
|
|
418
|
+
onClick={handleConnect}
|
|
419
|
+
disabled={!isValid}
|
|
420
|
+
className="flex items-center gap-2"
|
|
421
|
+
>
|
|
422
|
+
{(syncT?.connectButton as string) ?? 'Connect & Start Sync'}
|
|
423
|
+
</PrimaryButton>
|
|
105
424
|
)}
|
|
106
|
-
</div>
|
|
107
425
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
426
|
+
{(connecting || connectStep === 4) && (
|
|
427
|
+
<div className="space-y-2 py-1">
|
|
428
|
+
{connectSteps.map((label, i) => {
|
|
429
|
+
const isDone = connectStep > i || connectStep === 4;
|
|
430
|
+
const isActive = connectStep === i && connectStep < 4;
|
|
431
|
+
if (connectStep < i && connectStep < 4) return null; // not yet
|
|
432
|
+
return (
|
|
433
|
+
<div key={i} className="flex items-center gap-2 text-xs">
|
|
434
|
+
{isDone
|
|
435
|
+
? <Check size={13} className="text-success shrink-0" />
|
|
436
|
+
: <Loader2 size={13} className="animate-spin text-muted-foreground shrink-0" />
|
|
437
|
+
}
|
|
438
|
+
<span className={isDone ? 'text-success' : isActive ? 'text-foreground' : 'text-muted-foreground'}>
|
|
439
|
+
{label}
|
|
440
|
+
</span>
|
|
441
|
+
</div>
|
|
442
|
+
);
|
|
443
|
+
})}
|
|
444
|
+
{connectStep === 4 && (
|
|
445
|
+
<div className="flex items-center gap-2 text-xs">
|
|
446
|
+
<CheckCircle2 size={13} className="text-success shrink-0" />
|
|
447
|
+
<span className="text-success font-medium">{(syncT?.stepDone as string) ?? 'Sync configured successfully!'}</span>
|
|
448
|
+
</div>
|
|
449
|
+
)}
|
|
130
450
|
</div>
|
|
131
|
-
|
|
132
|
-
{syncT?.tokenHint ?? 'GitHub: Settings → Developer settings → Personal access tokens → repo scope'}
|
|
133
|
-
</p>
|
|
134
|
-
</div>
|
|
135
|
-
)}
|
|
136
|
-
|
|
137
|
-
{/* Branch */}
|
|
138
|
-
<div className="space-y-1.5">
|
|
139
|
-
<label className="text-sm font-medium text-foreground block">
|
|
140
|
-
{syncT?.branchLabel ?? 'Branch'}
|
|
141
|
-
</label>
|
|
142
|
-
<Input
|
|
143
|
-
type="text"
|
|
144
|
-
value={branch}
|
|
145
|
-
onChange={e => setBranch(e.target.value)}
|
|
146
|
-
placeholder="main"
|
|
147
|
-
className="max-w-[200px] font-mono"
|
|
148
|
-
/>
|
|
149
|
-
</div>
|
|
451
|
+
)}
|
|
150
452
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
{/* Error */}
|
|
164
|
-
{error && (
|
|
165
|
-
<div className="flex items-start gap-2 text-xs p-3 rounded-lg bg-destructive/10 text-destructive" role="alert" aria-live="polite">
|
|
166
|
-
<AlertCircle size={13} className="shrink-0 mt-0.5" />
|
|
167
|
-
<span>{error}</span>
|
|
168
|
-
</div>
|
|
169
|
-
)}
|
|
453
|
+
{/* Error */}
|
|
454
|
+
{error && (
|
|
455
|
+
<div className="flex items-start gap-2 text-xs p-3 rounded-lg bg-destructive/10 text-destructive" role="alert" aria-live="polite">
|
|
456
|
+
<AlertCircle size={13} className="shrink-0 mt-0.5" />
|
|
457
|
+
<div className="space-y-1">
|
|
458
|
+
{error.split('\n').map((line, i) => (
|
|
459
|
+
<span key={i} className={`block ${i > 0 ? 'text-destructive/70' : ''}`}>{line}</span>
|
|
460
|
+
))}
|
|
461
|
+
</div>
|
|
462
|
+
</div>
|
|
463
|
+
)}
|
|
464
|
+
</SettingCard>
|
|
170
465
|
|
|
171
466
|
{/* Features */}
|
|
172
|
-
<div className="grid grid-cols-2 gap-2 text-xs text-muted-foreground
|
|
467
|
+
<div className="grid grid-cols-2 gap-2 text-xs text-muted-foreground px-5">
|
|
173
468
|
{[
|
|
174
|
-
syncT?.featureAutoCommit ?? 'Auto-commit on save',
|
|
175
|
-
syncT?.featureAutoPull ?? 'Auto-pull from remote',
|
|
176
|
-
syncT?.featureConflict ?? 'Conflict detection',
|
|
177
|
-
syncT?.featureMultiDevice ?? 'Works across devices',
|
|
469
|
+
(syncT?.featureAutoCommit as string) ?? 'Auto-commit on save',
|
|
470
|
+
(syncT?.featureAutoPull as string) ?? 'Auto-pull from remote',
|
|
471
|
+
(syncT?.featureConflict as string) ?? 'Conflict detection',
|
|
472
|
+
(syncT?.featureMultiDevice as string) ?? 'Works across devices',
|
|
178
473
|
].map((f, i) => (
|
|
179
474
|
<div key={i} className="flex items-center gap-1.5">
|
|
180
475
|
<CheckCircle2 size={11} className="text-success/60 shrink-0" />
|
|
@@ -189,6 +484,7 @@ function SyncEmptyState({ t, onInitComplete }: { t: Messages; onInitComplete: ()
|
|
|
189
484
|
/* ── Main SyncTab ──────────────────────────────────────────────── */
|
|
190
485
|
|
|
191
486
|
export function SyncTab({ t }: SyncTabProps) {
|
|
487
|
+
const syncT = t.settings?.sync as Record<string, unknown> | undefined;
|
|
192
488
|
const [status, setStatus] = useState<SyncStatus | null>(null);
|
|
193
489
|
const [loading, setLoading] = useState(true);
|
|
194
490
|
const [syncing, setSyncing] = useState(false);
|
|
@@ -197,10 +493,12 @@ export function SyncTab({ t }: SyncTabProps) {
|
|
|
197
493
|
|
|
198
494
|
const fetchStatus = useCallback(async () => {
|
|
199
495
|
try {
|
|
200
|
-
const data = await apiFetch<SyncStatus>('/api/sync');
|
|
496
|
+
const data = await apiFetch<SyncStatus>('/api/sync', { timeout: 10000 });
|
|
201
497
|
setStatus(data);
|
|
202
498
|
} catch {
|
|
203
|
-
|
|
499
|
+
// Keep existing status on refresh failure (don't flash init form during recompile)
|
|
500
|
+
// Only set null if we never had a status (first load)
|
|
501
|
+
setStatus(prev => prev ?? null);
|
|
204
502
|
} finally {
|
|
205
503
|
setLoading(false);
|
|
206
504
|
}
|
|
@@ -216,11 +514,13 @@ export function SyncTab({ t }: SyncTabProps) {
|
|
|
216
514
|
method: 'POST',
|
|
217
515
|
headers: { 'Content-Type': 'application/json' },
|
|
218
516
|
body: JSON.stringify({ action: 'now' }),
|
|
517
|
+
timeout: 120_000, // sync can take 60s+ for large repos
|
|
219
518
|
});
|
|
220
|
-
setMessage({ type: 'success', text: 'Sync complete' });
|
|
519
|
+
setMessage({ type: 'success', text: (syncT?.syncComplete as string) ?? 'Sync complete' });
|
|
221
520
|
await fetchStatus();
|
|
222
|
-
} catch {
|
|
223
|
-
|
|
521
|
+
} catch (err: unknown) {
|
|
522
|
+
const raw = err instanceof Error ? err.message : 'Sync failed';
|
|
523
|
+
setMessage({ type: 'error', text: formatSyncError(raw, syncT) });
|
|
224
524
|
} finally {
|
|
225
525
|
setSyncing(false);
|
|
226
526
|
setTimeout(() => setMessage(null), 3000);
|
|
@@ -239,9 +539,26 @@ export function SyncTab({ t }: SyncTabProps) {
|
|
|
239
539
|
body: JSON.stringify({ action }),
|
|
240
540
|
});
|
|
241
541
|
await fetchStatus();
|
|
242
|
-
setMessage({ type: 'success', text: status.enabled ? 'Auto-sync disabled' : 'Auto-sync enabled' });
|
|
542
|
+
setMessage({ type: 'success', text: status.enabled ? ((syncT?.autoSyncDisabled as string) ?? 'Auto-sync disabled') : ((syncT?.autoSyncEnabled as string) ?? 'Auto-sync enabled') });
|
|
243
543
|
} catch {
|
|
244
|
-
setMessage({ type: 'error', text: 'Failed to toggle sync' });
|
|
544
|
+
setMessage({ type: 'error', text: (syncT?.toggleFailed as string) ?? 'Failed to toggle sync' });
|
|
545
|
+
} finally {
|
|
546
|
+
setToggling(false);
|
|
547
|
+
setTimeout(() => setMessage(null), 3000);
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
const handleReset = async () => {
|
|
552
|
+
setToggling(true);
|
|
553
|
+
try {
|
|
554
|
+
await apiFetch('/api/sync', {
|
|
555
|
+
method: 'POST',
|
|
556
|
+
headers: { 'Content-Type': 'application/json' },
|
|
557
|
+
body: JSON.stringify({ action: 'reset' }),
|
|
558
|
+
});
|
|
559
|
+
await fetchStatus();
|
|
560
|
+
} catch {
|
|
561
|
+
setMessage({ type: 'error', text: (syncT?.resetFailed as string) ?? 'Failed to reset sync configuration' });
|
|
245
562
|
} finally {
|
|
246
563
|
setToggling(false);
|
|
247
564
|
setTimeout(() => setMessage(null), 3000);
|
|
@@ -260,121 +577,189 @@ export function SyncTab({ t }: SyncTabProps) {
|
|
|
260
577
|
return <SyncEmptyState t={t} onInitComplete={fetchStatus} />;
|
|
261
578
|
}
|
|
262
579
|
|
|
580
|
+
// Broken state: config says enabled but repo/remote is missing
|
|
581
|
+
if (status.needsSetup) {
|
|
582
|
+
return (
|
|
583
|
+
<div className="space-y-6">
|
|
584
|
+
<div className="flex items-start gap-3 p-4 rounded-lg bg-destructive/10">
|
|
585
|
+
<AlertCircle size={18} className="text-destructive shrink-0 mt-0.5" />
|
|
586
|
+
<div className="space-y-2">
|
|
587
|
+
<h3 className="text-sm font-medium text-destructive">
|
|
588
|
+
{(syncT?.brokenTitle as string) ?? 'Sync configuration is broken'}
|
|
589
|
+
</h3>
|
|
590
|
+
<p className="text-xs text-destructive/80">
|
|
591
|
+
{status.lastError || ((syncT?.brokenDesc as string) ?? 'The git repository or remote is missing. Reset to re-configure.')}
|
|
592
|
+
</p>
|
|
593
|
+
<PrimaryButton
|
|
594
|
+
onClick={handleReset}
|
|
595
|
+
disabled={toggling}
|
|
596
|
+
className="flex items-center gap-2 mt-2"
|
|
597
|
+
>
|
|
598
|
+
{toggling && <Loader2 size={14} className="animate-spin" />}
|
|
599
|
+
{(syncT?.resetButton as string) ?? 'Reset & Re-configure'}
|
|
600
|
+
</PrimaryButton>
|
|
601
|
+
</div>
|
|
602
|
+
</div>
|
|
603
|
+
</div>
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
|
|
263
607
|
const conflicts = status.conflicts || [];
|
|
264
608
|
|
|
265
609
|
return (
|
|
266
|
-
<div className="space-y-
|
|
267
|
-
<
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
<span className="text-
|
|
273
|
-
|
|
274
|
-
</div>
|
|
275
|
-
<div className="flex items-center gap-2">
|
|
276
|
-
<span className="text-muted-foreground w-24 shrink-0">Remote</span>
|
|
277
|
-
<span className="font-mono text-sm truncate" title={status.remote}>{status.remote}</span>
|
|
278
|
-
</div>
|
|
279
|
-
<div className="flex items-center gap-2">
|
|
280
|
-
<span className="text-muted-foreground w-24 shrink-0">Branch</span>
|
|
281
|
-
<span className="font-mono text-sm">{status.branch}</span>
|
|
282
|
-
</div>
|
|
283
|
-
<div className="flex items-center gap-2">
|
|
284
|
-
<span className="text-muted-foreground w-24 shrink-0">Last sync</span>
|
|
285
|
-
<span className="text-sm">{timeAgo(status.lastSync)}</span>
|
|
286
|
-
</div>
|
|
287
|
-
<div className="flex items-center gap-2">
|
|
288
|
-
<span className="text-muted-foreground w-24 shrink-0">Unpushed</span>
|
|
289
|
-
<span className="text-sm">{status.unpushed} commits</span>
|
|
290
|
-
</div>
|
|
291
|
-
<div className="flex items-center gap-2">
|
|
292
|
-
<span className="text-muted-foreground w-24 shrink-0">Auto-sync</span>
|
|
293
|
-
<span className="text-sm">
|
|
294
|
-
commit: {status.autoCommitInterval}s, pull: {Math.floor((status.autoPullInterval || 300) / 60)}min
|
|
610
|
+
<div className="space-y-4">
|
|
611
|
+
<SettingCard
|
|
612
|
+
icon={<GitBranch size={15} />}
|
|
613
|
+
title={(syncT?.sectionTitle as string) ?? 'Sync'}
|
|
614
|
+
description={status.remote}
|
|
615
|
+
badge={
|
|
616
|
+
<span className="text-2xs px-1.5 py-0.5 rounded bg-success/15 text-success font-medium">
|
|
617
|
+
{(syncT?.labelEnabled as string) ?? 'Active'}
|
|
295
618
|
</span>
|
|
619
|
+
}
|
|
620
|
+
>
|
|
621
|
+
{/* Status rows */}
|
|
622
|
+
<div className="space-y-2 text-sm">
|
|
623
|
+
<div className="flex items-center justify-between">
|
|
624
|
+
<span className="text-muted-foreground">{(syncT?.labelBranch as string) ?? 'Branch'}</span>
|
|
625
|
+
<span className="font-mono text-xs">{status.branch}</span>
|
|
626
|
+
</div>
|
|
627
|
+
<div className="flex items-center justify-between">
|
|
628
|
+
<span className="text-muted-foreground">{(syncT?.labelLastSync as string) ?? 'Last sync'}</span>
|
|
629
|
+
<span className="text-xs">{timeAgo(status.lastSync, syncT)}</span>
|
|
630
|
+
</div>
|
|
631
|
+
<div className="flex items-center justify-between">
|
|
632
|
+
<span className="text-muted-foreground">{(syncT?.labelUnpushed as string) ?? 'Unpushed'}</span>
|
|
633
|
+
<span className="text-xs">
|
|
634
|
+
{typeof status.unpushed === 'string' && /^\d+$/.test(status.unpushed)
|
|
635
|
+
? ((syncT?.unpushedCommits as ((n: number) => string))?.(parseInt(status.unpushed, 10)) ?? `${status.unpushed} commits`)
|
|
636
|
+
: `${status.unpushed ?? '?'} commits`}
|
|
637
|
+
</span>
|
|
638
|
+
</div>
|
|
639
|
+
<div className="flex items-center justify-between">
|
|
640
|
+
<span className="text-muted-foreground">{(syncT?.labelAutoSync as string) ?? 'Auto-sync'}</span>
|
|
641
|
+
<span className="flex items-center gap-1 text-xs">
|
|
642
|
+
commit{' '}
|
|
643
|
+
<select
|
|
644
|
+
className="bg-muted rounded px-1.5 py-0.5 text-xs border border-border cursor-pointer"
|
|
645
|
+
value={status.autoCommitInterval}
|
|
646
|
+
onChange={async (e) => {
|
|
647
|
+
const val = parseInt(e.target.value, 10);
|
|
648
|
+
try {
|
|
649
|
+
const res = await fetch('/api/sync', {
|
|
650
|
+
method: 'POST',
|
|
651
|
+
headers: { 'Content-Type': 'application/json' },
|
|
652
|
+
body: JSON.stringify({ action: 'update-intervals', autoCommitInterval: val }),
|
|
653
|
+
});
|
|
654
|
+
if (res.ok) fetchStatus();
|
|
655
|
+
} catch {}
|
|
656
|
+
}}
|
|
657
|
+
>
|
|
658
|
+
<option value={10}>10s</option>
|
|
659
|
+
<option value={15}>15s</option>
|
|
660
|
+
<option value={30}>30s</option>
|
|
661
|
+
<option value={60}>60s</option>
|
|
662
|
+
<option value={120}>120s</option>
|
|
663
|
+
</select>
|
|
664
|
+
{' · pull '}
|
|
665
|
+
<select
|
|
666
|
+
className="bg-muted rounded px-1.5 py-0.5 text-xs border border-border cursor-pointer"
|
|
667
|
+
value={status.autoPullInterval}
|
|
668
|
+
onChange={async (e) => {
|
|
669
|
+
const val = parseInt(e.target.value, 10);
|
|
670
|
+
try {
|
|
671
|
+
const res = await fetch('/api/sync', {
|
|
672
|
+
method: 'POST',
|
|
673
|
+
headers: { 'Content-Type': 'application/json' },
|
|
674
|
+
body: JSON.stringify({ action: 'update-intervals', autoPullInterval: val }),
|
|
675
|
+
});
|
|
676
|
+
if (res.ok) fetchStatus();
|
|
677
|
+
} catch {}
|
|
678
|
+
}}
|
|
679
|
+
>
|
|
680
|
+
<option value={60}>1min</option>
|
|
681
|
+
<option value={120}>2min</option>
|
|
682
|
+
<option value={300}>5min</option>
|
|
683
|
+
<option value={600}>10min</option>
|
|
684
|
+
<option value={1800}>30min</option>
|
|
685
|
+
<option value={3600}>60min</option>
|
|
686
|
+
</select>
|
|
687
|
+
</span>
|
|
688
|
+
</div>
|
|
296
689
|
</div>
|
|
297
|
-
</div>
|
|
298
|
-
|
|
299
|
-
{/* Actions */}
|
|
300
|
-
<div className="flex items-center gap-2 pt-2">
|
|
301
|
-
<button
|
|
302
|
-
type="button"
|
|
303
|
-
onClick={handleSyncNow}
|
|
304
|
-
disabled={syncing}
|
|
305
|
-
title={syncing ? t.hints.syncInProgress : undefined}
|
|
306
|
-
className="flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg border border-border text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
|
|
307
|
-
>
|
|
308
|
-
<RefreshCw size={12} className={syncing ? 'animate-spin' : ''} />
|
|
309
|
-
Sync Now
|
|
310
|
-
</button>
|
|
311
|
-
<button
|
|
312
|
-
type="button"
|
|
313
|
-
onClick={handleToggle}
|
|
314
|
-
disabled={toggling}
|
|
315
|
-
title={toggling ? t.hints.toggleInProgress : undefined}
|
|
316
|
-
className={`flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg border transition-colors disabled:opacity-40 disabled:cursor-not-allowed ${
|
|
317
|
-
status.enabled
|
|
318
|
-
? 'border-border text-muted-foreground hover:text-destructive hover:border-destructive/50'
|
|
319
|
-
: 'border-success/30 text-success hover:bg-success/10'
|
|
320
|
-
}`}
|
|
321
|
-
>
|
|
322
|
-
{status.enabled ? 'Disable Auto-sync' : 'Enable Auto-sync'}
|
|
323
|
-
</button>
|
|
324
|
-
</div>
|
|
325
690
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
691
|
+
{/* Actions */}
|
|
692
|
+
<div className="flex items-center gap-2 pt-1">
|
|
693
|
+
<button
|
|
694
|
+
type="button"
|
|
695
|
+
onClick={handleSyncNow}
|
|
696
|
+
disabled={syncing}
|
|
697
|
+
className="flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg border border-border text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
|
|
698
|
+
>
|
|
699
|
+
<RefreshCw size={12} className={syncing ? 'animate-spin' : ''} />
|
|
700
|
+
{(syncT?.syncNow as string) ?? 'Sync Now'}
|
|
701
|
+
</button>
|
|
702
|
+
<button
|
|
703
|
+
type="button"
|
|
704
|
+
onClick={handleToggle}
|
|
705
|
+
disabled={toggling}
|
|
706
|
+
className="flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg border border-border text-muted-foreground hover:text-destructive hover:border-destructive/50 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
|
|
707
|
+
>
|
|
708
|
+
{(syncT?.disableAutoSync as string) ?? 'Disable Auto-sync'}
|
|
709
|
+
</button>
|
|
334
710
|
</div>
|
|
335
|
-
)}
|
|
336
711
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
<AlertCircle size={
|
|
345
|
-
<
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
>
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
<a
|
|
353
|
-
href={`/view/${encodeURIComponent(c.file + '.sync-conflict')}`}
|
|
354
|
-
className="opacity-0 group-hover:opacity-100 transition-opacity shrink-0 text-muted-foreground hover:text-foreground"
|
|
355
|
-
title="View remote version (.sync-conflict)"
|
|
356
|
-
>
|
|
357
|
-
<ExternalLink size={11} />
|
|
358
|
-
</a>
|
|
359
|
-
<span className="text-muted-foreground shrink-0 ml-auto">{timeAgo(c.time)}</span>
|
|
360
|
-
</div>
|
|
361
|
-
))}
|
|
712
|
+
{/* Message */}
|
|
713
|
+
{message && (
|
|
714
|
+
<div className="flex items-start gap-1.5 text-xs" role="status" aria-live="polite">
|
|
715
|
+
{message.type === 'success' ? (
|
|
716
|
+
<><CheckCircle2 size={13} className="text-success shrink-0 mt-0.5" /><span className="text-success">{message.text}</span></>
|
|
717
|
+
) : (
|
|
718
|
+
<>
|
|
719
|
+
<AlertCircle size={13} className="text-destructive shrink-0 mt-0.5" />
|
|
720
|
+
<div className="space-y-0.5">
|
|
721
|
+
{message.text.split('\n').map((line, i) => (
|
|
722
|
+
<span key={i} className={`block ${i > 0 ? 'text-destructive/70' : 'text-destructive'}`}>{line}</span>
|
|
723
|
+
))}
|
|
724
|
+
</div>
|
|
725
|
+
</>
|
|
726
|
+
)}
|
|
362
727
|
</div>
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
728
|
+
)}
|
|
729
|
+
|
|
730
|
+
{/* Conflicts */}
|
|
731
|
+
{conflicts.length > 0 && (
|
|
732
|
+
<div className="pt-2 border-t border-border/50 space-y-3">
|
|
733
|
+
<p className="text-xs font-medium text-foreground">
|
|
734
|
+
{(syncT?.conflictsTitle as ((n: number) => string))?.(conflicts.length) ?? `Conflicts (${conflicts.length})`}
|
|
735
|
+
</p>
|
|
736
|
+
<p className="text-2xs text-muted-foreground">
|
|
737
|
+
{(syncT?.conflictExplain as string) ?? 'These files were changed on both this device and the remote. Choose which version to keep for each file.'}
|
|
738
|
+
</p>
|
|
739
|
+
<div className="space-y-2">
|
|
740
|
+
{conflicts.map((c, i) => (
|
|
741
|
+
<ConflictRow key={i} file={c.file} time={c.time} syncT={syncT} onResolved={fetchStatus} />
|
|
742
|
+
))}
|
|
743
|
+
</div>
|
|
744
|
+
</div>
|
|
745
|
+
)}
|
|
368
746
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
<div className="flex items-start gap-2 text-xs text-destructive">
|
|
747
|
+
{/* Error — hide if conflicts section already explains the issue */}
|
|
748
|
+
{status.lastError && conflicts.length === 0 && (
|
|
749
|
+
<div className="flex items-start gap-2 text-xs p-2.5 rounded-lg bg-destructive/10 text-destructive">
|
|
373
750
|
<AlertCircle size={12} className="shrink-0 mt-0.5" />
|
|
374
|
-
<
|
|
751
|
+
<div className="space-y-1">
|
|
752
|
+
<span className="block">{status.lastError}</span>
|
|
753
|
+
{getSyncErrorHint(status.lastError, status.remote, syncT) && (
|
|
754
|
+
<span className="block text-destructive/70">{getSyncErrorHint(status.lastError, status.remote, syncT)}</span>
|
|
755
|
+
)}
|
|
756
|
+
</div>
|
|
375
757
|
</div>
|
|
376
|
-
|
|
377
|
-
|
|
758
|
+
)}
|
|
759
|
+
|
|
760
|
+
{/* Gitignore editor */}
|
|
761
|
+
<GitignoreEditor syncT={syncT} />
|
|
762
|
+
</SettingCard>
|
|
378
763
|
</div>
|
|
379
764
|
);
|
|
380
765
|
}
|