@nextclaw/ui 0.13.4 → 0.13.5
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/CHANGELOG.md +64 -0
- package/dist/assets/api-BAyyGaoz.js +15 -0
- package/dist/assets/app-presenter-provider-DqHHfC1K.js +3 -0
- package/dist/assets/arrow-left-Bn-3Pj3p.js +1 -0
- package/dist/assets/{boxes-BvA-I63l.js → boxes-ClVuotcz.js} +1 -1
- package/dist/assets/channels-list-page-BnGxv6ma.js +8 -0
- package/dist/assets/chat-page-DInyWLb4.js +105 -0
- package/dist/assets/config-split-page-CWN2YG9U.js +1 -0
- package/dist/assets/confirm-dialog-CVbgKuHp.js +5 -0
- package/dist/assets/{createLucideIcon-Br1EFMEr.js → createLucideIcon-CjPUPAAK.js} +1 -1
- package/dist/assets/desktop-update-config-abmYzHSy.js +1 -0
- package/dist/assets/{dist-rzakR_bu.js → dist-hkrb6Ynt.js} +1 -1
- package/dist/assets/doc-browser-BlrpUKVJ.js +1 -0
- package/dist/assets/doc-browser-context-Cb1sEUT0.js +1 -0
- package/dist/assets/doc-browser-kJ2ClG0H.js +1 -0
- package/dist/assets/ellipsis-CdkxFkVZ.js +1 -0
- package/dist/assets/{external-link-DHjFdCpy.js → external-link-CT9_qFwN.js} +1 -1
- package/dist/assets/index-BGXTR0F_.css +1 -0
- package/dist/assets/index-Ccbswzt9.js +101 -0
- package/dist/assets/{key-round-D41Oe35x.js → key-round-xJfR4iRe.js} +1 -1
- package/dist/assets/{book-open-CRotBOF2.js → loader-circle-BI6HJDg5.js} +1 -1
- package/dist/assets/{mcp-marketplace-page-Dvi8mCBd.js → mcp-marketplace-page-CmUKUeno.js} +2 -2
- package/dist/assets/mcp-marketplace-page-DH11bSVx.js +1 -0
- package/dist/assets/model-config-Dbo3zWDl.js +1 -0
- package/dist/assets/notice-card-CFTFtJky.js +1 -0
- package/dist/assets/play-DyBWW2j4.js +1 -0
- package/dist/assets/plus-BlnBmcKE.js +1 -0
- package/dist/assets/popover-DPqa_Mfb.js +1 -0
- package/dist/assets/provider-models-CXUgDxGR.js +1 -0
- package/dist/assets/provider-scoped-model-input-C6xL7zSJ.js +1 -0
- package/dist/assets/providers-list-DOj_7GL8.js +1 -0
- package/dist/assets/react-oAHNoVya.js +1 -0
- package/dist/assets/refresh-cw-o8NSmIYV.js +1 -0
- package/dist/assets/remote-fCE5fLsj.js +1 -0
- package/dist/assets/rotate-cw-DA8EqNAH.js +1 -0
- package/dist/assets/runtime-config-page-Dg8aEgWx.js +1 -0
- package/dist/assets/{save-aYdSdK97.js → save-D4-g0EAq.js} +1 -1
- package/dist/assets/search-G2cMn3M5.js +1 -0
- package/dist/assets/{search-config-G2O1fcRb.js → search-config-DAibVFGR.js} +1 -1
- package/dist/assets/{secrets-config-TenzxYbE.js → secrets-config-CoJzy13_.js} +2 -2
- package/dist/assets/{status-dot-BSMG7ZaC.js → status-dot-D8xx5ZR8.js} +1 -1
- package/dist/assets/{tabs-D1CjpWNX.js → tabs-DxmND60Q.js} +1 -1
- package/dist/assets/{tabs-custom-CRSN1ekg.js → tabs-custom-Cjo0bHw8.js} +1 -1
- package/dist/assets/{tag-chip-DEashiw6.js → tag-chip-DnNWFRMu.js} +1 -1
- package/dist/assets/{trash-2-DSWTsARW.js → trash-2-C9tc-9sQ.js} +1 -1
- package/dist/assets/x-DmLl2yG6.js +1 -0
- package/dist/index.html +24 -23
- package/dist/logos/mimo.svg +9 -0
- package/package.json +8 -8
- package/public/logos/mimo.svg +9 -0
- package/src/app/components/layout/app-layout.tsx +10 -2
- package/src/features/agents/components/agents-page.tsx +6 -4
- package/src/features/chat/hooks/use-ncp-chat-page-data.ts +17 -10
- package/src/features/marketplace/components/marketplace-list-card.tsx +22 -1
- package/src/features/marketplace/components/marketplace-page.tsx +3 -1
- package/src/features/marketplace/hooks/use-marketplace.ts +3 -1
- package/src/features/marketplace/utils/marketplace-installed-cache.utils.ts +8 -0
- package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +70 -6
- package/src/features/right-panel-resources/utils/right-panel-resource-route-resolver.utils.test.ts +25 -1
- package/src/features/right-panel-resources/utils/right-panel-resource-route-resolver.utils.ts +1 -1
- package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.test.ts +42 -0
- package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +22 -0
- package/src/features/service-apps/components/service-apps-panel.test.tsx +88 -0
- package/src/features/service-apps/components/service-apps-panel.tsx +246 -56
- package/src/features/service-apps/hooks/use-service-apps.ts +14 -0
- package/src/features/side-dock/components/side-dock.test.tsx +58 -3
- package/src/features/side-dock/components/side-dock.tsx +77 -24
- package/src/features/side-dock/configs/side-dock-built-in-items.config.ts +37 -34
- package/src/features/side-dock/index.ts +2 -0
- package/src/features/side-dock/managers/side-dock.manager.test.ts +84 -3
- package/src/features/side-dock/managers/side-dock.manager.ts +135 -12
- package/src/features/side-dock/types/side-dock.types.ts +11 -4
- package/src/features/side-dock/utils/side-dock-item.utils.test.ts +8 -8
- package/src/features/side-dock/utils/side-dock-item.utils.ts +13 -5
- package/src/platforms/desktop/components/desktop-app-shell.tsx +5 -2
- package/src/platforms/mobile/components/mobile-app-shell.tsx +4 -1
- package/src/shared/components/config/provider-form-support.test.ts +21 -0
- package/src/shared/components/config/provider-form-support.ts +38 -78
- package/src/shared/components/config/provider-form.tsx +54 -67
- package/src/shared/components/config/providers-list.tsx +211 -73
- package/src/shared/components/doc-browser/doc-browser-context.test.tsx +73 -0
- package/src/shared/components/doc-browser/doc-browser-context.tsx +3 -0
- package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +25 -2
- package/src/shared/components/doc-browser/doc-browser.test.tsx +42 -0
- package/src/shared/components/doc-browser/doc-browser.tsx +38 -7
- package/src/shared/components/doc-browser/index.ts +1 -0
- package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +30 -6
- package/src/shared/components/doc-browser/stores/doc-browser.store.ts +29 -0
- package/src/shared/components/doc-browser/types/doc-browser.types.ts +23 -0
- package/src/shared/components/doc-browser/utils/doc-browser-state.utils.ts +7 -0
- package/src/shared/components/model-config.tsx +5 -4
- package/src/shared/components/provider-auth-section.tsx +2 -2
- package/src/shared/components/ui/switch.tsx +5 -2
- package/src/shared/hooks/use-config.ts +27 -6
- package/src/shared/lib/api/marketplace.types.ts +193 -0
- package/src/shared/lib/api/types.ts +23 -200
- package/src/shared/lib/api/utils/config.utils.ts +17 -7
- package/src/shared/lib/i18n/index.ts +10 -12
- package/src/shared/lib/i18n/{marketplace.ts → marketplace-labels.utils.ts} +3 -0
- package/src/shared/lib/i18n/runtime/doc-browser-labels.utils.ts +46 -2
- package/src/shared/lib/provider-models/index.test.ts +93 -15
- package/src/shared/lib/provider-models/index.ts +35 -20
- package/src/shared/lib/transport/request-raw-api-response.utils.ts +1 -1
- package/dist/assets/api-DruAcori.js +0 -15
- package/dist/assets/app-presenter-provider-DIcnNB9s.js +0 -3
- package/dist/assets/channels-list-page-wK3l7p5R.js +0 -8
- package/dist/assets/chat-page-DgehvdJT.js +0 -105
- package/dist/assets/config-split-page-BnTO1mAM.js +0 -1
- package/dist/assets/confirm-dialog-CGrKHbAW.js +0 -5
- package/dist/assets/desktop-update-config-CehWxSSg.js +0 -1
- package/dist/assets/dist-CpwDZDtv.js +0 -1
- package/dist/assets/doc-browser-BgxmVsTx.js +0 -1
- package/dist/assets/doc-browser-CZn5-Qbu.js +0 -1
- package/dist/assets/doc-browser-context-B8gk7HMr.js +0 -1
- package/dist/assets/index-DORmh0Cy.css +0 -1
- package/dist/assets/index-DcFpvnge.js +0 -101
- package/dist/assets/mcp-marketplace-page-DBLhJWOJ.js +0 -1
- package/dist/assets/model-config-B-EJXGtO.js +0 -1
- package/dist/assets/play-C-0vo7hi.js +0 -1
- package/dist/assets/plus-Cr_akLp2.js +0 -1
- package/dist/assets/popover-YieElO8c.js +0 -1
- package/dist/assets/provider-scoped-model-input-BPRNGqYn.js +0 -1
- package/dist/assets/providers-list-CtBpL1ZY.js +0 -1
- package/dist/assets/react-B2X_ph0a.js +0 -1
- package/dist/assets/remote-BGHbHoHf.js +0 -1
- package/dist/assets/rotate-cw-jueVCNJQ.js +0 -1
- package/dist/assets/runtime-config-page-C1Hv7mad.js +0 -1
- package/dist/assets/search-CdhgFNwf.js +0 -1
- package/dist/assets/setting-row-BNu0qhOM.js +0 -1
- package/dist/assets/x-D1v_vb54.js +0 -1
- package/src/shared/components/provider-enabled-field.tsx +0 -23
- /package/dist/assets/{config-hints-A7G_jMTU.js → config-hints-TmNgpFHv.js} +0 -0
|
@@ -2,13 +2,102 @@ import { describe, expect, it } from 'vitest';
|
|
|
2
2
|
import { buildProviderModelCatalog } from './index';
|
|
3
3
|
|
|
4
4
|
describe('buildProviderModelCatalog', () => {
|
|
5
|
+
it('keeps empty provider models empty', () => {
|
|
6
|
+
const catalog = buildProviderModelCatalog({
|
|
7
|
+
onlyConfigured: false,
|
|
8
|
+
providersView: {
|
|
9
|
+
providers: {
|
|
10
|
+
openai: {
|
|
11
|
+
providerId: 'openai',
|
|
12
|
+
providerType: 'openai',
|
|
13
|
+
isBuiltInType: true,
|
|
14
|
+
isCustom: false,
|
|
15
|
+
enabled: true,
|
|
16
|
+
apiKeySet: true,
|
|
17
|
+
models: []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
templatesView: {
|
|
22
|
+
providerTemplates: [
|
|
23
|
+
{
|
|
24
|
+
id: 'openai',
|
|
25
|
+
providerType: 'openai',
|
|
26
|
+
displayName: 'OpenAI',
|
|
27
|
+
modelPrefix: 'openai',
|
|
28
|
+
defaultModels: ['openai/gpt-5.5', 'openai/gpt-5.4'],
|
|
29
|
+
keywords: [],
|
|
30
|
+
envKey: 'OPENAI_API_KEY'
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(catalog).toHaveLength(1);
|
|
37
|
+
expect(catalog[0]?.models).toEqual([]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('keeps builtin modelConfig when a configured provider has an empty persisted modelConfig', () => {
|
|
41
|
+
const catalog = buildProviderModelCatalog({
|
|
42
|
+
onlyConfigured: true,
|
|
43
|
+
providersView: {
|
|
44
|
+
providers: {
|
|
45
|
+
gemini: {
|
|
46
|
+
providerId: 'gemini',
|
|
47
|
+
providerType: 'gemini',
|
|
48
|
+
isBuiltInType: true,
|
|
49
|
+
isCustom: false,
|
|
50
|
+
enabled: true,
|
|
51
|
+
apiKeySet: true,
|
|
52
|
+
models: ['gemini/gemini-3.1-pro-preview'],
|
|
53
|
+
modelConfig: {}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
templatesView: {
|
|
58
|
+
providerTemplates: [
|
|
59
|
+
{
|
|
60
|
+
id: 'gemini',
|
|
61
|
+
providerType: 'gemini',
|
|
62
|
+
displayName: 'Gemini',
|
|
63
|
+
modelPrefix: 'gemini',
|
|
64
|
+
defaultModels: ['gemini/gemini-3.1-pro-preview'],
|
|
65
|
+
modelConfig: {
|
|
66
|
+
'gemini/gemini-3.1-pro-preview': { vision: true }
|
|
67
|
+
},
|
|
68
|
+
keywords: [],
|
|
69
|
+
envKey: 'GEMINI_API_KEY'
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
expect(catalog[0]?.modelConfig).toEqual({
|
|
76
|
+
'gemini-3.1-pro-preview': { vision: true }
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
5
80
|
it('does not resurrect an OpenRouter model removed from config models', () => {
|
|
6
81
|
const catalog = buildProviderModelCatalog({
|
|
7
82
|
onlyConfigured: true,
|
|
8
|
-
|
|
9
|
-
providers:
|
|
83
|
+
providersView: {
|
|
84
|
+
providers: {
|
|
85
|
+
openrouter: {
|
|
86
|
+
providerId: 'openrouter',
|
|
87
|
+
providerType: 'openrouter',
|
|
88
|
+
isBuiltInType: true,
|
|
89
|
+
isCustom: false,
|
|
90
|
+
enabled: true,
|
|
91
|
+
apiKeySet: true,
|
|
92
|
+
models: ['openrouter/openai/gpt-5.3-codex']
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
templatesView: {
|
|
97
|
+
providerTemplates: [
|
|
10
98
|
{
|
|
11
|
-
|
|
99
|
+
id: 'openrouter',
|
|
100
|
+
providerType: 'openrouter',
|
|
12
101
|
displayName: 'OpenRouter',
|
|
13
102
|
modelPrefix: 'openrouter',
|
|
14
103
|
defaultModels: [
|
|
@@ -19,18 +108,7 @@ describe('buildProviderModelCatalog', () => {
|
|
|
19
108
|
envKey: 'OPENROUTER_API_KEY'
|
|
20
109
|
}
|
|
21
110
|
],
|
|
22
|
-
|
|
23
|
-
channels: []
|
|
24
|
-
},
|
|
25
|
-
config: {
|
|
26
|
-
providers: {
|
|
27
|
-
openrouter: {
|
|
28
|
-
enabled: true,
|
|
29
|
-
apiKeySet: true,
|
|
30
|
-
models: ['openai/gpt-5.3-codex']
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
} as never
|
|
111
|
+
}
|
|
34
112
|
});
|
|
35
113
|
|
|
36
114
|
expect(catalog).toHaveLength(1);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ConfigView, ProviderConfigView, ProviderTemplateView, ProvidersView, ProviderTemplatesView, ThinkingLevel } from '@/shared/lib/api';
|
|
2
2
|
|
|
3
|
-
const THINKING_LEVELS: ThinkingLevel[] = ['off', 'minimal', 'low', 'medium', 'high', 'adaptive', 'xhigh'];
|
|
3
|
+
export const THINKING_LEVELS: ThinkingLevel[] = ['off', 'minimal', 'low', 'medium', 'high', 'adaptive', 'xhigh'];
|
|
4
4
|
const THINKING_LEVEL_SET = new Set<string>(THINKING_LEVELS);
|
|
5
5
|
|
|
6
6
|
export type ModelThinkingCapability = {
|
|
@@ -38,6 +38,14 @@ export function normalizeStringList(input: string[] | null | undefined): string[
|
|
|
38
38
|
return [...deduped];
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export function resolveModelsWithDefaults(defaultModels: string[], savedModels: string[]): string[] {
|
|
42
|
+
const normalizedSavedModels = normalizeStringList(savedModels);
|
|
43
|
+
if (normalizedSavedModels.length > 0) {
|
|
44
|
+
return normalizedSavedModels;
|
|
45
|
+
}
|
|
46
|
+
return normalizeStringList(defaultModels);
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
export function stripProviderPrefix(model: string, prefix: string): string {
|
|
42
50
|
const trimmed = model.trim();
|
|
43
51
|
const cleanPrefix = prefix.trim();
|
|
@@ -74,7 +82,7 @@ export function composeProviderModel(prefix: string, localModel: string): string
|
|
|
74
82
|
return `${normalizedPrefix}/${normalizedModel}`;
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
function parseThinkingLevel(value: unknown): ThinkingLevel | null {
|
|
85
|
+
export function parseThinkingLevel(value: unknown): ThinkingLevel | null {
|
|
78
86
|
if (typeof value !== 'string') {
|
|
79
87
|
return null;
|
|
80
88
|
}
|
|
@@ -85,7 +93,7 @@ function parseThinkingLevel(value: unknown): ThinkingLevel | null {
|
|
|
85
93
|
return THINKING_LEVEL_SET.has(normalized) ? (normalized as ThinkingLevel) : null;
|
|
86
94
|
}
|
|
87
95
|
|
|
88
|
-
function normalizeThinkingLevels(values: unknown): ThinkingLevel[] {
|
|
96
|
+
export function normalizeThinkingLevels(values: unknown): ThinkingLevel[] {
|
|
89
97
|
if (!Array.isArray(values)) {
|
|
90
98
|
return [];
|
|
91
99
|
}
|
|
@@ -132,11 +140,9 @@ export function normalizeModelConfigMap(
|
|
|
132
140
|
return normalized;
|
|
133
141
|
}
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
aliases: string[]
|
|
143
|
+
function extractModelThinkingMap(
|
|
144
|
+
modelConfig: Record<string, ModelConfig>
|
|
138
145
|
): Record<string, ModelThinkingCapability> {
|
|
139
|
-
const modelConfig = normalizeModelConfigMap(input, aliases);
|
|
140
146
|
return Object.fromEntries(
|
|
141
147
|
Object.entries(modelConfig)
|
|
142
148
|
.filter((entry): entry is [string, ModelConfig & { thinking: ModelThinkingCapability }] =>
|
|
@@ -204,28 +210,37 @@ function isProviderConfigured(provider: ProviderConfigView | undefined): boolean
|
|
|
204
210
|
}
|
|
205
211
|
|
|
206
212
|
export function buildProviderModelCatalog(params: {
|
|
207
|
-
|
|
213
|
+
providersView?: ProvidersView;
|
|
214
|
+
templatesView?: ProviderTemplatesView;
|
|
208
215
|
config?: ConfigView;
|
|
209
216
|
onlyConfigured?: boolean;
|
|
210
217
|
}): ProviderModelCatalogItem[] {
|
|
211
|
-
const {
|
|
218
|
+
const { providersView, templatesView, config, onlyConfigured = false } = params;
|
|
219
|
+
const templateByType = new Map((templatesView?.providerTemplates ?? []).map((template) => [template.providerType, template]));
|
|
220
|
+
const providerEntries = Object.values(providersView?.providers ?? config?.providers ?? {});
|
|
212
221
|
|
|
213
|
-
const catalog =
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
222
|
+
const catalog = providerEntries.map((providerConfig) => {
|
|
223
|
+
const { providerId } = providerConfig;
|
|
224
|
+
const template: ProviderTemplateView | undefined = providerConfig.providerType
|
|
225
|
+
? templateByType.get(providerConfig.providerType)
|
|
226
|
+
: undefined;
|
|
227
|
+
const prefix = providerId.trim();
|
|
228
|
+
const aliases = normalizeStringList([providerId, template?.modelPrefix || '', template?.providerType || '']);
|
|
229
|
+
const savedModels = normalizeStringList(
|
|
218
230
|
(providerConfig?.models ?? []).map((model) => toProviderLocalModel(model, aliases))
|
|
219
231
|
);
|
|
220
|
-
const
|
|
221
|
-
const modelConfig =
|
|
222
|
-
|
|
232
|
+
const models = savedModels;
|
|
233
|
+
const modelConfig = {
|
|
234
|
+
...normalizeModelConfigMap(template?.modelConfig, aliases),
|
|
235
|
+
...normalizeModelConfigMap(providerConfig?.modelConfig, aliases)
|
|
236
|
+
};
|
|
237
|
+
const modelThinking = extractModelThinkingMap(modelConfig);
|
|
223
238
|
const configDisplayName = providerConfig?.displayName?.trim();
|
|
224
239
|
const configured = isProviderConfigured(providerConfig);
|
|
225
240
|
|
|
226
241
|
return {
|
|
227
|
-
name:
|
|
228
|
-
displayName: configDisplayName ||
|
|
242
|
+
name: providerId,
|
|
243
|
+
displayName: configDisplayName || template?.displayName || providerId,
|
|
229
244
|
prefix,
|
|
230
245
|
aliases,
|
|
231
246
|
models,
|
|
@@ -8,7 +8,7 @@ function compactSnippet(text: string) {
|
|
|
8
8
|
function inferNonJsonHint(endpoint: string, status: number): string | undefined {
|
|
9
9
|
if (
|
|
10
10
|
status === 404 &&
|
|
11
|
-
endpoint.startsWith('/api/
|
|
11
|
+
endpoint.startsWith('/api/providers/') &&
|
|
12
12
|
endpoint.endsWith('/test')
|
|
13
13
|
) {
|
|
14
14
|
return 'Provider test endpoint is missing. This usually means nextclaw runtime version is outdated.';
|