@geminilight/mindos 0.6.59 → 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 +20 -19
- package/_standalone/.next/build-manifest.json +2 -2
- package/_standalone/.next/cache/.previewinfo +1 -1
- package/_standalone/.next/cache/.rscinfo +1 -1
- package/_standalone/.next/cache/config.json +3 -3
- package/_standalone/.next/prerender-manifest.json +3 -3
- package/_standalone/.next/routes-manifest.json +6 -0
- package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error.html +2 -2
- package/_standalone/.next/server/app/_global-error.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/_standalone/.next/server/app/_not-found/page.js +1 -1
- package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/page.js +1 -1
- package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/registry/route_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 +17 -6
- 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 +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/echo/page.js +1 -1
- package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/explore/page.js +1 -1
- package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/help/page.js +1 -1
- package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/inbox/history/page.js +1 -1
- package/_standalone/.next/server/app/inbox/history/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/inbox/history/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/login/page.js +1 -1
- package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/page.js +1 -1
- package/_standalone/.next/server/app/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/setup/page.js +1 -1
- package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/trash/page.js +3 -3
- package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/view/[...path]/page.js +2 -2
- package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/wiki/page.js +1 -1
- package/_standalone/.next/server/app/wiki/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/wiki/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app-paths-manifest.json +20 -19
- 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 +35 -35
- package/_standalone/.next/server/chunks/{8343.js → 9753.js} +2 -2
- 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/{5581-dac72e9f16e5ea29.js → 5581-974dfb26d1d1b38f.js} +2 -2
- package/_standalone/.next/static/chunks/7249-b0a9c77b9a84b11c.js +11 -0
- package/_standalone/.next/static/chunks/7637-904b0a381dc3ec02.js +1 -0
- package/_standalone/.next/static/chunks/8520-76d1b05072178b43.js +22 -0
- package/_standalone/.next/static/chunks/9186-ead47513192f658b.js +1 -0
- package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/_global-error/{page-2f4705aa66819b86.js → page-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-0ea3571c8fbae823.js +1 -0
- package/_standalone/.next/static/chunks/app/agents/{page-b172ea3743adb047.js → page-66858acbcd1d4bf8.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/agents/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/delegations/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/a2a/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/config/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/install/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/session/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/copy-skill/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/custom/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/auth/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/backlinks/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/changes/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/export/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/import/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/raw/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/files/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/git/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/graph/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/health/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/inbox/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/init/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/monitoring/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/recent-files/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/restart/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/search/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/skills/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/sync/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/tree-version/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/uninstall/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-check/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-status/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/api/workflows/route-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/changes/page-dd0b00a7b81f74e2.js +1 -0
- package/_standalone/.next/static/chunks/app/echo/[segment]/{page-84b95256f6e38aae.js → page-bf5c290fa3ccff09.js} +1 -1
- package/_standalone/.next/static/chunks/app/echo/page-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/inbox/history/{page-26e71fb6f716a4c4.js → page-3279585360df132c.js} +1 -1
- package/_standalone/.next/static/chunks/app/{layout-b89b0d955f39a753.js → layout-6a0169582db11a08.js} +24 -24
- package/_standalone/.next/static/chunks/app/loading-2ceea6eabf25b1f2.js +1 -0
- package/_standalone/.next/static/chunks/app/{page-a8e6f085f38388bf.js → page-6a1f8d21c12b829e.js} +1 -1
- package/_standalone/.next/static/chunks/app/trash/page-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]/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/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/components/AskFab.tsx +7 -1
- package/_standalone/components/FileTree.tsx +83 -1
- package/_standalone/components/Panel.tsx +6 -1
- package/_standalone/components/agents/AgentsOverviewSection.tsx +13 -11
- package/_standalone/components/agents/CustomAgentModal.tsx +72 -18
- package/_standalone/components/ask/AskContent.tsx +19 -3
- package/_standalone/components/ask/FileChip.tsx +93 -12
- package/_standalone/components/changes/ChangesBanner.tsx +1 -1
- package/_standalone/components/walkthrough/WalkthroughTooltip.tsx +3 -1
- package/_standalone/components/walkthrough/steps.ts +1 -1
- package/_standalone/hooks/useAskChat.ts +10 -8
- package/_standalone/hooks/useFileUpload.ts +97 -43
- package/_standalone/hooks/useImageUpload.ts +1 -1
- package/_standalone/lib/inbox-upload.ts +86 -0
- package/_standalone/package-lock.json +2 -2
- package/_standalone/package.json +1 -1
- package/_standalone/scripts/extract-pdf.cjs +110 -3
- package/_standalone/tsconfig.tsbuildinfo +1 -1
- package/app/app/api/agents/copy-skill/route.ts +110 -0
- package/app/app/api/agents/custom/detect/route.ts +16 -1
- package/app/app/api/ask/route.ts +7 -1
- package/app/app/api/extract-pdf/route.ts +12 -5
- package/app/app/api/mcp/agents/route.ts +64 -2
- package/app/components/AskFab.tsx +7 -1
- package/app/components/FileTree.tsx +83 -1
- package/app/components/HomeContent.tsx +14 -6
- package/app/components/Panel.tsx +6 -1
- package/app/components/agents/AgentDetailContent.tsx +58 -1
- package/app/components/agents/AgentsOverviewSection.tsx +13 -11
- package/app/components/agents/CustomAgentModal.tsx +72 -18
- package/app/components/ask/AskContent.tsx +19 -3
- package/app/components/ask/FileChip.tsx +93 -12
- package/app/components/changes/ChangesBanner.tsx +1 -1
- package/app/components/changes/ChangesContentPage.tsx +368 -168
- package/app/components/walkthrough/WalkthroughTooltip.tsx +3 -1
- package/app/components/walkthrough/steps.ts +1 -1
- package/app/hooks/useAskChat.ts +10 -8
- package/app/hooks/useFileUpload.ts +97 -43
- package/app/hooks/useImageUpload.ts +1 -1
- package/app/lib/agent/prompt.ts +15 -4
- package/app/lib/custom-agents.ts +109 -1
- package/app/lib/file-ops.ts +58 -0
- package/app/lib/i18n/modules/ai-chat.ts +37 -0
- package/app/lib/i18n/modules/knowledge.ts +2 -0
- package/app/lib/inbox-upload.ts +86 -0
- package/app/lib/mcp-agents.ts +21 -1
- package/app/lib/types.ts +12 -0
- package/app/package.json +1 -1
- package/app/scripts/extract-pdf.cjs +110 -3
- package/package.json +1 -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-6cf8f2b78718c59e.js +0 -11
- package/_standalone/.next/static/chunks/8520-56ec9ff087c15204.js +0 -22
- package/_standalone/.next/static/chunks/9286-5b09baa5200318c2.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-35ea6de1af2be3b5.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/config/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/install/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/session/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agents/custom/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/auth/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/backlinks/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/changes/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/export/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/import/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/raw/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/files/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/git/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/graph/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/health/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/inbox/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/init/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/monitoring/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/recent-files/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/restart/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/search/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/skills/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/sync/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/tree-version/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/uninstall/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-check/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-status/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/api/workflows/route-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/changes/page-6d2f49651c0061f7.js +0 -1
- package/_standalone/.next/static/chunks/app/echo/page-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/loading-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/trash/page-f92b728b78ac0f7e.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/page-f87f4901b5e1a88f.js +0 -12
- package/_standalone/.next/static/chunks/app/wiki/page-641edb1f3cff2f93.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2f4705aa66819b86.js +0 -1
- package/_standalone/.next/static/css/6c104b118d3bc9b7.css +0 -1
- package/_standalone/.next/static/u8p6oIRTcr_ns-ElNZ9rl/_buildManifest.js +0 -1
- /package/_standalone/.next/static/{u8p6oIRTcr_ns-ElNZ9rl → K3wZNf5bj_AFYwtqcRXIf}/_ssgManifest.js +0 -0
package/app/hooks/useAskChat.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useRef, useState, useCallback } from 'react';
|
|
4
|
-
import type { Message, ImagePart, AskMode } from '@/lib/types';
|
|
4
|
+
import type { Message, ImagePart, AskMode, LocalAttachment } from '@/lib/types';
|
|
5
5
|
import type { ProviderId } from '@/lib/agent/providers';
|
|
6
6
|
import { consumeUIMessageStream } from '@/lib/agent/stream-consumer';
|
|
7
7
|
import { isRetryableError, retryDelay, sleep } from '@/lib/agent/reconnect';
|
|
@@ -18,7 +18,7 @@ export interface AskChatRefs {
|
|
|
18
18
|
setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
|
|
19
19
|
}>;
|
|
20
20
|
uploadRef: React.RefObject<{
|
|
21
|
-
localAttachments:
|
|
21
|
+
localAttachments: LocalAttachment[];
|
|
22
22
|
}>;
|
|
23
23
|
selectedSkillRef: React.RefObject<{ name: string } | null>;
|
|
24
24
|
selectedAcpAgentRef: React.RefObject<unknown>;
|
|
@@ -103,12 +103,14 @@ export function useAskChat({
|
|
|
103
103
|
messages: requestMessages,
|
|
104
104
|
currentFile,
|
|
105
105
|
attachedFiles: refs.attachedFilesRef.current,
|
|
106
|
-
uploadedFiles: upl.localAttachments
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
: f.content
|
|
111
|
-
|
|
106
|
+
uploadedFiles: upl.localAttachments
|
|
107
|
+
.filter(f => f.status !== 'loading')
|
|
108
|
+
.map(f => ({
|
|
109
|
+
name: f.name,
|
|
110
|
+
content: f.content.length > 80_000
|
|
111
|
+
? f.content.slice(0, 80_000) + '\n\n[...truncated to first ~80000 chars]'
|
|
112
|
+
: f.content,
|
|
113
|
+
})),
|
|
112
114
|
selectedAcpAgent: acpAgent,
|
|
113
115
|
mode: chatMode,
|
|
114
116
|
providerOverride: providerOverride ?? undefined,
|
|
@@ -22,28 +22,76 @@ function uint8ToBase64(bytes: Uint8Array): string {
|
|
|
22
22
|
return btoa(binary);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Extract text from a PDF file via the backend API.
|
|
27
|
+
* Returns a LocalAttachment with `status` reflecting the outcome.
|
|
28
|
+
*/
|
|
29
|
+
async function extractPdfToAttachment(file: File): Promise<LocalAttachment> {
|
|
30
|
+
const name = file.name;
|
|
28
31
|
|
|
29
|
-
const res = await fetch('/api/extract-pdf', {
|
|
30
|
-
method: 'POST',
|
|
31
|
-
headers: { 'Content-Type': 'application/json' },
|
|
32
|
-
body: JSON.stringify({ name: file.name, dataBase64 }),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
let payload: { text?: string; extracted?: boolean; error?: string } = {};
|
|
36
32
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// ignore JSON parse error
|
|
40
|
-
}
|
|
33
|
+
const buffer = await file.arrayBuffer();
|
|
34
|
+
const dataBase64 = uint8ToBase64(new Uint8Array(buffer));
|
|
41
35
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
const res = await fetch('/api/extract-pdf', {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: { 'Content-Type': 'application/json' },
|
|
39
|
+
body: JSON.stringify({ name, dataBase64 }),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
let payload: {
|
|
43
|
+
text?: string;
|
|
44
|
+
extracted?: boolean;
|
|
45
|
+
error?: string;
|
|
46
|
+
truncated?: boolean;
|
|
47
|
+
totalChars?: number;
|
|
48
|
+
pagesParsed?: number;
|
|
49
|
+
} = {};
|
|
50
|
+
try {
|
|
51
|
+
payload = await res.json();
|
|
52
|
+
} catch {
|
|
53
|
+
throw new Error('Failed to parse extraction response');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
throw new Error(payload.error || `PDF extraction failed (${res.status})`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const extracted = payload.extracted ? (payload.text || '') : '';
|
|
61
|
+
|
|
62
|
+
if (!extracted) {
|
|
63
|
+
return {
|
|
64
|
+
name,
|
|
65
|
+
content: `[PDF: ${name}] Could not extract readable text (possibly scanned/image PDF).`,
|
|
66
|
+
status: 'error',
|
|
67
|
+
error: 'Scanned or image-only PDF — no extractable text',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const att: LocalAttachment = {
|
|
72
|
+
name,
|
|
73
|
+
content: `[PDF TEXT EXTRACTED: ${name}]\n\n${extracted}`,
|
|
74
|
+
status: 'success',
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
if (payload.truncated && payload.totalChars) {
|
|
78
|
+
att.truncatedInfo = {
|
|
79
|
+
totalChars: payload.totalChars,
|
|
80
|
+
includedChars: extracted.length,
|
|
81
|
+
totalPages: payload.pagesParsed ?? 0,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
45
84
|
|
|
46
|
-
|
|
85
|
+
return att;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
88
|
+
return {
|
|
89
|
+
name,
|
|
90
|
+
content: `[PDF: ${name}] Failed to extract text from this PDF.`,
|
|
91
|
+
status: 'error',
|
|
92
|
+
error: msg,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
47
95
|
}
|
|
48
96
|
|
|
49
97
|
export function useFileUpload() {
|
|
@@ -73,37 +121,43 @@ export function useFileUpload() {
|
|
|
73
121
|
setUploadError('');
|
|
74
122
|
}
|
|
75
123
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return { name: f.name, content: await f.text() };
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
124
|
+
// Phase 1: Immediately add all files — PDFs start in 'loading' state
|
|
125
|
+
const pdfFiles: File[] = [];
|
|
126
|
+
const immediateItems: LocalAttachment[] = [];
|
|
127
|
+
|
|
128
|
+
for (const f of accepted) {
|
|
129
|
+
if (getExt(f.name) === '.pdf') {
|
|
130
|
+
immediateItems.push({ name: f.name, content: '', status: 'loading' });
|
|
131
|
+
pdfFiles.push(f);
|
|
132
|
+
} else {
|
|
133
|
+
immediateItems.push({
|
|
134
|
+
name: f.name,
|
|
135
|
+
content: await f.text(),
|
|
136
|
+
status: 'success',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
98
140
|
|
|
99
141
|
setLocalAttachments((prev) => {
|
|
100
142
|
const merged = [...prev];
|
|
101
|
-
for (const item of
|
|
102
|
-
if (!merged.some((m) => m.name === item.name
|
|
103
|
-
merged.push(item);
|
|
143
|
+
for (const item of immediateItems) {
|
|
144
|
+
if (!merged.some((m) => m.name === item.name)) merged.push(item);
|
|
104
145
|
}
|
|
105
146
|
return merged;
|
|
106
147
|
});
|
|
148
|
+
|
|
149
|
+
// Phase 2: Extract PDFs in parallel, then update each one in-place
|
|
150
|
+
if (pdfFiles.length > 0) {
|
|
151
|
+
const results = await Promise.all(pdfFiles.map(extractPdfToAttachment));
|
|
152
|
+
|
|
153
|
+
setLocalAttachments((prev) =>
|
|
154
|
+
prev.map((att) => {
|
|
155
|
+
if (att.status !== 'loading') return att;
|
|
156
|
+
const result = results.find((r) => r.name === att.name);
|
|
157
|
+
return result ?? att;
|
|
158
|
+
}),
|
|
159
|
+
);
|
|
160
|
+
}
|
|
107
161
|
}, []);
|
|
108
162
|
|
|
109
163
|
const removeAttachment = useCallback((idx: number) => {
|
|
@@ -86,7 +86,7 @@ export function useImageUpload() {
|
|
|
86
86
|
}
|
|
87
87
|
try {
|
|
88
88
|
const { data, mimeType } = await compressImage(file);
|
|
89
|
-
results.push({ type: 'image', data, mimeType });
|
|
89
|
+
results.push({ type: 'image', data, mimeType, fileName: file.name || undefined });
|
|
90
90
|
} catch {
|
|
91
91
|
setImageError(`Failed to process image: ${file.name}`);
|
|
92
92
|
}
|
package/app/lib/agent/prompt.ts
CHANGED
|
@@ -6,12 +6,21 @@
|
|
|
6
6
|
* - SKILL.md owns: knowledge-base-specific execution patterns, tool selection, safety rules
|
|
7
7
|
* - Tool descriptions own: per-tool usage instructions (no duplication here)
|
|
8
8
|
*
|
|
9
|
-
* Token budget: ~
|
|
10
|
-
* SKILL.md + bootstrap context within the same context window.
|
|
9
|
+
* Token budget: ~750 tokens (v4 added persona warmth + self-introduction).
|
|
10
|
+
* Freed space = more room for SKILL.md + bootstrap context within the same context window.
|
|
11
11
|
*/
|
|
12
12
|
export const AGENT_SYSTEM_PROMPT = `You are MindOS Agent — the operator of the user's second brain.
|
|
13
13
|
|
|
14
|
-
Persona:
|
|
14
|
+
Persona: Warm yet precise, reliable, execution-oriented. Like a trusted notebook that understands you — quiet confidence, zero fluff. Be professional but never cold; be helpful but never verbose.
|
|
15
|
+
|
|
16
|
+
## Self-Introduction
|
|
17
|
+
|
|
18
|
+
When the user greets you ("你好", "hi", "你是谁", "what can you do", etc.) or this appears to be their first message in a new conversation, introduce yourself briefly:
|
|
19
|
+
|
|
20
|
+
- Who: MindOS Agent, the operator of their personal knowledge base (second brain).
|
|
21
|
+
- What: You can search, read, write, and organize their notes; capture decisions and lessons; run workflows/SOPs; and help them build a lasting, structured memory.
|
|
22
|
+
- Tone: Warm, concise, confident. One short paragraph, then invite them to try something — e.g., "想查点什么,还是有东西要记下来?"
|
|
23
|
+
- Do NOT self-introduce when the user jumps straight into a task (search, save, edit, etc.).
|
|
15
24
|
|
|
16
25
|
## Core Directives
|
|
17
26
|
|
|
@@ -45,7 +54,9 @@ Persona: Methodical, strictly objective, execution-oriented. Zero fluff. Never u
|
|
|
45
54
|
*/
|
|
46
55
|
export const CHAT_SYSTEM_PROMPT = `You are MindOS Agent — the operator of the user's second brain.
|
|
47
56
|
|
|
48
|
-
Persona:
|
|
57
|
+
Persona: Warm yet precise, reliable, execution-oriented. Like a trusted notebook that understands you — quiet confidence, zero fluff. Be professional but never cold; be helpful but never verbose.
|
|
58
|
+
|
|
59
|
+
When the user greets you or asks who you are, briefly introduce yourself: you're MindOS Agent, here to help them search and read their knowledge base. Keep it warm and concise, then invite them to ask something.
|
|
49
60
|
|
|
50
61
|
## Mode: Chat (Read-Only)
|
|
51
62
|
|
package/app/lib/custom-agents.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import fs from 'fs';
|
|
10
10
|
import path from 'path';
|
|
11
|
-
import { expandHome, MCP_AGENTS } from './mcp-agents';
|
|
11
|
+
import { expandHome, MCP_AGENTS, parseJsonc } from './mcp-agents';
|
|
12
12
|
import type { AgentDef } from './mcp-agents';
|
|
13
13
|
import { readSettings, writeSettings } from './settings';
|
|
14
14
|
|
|
@@ -39,6 +39,8 @@ export interface DetectResult {
|
|
|
39
39
|
detectedSkillDir?: string;
|
|
40
40
|
skillCount?: number;
|
|
41
41
|
skillNames?: string[];
|
|
42
|
+
mcpServers?: string[];
|
|
43
|
+
mcpParseError?: string;
|
|
42
44
|
suggestedName?: string;
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -282,6 +284,112 @@ export function scanCustomAgentSkills(custom: CustomAgentDef): { skills: string[
|
|
|
282
284
|
}
|
|
283
285
|
}
|
|
284
286
|
|
|
287
|
+
/* ─── Enhanced Skill & MCP Detection ─── */
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Parse JSON config to extract MCP server names from a config key.
|
|
291
|
+
*/
|
|
292
|
+
function parseJsonMcpServers(content: string, key: string): string[] {
|
|
293
|
+
try {
|
|
294
|
+
const config = parseJsonc(content);
|
|
295
|
+
const servers = config[key];
|
|
296
|
+
if (servers && typeof servers === 'object') {
|
|
297
|
+
return Object.keys(servers).sort();
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
return [];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Parse TOML config to extract MCP server names from a section key.
|
|
307
|
+
*/
|
|
308
|
+
function parseTomlMcpServers(content: string, sectionKey: string): string[] {
|
|
309
|
+
const names = new Set<string>();
|
|
310
|
+
const lines = content.split('\n');
|
|
311
|
+
const sectionPrefix = `${sectionKey}.`;
|
|
312
|
+
|
|
313
|
+
for (const line of lines) {
|
|
314
|
+
const trimmed = line.trim();
|
|
315
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
316
|
+
const section = trimmed.slice(1, -1).trim();
|
|
317
|
+
if (section.startsWith(sectionPrefix)) {
|
|
318
|
+
const name = section.slice(sectionPrefix.length).split('.')[0];
|
|
319
|
+
if (name) names.add(name);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return [...names].sort();
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Detect config format from file extension.
|
|
329
|
+
*/
|
|
330
|
+
function detectConfigFormat(configPath: string): 'json' | 'toml' {
|
|
331
|
+
return configPath.toLowerCase().endsWith('.toml') ? 'toml' : 'json';
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Comprehensive profile detection for a custom agent.
|
|
336
|
+
* Returns MCP servers, skills, and any parse errors.
|
|
337
|
+
*/
|
|
338
|
+
export function detectCustomAgentProfile(
|
|
339
|
+
baseDir: string,
|
|
340
|
+
configPath: string,
|
|
341
|
+
configKey: string,
|
|
342
|
+
): {
|
|
343
|
+
mcpServers: string[];
|
|
344
|
+
skillNames: string[];
|
|
345
|
+
skillDir: string;
|
|
346
|
+
configFormat: 'json' | 'toml';
|
|
347
|
+
parseError?: string;
|
|
348
|
+
} {
|
|
349
|
+
const expanded = expandHome(baseDir);
|
|
350
|
+
const configAbsPath = expandHome(configPath);
|
|
351
|
+
|
|
352
|
+
const result = {
|
|
353
|
+
mcpServers: [] as string[],
|
|
354
|
+
skillNames: [] as string[],
|
|
355
|
+
skillDir: '',
|
|
356
|
+
configFormat: detectConfigFormat(configPath) as 'json' | 'toml',
|
|
357
|
+
parseError: undefined as string | undefined,
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
// 1. Read MCP servers from config
|
|
361
|
+
if (fs.existsSync(configAbsPath)) {
|
|
362
|
+
try {
|
|
363
|
+
const content = fs.readFileSync(configAbsPath, 'utf-8');
|
|
364
|
+
result.mcpServers =
|
|
365
|
+
result.configFormat === 'json'
|
|
366
|
+
? parseJsonMcpServers(content, configKey)
|
|
367
|
+
: parseTomlMcpServers(content, configKey);
|
|
368
|
+
} catch (err) {
|
|
369
|
+
result.parseError = `Failed to parse MCP config: ${err instanceof Error ? err.message : 'Unknown error'}`;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// 2. Scan Skill directory
|
|
374
|
+
const skillDirPath = path.join(expanded, 'skills');
|
|
375
|
+
if (fs.existsSync(skillDirPath)) {
|
|
376
|
+
result.skillDir = baseDir.endsWith('/') ? baseDir + 'skills/' : baseDir + '/skills/';
|
|
377
|
+
try {
|
|
378
|
+
const entries = fs.readdirSync(skillDirPath, { withFileTypes: true });
|
|
379
|
+
result.skillNames = entries
|
|
380
|
+
.filter(e => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith('.'))
|
|
381
|
+
.map(e => e.name)
|
|
382
|
+
.sort((a, b) => a.localeCompare(b));
|
|
383
|
+
} catch {
|
|
384
|
+
// Skill dir exists but not readable, continue
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
result.skillDir = baseDir.endsWith('/') ? baseDir + 'skills/' : baseDir + '/skills/';
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return result;
|
|
391
|
+
}
|
|
392
|
+
|
|
285
393
|
/* ─── Validation ─── */
|
|
286
394
|
|
|
287
395
|
export function validateCustomAgentInput(input: {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File operations utilities.
|
|
3
|
+
* Used for recursive directory copying and other file system tasks.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Recursively copy a directory and all its contents.
|
|
11
|
+
*
|
|
12
|
+
* @param src Source directory path
|
|
13
|
+
* @param dst Destination directory path
|
|
14
|
+
* @throws Error if source doesn't exist or copy fails
|
|
15
|
+
*/
|
|
16
|
+
export async function copyDir(src: string, dst: string): Promise<void> {
|
|
17
|
+
// Create destination directory
|
|
18
|
+
await fs.promises.mkdir(dst, { recursive: true });
|
|
19
|
+
|
|
20
|
+
// Read source directory
|
|
21
|
+
const entries = await fs.promises.readdir(src, { withFileTypes: true });
|
|
22
|
+
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
const srcPath = path.join(src, entry.name);
|
|
25
|
+
const dstPath = path.join(dst, entry.name);
|
|
26
|
+
|
|
27
|
+
if (entry.isDirectory()) {
|
|
28
|
+
// Recursively copy subdirectory
|
|
29
|
+
await copyDir(srcPath, dstPath);
|
|
30
|
+
} else if (entry.isFile()) {
|
|
31
|
+
// Copy file
|
|
32
|
+
await fs.promises.copyFile(srcPath, dstPath);
|
|
33
|
+
} else if (entry.isSymbolicLink()) {
|
|
34
|
+
// Copy symbolic link target
|
|
35
|
+
const linkTarget = await fs.promises.readlink(srcPath);
|
|
36
|
+
await fs.promises.symlink(linkTarget, dstPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if a directory exists.
|
|
43
|
+
*/
|
|
44
|
+
export function dirExists(dir: string): boolean {
|
|
45
|
+
try {
|
|
46
|
+
const stat = fs.statSync(dir);
|
|
47
|
+
return stat.isDirectory();
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create a directory recursively.
|
|
55
|
+
*/
|
|
56
|
+
export async function ensureDir(dir: string): Promise<void> {
|
|
57
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
58
|
+
}
|
|
@@ -125,6 +125,7 @@ export const aiChatEn = {
|
|
|
125
125
|
},
|
|
126
126
|
loading: 'Loading changes...',
|
|
127
127
|
empty: 'No content changes yet.',
|
|
128
|
+
emptyHint: 'Changes made to your files will appear here when you or an agent edits content.',
|
|
128
129
|
open: 'Open',
|
|
129
130
|
unchangedLines: (n: number) => `... ${n} unchanged lines ...`,
|
|
130
131
|
operations: {
|
|
@@ -144,6 +145,24 @@ export const aiChatEn = {
|
|
|
144
145
|
import_file: 'Import file',
|
|
145
146
|
legacy_agent_diff_import: 'Import from Agent Diff',
|
|
146
147
|
},
|
|
148
|
+
/** Frontend-side summary translations for known backend summary patterns */
|
|
149
|
+
summaries: {
|
|
150
|
+
updatedFileContent: 'Updated file content',
|
|
151
|
+
appendedContent: 'Appended content to file',
|
|
152
|
+
insertedLines: (n: number) => `Inserted ${n} line(s)`,
|
|
153
|
+
updatedLines: (start: number, end: number) => `Updated lines ${start}-${end}`,
|
|
154
|
+
insertedAfterHeading: (h: string) => `Inserted content after heading "${h}"`,
|
|
155
|
+
updatedSection: (h: string) => `Updated section "${h}"`,
|
|
156
|
+
movedToTrash: 'Moved to trash',
|
|
157
|
+
renamedFile: (name: string) => `Renamed file to ${name}`,
|
|
158
|
+
createdFile: 'Created file',
|
|
159
|
+
movedFile: (p: string) => `Moved file to ${p}`,
|
|
160
|
+
createdSpace: 'Created space',
|
|
161
|
+
renamedSpace: (name: string) => `Renamed space to ${name}`,
|
|
162
|
+
appendedCsvRow: (n: number) => `Appended CSV row (${n} cell${n === 1 ? '' : 's'})`,
|
|
163
|
+
importedFile: 'Imported file into knowledge base',
|
|
164
|
+
importedLegacyDiff: 'Imported legacy agent diff',
|
|
165
|
+
},
|
|
147
166
|
relativeTime: {
|
|
148
167
|
justNow: 'just now',
|
|
149
168
|
minutesAgo: (n: number) => `${n}m ago`,
|
|
@@ -307,6 +326,7 @@ export const aiChatZh = {
|
|
|
307
326
|
},
|
|
308
327
|
loading: '正在加载变更...',
|
|
309
328
|
empty: '暂无内容变更。',
|
|
329
|
+
emptyHint: '你或 Agent 编辑文件时,变更会显示在这里。',
|
|
310
330
|
open: '打开',
|
|
311
331
|
unchangedLines: (n: number) => `... ${n} 行未变更 ...`,
|
|
312
332
|
operations: {
|
|
@@ -326,6 +346,23 @@ export const aiChatZh = {
|
|
|
326
346
|
import_file: '导入文件',
|
|
327
347
|
legacy_agent_diff_import: '从 Agent Diff 导入',
|
|
328
348
|
},
|
|
349
|
+
summaries: {
|
|
350
|
+
updatedFileContent: '更新了文件内容',
|
|
351
|
+
appendedContent: '追加了文件内容',
|
|
352
|
+
insertedLines: (n: number) => `插入了 ${n} 行`,
|
|
353
|
+
updatedLines: (start: number, end: number) => `更新了第 ${start}-${end} 行`,
|
|
354
|
+
insertedAfterHeading: (h: string) => `在标题「${h}」后插入了内容`,
|
|
355
|
+
updatedSection: (h: string) => `更新了章节「${h}」`,
|
|
356
|
+
movedToTrash: '移到了回收站',
|
|
357
|
+
renamedFile: (name: string) => `重命名为 ${name}`,
|
|
358
|
+
createdFile: '创建了文件',
|
|
359
|
+
movedFile: (p: string) => `移动到了 ${p}`,
|
|
360
|
+
createdSpace: '创建了空间',
|
|
361
|
+
renamedSpace: (name: string) => `重命名空间为 ${name}`,
|
|
362
|
+
appendedCsvRow: (n: number) => `追加了 CSV 行(${n} 个单元格)`,
|
|
363
|
+
importedFile: '导入了文件到知识库',
|
|
364
|
+
importedLegacyDiff: '从 Agent Diff 导入了变更',
|
|
365
|
+
},
|
|
329
366
|
relativeTime: {
|
|
330
367
|
justNow: '刚刚',
|
|
331
368
|
minutesAgo: (n: number) => `${n} 分钟前`,
|
|
@@ -103,6 +103,7 @@ export const knowledgeEn = {
|
|
|
103
103
|
viewAllHistory: (n: number) => `View all ${n} records →`,
|
|
104
104
|
agingHint: '7+ days',
|
|
105
105
|
savedToast: (n: number) => `${n} file${n === 1 ? '' : 's'} saved to Capture`,
|
|
106
|
+
savedToDir: (n: number, dir: string) => `${n} file${n === 1 ? '' : 's'} saved to ${dir}`,
|
|
106
107
|
savedWithSkipped: (saved: number, skipped: number) =>
|
|
107
108
|
saved > 0
|
|
108
109
|
? `${saved} saved, ${skipped} skipped (unsupported format)`
|
|
@@ -481,6 +482,7 @@ export const knowledgeZh = {
|
|
|
481
482
|
viewAllHistory: (n: number) => `查看全部 ${n} 条记录 →`,
|
|
482
483
|
agingHint: '7天+',
|
|
483
484
|
savedToast: (n: number) => `${n} 个文件已保存到暂存台`,
|
|
485
|
+
savedToDir: (n: number, dir: string) => `${n} 个文件已保存到 ${dir}`,
|
|
484
486
|
savedWithSkipped: (saved: number, skipped: number) =>
|
|
485
487
|
saved > 0
|
|
486
488
|
? `已保存 ${saved} 个,跳过 ${skipped} 个(格式不支持)`
|
package/app/lib/inbox-upload.ts
CHANGED
|
@@ -91,3 +91,89 @@ export async function quickDropToInbox(
|
|
|
91
91
|
toast.error(t.inbox.saveFailed, 4000);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Drop files into a specific directory via /api/file/import.
|
|
97
|
+
* Used when user drags external files onto a directory in the file tree.
|
|
98
|
+
*/
|
|
99
|
+
export async function quickDropToDirectory(
|
|
100
|
+
files: File[],
|
|
101
|
+
targetDir: string,
|
|
102
|
+
t: ReturnType<typeof useLocale>['t'],
|
|
103
|
+
) {
|
|
104
|
+
const payload: Array<{ name: string; content: string; encoding?: string }> = [];
|
|
105
|
+
let oversizedCount = 0;
|
|
106
|
+
|
|
107
|
+
const BINARY_EXTS = new Set([
|
|
108
|
+
'pdf', 'png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'ico',
|
|
109
|
+
'mp3', 'wav', 'm4a', 'ogg', 'flac', 'aac', 'mp4', 'webm', 'mov', 'mkv',
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
for (const file of files) {
|
|
113
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
114
|
+
oversizedCount++;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const ext = (file.name.split('.').pop() ?? '').toLowerCase();
|
|
119
|
+
if (BINARY_EXTS.has(ext)) {
|
|
120
|
+
const buf = await file.arrayBuffer();
|
|
121
|
+
payload.push({ name: file.name, content: arrayBufferToBase64(buf), encoding: 'base64' });
|
|
122
|
+
} else {
|
|
123
|
+
const text = await file.text();
|
|
124
|
+
payload.push({ name: file.name, content: text });
|
|
125
|
+
}
|
|
126
|
+
} catch {
|
|
127
|
+
/* skip unreadable files */
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (payload.length === 0) {
|
|
132
|
+
if (oversizedCount > 0) {
|
|
133
|
+
toast.error(t.inbox.tooLarge(oversizedCount), 4000);
|
|
134
|
+
} else if (files.length > 0) {
|
|
135
|
+
toast.error(t.inbox.saveFailed, 4000);
|
|
136
|
+
}
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const dirName = targetDir.split('/').pop() || targetDir;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
const res = await fetch('/api/file/import', {
|
|
144
|
+
method: 'POST',
|
|
145
|
+
headers: { 'Content-Type': 'application/json' },
|
|
146
|
+
body: JSON.stringify({
|
|
147
|
+
files: payload,
|
|
148
|
+
targetSpace: targetDir,
|
|
149
|
+
organize: false,
|
|
150
|
+
conflict: 'rename',
|
|
151
|
+
}),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!res.ok) {
|
|
155
|
+
const data = await res.json().catch(() => ({}));
|
|
156
|
+
console.error('[TreeDrop] Save failed:', data.error);
|
|
157
|
+
toast.error(t.inbox.saveFailed, 4000);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const result = await res.json();
|
|
162
|
+
const saved = result.created?.length ?? 0;
|
|
163
|
+
const skipped = result.skipped?.length ?? 0;
|
|
164
|
+
|
|
165
|
+
if (saved > 0 && (skipped + oversizedCount) > 0) {
|
|
166
|
+
toast.success(t.inbox.savedWithSkipped(saved, skipped + oversizedCount), 4000);
|
|
167
|
+
} else if (saved > 0) {
|
|
168
|
+
toast.success(t.inbox.savedToDir(saved, dirName), 3000);
|
|
169
|
+
} else {
|
|
170
|
+
if (oversizedCount > 0) toast.error(t.inbox.tooLarge(oversizedCount), 4000);
|
|
171
|
+
if (skipped > 0) toast.error(t.inbox.savedWithSkipped(0, skipped), 4000);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
window.dispatchEvent(new Event('mindos:files-changed'));
|
|
175
|
+
} catch (err) {
|
|
176
|
+
console.error('[TreeDrop] Network error:', err);
|
|
177
|
+
toast.error(t.inbox.saveFailed, 4000);
|
|
178
|
+
}
|
|
179
|
+
}
|
package/app/lib/mcp-agents.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { execSync } from 'child_process';
|
|
|
5
5
|
|
|
6
6
|
/** Parse JSONC — strips single-line (//) and block comments before JSON.parse */
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
-
function parseJsonc(text: string): any {
|
|
8
|
+
export function parseJsonc(text: string): any {
|
|
9
9
|
let stripped = text.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*$)/gm, (m, g) => g ? '' : m);
|
|
10
10
|
stripped = stripped.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
11
11
|
if (!stripped.trim()) return {};
|
|
@@ -244,6 +244,24 @@ export const MCP_AGENTS: Record<string, AgentDef> = {
|
|
|
244
244
|
presenceCli: 'agy',
|
|
245
245
|
presenceDirs: ['~/.gemini/antigravity/'],
|
|
246
246
|
},
|
|
247
|
+
'qclaw': {
|
|
248
|
+
name: 'QClaw',
|
|
249
|
+
project: null,
|
|
250
|
+
global: '~/.qclaw/mcp.json',
|
|
251
|
+
key: 'mcpServers',
|
|
252
|
+
preferredTransport: 'stdio',
|
|
253
|
+
presenceCli: 'qclaw',
|
|
254
|
+
presenceDirs: ['~/.qclaw/'],
|
|
255
|
+
},
|
|
256
|
+
'workbuddy': {
|
|
257
|
+
name: 'WorkBuddy',
|
|
258
|
+
project: null,
|
|
259
|
+
global: '~/.workbuddy/mcp.json',
|
|
260
|
+
key: 'mcpServers',
|
|
261
|
+
preferredTransport: 'stdio',
|
|
262
|
+
presenceCli: 'workbuddy',
|
|
263
|
+
presenceDirs: ['~/.workbuddy/'],
|
|
264
|
+
},
|
|
247
265
|
};
|
|
248
266
|
|
|
249
267
|
/**
|
|
@@ -271,6 +289,8 @@ export const SKILL_AGENT_REGISTRY: Record<string, SkillAgentRegistration> = {
|
|
|
271
289
|
'github-copilot': { mode: 'universal' },
|
|
272
290
|
'codex': { mode: 'universal' },
|
|
273
291
|
'antigravity': { mode: 'additional', skillAgentName: 'antigravity' },
|
|
292
|
+
'qclaw': { mode: 'unsupported' },
|
|
293
|
+
'workbuddy': { mode: 'unsupported' },
|
|
274
294
|
};
|
|
275
295
|
|
|
276
296
|
export interface SkillWorkspaceProfile {
|
package/app/lib/types.ts
CHANGED
|
@@ -52,6 +52,8 @@ export interface ImagePart {
|
|
|
52
52
|
/** Base64-encoded image data (no data: prefix) */
|
|
53
53
|
data: string;
|
|
54
54
|
mimeType: ImageMimeType;
|
|
55
|
+
/** Original file name, if available */
|
|
56
|
+
fileName?: string;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export type MessagePart = TextPart | ToolCallPart | ReasoningPart | ImagePart;
|
|
@@ -72,6 +74,16 @@ export interface Message {
|
|
|
72
74
|
export interface LocalAttachment {
|
|
73
75
|
name: string;
|
|
74
76
|
content: string;
|
|
77
|
+
/** Extraction status for PDF uploads. Absent / undefined = legacy (treated as success). */
|
|
78
|
+
status?: 'loading' | 'success' | 'error';
|
|
79
|
+
/** Human-readable error message (only when status = 'error'). */
|
|
80
|
+
error?: string;
|
|
81
|
+
/** Present when the full text was too long and had to be truncated. */
|
|
82
|
+
truncatedInfo?: {
|
|
83
|
+
totalChars: number;
|
|
84
|
+
includedChars: number;
|
|
85
|
+
totalPages: number;
|
|
86
|
+
};
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
/** User-facing Ask modes. 'organize' is internal-only (not selectable by users). */
|