@geminilight/mindos 0.6.63 → 0.6.65
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 +21 -21
- 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/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.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 +48 -42
- 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/export/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/import/route.js +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/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/mcp/agents/route.js +1 -1
- package/_standalone/.next/server/app/api/mcp/agents/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install/route_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.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.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.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.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/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 +2 -2
- 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 +2 -2
- package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/trash/page.js +3 -3
- package/_standalone/.next/server/app/trash/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/view/[...path]/page.js +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 +21 -21
- package/_standalone/.next/server/chunks/122.js +222 -0
- package/_standalone/.next/server/chunks/3113.js +52 -0
- package/_standalone/.next/server/chunks/6539.js +1 -1
- package/_standalone/.next/server/chunks/8388.js +2 -2
- package/_standalone/.next/server/chunks/953.js +3 -3
- package/_standalone/.next/server/chunks/9787.js +2 -0
- 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/1001-99da82ec8d8c136f.js +1 -0
- package/_standalone/.next/static/chunks/5149-4d828886dda479fa.js +1 -0
- package/_standalone/.next/static/chunks/{5581-82e5db227f8e9393.js → 5581-c671163a2fe1b312.js} +2 -2
- package/_standalone/.next/static/chunks/6636-53238eff89503f03.js +6 -0
- package/_standalone/.next/static/chunks/6757-1c1a89720fdda8f0.js +1 -0
- package/_standalone/.next/static/chunks/7129-20e9d2463a9da646.js +1 -0
- package/_standalone/.next/static/chunks/{3674-be69a8b858ceacdd.js → 7294-cac25d97869afadc.js} +1 -1
- package/_standalone/.next/static/chunks/8225-21e5cebc3731ddf0.js +1 -0
- package/_standalone/.next/static/chunks/8520-b51810e66293ceb8.js +22 -0
- package/_standalone/.next/static/chunks/9207-dc9c31b351a2ed78.js +1 -0
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/{page-b0dabe793500383d.js → page-2f5cf97e03dc1cc9.js} +1 -1
- package/_standalone/.next/static/chunks/app/agents/{page-1f1ac330c8177cf6.js → page-50eac58d511dcc6e.js} +1 -1
- package/_standalone/.next/static/chunks/app/echo/[segment]/page-2a00f4686adf3885.js +11 -0
- package/_standalone/.next/static/chunks/app/{layout-50a6b1164ee98ab9.js → layout-2cb7a6602d2e5d5f.js} +62 -58
- package/_standalone/.next/static/chunks/app/{page-73802bd31d7f6c9f.js → page-5ab911b2226f6ff7.js} +1 -1
- package/_standalone/.next/static/chunks/app/setup/page-907b7c57fad2292b.js +1 -0
- package/_standalone/.next/static/chunks/app/trash/page-11a511b065ea84c2.js +1 -0
- package/_standalone/.next/static/chunks/app/view/[...path]/{page-808f39963bf04715.js → page-26e47dd4c533a58c.js} +2 -2
- package/_standalone/.next/static/css/67e7918f5ed7d147.css +1 -0
- package/_standalone/.next/trace +65 -65
- package/_standalone/__tests__/api/ask-attachments.test.ts +194 -0
- package/_standalone/__tests__/api/settings.test.ts +16 -12
- package/_standalone/__tests__/api/setup.test.ts +11 -9
- package/_standalone/__tests__/api/test-key.test.ts +0 -10
- package/_standalone/__tests__/components/UpdateToast.test.ts +344 -0
- package/_standalone/__tests__/core/context.test.ts +48 -426
- package/_standalone/__tests__/lib/pi-skills.test.ts +4 -4
- package/_standalone/__tests__/lib/settings-ai-client.test.ts +32 -12
- package/_standalone/__tests__/setup.ts +5 -5
- package/_standalone/components/ask/AskContent.tsx +70 -40
- package/_standalone/components/ask/AskHeader.tsx +8 -1
- package/_standalone/components/ask/MessageList.tsx +37 -3
- package/_standalone/components/ask/ProviderModelCapsule.tsx +51 -129
- package/_standalone/components/settings/AiTab.tsx +270 -347
- package/_standalone/components/settings/CustomProviderFields.tsx +121 -0
- package/_standalone/components/settings/CustomProvidersCard.tsx +2 -2
- package/_standalone/components/settings/KnowledgeTab.tsx +6 -20
- package/_standalone/components/settings/McpAgentInstall.tsx +7 -2
- package/_standalone/components/settings/Primitives.tsx +48 -104
- package/_standalone/components/settings/ProviderModal.tsx +38 -221
- package/_standalone/components/settings/SettingsContent.tsx +5 -12
- package/_standalone/components/settings/TestButton.tsx +64 -0
- package/_standalone/components/settings/types.ts +3 -12
- package/_standalone/components/settings/useCustomProviderForm.ts +132 -0
- package/_standalone/components/setup/StepAI.tsx +3 -3
- package/_standalone/components/shared/ModelInput.tsx +18 -4
- package/_standalone/components/shared/ProviderSelect.tsx +126 -134
- package/_standalone/hooks/useAskChat.ts +97 -13
- package/_standalone/hooks/useAskPanel.ts +17 -1
- package/_standalone/lib/settings-ai-client.ts +17 -8
- package/_standalone/tsconfig.tsbuildinfo +1 -1
- package/app/app/api/ask/route.ts +124 -44
- package/app/app/api/mcp/agents/route.ts +3 -3
- package/app/app/api/settings/list-models/route.ts +15 -26
- package/app/app/api/settings/route.ts +14 -59
- package/app/app/api/settings/test-key/route.ts +47 -12
- package/app/app/api/setup/route.ts +36 -18
- package/app/app/api/skills/route.ts +1 -1
- package/app/app/layout.tsx +5 -3
- package/app/components/HomeContent.tsx +11 -0
- package/app/components/UpdateToast.tsx +255 -0
- package/app/components/ask/AskContent.tsx +70 -40
- package/app/components/ask/AskHeader.tsx +8 -1
- package/app/components/ask/MessageList.tsx +37 -3
- package/app/components/ask/ProviderModelCapsule.tsx +51 -129
- package/app/components/settings/AiTab.tsx +270 -347
- package/app/components/settings/CustomProviderFields.tsx +121 -0
- package/app/components/settings/CustomProvidersCard.tsx +2 -2
- package/app/components/settings/KnowledgeTab.tsx +6 -20
- package/app/components/settings/McpAgentInstall.tsx +7 -2
- package/app/components/settings/Primitives.tsx +48 -104
- package/app/components/settings/ProviderModal.tsx +38 -221
- package/app/components/settings/SettingsContent.tsx +5 -12
- package/app/components/settings/TestButton.tsx +64 -0
- package/app/components/settings/types.ts +3 -12
- package/app/components/settings/useCustomProviderForm.ts +132 -0
- package/app/components/setup/StepAI.tsx +3 -3
- package/app/components/shared/ModelInput.tsx +18 -4
- package/app/components/shared/ProviderSelect.tsx +126 -134
- package/app/hooks/useAskChat.ts +97 -13
- package/app/hooks/useAskPanel.ts +17 -1
- package/app/lib/agent/context.ts +65 -0
- package/app/lib/agent/providers.ts +25 -0
- package/app/lib/agent/tools.ts +1 -1
- package/app/lib/custom-endpoints.ts +129 -29
- package/app/lib/i18n/modules/settings.ts +20 -0
- package/app/lib/pi-integration/skills.ts +16 -4
- package/app/lib/settings-ai-client.ts +17 -8
- package/app/lib/settings.ts +64 -90
- package/app/lib/types.ts +4 -0
- package/package.json +1 -1
- package/_standalone/.next/server/chunks/530.js +0 -218
- package/_standalone/.next/server/chunks/9007.js +0 -2
- package/_standalone/.next/server/chunks/9137.js +0 -52
- package/_standalone/.next/static/chunks/1309-373ade1b40aea186.js +0 -1
- package/_standalone/.next/static/chunks/3165-9189a38fd9ebf6f2.js +0 -1
- package/_standalone/.next/static/chunks/4587-5d06728133fff222.js +0 -1
- package/_standalone/.next/static/chunks/6261-5ce86db54b19ae46.js +0 -1
- package/_standalone/.next/static/chunks/6636-9bbc90fb3b8731fe.js +0 -6
- package/_standalone/.next/static/chunks/7637-904b0a381dc3ec02.js +0 -1
- package/_standalone/.next/static/chunks/8520-84e607f33c409f91.js +0 -22
- package/_standalone/.next/static/chunks/9207-9a4a1a1ede4f8e6e.js +0 -1
- package/_standalone/.next/static/chunks/app/echo/[segment]/page-bc5e104eb7ae6327.js +0 -11
- package/_standalone/.next/static/chunks/app/setup/page-79acb0baf38184c6.js +0 -1
- package/_standalone/.next/static/chunks/app/trash/page-d040db56863da504.js +0 -1
- package/_standalone/.next/static/css/1287672978833d07.css +0 -1
- package/_standalone/lib/agent/context.ts +0 -403
- /package/_standalone/.next/static/{X86rF8dKEO0InosOw4a2_ → eIlwbGas1iRGonlPyEwj7}/_buildManifest.js +0 -0
- /package/_standalone/.next/static/{X86rF8dKEO0InosOw4a2_ → eIlwbGas1iRGonlPyEwj7}/_ssgManifest.js +0 -0
|
@@ -7,15 +7,13 @@ import { useLocale } from '@/lib/stores/locale-store';
|
|
|
7
7
|
import {
|
|
8
8
|
type ProviderId,
|
|
9
9
|
PROVIDER_PRESETS,
|
|
10
|
-
ALL_PROVIDER_IDS,
|
|
11
10
|
isProviderId,
|
|
12
|
-
getApiKeyEnvVar,
|
|
13
11
|
} from '@/lib/agent/providers';
|
|
14
|
-
import { type
|
|
12
|
+
import { type Provider, isProviderEntryId, findProvider } from '@/lib/custom-endpoints';
|
|
15
13
|
|
|
16
14
|
const STORAGE_KEY = 'mindos-provider-model';
|
|
17
15
|
|
|
18
|
-
type ProviderSelection = ProviderId | `
|
|
16
|
+
type ProviderSelection = ProviderId | `p_${string}` | null;
|
|
19
17
|
|
|
20
18
|
interface ProviderModelCapsuleProps {
|
|
21
19
|
providerValue: ProviderSelection;
|
|
@@ -27,10 +25,9 @@ interface ProviderModelCapsuleProps {
|
|
|
27
25
|
|
|
28
26
|
interface SettingsData {
|
|
29
27
|
ai?: {
|
|
30
|
-
|
|
31
|
-
providers?:
|
|
28
|
+
activeProvider?: string;
|
|
29
|
+
providers?: Provider[];
|
|
32
30
|
};
|
|
33
|
-
customProviders?: CustomProvider[];
|
|
34
31
|
envOverrides?: Record<string, boolean>;
|
|
35
32
|
}
|
|
36
33
|
|
|
@@ -42,11 +39,11 @@ export function getPersistedProviderModel(): { provider: ProviderSelection; mode
|
|
|
42
39
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
43
40
|
if (!raw) {
|
|
44
41
|
const old = localStorage.getItem('mindos-provider-override');
|
|
45
|
-
if (old && (isProviderId(old) ||
|
|
42
|
+
if (old && (isProviderId(old) || isProviderEntryId(old))) return { provider: old as any, model: null };
|
|
46
43
|
return { provider: null, model: null };
|
|
47
44
|
}
|
|
48
45
|
const parsed = JSON.parse(raw);
|
|
49
|
-
const provider = parsed?.provider && (isProviderId(parsed.provider) ||
|
|
46
|
+
const provider = parsed?.provider && (isProviderId(parsed.provider) || isProviderEntryId(parsed.provider))
|
|
50
47
|
? parsed.provider : null;
|
|
51
48
|
const model = typeof parsed?.model === 'string' ? parsed.model : null;
|
|
52
49
|
return { provider, model };
|
|
@@ -63,24 +60,8 @@ function persistProviderModel(provider: ProviderSelection, model: string | null)
|
|
|
63
60
|
|
|
64
61
|
/* ── Configured providers ── */
|
|
65
62
|
|
|
66
|
-
function getConfiguredProviders(data: SettingsData):
|
|
67
|
-
|
|
68
|
-
const providers = data.ai?.providers ?? {};
|
|
69
|
-
const customProviders = data.customProviders ?? [];
|
|
70
|
-
const env = data.envOverrides ?? {};
|
|
71
|
-
for (const id of ALL_PROVIDER_IDS) {
|
|
72
|
-
const preset = PROVIDER_PRESETS[id];
|
|
73
|
-
const hasKey = providers[id]?.apiKey === '***set***';
|
|
74
|
-
const envVar = getApiKeyEnvVar(id);
|
|
75
|
-
const hasEnv = envVar ? !!env[envVar] : false;
|
|
76
|
-
if (hasKey || hasEnv) { result.push(id); }
|
|
77
|
-
else if (preset.apiKeyFallback) {
|
|
78
|
-
const cfg = providers[id];
|
|
79
|
-
if (data.ai?.provider === id || (cfg && (cfg.model || cfg.baseUrl))) result.push(id);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
for (const cp of customProviders) result.push(cp.id as `cp_${string}`);
|
|
83
|
-
return result;
|
|
63
|
+
function getConfiguredProviders(data: SettingsData): string[] {
|
|
64
|
+
return (data.ai?.providers ?? []).map(p => p.id);
|
|
84
65
|
}
|
|
85
66
|
|
|
86
67
|
/* ── Component ── */
|
|
@@ -101,7 +82,7 @@ export default function ProviderModelCapsule({
|
|
|
101
82
|
// Flyout state
|
|
102
83
|
const providerPanelRef = useRef<HTMLDivElement>(null);
|
|
103
84
|
const hoveredRowRef = useRef<HTMLDivElement>(null);
|
|
104
|
-
const [hoveredProvider, setHoveredProvider] = useState<
|
|
85
|
+
const [hoveredProvider, setHoveredProvider] = useState<string | null>(null);
|
|
105
86
|
const [flyoutStyle, setFlyoutStyle] = useState<React.CSSProperties>({});
|
|
106
87
|
const [expandedModels, setExpandedModels] = useState<string[] | null>(null);
|
|
107
88
|
const [modelsLoading, setModelsLoading] = useState(false);
|
|
@@ -151,8 +132,7 @@ export default function ProviderModelCapsule({
|
|
|
151
132
|
return () => { cancelled = true; document.removeEventListener('visibilitychange', onVisible); window.removeEventListener('mindos:settings-changed', onChange); };
|
|
152
133
|
}, []);
|
|
153
134
|
|
|
154
|
-
const defaultProvider =
|
|
155
|
-
? settingsData.ai.provider as ProviderId : 'anthropic';
|
|
135
|
+
const defaultProvider = settingsData?.ai?.activeProvider || '';
|
|
156
136
|
|
|
157
137
|
const configuredProviders = useMemo(
|
|
158
138
|
() => settingsData ? getConfiguredProviders(settingsData) : [],
|
|
@@ -170,14 +150,12 @@ export default function ProviderModelCapsule({
|
|
|
170
150
|
|
|
171
151
|
// Resolve active display
|
|
172
152
|
const activeProvider = providerValue ?? defaultProvider;
|
|
173
|
-
const
|
|
174
|
-
const
|
|
175
|
-
const
|
|
176
|
-
const defaultModel = customProvider?.model
|
|
177
|
-
|| settingsData?.ai?.providers?.[activeProvider as ProviderId]?.model
|
|
153
|
+
const activeEntry = findProvider(settingsData?.ai?.providers ?? [], String(activeProvider));
|
|
154
|
+
const activePreset = activeEntry ? PROVIDER_PRESETS[activeEntry.protocol] : null;
|
|
155
|
+
const defaultModel = activeEntry?.model
|
|
178
156
|
|| activePreset?.defaultModel || '';
|
|
179
157
|
const displayModel = modelValue || defaultModel;
|
|
180
|
-
const displayName =
|
|
158
|
+
const displayName = activeEntry?.name
|
|
181
159
|
|| (activePreset ? (locale === 'zh' ? activePreset.nameZh : activePreset.name) : String(activeProvider));
|
|
182
160
|
|
|
183
161
|
/* ── Dropdown positioning ── */
|
|
@@ -244,7 +222,7 @@ export default function ProviderModelCapsule({
|
|
|
244
222
|
}, [open, hoveredProvider]);
|
|
245
223
|
|
|
246
224
|
/* ── Model fetching ── */
|
|
247
|
-
const fetchModels = useCallback(async (providerId:
|
|
225
|
+
const fetchModels = useCallback(async (providerId: string, force = false) => {
|
|
248
226
|
if (!force && modelsCacheRef.current[providerId]) {
|
|
249
227
|
setExpandedModels(modelsCacheRef.current[providerId]);
|
|
250
228
|
setModelsLoading(false);
|
|
@@ -254,14 +232,9 @@ export default function ProviderModelCapsule({
|
|
|
254
232
|
setModelsLoading(true); setModelsError(''); setExpandedModels(null);
|
|
255
233
|
const version = ++fetchVersionRef.current;
|
|
256
234
|
try {
|
|
257
|
-
const isCustom = isCustomProviderId(String(providerId));
|
|
258
|
-
const body: Record<string, string> = isCustom
|
|
259
|
-
? { customProviderId: providerId }
|
|
260
|
-
: { provider: providerId };
|
|
261
|
-
|
|
262
235
|
const res = await fetch('/api/settings/list-models', {
|
|
263
236
|
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
264
|
-
body: JSON.stringify(
|
|
237
|
+
body: JSON.stringify({ provider: providerId }),
|
|
265
238
|
});
|
|
266
239
|
if (version !== fetchVersionRef.current) return;
|
|
267
240
|
const json = await res.json();
|
|
@@ -277,19 +250,13 @@ export default function ProviderModelCapsule({
|
|
|
277
250
|
}
|
|
278
251
|
}, []);
|
|
279
252
|
|
|
280
|
-
const canCustomProviderExpand = useCallback((cpId: string) => {
|
|
281
|
-
if (!isCustomProviderId(cpId)) return false;
|
|
282
|
-
const cp = findCustomProvider(settingsData?.customProviders ?? [], cpId);
|
|
283
|
-
return !!cp; // All custom providers can now expand (they use their baseProviderId)
|
|
284
|
-
}, [settingsData]);
|
|
285
|
-
|
|
286
253
|
// Determine if a provider can show model flyout
|
|
287
|
-
const canProviderExpand = useCallback((id:
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
return
|
|
292
|
-
}, [
|
|
254
|
+
const canProviderExpand = useCallback((id: string) => {
|
|
255
|
+
const entry = findProvider(settingsData?.ai?.providers ?? [], id);
|
|
256
|
+
if (!entry) return false;
|
|
257
|
+
const preset = PROVIDER_PRESETS[entry.protocol];
|
|
258
|
+
return preset?.supportsListModels ?? false;
|
|
259
|
+
}, [settingsData]);
|
|
293
260
|
|
|
294
261
|
// Compute flyout position: anchored to right edge of provider panel, aligned to hovered row
|
|
295
262
|
const computeFlyoutPosition = useCallback(() => {
|
|
@@ -323,7 +290,7 @@ export default function ProviderModelCapsule({
|
|
|
323
290
|
}, []);
|
|
324
291
|
|
|
325
292
|
// Open flyout for a provider (debounced to prevent flicker)
|
|
326
|
-
const openFlyout = useCallback((providerId:
|
|
293
|
+
const openFlyout = useCallback((providerId: string) => {
|
|
327
294
|
cancelCloseTimer();
|
|
328
295
|
if (openTimerRef.current) clearTimeout(openTimerRef.current);
|
|
329
296
|
openTimerRef.current = setTimeout(() => {
|
|
@@ -378,7 +345,7 @@ export default function ProviderModelCapsule({
|
|
|
378
345
|
if (e.key === 'ArrowDown') { e.preventDefault(); setModelHighlight(i => (i + 1) % filteredModels.length); }
|
|
379
346
|
else if (e.key === 'ArrowUp') { e.preventDefault(); setModelHighlight(i => (i - 1 + filteredModels.length) % filteredModels.length); }
|
|
380
347
|
else if (e.key === 'Enter' && modelHighlight >= 0 && modelHighlight < filteredModels.length && hoveredProvider) {
|
|
381
|
-
e.preventDefault(); handleSelectModel(hoveredProvider, filteredModels[modelHighlight]);
|
|
348
|
+
e.preventDefault(); handleSelectModel(hoveredProvider as ProviderSelection, filteredModels[modelHighlight]);
|
|
382
349
|
} else if (e.key === 'Escape') { e.preventDefault(); setHoveredProvider(null); setModelSearch(''); }
|
|
383
350
|
}, [filteredModels, modelHighlight, hoveredProvider, handleSelectModel]);
|
|
384
351
|
|
|
@@ -391,19 +358,22 @@ export default function ProviderModelCapsule({
|
|
|
391
358
|
/* ── Guards ── */
|
|
392
359
|
if (!settingsData || configuredProviders.length === 0) return null;
|
|
393
360
|
|
|
394
|
-
const modelShort = (displayModel || '').length >
|
|
395
|
-
? (displayModel || '').slice(0,
|
|
396
|
-
|
|
397
|
-
const
|
|
361
|
+
const modelShort = (displayModel || '').length > 20
|
|
362
|
+
? (displayModel || '').slice(0, 18) + '…' : displayModel;
|
|
363
|
+
// For built-in providers, use shortLabel; for custom, truncate if too long
|
|
364
|
+
const providerDisplay = (displayName || '').length > 12
|
|
365
|
+
? (displayName || '').slice(0, 10) + '…'
|
|
366
|
+
: (activePreset?.shortLabel || displayName);
|
|
367
|
+
const capsuleTooltip = `${displayName} · ${displayModel}`;
|
|
368
|
+
const providerIds = configuredProviders;
|
|
398
369
|
const hasModelOverride = !!(modelValue && modelValue !== defaultModel);
|
|
399
370
|
|
|
400
371
|
/* ── Render: flyout (right panel) — positioned absolutely via portal ── */
|
|
401
372
|
const renderFlyout = () => {
|
|
402
373
|
if (!hoveredProvider) return null;
|
|
403
|
-
const
|
|
404
|
-
const preset =
|
|
405
|
-
const
|
|
406
|
-
const displayName = customProvider?.name || (preset ? (locale === 'zh' ? preset.nameZh : preset.name) : String(hoveredProvider));
|
|
374
|
+
const hovEntry = findProvider(settingsData?.ai?.providers ?? [], hoveredProvider);
|
|
375
|
+
const preset = hovEntry ? PROVIDER_PRESETS[hovEntry.protocol] : null;
|
|
376
|
+
const displayName = hovEntry?.name || (preset ? (locale === 'zh' ? preset.nameZh : preset.name) : String(hoveredProvider));
|
|
407
377
|
|
|
408
378
|
return createPortal(
|
|
409
379
|
<div
|
|
@@ -462,11 +432,11 @@ export default function ProviderModelCapsule({
|
|
|
462
432
|
)}
|
|
463
433
|
{filteredModels.map((m, i) => {
|
|
464
434
|
const isModelSelected = providerValue === hoveredProvider && modelValue === m;
|
|
465
|
-
const defModel =
|
|
435
|
+
const defModel = hovEntry?.model || preset?.defaultModel;
|
|
466
436
|
return (
|
|
467
437
|
<button
|
|
468
438
|
key={m} type="button" data-model-item
|
|
469
|
-
onClick={() => handleSelectModel(hoveredProvider, m)}
|
|
439
|
+
onClick={() => handleSelectModel(hoveredProvider as ProviderSelection, m)}
|
|
470
440
|
className={`w-full text-left px-2 py-1 text-2xs rounded transition-colors flex items-center gap-1 ${
|
|
471
441
|
isModelSelected ? 'bg-[var(--amber)]/12 text-foreground font-medium'
|
|
472
442
|
: i === modelHighlight ? 'bg-accent' : 'hover:bg-accent/60'
|
|
@@ -502,26 +472,28 @@ export default function ProviderModelCapsule({
|
|
|
502
472
|
className="w-[220px] rounded-lg border border-border bg-card shadow-lg py-1 animate-in fade-in-0 zoom-in-95 duration-100"
|
|
503
473
|
style={{ maxHeight: '70vh', overflowY: 'auto' }}
|
|
504
474
|
>
|
|
505
|
-
{
|
|
506
|
-
const
|
|
507
|
-
|
|
475
|
+
{providerIds.map((id) => {
|
|
476
|
+
const entry = findProvider(settingsData?.ai?.providers ?? [], id);
|
|
477
|
+
if (!entry) return null;
|
|
478
|
+
const preset = PROVIDER_PRESETS[entry.protocol];
|
|
479
|
+
const provName = entry.name || (locale === 'zh' ? preset?.nameZh : preset?.name) || id;
|
|
508
480
|
const provModel = modelValue && providerValue === id ? modelValue
|
|
509
|
-
:
|
|
481
|
+
: entry.model || preset?.defaultModel || '';
|
|
510
482
|
const isSelected = providerValue === id || (!providerValue && defaultProvider === id);
|
|
511
483
|
const isHovered = hoveredProvider === id;
|
|
512
|
-
const canExpand = canProviderExpand(id
|
|
484
|
+
const canExpand = canProviderExpand(id);
|
|
513
485
|
|
|
514
486
|
return (
|
|
515
487
|
<div
|
|
516
488
|
key={id}
|
|
517
489
|
ref={isHovered ? hoveredRowRef : undefined}
|
|
518
|
-
onMouseEnter={() => canExpand ? openFlyout(id
|
|
490
|
+
onMouseEnter={() => canExpand ? openFlyout(id) : closeFlyoutImmediate()}
|
|
519
491
|
onMouseLeave={startCloseTimer}
|
|
520
492
|
>
|
|
521
493
|
<div className={`flex w-full items-center text-xs transition-colors ${isHovered ? 'bg-accent/60' : 'hover:bg-muted/60'}`}>
|
|
522
494
|
<button
|
|
523
495
|
type="button" role="option" aria-selected={isSelected}
|
|
524
|
-
onClick={() => handleSelectProvider(id as
|
|
496
|
+
onClick={() => handleSelectProvider(id as ProviderSelection)}
|
|
525
497
|
className="flex flex-1 items-center gap-2 px-3 py-1.5 min-w-0"
|
|
526
498
|
>
|
|
527
499
|
<div className="flex-1 min-w-0 truncate">
|
|
@@ -538,57 +510,7 @@ export default function ProviderModelCapsule({
|
|
|
538
510
|
onClick={(e) => {
|
|
539
511
|
e.stopPropagation();
|
|
540
512
|
if (hoveredProvider === id) closeFlyoutImmediate();
|
|
541
|
-
else openFlyout(id
|
|
542
|
-
}}
|
|
543
|
-
className={`shrink-0 px-1.5 py-1.5 mr-1 rounded transition-colors ${
|
|
544
|
-
isHovered ? 'text-foreground' : 'text-muted-foreground/40 hover:text-muted-foreground'
|
|
545
|
-
}`}
|
|
546
|
-
title={t.ask?.selectModel ?? 'Select model'}
|
|
547
|
-
>
|
|
548
|
-
<ChevronRight size={11} />
|
|
549
|
-
</button>
|
|
550
|
-
)}
|
|
551
|
-
</div>
|
|
552
|
-
</div>
|
|
553
|
-
);
|
|
554
|
-
})}
|
|
555
|
-
|
|
556
|
-
{customIds.map((id) => {
|
|
557
|
-
const cp = findCustomProvider(settingsData?.customProviders ?? [], String(id));
|
|
558
|
-
if (!cp) return null;
|
|
559
|
-
const cpModel = modelValue && providerValue === id ? modelValue : cp.model;
|
|
560
|
-
const isSelected = providerValue === id;
|
|
561
|
-
const isHovered = hoveredProvider === id;
|
|
562
|
-
const canExpand = canProviderExpand(id as `cp_${string}`);
|
|
563
|
-
|
|
564
|
-
return (
|
|
565
|
-
<div
|
|
566
|
-
key={id}
|
|
567
|
-
ref={isHovered ? hoveredRowRef : undefined}
|
|
568
|
-
onMouseEnter={() => canExpand ? openFlyout(id as `cp_${string}`) : closeFlyoutImmediate()}
|
|
569
|
-
onMouseLeave={startCloseTimer}
|
|
570
|
-
>
|
|
571
|
-
<div className={`flex w-full items-center text-xs transition-colors ${isHovered ? 'bg-accent/60' : 'hover:bg-muted/60'}`}>
|
|
572
|
-
<button
|
|
573
|
-
type="button" role="option" aria-selected={isSelected}
|
|
574
|
-
onClick={() => handleSelectProvider(id)}
|
|
575
|
-
className="flex flex-1 items-center gap-2 px-3 py-1.5 min-w-0"
|
|
576
|
-
>
|
|
577
|
-
<div className="flex-1 min-w-0 truncate">
|
|
578
|
-
<span className={`text-xs ${isSelected ? 'font-medium text-foreground' : 'text-foreground/80'}`}>
|
|
579
|
-
{cp.name}
|
|
580
|
-
</span>
|
|
581
|
-
<span className="text-2xs text-muted-foreground ml-1.5">{cpModel}</span>
|
|
582
|
-
</div>
|
|
583
|
-
{isSelected && <Check size={11} className="shrink-0 text-[var(--amber)]" />}
|
|
584
|
-
</button>
|
|
585
|
-
{canExpand && (
|
|
586
|
-
<button
|
|
587
|
-
type="button"
|
|
588
|
-
onClick={(e) => {
|
|
589
|
-
e.stopPropagation();
|
|
590
|
-
if (hoveredProvider === id) closeFlyoutImmediate();
|
|
591
|
-
else openFlyout(id as `cp_${string}`);
|
|
513
|
+
else openFlyout(id);
|
|
592
514
|
}}
|
|
593
515
|
className={`shrink-0 px-1.5 py-1.5 mr-1 rounded transition-colors ${
|
|
594
516
|
isHovered ? 'text-foreground' : 'text-muted-foreground/40 hover:text-muted-foreground'
|
|
@@ -620,7 +542,7 @@ export default function ProviderModelCapsule({
|
|
|
620
542
|
disabled={disabled}
|
|
621
543
|
className={`
|
|
622
544
|
inline-flex items-center gap-1 rounded-full px-2.5 py-0.5
|
|
623
|
-
text-2xs font-medium transition-colors select-none
|
|
545
|
+
text-2xs font-medium transition-colors select-none max-w-[260px]
|
|
624
546
|
border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring
|
|
625
547
|
disabled:opacity-40 disabled:cursor-not-allowed
|
|
626
548
|
${providerValue || hasModelOverride
|
|
@@ -628,13 +550,13 @@ export default function ProviderModelCapsule({
|
|
|
628
550
|
: 'bg-muted/50 border-border/50 text-muted-foreground hover:bg-muted hover:text-foreground'
|
|
629
551
|
}
|
|
630
552
|
`}
|
|
631
|
-
title={
|
|
553
|
+
title={capsuleTooltip}
|
|
632
554
|
aria-expanded={open}
|
|
633
555
|
aria-haspopup="listbox"
|
|
634
556
|
>
|
|
635
557
|
<Cpu size={11} className="shrink-0" />
|
|
636
|
-
<span className="truncate
|
|
637
|
-
{
|
|
558
|
+
<span className="truncate">
|
|
559
|
+
{providerDisplay}
|
|
638
560
|
<span className="text-muted-foreground"> · </span>
|
|
639
561
|
<span className={hasModelOverride ? 'text-[var(--amber)]' : 'text-muted-foreground'}>{modelShort}</span>
|
|
640
562
|
</span>
|