@geminilight/mindos 0.6.67 → 0.6.70
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 +26 -25
- 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 +7 -7
- 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.js +1 -1
- package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/registry/route.js +1 -1
- package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/session/route.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_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/agents/copy-skill/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/agents/copy-skill/route_client-reference-manifest.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_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask/route.js +17 -17
- 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.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.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.nft.json +1 -1
- package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/channels/verify/route.js +1 -0
- package/_standalone/.next/server/app/api/channels/verify/route.js.nft.json +1 -0
- package/_standalone/.next/server/app/api/channels/verify/route_client-reference-manifest.js +1 -0
- package/_standalone/.next/server/app/api/connect/route_client-reference-manifest.js +1 -1
- 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.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.js +1 -1
- 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/raw/route.js.nft.json +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.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.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.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.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/im/config/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/im/status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/im/test/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/inbox/clip/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/inbox/clip/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/inbox/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.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/lint/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/lint/route_client-reference-manifest.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/direct-tools/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/tools/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.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.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.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_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.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_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/space-overview/route.js +2 -2
- package/_standalone/.next/server/app/api/space-overview/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/space-overview/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.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_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.nft.json +1 -1
- package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/changelog/page.js +1 -1
- package/_standalone/.next/server/app/changelog/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/changes/page.js +1 -1
- 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.js.nft.json +1 -1
- package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/view/[...path]/page.js +3 -3
- package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/wiki/page.js +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 +26 -25
- package/_standalone/.next/server/chunks/3437.js +2 -2
- package/_standalone/.next/server/chunks/5299.js +1 -0
- package/_standalone/.next/server/chunks/6022.js +39 -39
- package/_standalone/.next/server/chunks/6133.js +54 -0
- package/_standalone/.next/server/chunks/6539.js +1 -1
- package/_standalone/.next/server/chunks/8326.js +1 -0
- package/_standalone/.next/server/chunks/8388.js +5 -3
- package/_standalone/.next/server/chunks/953.js +6 -4
- package/_standalone/.next/server/chunks/9938.js +24 -0
- package/_standalone/.next/server/middleware-build-manifest.js +1 -1
- package/_standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/_standalone/.next/server/pages/500.html +2 -2
- package/_standalone/.next/server/server-reference-manifest.js +1 -1
- package/_standalone/.next/server/server-reference-manifest.json +1 -1
- package/_standalone/.next/static/chunks/1814.8a1fef15856dce84.js +1 -0
- package/_standalone/.next/static/chunks/2654-e07c692d6c99f25b.js +1 -0
- package/_standalone/.next/static/chunks/{2935.7d75923daaf448d3.js → 2935.9b08eeade3644806.js} +1 -1
- package/_standalone/.next/static/chunks/3269.a7343771e3f0ff58.js +48 -0
- package/_standalone/.next/static/chunks/3637.2b2697198968d83f.js +1 -0
- package/_standalone/.next/static/chunks/{5550-b7c97fc13628db15.js → 4327-d70a8d457e2d03fe.js} +1 -1
- package/_standalone/.next/static/chunks/48-c88ea6a2a45f15b4.js +28 -0
- package/_standalone/.next/static/chunks/5581-6d403608b5dfb20b.js +29 -0
- package/_standalone/.next/static/chunks/6902-edc5c487c696bd0b.js +3 -0
- package/_standalone/.next/static/chunks/808.72eb7bdd399e9a24.js +1 -0
- package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/{route-e0c1e2c67572781c.js → route-930dfa67e2789df5.js} +1 -1
- package/_standalone/.next/static/chunks/app/_global-error/{page-e0c1e2c67572781c.js → page-930dfa67e2789df5.js} +1 -1
- package/_standalone/.next/static/chunks/app/agents/page-3dc2bf2f6bc7334c.js +1 -0
- package/_standalone/.next/static/chunks/app/api/a2a/agents/{route-e0c1e2c67572781c.js → route-930dfa67e2789df5.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/delegations/{route-e0c1e2c67572781c.js → route-930dfa67e2789df5.js} +1 -1
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/a2a/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/config/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/install/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/acp/session/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/copy-skill/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/agents/custom/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/auth/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/backlinks/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/changes/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/channels/verify/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/connect/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/export/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/import/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/raw/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/file/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/files/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/git/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/graph/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/health/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/im/config/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/im/status/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/im/test/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/inbox/clip/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/inbox/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/init/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/lint/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/direct-tools/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/tools/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/monitoring/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/recent-files/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/restart/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/search/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/setup/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/skills/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/space-overview/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/sync/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/tree-version/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/uninstall/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-check/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/update-status/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/api/workflows/route-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/changes/page-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/echo/[segment]/page-75a6330292613587.js +157 -0
- package/_standalone/.next/static/chunks/app/echo/page-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/{layout-9bb19a959ffb87ac.js → layout-8aa53b34ef34a246.js} +28 -28
- package/_standalone/.next/static/chunks/app/loading-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/{page-c3be6477dbcf182d.js → page-318332501426ef5b.js} +1 -1
- package/_standalone/.next/static/chunks/app/trash/page-17bd5aedcfea9b65.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/page-d5c37c41c556013d.js +12 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-930dfa67e2789df5.js +1 -0
- package/_standalone/.next/static/chunks/webpack-1c2d44f6d86f3986.js +1 -0
- package/_standalone/.next/static/css/a8cadde78aea8585.css +1 -0
- package/_standalone/.next/static/ixCTELNH6V05Z00pC6ZMO/_buildManifest.js +1 -0
- package/_standalone/.next/trace +72 -71
- package/_standalone/.next/types/routes.d.ts +2 -1
- package/_standalone/.next/types/validator.ts +9 -0
- package/_standalone/MINDOS_ARCHITECTURE_DIAGRAM.md +488 -0
- package/_standalone/MINDOS_EXPLORATION_SUMMARY.md +229 -0
- package/_standalone/MINDOS_INFRASTRUCTURE_ANALYSIS.md +732 -0
- package/_standalone/__tests__/acp/agent-descriptors.test.ts +101 -3
- package/_standalone/__tests__/acp/registry.test.ts +34 -5
- package/_standalone/__tests__/acp/session.test.ts +346 -167
- package/_standalone/__tests__/agent/provider-endpoints.test.ts +70 -0
- package/_standalone/__tests__/api/channels-verify.test.ts +75 -0
- package/_standalone/__tests__/api/extract-pdf.test.ts +265 -0
- package/_standalone/__tests__/api/test-key.test.ts +15 -3
- package/_standalone/__tests__/channel-mgmt.test.js +11 -0
- package/_standalone/__tests__/components/breadcrumb-header-ux.test.ts +14 -0
- package/_standalone/__tests__/components/header-toc-vertical-alignment.test.ts +23 -0
- package/_standalone/__tests__/components/table-of-contents-header-layout.test.ts +15 -0
- package/_standalone/__tests__/components/view-page-header-layout.test.ts +13 -0
- package/_standalone/__tests__/components/view-page-header-scroll-stability.test.ts +34 -0
- package/_standalone/__tests__/core/hybrid-search.test.ts +109 -0
- package/_standalone/components/Breadcrumb.tsx +10 -10
- package/_standalone/components/FindInPage.tsx +1 -1
- package/_standalone/components/MarkdownView.tsx +4 -0
- package/_standalone/components/Panel.tsx +17 -10
- package/_standalone/components/TableOfContents.tsx +9 -9
- package/_standalone/components/agents/AgentsContentChannelDetail.tsx +168 -54
- package/_standalone/components/agents/AgentsContentChannels.tsx +22 -22
- package/_standalone/components/ask/AskContent.tsx +68 -28
- package/_standalone/components/ask/AskHeader.tsx +6 -2
- package/_standalone/components/ask/ProviderModelCapsule.tsx +11 -9
- package/_standalone/components/ask/SessionHistoryPanel.tsx +398 -0
- package/_standalone/components/panels/AgentsPanel.tsx +8 -1
- package/_standalone/components/settings/AiTab.tsx +5 -1
- package/_standalone/components/settings/KnowledgeTab.tsx +92 -1
- package/_standalone/components/settings/McpConnectGuides.tsx +4 -0
- package/_standalone/components/settings/McpPortSection.tsx +207 -0
- package/_standalone/components/settings/McpTab.tsx +1 -5
- package/_standalone/components/settings/TestButton.tsx +1 -0
- package/_standalone/components/settings/{ServerPortsCard.tsx → WebPortSection.tsx} +66 -151
- package/_standalone/components/settings/types.ts +12 -0
- package/_standalone/components/settings/useCustomProviderForm.ts +2 -2
- package/_standalone/data/skills/mindos/SKILL.md +45 -1
- package/_standalone/hooks/useAcpDetection.ts +1 -1
- package/_standalone/hooks/useAcpRegistry.ts +1 -1
- package/_standalone/hooks/useFileImport.ts +7 -2
- package/_standalone/hooks/useFileUpload.ts +17 -10
- package/_standalone/lib/acp/index.ts +4 -6
- package/_standalone/lib/acp/types.ts +0 -29
- package/_standalone/lib/im/platforms.ts +6 -2
- package/_standalone/lib/pdf-extract.ts +6 -2
- package/_standalone/package-lock.json +12 -2
- package/_standalone/package.json +2 -1
- package/_standalone/tsconfig.tsbuildinfo +1 -1
- package/app/MINDOS_ARCHITECTURE_DIAGRAM.md +488 -0
- package/app/MINDOS_EXPLORATION_SUMMARY.md +229 -0
- package/app/MINDOS_INFRASTRUCTURE_ANALYSIS.md +732 -0
- package/app/app/api/acp/detect/route.ts +9 -15
- package/app/app/api/channels/verify/route.ts +54 -0
- package/app/app/api/extract-pdf/route.ts +17 -3
- package/app/app/api/settings/list-models/route.ts +40 -44
- package/app/app/api/settings/route.ts +16 -0
- package/app/app/api/settings/test-key/route.ts +5 -2
- package/app/app/view/[...path]/ViewPageClient.tsx +1 -1
- package/app/components/Breadcrumb.tsx +10 -10
- package/app/components/DirView.tsx +1 -1
- package/app/components/FindInPage.tsx +1 -1
- package/app/components/InboxView.tsx +2 -2
- package/app/components/MarkdownView.tsx +4 -0
- package/app/components/Panel.tsx +17 -10
- package/app/components/TableOfContents.tsx +9 -9
- package/app/components/agents/AgentsContentChannelDetail.tsx +168 -54
- package/app/components/agents/AgentsContentChannels.tsx +22 -22
- package/app/components/ask/AskContent.tsx +68 -28
- package/app/components/ask/AskHeader.tsx +6 -2
- package/app/components/ask/ProviderModelCapsule.tsx +11 -9
- package/app/components/ask/SessionHistoryPanel.tsx +398 -0
- package/app/components/panels/AgentsPanel.tsx +8 -1
- package/app/components/settings/AiTab.tsx +5 -1
- package/app/components/settings/KnowledgeTab.tsx +92 -1
- package/app/components/settings/McpConnectGuides.tsx +4 -0
- package/app/components/settings/McpPortSection.tsx +207 -0
- package/app/components/settings/McpTab.tsx +1 -5
- package/app/components/settings/TestButton.tsx +1 -0
- package/app/components/settings/{ServerPortsCard.tsx → WebPortSection.tsx} +66 -151
- package/app/components/settings/types.ts +12 -0
- package/app/components/settings/useCustomProviderForm.ts +2 -2
- package/app/data/skills/mindos/SKILL.md +45 -1
- package/app/hooks/useAcpDetection.ts +1 -1
- package/app/hooks/useAcpRegistry.ts +1 -1
- package/app/hooks/useFileImport.ts +7 -2
- package/app/hooks/useFileUpload.ts +17 -10
- package/app/lib/acp/agent-descriptors.ts +69 -29
- package/app/lib/acp/index.ts +4 -6
- package/app/lib/acp/registry.ts +43 -47
- package/app/lib/acp/session.ts +253 -517
- package/app/lib/acp/subprocess.ts +249 -414
- package/app/lib/acp/types.ts +0 -29
- package/app/lib/agent/model.ts +20 -4
- package/app/lib/agent/non-streaming.ts +37 -20
- package/app/lib/agent/providers.ts +31 -0
- package/app/lib/agent/tools.ts +5 -3
- package/app/lib/core/embedding-index.ts +285 -0
- package/app/lib/core/embedding-provider.ts +164 -0
- package/app/lib/core/hybrid-search.ts +160 -0
- package/app/lib/core/search.ts +11 -21
- package/app/lib/i18n/modules/ai-chat.ts +26 -0
- package/app/lib/i18n/modules/panels.ts +14 -0
- package/app/lib/i18n/modules/settings.ts +2 -0
- package/app/lib/im/platforms.ts +6 -2
- package/app/lib/im/verify.ts +94 -0
- package/app/lib/pdf-extract.ts +6 -2
- package/app/lib/settings.ts +23 -0
- package/app/package.json +2 -1
- package/bin/cli.js +3 -1
- package/bin/commands/channel.js +342 -0
- package/bin/commands/update.js +11 -4
- package/bin/lib/build.js +34 -16
- package/bin/lib/channel-config.js +168 -0
- package/bin/lib/channel-constants.js +88 -0
- package/bin/lib/channel-mgmt.js +244 -0
- package/bin/lib/channel-prompts.js +72 -0
- package/bin/lib/channel-validate.js +57 -0
- package/bin/lib/safe-rm.js +165 -0
- package/package.json +1 -1
- package/skills/mindos/SKILL.md +45 -1
- package/_standalone/.next/server/chunks/1750.js +0 -1
- package/_standalone/.next/server/chunks/8947.js +0 -52
- package/_standalone/.next/static/0JtsgqDZLSJ6MrIZIV6gC/_buildManifest.js +0 -1
- package/_standalone/.next/static/chunks/1814.a79b84d37df75c43.js +0 -1
- package/_standalone/.next/static/chunks/3637.38c4f28d8f698e0e.js +0 -1
- package/_standalone/.next/static/chunks/4351-9ab695985bb808ad.js +0 -1
- package/_standalone/.next/static/chunks/476.463546c195b89cce.js +0 -48
- package/_standalone/.next/static/chunks/5133-3779d65f4fdfb041.js +0 -30
- package/_standalone/.next/static/chunks/5581-4dd3d32f6e8606ec.js +0 -29
- package/_standalone/.next/static/chunks/5998.7bd28de9747440b5.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/page-4c0637183e46c8d3.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/discover/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/a2a/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/config/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/detect/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/install/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/registry/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/acp/session/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agent-activity/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agents/copy-skill/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/agents/custom/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/ask-sessions/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/auth/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/backlinks/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/bootstrap/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/changes/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/connect/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/export/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/extract-pdf/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/import/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/raw/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/file/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/files/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/git/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/graph/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/health/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/im/config/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/im/status/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/im/test/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/inbox/clip/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/inbox/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/init/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/lint/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/agents/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/direct-tools/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/restart/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/status/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/tools/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/monitoring/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/recent-files/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/restart/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/search/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/list-models/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/settings/test-key/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-path/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/check-port/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/ls/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/setup/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/skills/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/space-overview/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/sync/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/tree-version/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/uninstall/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-check/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/update-status/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/api/workflows/route-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/changes/page-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/echo/[segment]/page-5333ab47257fab7f.js +0 -159
- package/_standalone/.next/static/chunks/app/echo/page-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/loading-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/trash/page-bebb28bf472cf691.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/loading-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/page-dd5698f3df138835.js +0 -12
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-e0c1e2c67572781c.js +0 -1
- package/_standalone/.next/static/chunks/webpack-043f40ef7816d8c4.js +0 -1
- package/_standalone/.next/static/css/8b1f248d6540e52f.css +0 -1
- package/_standalone/lib/core/__tests__/synonym-dict.test.ts +0 -82
- package/app/lib/core/__tests__/synonym-dict.test.ts +0 -82
- package/app/lib/core/synonym-dict.ts +0 -139
- /package/_standalone/.next/static/{0JtsgqDZLSJ6MrIZIV6gC → ixCTELNH6V05Z00pC6ZMO}/_ssgManifest.js +0 -0
package/app/lib/acp/types.ts
CHANGED
|
@@ -100,37 +100,8 @@ export interface AcpSessionInfo {
|
|
|
100
100
|
updatedAt?: string;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
/* ── JSON-RPC (ACP uses JSON-RPC 2.0 over stdio) ─────────────────────── */
|
|
104
|
-
|
|
105
|
-
export interface AcpJsonRpcRequest {
|
|
106
|
-
jsonrpc: '2.0';
|
|
107
|
-
id: string | number;
|
|
108
|
-
method: string;
|
|
109
|
-
params?: Record<string, unknown>;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export interface AcpJsonRpcResponse {
|
|
113
|
-
jsonrpc: '2.0';
|
|
114
|
-
id: string | number | null;
|
|
115
|
-
result?: unknown;
|
|
116
|
-
error?: AcpJsonRpcError;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export interface AcpJsonRpcError {
|
|
120
|
-
code: number;
|
|
121
|
-
message: string;
|
|
122
|
-
data?: unknown;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
103
|
/* ── Prompt ────────────────────────────────────────────────────────────── */
|
|
126
104
|
|
|
127
|
-
export interface AcpPromptRequest {
|
|
128
|
-
sessionId: string;
|
|
129
|
-
prompt: AcpContentBlock[];
|
|
130
|
-
context?: { cwd?: string };
|
|
131
|
-
stream?: boolean;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
105
|
export interface AcpPromptResponse {
|
|
135
106
|
sessionId: string;
|
|
136
107
|
text: string;
|
package/app/lib/agent/model.ts
CHANGED
|
@@ -13,6 +13,18 @@ function ensureVisionCapable(model: Model<any>): Model<any> {
|
|
|
13
13
|
return { ...model, input: [...inputs, 'image'] as any };
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Normalize a user-provided baseUrl without changing its semantic path.
|
|
18
|
+
*
|
|
19
|
+
* We only trim whitespace and trailing slashes. We intentionally do not
|
|
20
|
+
* rewrite path segments like `/1` or `/v1`, because some gateways may use
|
|
21
|
+
* custom prefixes and mutating them could break valid configurations.
|
|
22
|
+
*/
|
|
23
|
+
export function normalizeBaseUrl(url: string): string {
|
|
24
|
+
if (!url) return url;
|
|
25
|
+
return url.trim().replace(/\/+$/, '');
|
|
26
|
+
}
|
|
27
|
+
|
|
16
28
|
export interface ModelConfigOverrides {
|
|
17
29
|
provider?: ProviderId;
|
|
18
30
|
apiKey?: string;
|
|
@@ -44,13 +56,14 @@ export function getModelConfig(options?: ModelConfigOverrides): {
|
|
|
44
56
|
};
|
|
45
57
|
|
|
46
58
|
const modelName = cfg.model;
|
|
47
|
-
|
|
59
|
+
const normalizedBaseUrl = normalizeBaseUrl(cfg.baseUrl);
|
|
60
|
+
let model = resolveModel(cfg.provider, modelName, normalizedBaseUrl);
|
|
48
61
|
|
|
49
62
|
if (options?.hasImages) {
|
|
50
63
|
model = ensureVisionCapable(model);
|
|
51
64
|
}
|
|
52
65
|
|
|
53
|
-
return { model, modelName, apiKey: cfg.apiKey, provider: cfg.provider, baseUrl:
|
|
66
|
+
return { model, modelName, apiKey: cfg.apiKey, provider: cfg.provider, baseUrl: normalizedBaseUrl };
|
|
54
67
|
}
|
|
55
68
|
|
|
56
69
|
/**
|
|
@@ -61,7 +74,10 @@ function resolveModel(providerId: ProviderId, modelName: string, baseUrl: string
|
|
|
61
74
|
const piProvider = toPiProvider(providerId);
|
|
62
75
|
const preset = getPreset(providerId);
|
|
63
76
|
let model: Model<any>;
|
|
64
|
-
|
|
77
|
+
|
|
78
|
+
// Normalize user-provided baseUrl before use
|
|
79
|
+
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
80
|
+
const hasCustomBase = !!normalizedBaseUrl;
|
|
65
81
|
|
|
66
82
|
// 1. Try pi-ai registry lookup
|
|
67
83
|
try {
|
|
@@ -92,7 +108,7 @@ function resolveModel(providerId: ProviderId, modelName: string, baseUrl: string
|
|
|
92
108
|
|
|
93
109
|
// 3. Apply user's custom baseUrl
|
|
94
110
|
if (hasCustomBase) {
|
|
95
|
-
model = { ...model, baseUrl };
|
|
111
|
+
model = { ...model, baseUrl: normalizedBaseUrl };
|
|
96
112
|
|
|
97
113
|
if (model.api === 'openai-responses') {
|
|
98
114
|
model = { ...model, api: 'openai-completions' as any };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AgentTool } from '@mariozechner/pi-agent-core';
|
|
2
2
|
import type { MindOSSSEvent } from '@/lib/sse/events';
|
|
3
|
+
import { buildCompatEndpointCandidates } from './providers';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Reassemble SSE chunks (from proxies that ignore stream:false) into a
|
|
@@ -173,32 +174,48 @@ export async function runNonStreamingFallback(opts: NonStreamingOptions): Promis
|
|
|
173
174
|
];
|
|
174
175
|
|
|
175
176
|
const toolMap = new Map(tools.map(t => [t.name, t]));
|
|
176
|
-
const
|
|
177
|
+
const endpoints = buildCompatEndpointCandidates(baseUrl, '/chat/completions', 'openai-completions');
|
|
178
|
+
const attemptedEndpoints = endpoints.join(' , ');
|
|
177
179
|
let step = 0;
|
|
178
180
|
|
|
179
181
|
while (step < maxSteps) {
|
|
180
182
|
if (signal.aborted) throw new Error('Request aborted');
|
|
181
183
|
step++;
|
|
182
184
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
185
|
+
let resp: Response | null = null;
|
|
186
|
+
let lastEndpointError = '';
|
|
187
|
+
|
|
188
|
+
for (const endpoint of endpoints) {
|
|
189
|
+
const attempt = await fetch(endpoint, {
|
|
190
|
+
method: 'POST',
|
|
191
|
+
headers: {
|
|
192
|
+
'Content-Type': 'application/json',
|
|
193
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
194
|
+
},
|
|
195
|
+
body: JSON.stringify({
|
|
196
|
+
model,
|
|
197
|
+
messages,
|
|
198
|
+
tools: openaiTools.length > 0 ? openaiTools : undefined,
|
|
199
|
+
tool_choice: openaiTools.length > 0 ? 'auto' : undefined,
|
|
200
|
+
stream: true,
|
|
201
|
+
}),
|
|
202
|
+
signal,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
if (attempt.ok) {
|
|
206
|
+
resp = attempt;
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const errText = await attempt.text().catch(() => '');
|
|
211
|
+
lastEndpointError = `HTTP ${attempt.status} @ ${endpoint}: ${errText.slice(0, 200)}`;
|
|
212
|
+
if (attempt.status !== 404) {
|
|
213
|
+
throw new Error(`Non-streaming API error ${lastEndpointError}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!resp) {
|
|
218
|
+
throw new Error(`Non-streaming API error ${lastEndpointError || 'all endpoint candidates failed'}; tried ${attemptedEndpoints}`);
|
|
202
219
|
}
|
|
203
220
|
|
|
204
221
|
const rawText = await resp.text();
|
|
@@ -323,6 +323,37 @@ export function getDefaultApi(id: ProviderId): string {
|
|
|
323
323
|
}
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
+
/** Return the effective API type used by a provider (openai-completions, anthropic-messages, etc.). */
|
|
327
|
+
export function getProviderApiType(id: ProviderId): string {
|
|
328
|
+
return getDefaultApi(id);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Build endpoint candidates for compatible providers.
|
|
333
|
+
*
|
|
334
|
+
* We do not assume whether the user-supplied baseUrl already includes a version
|
|
335
|
+
* prefix. For OpenAI- and Anthropic-compatible gateways we try both forms:
|
|
336
|
+
* 1. base + path
|
|
337
|
+
* 2. base + /v1 + path (if base does not already contain /vN)
|
|
338
|
+
*
|
|
339
|
+
* This avoids breaking providers like GLM/Kimi/MiniMax that may use custom path
|
|
340
|
+
* prefixes, while still handling common OpenAI-compatible gateways that expect /v1.
|
|
341
|
+
*/
|
|
342
|
+
export function buildCompatEndpointCandidates(baseUrl: string, path: string, apiType: string): string[] {
|
|
343
|
+
const base = baseUrl.replace(/\/+$/, '');
|
|
344
|
+
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
|
345
|
+
const hasVersionPrefix = /\/v\d+(?:$|\/)/.test(base);
|
|
346
|
+
const candidates = new Set<string>();
|
|
347
|
+
|
|
348
|
+
candidates.add(`${base}${cleanPath}`);
|
|
349
|
+
|
|
350
|
+
if (!hasVersionPrefix && (apiType === 'openai-completions' || apiType === 'openai-responses' || apiType === 'anthropic-messages')) {
|
|
351
|
+
candidates.add(`${base}/v1${cleanPath}`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return Array.from(candidates);
|
|
355
|
+
}
|
|
356
|
+
|
|
326
357
|
// ---------------------------------------------------------------------------
|
|
327
358
|
// Internal: reverse-engineer pi-ai's env var name mapping (for UI display)
|
|
328
359
|
// ---------------------------------------------------------------------------
|
package/app/lib/agent/tools.ts
CHANGED
|
@@ -2,11 +2,13 @@ import path from 'path';
|
|
|
2
2
|
import { Type, type Static } from '@sinclair/typebox';
|
|
3
3
|
import type { AgentTool, AgentToolResult } from '@mariozechner/pi-agent-core';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
getFileContent, getFileTree, getRecentlyModified,
|
|
6
6
|
saveFileContent, createFile, appendToFile, insertAfterHeading, updateSection,
|
|
7
7
|
moveToTrashFile, renameFile, moveFile, findBacklinks, gitLog, gitShowFile, appendCsvRow,
|
|
8
8
|
getMindRoot,
|
|
9
9
|
} from '@/lib/fs';
|
|
10
|
+
import { searchFiles } from '@/lib/core/search';
|
|
11
|
+
import { hybridSearch } from '@/lib/core/hybrid-search';
|
|
10
12
|
import { readSkillContentByName } from '@/lib/pi-integration/skills';
|
|
11
13
|
import { a2aTools } from '@/lib/a2a/a2a-tools';
|
|
12
14
|
import { acpTools } from '@/lib/acp/acp-tools';
|
|
@@ -353,9 +355,9 @@ export const knowledgeBaseTools: AgentTool<any>[] = [
|
|
|
353
355
|
description: 'Full-text search across all files in the knowledge base. Returns matching files with context snippets.',
|
|
354
356
|
parameters: QueryParam,
|
|
355
357
|
execute: safeExecute(async (_id, params: Static<typeof QueryParam>) => {
|
|
356
|
-
const results =
|
|
358
|
+
const results = await hybridSearch(getMindRoot(), params.query);
|
|
357
359
|
if (results.length === 0) return textResult('No results found.');
|
|
358
|
-
return textResult(results.map(r => `- **${r.path}
|
|
360
|
+
return textResult(results.map(r => `- **${r.path}** (score: ${r.score.toFixed(1)}): ${r.snippet}`).join('\n'));
|
|
359
361
|
}),
|
|
360
362
|
},
|
|
361
363
|
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory embedding vector index with JSON file persistence.
|
|
3
|
+
*
|
|
4
|
+
* Stores one embedding vector per file. Supports:
|
|
5
|
+
* - Cosine similarity search
|
|
6
|
+
* - Incremental add/update/remove
|
|
7
|
+
* - Persist to / load from ~/.mindos/embedding-index.json
|
|
8
|
+
*
|
|
9
|
+
* Designed for <2000 files — brute-force cosine is fast enough (~2ms for 1000 docs).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import os from 'os';
|
|
15
|
+
import { collectAllFiles } from './tree';
|
|
16
|
+
import { readFile } from './fs-ops';
|
|
17
|
+
import { getEmbeddings, getEmbedding, getEmbeddingConfig } from './embedding-provider';
|
|
18
|
+
|
|
19
|
+
const MAX_CONTENT_LENGTH = 8_000; // Truncate long files (embedding context window)
|
|
20
|
+
|
|
21
|
+
export interface EmbeddingSearchResult {
|
|
22
|
+
path: string;
|
|
23
|
+
similarity: number; // 0..1 cosine similarity
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class EmbeddingIndex {
|
|
27
|
+
/** filePath → Float32Array (embedding vector) */
|
|
28
|
+
private vectors = new Map<string, Float32Array>();
|
|
29
|
+
private dimensions = 0;
|
|
30
|
+
private builtForRoot: string | null = null;
|
|
31
|
+
|
|
32
|
+
/** Whether a full build or load has been done for this root. */
|
|
33
|
+
private _ready = false;
|
|
34
|
+
|
|
35
|
+
/** Background build in progress — callers should not wait, just use BM25. */
|
|
36
|
+
private _building = false;
|
|
37
|
+
|
|
38
|
+
isReady(): boolean { return this._ready; }
|
|
39
|
+
isBuilding(): boolean { return this._building; }
|
|
40
|
+
|
|
41
|
+
/** Number of indexed documents. */
|
|
42
|
+
getDocCount(): number { return this.vectors.size; }
|
|
43
|
+
|
|
44
|
+
// ── Build ────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Full rebuild: embed all files. Runs async — returns immediately.
|
|
48
|
+
* Callers should check isReady() before calling search().
|
|
49
|
+
*/
|
|
50
|
+
async rebuild(mindRoot: string): Promise<void> {
|
|
51
|
+
if (this._building) return;
|
|
52
|
+
this._building = true;
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const config = getEmbeddingConfig();
|
|
56
|
+
if (!config) { this._building = false; return; }
|
|
57
|
+
|
|
58
|
+
const allFiles = collectAllFiles(mindRoot);
|
|
59
|
+
const texts: string[] = [];
|
|
60
|
+
const paths: string[] = [];
|
|
61
|
+
|
|
62
|
+
for (const filePath of allFiles) {
|
|
63
|
+
// Skip non-text files for embedding
|
|
64
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
65
|
+
if (ext !== '.md' && ext !== '.csv') continue;
|
|
66
|
+
|
|
67
|
+
let content: string;
|
|
68
|
+
try { content = readFile(mindRoot, filePath); } catch { continue; }
|
|
69
|
+
|
|
70
|
+
// Prepend file path as context
|
|
71
|
+
const text = `${filePath}\n${content}`.slice(0, MAX_CONTENT_LENGTH);
|
|
72
|
+
texts.push(text);
|
|
73
|
+
paths.push(filePath);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (texts.length === 0) {
|
|
77
|
+
this._building = false;
|
|
78
|
+
this._ready = true;
|
|
79
|
+
this.builtForRoot = mindRoot;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Batch embed all documents
|
|
84
|
+
const vectors = await getEmbeddings(texts);
|
|
85
|
+
|
|
86
|
+
if (vectors.length !== texts.length) {
|
|
87
|
+
console.error(`[embedding-index] Expected ${texts.length} vectors, got ${vectors.length}`);
|
|
88
|
+
this._building = false;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this.vectors.clear();
|
|
93
|
+
this.dimensions = vectors[0].length;
|
|
94
|
+
for (let i = 0; i < paths.length; i++) {
|
|
95
|
+
this.vectors.set(paths[i], vectors[i]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.builtForRoot = mindRoot;
|
|
99
|
+
this._ready = true;
|
|
100
|
+
|
|
101
|
+
// Persist in background
|
|
102
|
+
try { this.persist(); } catch { /* non-critical */ }
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.error('[embedding-index] Rebuild failed:', err instanceof Error ? err.message : err);
|
|
105
|
+
} finally {
|
|
106
|
+
this._building = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ── Incremental updates ──────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
/** Add or update a single file's embedding. */
|
|
113
|
+
async updateFile(mindRoot: string, filePath: string): Promise<void> {
|
|
114
|
+
if (!this._ready) return;
|
|
115
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
116
|
+
if (ext !== '.md' && ext !== '.csv') return;
|
|
117
|
+
|
|
118
|
+
let content: string;
|
|
119
|
+
try { content = readFile(mindRoot, filePath); } catch { return; }
|
|
120
|
+
|
|
121
|
+
const text = `${filePath}\n${content}`.slice(0, MAX_CONTENT_LENGTH);
|
|
122
|
+
const vector = await getEmbedding(text);
|
|
123
|
+
if (vector) {
|
|
124
|
+
this.vectors.set(filePath, vector);
|
|
125
|
+
if (this.dimensions === 0) this.dimensions = vector.length;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Remove a file from the index. */
|
|
130
|
+
removeFile(filePath: string): void {
|
|
131
|
+
this.vectors.delete(filePath);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ── Search ───────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Find the top-K most similar documents to the query vector.
|
|
138
|
+
* Returns results sorted by descending similarity.
|
|
139
|
+
*/
|
|
140
|
+
searchByVector(queryVector: Float32Array, topK: number = 20): EmbeddingSearchResult[] {
|
|
141
|
+
if (!this._ready || this.vectors.size === 0) return [];
|
|
142
|
+
|
|
143
|
+
const results: EmbeddingSearchResult[] = [];
|
|
144
|
+
|
|
145
|
+
for (const [filePath, docVector] of this.vectors) {
|
|
146
|
+
const sim = cosineSimilarity(queryVector, docVector);
|
|
147
|
+
results.push({ path: filePath, similarity: sim });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
results.sort((a, b) => b.similarity - a.similarity);
|
|
151
|
+
return results.slice(0, topK);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Search by text query: embed the query, then find similar docs.
|
|
156
|
+
* Returns empty array if embedding fails or index not ready.
|
|
157
|
+
*/
|
|
158
|
+
async search(query: string, topK: number = 20): Promise<EmbeddingSearchResult[]> {
|
|
159
|
+
if (!this._ready) return [];
|
|
160
|
+
|
|
161
|
+
const queryVector = await getEmbedding(query);
|
|
162
|
+
if (!queryVector) return [];
|
|
163
|
+
|
|
164
|
+
return this.searchByVector(queryVector, topK);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ── Persistence ──────────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
private get persistPath(): string {
|
|
170
|
+
return path.join(os.homedir(), '.mindos', 'embedding-index.json');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** Serialize to disk. */
|
|
174
|
+
persist(): void {
|
|
175
|
+
if (this.vectors.size === 0) return;
|
|
176
|
+
|
|
177
|
+
const data: PersistedEmbeddingIndex = {
|
|
178
|
+
version: 1,
|
|
179
|
+
builtForRoot: this.builtForRoot ?? '',
|
|
180
|
+
dimensions: this.dimensions,
|
|
181
|
+
docCount: this.vectors.size,
|
|
182
|
+
timestamp: Date.now(),
|
|
183
|
+
vectors: {},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
for (const [filePath, vec] of this.vectors) {
|
|
187
|
+
// Store as regular number array for JSON serialization
|
|
188
|
+
data.vectors[filePath] = Array.from(vec);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const dir = path.dirname(this.persistPath);
|
|
192
|
+
try {
|
|
193
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
194
|
+
fs.writeFileSync(this.persistPath, JSON.stringify(data), 'utf-8');
|
|
195
|
+
} catch {
|
|
196
|
+
// Non-critical
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Load from disk. Returns true if loaded successfully.
|
|
202
|
+
* Staleness check: file count must match and root must match.
|
|
203
|
+
*/
|
|
204
|
+
load(mindRoot: string): boolean {
|
|
205
|
+
try {
|
|
206
|
+
const raw = fs.readFileSync(this.persistPath, 'utf-8');
|
|
207
|
+
const data: PersistedEmbeddingIndex = JSON.parse(raw);
|
|
208
|
+
|
|
209
|
+
if (data.version !== 1 || data.builtForRoot !== mindRoot) return false;
|
|
210
|
+
|
|
211
|
+
// Basic staleness: check file count
|
|
212
|
+
const currentFiles = collectAllFiles(mindRoot);
|
|
213
|
+
const mdCsvCount = currentFiles.filter(f => {
|
|
214
|
+
const ext = path.extname(f).toLowerCase();
|
|
215
|
+
return ext === '.md' || ext === '.csv';
|
|
216
|
+
}).length;
|
|
217
|
+
|
|
218
|
+
// Allow some drift (files added/removed since last persist)
|
|
219
|
+
// If >10% drift, force rebuild
|
|
220
|
+
if (Math.abs(mdCsvCount - data.docCount) > Math.max(5, mdCsvCount * 0.1)) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this.vectors.clear();
|
|
225
|
+
this.dimensions = data.dimensions;
|
|
226
|
+
for (const [filePath, arr] of Object.entries(data.vectors)) {
|
|
227
|
+
this.vectors.set(filePath, new Float32Array(arr));
|
|
228
|
+
}
|
|
229
|
+
this.builtForRoot = data.builtForRoot;
|
|
230
|
+
this._ready = true;
|
|
231
|
+
|
|
232
|
+
return true;
|
|
233
|
+
} catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Clear all state. */
|
|
239
|
+
invalidate(): void {
|
|
240
|
+
this.vectors.clear();
|
|
241
|
+
this.dimensions = 0;
|
|
242
|
+
this.builtForRoot = null;
|
|
243
|
+
this._ready = false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Check if index is built for this root. */
|
|
247
|
+
isBuiltFor(mindRoot: string): boolean {
|
|
248
|
+
return this._ready && this.builtForRoot === mindRoot;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ── Math ─────────────────────────────────────────────────────────
|
|
253
|
+
|
|
254
|
+
/** Cosine similarity between two vectors. Returns 0..1 (clamped). */
|
|
255
|
+
export function cosineSimilarity(a: Float32Array, b: Float32Array): number {
|
|
256
|
+
if (a.length !== b.length || a.length === 0) return 0;
|
|
257
|
+
|
|
258
|
+
let dot = 0;
|
|
259
|
+
let normA = 0;
|
|
260
|
+
let normB = 0;
|
|
261
|
+
|
|
262
|
+
for (let i = 0; i < a.length; i++) {
|
|
263
|
+
dot += a[i] * b[i];
|
|
264
|
+
normA += a[i] * a[i];
|
|
265
|
+
normB += b[i] * b[i];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
269
|
+
if (denom === 0) return 0;
|
|
270
|
+
|
|
271
|
+
// Clamp to [0, 1] — embeddings from the same model are usually positive,
|
|
272
|
+
// but numerical noise can push slightly below 0 or above 1.
|
|
273
|
+
return Math.max(0, Math.min(1, dot / denom));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ── Persistence types ────────────────────────────────────────────
|
|
277
|
+
|
|
278
|
+
interface PersistedEmbeddingIndex {
|
|
279
|
+
version: number;
|
|
280
|
+
builtForRoot: string;
|
|
281
|
+
dimensions: number;
|
|
282
|
+
docCount: number;
|
|
283
|
+
timestamp: number;
|
|
284
|
+
vectors: Record<string, number[]>;
|
|
285
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding API provider — calls OpenAI-compatible /v1/embeddings endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Supports: OpenAI, DeepSeek, Ollama, any OpenAI-compatible embedding API.
|
|
5
|
+
* Config is stored in ~/.mindos/config.json under the `embedding` key.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readSettings } from '@/lib/settings';
|
|
9
|
+
|
|
10
|
+
export interface EmbeddingConfig {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
baseUrl: string; // e.g. "https://api.openai.com/v1"
|
|
13
|
+
apiKey: string;
|
|
14
|
+
model: string; // e.g. "text-embedding-3-small"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Read embedding config from settings. Returns null if not configured or disabled. */
|
|
18
|
+
export function getEmbeddingConfig(): EmbeddingConfig | null {
|
|
19
|
+
try {
|
|
20
|
+
const s = readSettings();
|
|
21
|
+
const e = s.embedding;
|
|
22
|
+
if (!e || !e.enabled) return null;
|
|
23
|
+
if (!e.baseUrl || !e.model) return null;
|
|
24
|
+
// apiKey can be empty for local providers like Ollama
|
|
25
|
+
return {
|
|
26
|
+
enabled: true,
|
|
27
|
+
baseUrl: e.baseUrl.replace(/\/+$/, ''), // strip trailing slash
|
|
28
|
+
apiKey: e.apiKey || '',
|
|
29
|
+
model: e.model,
|
|
30
|
+
};
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Maximum texts per batch (OpenAI limit is 2048, we use a conservative default). */
|
|
37
|
+
const BATCH_SIZE = 100;
|
|
38
|
+
|
|
39
|
+
/** Request timeout in ms. */
|
|
40
|
+
const TIMEOUT_MS = 30_000;
|
|
41
|
+
|
|
42
|
+
/** Max retries on transient errors (429, 5xx). */
|
|
43
|
+
const MAX_RETRIES = 2;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get embeddings for an array of texts.
|
|
47
|
+
* Returns Float32Array[] with one vector per input text.
|
|
48
|
+
* Returns empty array on failure (graceful fallback — never throws).
|
|
49
|
+
*/
|
|
50
|
+
export async function getEmbeddings(texts: string[]): Promise<Float32Array[]> {
|
|
51
|
+
const config = getEmbeddingConfig();
|
|
52
|
+
if (!config || texts.length === 0) return [];
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const results: Float32Array[] = [];
|
|
56
|
+
|
|
57
|
+
// Process in batches
|
|
58
|
+
for (let i = 0; i < texts.length; i += BATCH_SIZE) {
|
|
59
|
+
const batch = texts.slice(i, i + BATCH_SIZE);
|
|
60
|
+
const batchResults = await callEmbeddingApi(config, batch);
|
|
61
|
+
if (batchResults.length === 0) return []; // Abort on any batch failure
|
|
62
|
+
results.push(...batchResults);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return results;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error('[embedding] Failed to get embeddings:', err instanceof Error ? err.message : err);
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get embedding for a single text. Convenience wrapper.
|
|
74
|
+
* Returns null on failure.
|
|
75
|
+
*/
|
|
76
|
+
export async function getEmbedding(text: string): Promise<Float32Array | null> {
|
|
77
|
+
const results = await getEmbeddings([text]);
|
|
78
|
+
return results.length > 0 ? results[0] : null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Call the OpenAI-compatible /v1/embeddings endpoint with retry logic. */
|
|
82
|
+
async function callEmbeddingApi(
|
|
83
|
+
config: EmbeddingConfig,
|
|
84
|
+
texts: string[],
|
|
85
|
+
): Promise<Float32Array[]> {
|
|
86
|
+
const url = `${config.baseUrl}/embeddings`;
|
|
87
|
+
const body = JSON.stringify({
|
|
88
|
+
model: config.model,
|
|
89
|
+
input: texts,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const headers: Record<string, string> = {
|
|
93
|
+
'Content-Type': 'application/json',
|
|
94
|
+
};
|
|
95
|
+
if (config.apiKey) {
|
|
96
|
+
headers['Authorization'] = `Bearer ${config.apiKey}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
100
|
+
try {
|
|
101
|
+
const controller = new AbortController();
|
|
102
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
103
|
+
|
|
104
|
+
const res = await fetch(url, {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers,
|
|
107
|
+
body,
|
|
108
|
+
signal: controller.signal,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
clearTimeout(timer);
|
|
112
|
+
|
|
113
|
+
if (!res.ok) {
|
|
114
|
+
const status = res.status;
|
|
115
|
+
// Retry on rate limit or server errors
|
|
116
|
+
if ((status === 429 || status >= 500) && attempt < MAX_RETRIES) {
|
|
117
|
+
const retryAfter = parseInt(res.headers.get('retry-after') || '1', 10);
|
|
118
|
+
await sleep(Math.min(retryAfter * 1000, 5000));
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const errText = await res.text().catch(() => '');
|
|
122
|
+
console.error(`[embedding] API error ${status}: ${errText.slice(0, 200)}`);
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const json = await res.json() as EmbeddingResponse;
|
|
127
|
+
if (!json.data || !Array.isArray(json.data)) {
|
|
128
|
+
console.error('[embedding] Unexpected response shape');
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Sort by index (API may return out of order)
|
|
133
|
+
json.data.sort((a, b) => a.index - b.index);
|
|
134
|
+
|
|
135
|
+
return json.data.map(d => new Float32Array(d.embedding));
|
|
136
|
+
} catch (err) {
|
|
137
|
+
if (attempt < MAX_RETRIES) {
|
|
138
|
+
await sleep(1000 * (attempt + 1)); // Exponential-ish backoff
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
console.error('[embedding] Request failed:', err instanceof Error ? err.message : err);
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** OpenAI /v1/embeddings response shape. */
|
|
150
|
+
interface EmbeddingResponse {
|
|
151
|
+
data: Array<{
|
|
152
|
+
index: number;
|
|
153
|
+
embedding: number[];
|
|
154
|
+
}>;
|
|
155
|
+
model: string;
|
|
156
|
+
usage?: {
|
|
157
|
+
prompt_tokens: number;
|
|
158
|
+
total_tokens: number;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function sleep(ms: number): Promise<void> {
|
|
163
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
164
|
+
}
|