@nextclaw/ui 0.15.0 → 0.15.2
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 +50 -0
- package/dist/assets/{api-DLtsiBKm.js → api-B7Qigvtm.js} +2 -2
- package/dist/assets/{appearance-settings-page-CtkeYXux.js → appearance-settings-page-CuE0Iiqj.js} +1 -1
- package/dist/assets/{book-open-BQwWBDKb.js → book-open-Ba2f7YiG.js} +1 -1
- package/dist/assets/channels-list-page-CTsM6TcP.js +8 -0
- package/dist/assets/chat-page-C_5dcuE3.js +1 -0
- package/dist/assets/config-split-page-Fbb4PtTf.js +1 -0
- package/dist/assets/{confirm-dialog-iIJFFp2T.js → confirm-dialog-D2EG3nqE.js} +1 -1
- package/dist/assets/desktop-update-config-BGR3HUi1.js +1 -0
- package/dist/assets/{dist-D2eZC3OR.js → dist-7JTjycxE.js} +1 -1
- package/dist/assets/{dist-CBxWOazz.js → dist-wXLhk4hl.js} +1 -1
- package/dist/assets/doc-browser-bHyXnxlj.js +1 -0
- package/dist/assets/doc-browser-context-CYAGm5d5.js +1 -0
- package/dist/assets/doc-browser-gTrQ3jCF.js +1 -0
- package/dist/assets/{es2015-DhQo_oS6.js → es2015-j1SRCIX5.js} +1 -1
- package/dist/assets/{external-link-CM5dnUI6.js → external-link-DxuPaDoK.js} +1 -1
- package/dist/assets/form-actions-BztL7P_T.js +1 -0
- package/dist/assets/{i18n-provider-di1waTGX.js → i18n-provider-B4oMxOFx.js} +1 -1
- package/dist/assets/index-CvrvblgX.css +1 -0
- package/dist/assets/index-Obd4JYU2.js +104 -0
- package/dist/assets/loader-circle-CdzgK4eH.js +1 -0
- package/dist/assets/{mcp-marketplace-page-C_MVQUbT.js → mcp-marketplace-page-Bt7CuOoq.js} +2 -2
- package/dist/assets/mcp-marketplace-page-Ck3t78_n.js +1 -0
- package/dist/assets/model-config-page-DeKk9gvE.js +1 -0
- package/dist/assets/plus-Bx7wQbhG.js +1 -0
- package/dist/assets/{provider-scoped-model-input-g1WkGiJ8.js → provider-scoped-model-input-DsH2LF1q.js} +1 -1
- package/dist/assets/providers-config-page-BFnGp68F.js +1 -0
- package/dist/assets/{react-DjpzoZXB.js → react-UirzUuST.js} +1 -1
- package/dist/assets/{refresh-cw-DaTv3zxE.js → refresh-cw-eT8BF-8B.js} +1 -1
- package/dist/assets/remote-CDkHZtA8.js +1 -0
- package/dist/assets/rotate-cw-1JqxHTuw.js +1 -0
- package/dist/assets/runtime-config-page-BelAqiNG.js +1 -0
- package/dist/assets/{save-BZof1uie.js → save-Cb2g0BOi.js} +1 -1
- package/dist/assets/{search-MxAarS_g.js → search-BcHjwdsb.js} +1 -1
- package/dist/assets/search-config-page-zPm6--Ig.js +1 -0
- package/dist/assets/secrets-config-page-Cxyp-KuQ.js +3 -0
- package/dist/assets/security-config-B_gCq9fn.js +1 -0
- package/dist/assets/{select-D7GcNP0z.js → select-CdSEOwVM.js} +1 -1
- package/dist/assets/{setting-row-CuozlnJd.js → setting-row-CTAtGexr.js} +1 -1
- package/dist/assets/settings-2-2DWauOjY.js +1 -0
- package/dist/assets/{side-dock-BcLau5S_.js → side-dock-DPvakJ0a.js} +2 -2
- package/dist/assets/{skeleton-shfmXuYp.js → skeleton-P5oM14E1.js} +1 -1
- package/dist/assets/{switch-C1BWMU5c.js → switch-BU_UEULb.js} +1 -1
- package/dist/assets/{tag-chip-DCUrQUCP.js → tag-chip-D-WsKoT1.js} +1 -1
- package/dist/assets/{tooltip-DfAHHA76.js → tooltip-CjkOaHW7.js} +1 -1
- package/dist/assets/{use-config-DAdbT5QJ.js → use-config--hx5oxQn.js} +1 -1
- package/dist/assets/{use-confirm-dialog-eWcJ6V-s.js → use-confirm-dialog-CD9a_SK1.js} +1 -1
- package/dist/assets/x-DT5x45JU.js +1 -0
- package/dist/index.html +38 -30
- package/index.html +12 -4
- package/package.json +9 -9
- package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +29 -1
- package/src/app/components/layout/sidebar-items.tsx +43 -4
- package/src/app/components/layout/sidebar.tsx +83 -61
- package/src/app/configs/app-navigation.config.ts +49 -0
- package/src/app/styles/design-system.css +82 -0
- package/src/features/agents/components/__tests__/agents-page.test.tsx +135 -2
- package/src/features/agents/components/agent-advanced-config-fields.tsx +70 -0
- package/src/features/agents/components/agent-details-dialog.tsx +398 -0
- package/src/features/agents/components/agent-dialogs.tsx +20 -47
- package/src/features/agents/components/agents-page.tsx +76 -10
- package/src/features/agents/types/agent-form.types.ts +21 -0
- package/src/features/agents/utils/agent-form.utils.ts +39 -0
- package/src/features/channels/components/config/channel-form.tsx +14 -11
- package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +172 -1
- package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +11 -1
- package/src/features/chat/components/conversation/chat-conversation-header.tsx +7 -3
- package/src/features/chat/components/conversation/chat-conversation-panel.tsx +1 -1
- package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +48 -0
- package/src/features/chat/components/layout/__tests__/chat-sidebar-utility-menu.test.tsx +55 -0
- package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +0 -3
- package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +3 -4
- package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +29 -30
- package/src/features/chat/components/layout/chat-sidebar.tsx +21 -7
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +18 -3
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +2 -1
- package/src/features/chat/features/message/components/__tests__/chat-inline-panel-app-card.test.tsx +22 -1
- package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +1 -1
- package/src/features/chat/features/message/components/chat-inline-panel-app-card.tsx +10 -5
- package/src/features/chat/features/message/utils/chat-inline-panel-app-card.utils.ts +0 -11
- package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-agent-runtime.test.tsx +23 -1
- package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-session-list-view.test.tsx +74 -0
- package/src/features/chat/features/ncp/hooks/use-ncp-session-list-view.ts +3 -2
- package/src/features/chat/features/session/components/__tests__/chat-sidebar-project-groups.test.tsx +116 -0
- package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +108 -46
- package/src/features/chat/features/session/components/chat-sidebar-session-entry.tsx +6 -0
- package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +48 -24
- package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +0 -3
- package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +0 -4
- package/src/features/chat/features/session/components/session-header/chat-session-title-switcher.tsx +294 -0
- package/src/features/chat/features/session/utils/__tests__/chat-session-display.utils.test.ts +15 -1
- package/src/features/chat/features/session/utils/__tests__/ncp-session-adapter.utils.test.ts +24 -4
- package/src/features/chat/features/session/utils/chat-session-display.utils.ts +3 -0
- package/src/features/chat/features/session/utils/chat-sidebar-session-groups.utils.ts +25 -3
- package/src/features/chat/features/session/utils/ncp-session-adapter.utils.ts +1 -0
- package/src/features/chat/features/welcome/components/chat-welcome-capability-grid.tsx +9 -4
- package/src/features/chat/features/welcome/components/chat-welcome.tsx +0 -5
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +193 -56
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +1 -0
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +144 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +99 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +3 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +67 -14
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +3 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +44 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +45 -3
- package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +46 -0
- package/src/features/chat/managers/__tests__/chat-session-list.manager.test.ts +33 -2
- package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +47 -0
- package/src/features/chat/managers/chat-session-list.manager.ts +32 -0
- package/src/features/chat/managers/chat-thread.manager.ts +8 -2
- package/src/features/chat/stores/chat-session-list.store.ts +28 -5
- package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +5 -12
- package/src/features/panel-apps/components/panel-app-list-item.tsx +6 -6
- package/src/features/panel-apps/index.ts +1 -0
- package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +2 -10
- package/src/features/panel-apps/utils/panel-app-iframe.utils.ts +6 -0
- package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +11 -3
- package/src/features/pwa/managers/pwa-shell-theme.manager.ts +3 -1
- package/src/features/service-apps/components/service-apps-panel.tsx +145 -35
- package/src/features/settings/components/config/provider-auth-section.tsx +1 -1
- package/src/features/settings/components/config/provider-form.tsx +11 -8
- package/src/features/settings/components/config/provider-models-section.tsx +7 -7
- package/src/features/settings/components/config/provider-pill-selector.tsx +1 -1
- package/src/features/settings/components/config/secrets-config-form.tsx +5 -4
- package/src/features/settings/pages/model-config-page.tsx +26 -25
- package/src/features/settings/pages/providers-config-page.tsx +10 -13
- package/src/features/settings/pages/search-config-page.tsx +8 -5
- package/src/features/system-status/components/__tests__/desktop-update-config.test.tsx +97 -5
- package/src/features/system-status/components/config/runtime-config-editor.tsx +5 -4
- package/src/features/system-status/components/desktop-update-config.tsx +91 -2
- package/src/features/system-status/utils/update-release-notes.utils.ts +94 -0
- package/src/index.css +18 -0
- package/src/shared/components/config-split-page.tsx +6 -6
- package/src/shared/components/doc-browser/__tests__/doc-browser-url.utils.test.ts +73 -0
- package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +48 -0
- package/src/shared/components/doc-browser/doc-browser-context.tsx +4 -0
- package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +5 -1
- package/src/shared/components/doc-browser/doc-browser-renderer.types.ts +2 -1
- package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +10 -10
- package/src/shared/components/doc-browser/doc-browser.tsx +6 -4
- package/src/shared/components/doc-browser/utils/doc-browser-url.utils.ts +62 -4
- package/src/shared/components/resizable-right-panel/__tests__/resizable-right-panel.test.tsx +18 -0
- package/src/shared/components/resizable-right-panel/resizable-right-panel.tsx +28 -3
- package/src/shared/components/ui/actions/__tests__/icon-action-button.test.tsx +36 -0
- package/src/shared/components/ui/actions/form-actions.tsx +25 -0
- package/src/shared/components/ui/actions/icon-action-button.tsx +25 -2
- package/src/shared/components/ui/card.tsx +12 -4
- package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +2 -1
- package/src/shared/hooks/use-server-path-browse.ts +26 -4
- package/src/shared/hooks/use-server-path-read.ts +11 -1
- package/src/shared/lib/api/ncp-session.types.ts +1 -1
- package/src/shared/lib/api/types.ts +12 -3
- package/src/shared/lib/api/utils/server-path.utils.ts +1 -0
- package/src/shared/lib/i18n/locales/en-US/agents.json +41 -0
- package/src/shared/lib/i18n/locales/en-US/chat.json +19 -0
- package/src/shared/lib/i18n/locales/en-US/core.json +3 -0
- package/src/shared/lib/i18n/locales/en-US/desktop-update.json +8 -0
- package/src/shared/lib/i18n/locales/en-US/doc-browser.json +5 -0
- package/src/shared/lib/i18n/locales/zh-CN/agents.json +41 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +19 -0
- package/src/shared/lib/i18n/locales/zh-CN/core.json +3 -0
- package/src/shared/lib/i18n/locales/zh-CN/desktop-update.json +8 -0
- package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +5 -0
- package/src/shared/lib/session-project/workspace-file-breadcrumb.utils.ts +9 -5
- package/src/shared/lib/theme/index.test.ts +21 -0
- package/src/shared/lib/theme/index.ts +6 -4
- package/src/vite-env.d.ts +2 -0
- package/dist/assets/channels-list-page-Cv8o9Hxg.js +0 -8
- package/dist/assets/chat-page-BtA7H1Ea.js +0 -1
- package/dist/assets/config-split-page-EidRBpP2.js +0 -1
- package/dist/assets/desktop-update-config-C6n_TB1r.js +0 -1
- package/dist/assets/doc-browser-B76XOXmW.js +0 -1
- package/dist/assets/doc-browser-DBnj9UMB.js +0 -1
- package/dist/assets/doc-browser-context-Sv-044Cl.js +0 -1
- package/dist/assets/ellipsis-2uzhypw5.js +0 -1
- package/dist/assets/index-CBRP-7-a.css +0 -1
- package/dist/assets/index-Z1fYpbNd.js +0 -104
- package/dist/assets/loader-circle-BjmN5DeJ.js +0 -1
- package/dist/assets/mcp-marketplace-page-CoZIiD6G.js +0 -1
- package/dist/assets/model-config-page-Cdr9P6TQ.js +0 -1
- package/dist/assets/plus-3ztRZD_l.js +0 -1
- package/dist/assets/providers-config-page-CWlO7J4A.js +0 -1
- package/dist/assets/remote-CKWZfVVB.js +0 -1
- package/dist/assets/rotate-cw-CHcaRUDz.js +0 -1
- package/dist/assets/runtime-config-page-CfTqh1nv.js +0 -1
- package/dist/assets/search-config-page-Dm8daYny.js +0 -1
- package/dist/assets/secrets-config-page-D8AbcR05.js +0 -3
- package/dist/assets/security-config-Ds0LsJmo.js +0 -1
- package/dist/assets/x-DqL1mYLC.js +0 -1
- /package/dist/assets/{config-hints-fGnUjDe9.js → config-hints-C_iP1zl_.js} +0 -0
|
@@ -2,6 +2,7 @@ import type { LucideIcon } from "lucide-react";
|
|
|
2
2
|
import {
|
|
3
3
|
Bot,
|
|
4
4
|
BrainCircuit,
|
|
5
|
+
AlarmClock,
|
|
5
6
|
Cpu,
|
|
6
7
|
Download,
|
|
7
8
|
KeyRound,
|
|
@@ -25,6 +26,11 @@ export type AppNavigationItem = {
|
|
|
25
26
|
icon: LucideIcon;
|
|
26
27
|
};
|
|
27
28
|
|
|
29
|
+
export type AppNavigationSection = {
|
|
30
|
+
label: string;
|
|
31
|
+
items: AppNavigationItem[];
|
|
32
|
+
};
|
|
33
|
+
|
|
28
34
|
function matchesRouteTarget(pathname: string, target: string): boolean {
|
|
29
35
|
const normalizedPath = pathname.toLowerCase();
|
|
30
36
|
const normalizedTarget = target.toLowerCase();
|
|
@@ -80,6 +86,33 @@ export function getMobileBottomNavItems(
|
|
|
80
86
|
];
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
export function getMainSidebarNavItems(
|
|
90
|
+
translate: Translate,
|
|
91
|
+
): AppNavigationItem[] {
|
|
92
|
+
return [
|
|
93
|
+
{
|
|
94
|
+
target: "/chat",
|
|
95
|
+
label: translate("chat"),
|
|
96
|
+
icon: MessageCircle,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
target: "/chat/cron",
|
|
100
|
+
label: translate("cron"),
|
|
101
|
+
icon: AlarmClock,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
target: "/chat/skills",
|
|
105
|
+
label: translate("marketplaceFilterSkills"),
|
|
106
|
+
icon: BrainCircuit,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
target: "/agents",
|
|
110
|
+
label: translate("agentsPageTitle"),
|
|
111
|
+
icon: Bot,
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
|
|
83
116
|
export function getSettingsNavItems(
|
|
84
117
|
translate: Translate,
|
|
85
118
|
): AppNavigationItem[] {
|
|
@@ -142,6 +175,22 @@ export function getSettingsNavItems(
|
|
|
142
175
|
];
|
|
143
176
|
}
|
|
144
177
|
|
|
178
|
+
export function getSettingsNavSections(
|
|
179
|
+
translate: Translate,
|
|
180
|
+
): AppNavigationSection[] {
|
|
181
|
+
const items = getSettingsNavItems(translate);
|
|
182
|
+
return [
|
|
183
|
+
{
|
|
184
|
+
label: translate("settingsGroupBasic"),
|
|
185
|
+
items: items.slice(0, 3),
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
label: translate("settingsGroupAdvanced"),
|
|
189
|
+
items: items.slice(3),
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
|
|
145
194
|
export function getMobileSettingsNavItems(
|
|
146
195
|
translate: Translate,
|
|
147
196
|
): AppNavigationItem[] {
|
|
@@ -284,6 +284,88 @@
|
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
@layer base {
|
|
288
|
+
:root[data-theme="work"] {
|
|
289
|
+
/* ========================================
|
|
290
|
+
BRAND COLORS (Work White Ink)
|
|
291
|
+
======================================== */
|
|
292
|
+
--brand-50: 0 0% 97%;
|
|
293
|
+
--brand-100: 0 0% 94%;
|
|
294
|
+
--brand-200: 0 0% 88%;
|
|
295
|
+
--brand-300: 0 0% 78%;
|
|
296
|
+
--brand-400: 0 0% 58%;
|
|
297
|
+
--brand-500: 0 0% 23%;
|
|
298
|
+
--brand-600: 0 0% 18%;
|
|
299
|
+
--brand-700: 0 0% 12%;
|
|
300
|
+
--brand-800: 0 0% 7%;
|
|
301
|
+
--brand-900: 0 0% 4%;
|
|
302
|
+
|
|
303
|
+
/* ========================================
|
|
304
|
+
NEUTRAL COLORS (White Canvas / Soft Gray Rail)
|
|
305
|
+
======================================== */
|
|
306
|
+
--gray-50: 0 0% 100%;
|
|
307
|
+
--gray-100: 0 0% 95%;
|
|
308
|
+
--gray-200: 0 0% 90%;
|
|
309
|
+
--gray-300: 0 0% 84%;
|
|
310
|
+
--gray-400: 0 0% 70%;
|
|
311
|
+
--gray-500: 0 0% 46%;
|
|
312
|
+
--gray-600: 0 0% 34%;
|
|
313
|
+
--gray-700: 0 0% 28%;
|
|
314
|
+
--gray-800: 0 0% 13%;
|
|
315
|
+
--gray-900: 0 0% 7%;
|
|
316
|
+
|
|
317
|
+
/* Semantic Colors */
|
|
318
|
+
--background: var(--gray-50);
|
|
319
|
+
--background-secondary: var(--gray-100);
|
|
320
|
+
--background-tertiary: var(--gray-200);
|
|
321
|
+
--foreground: var(--gray-800);
|
|
322
|
+
--foreground-secondary: var(--gray-700);
|
|
323
|
+
--foreground-tertiary: var(--gray-500);
|
|
324
|
+
--foreground-muted: var(--gray-400);
|
|
325
|
+
--primary: var(--brand-500);
|
|
326
|
+
--primary-hover: var(--brand-600);
|
|
327
|
+
--primary-active: var(--brand-700);
|
|
328
|
+
--primary-foreground: 0 0% 100%;
|
|
329
|
+
--secondary: var(--gray-100);
|
|
330
|
+
--secondary-hover: var(--gray-200);
|
|
331
|
+
--secondary-foreground: var(--gray-800);
|
|
332
|
+
--accent: var(--gray-200);
|
|
333
|
+
--accent-foreground: var(--gray-800);
|
|
334
|
+
--muted: var(--gray-100);
|
|
335
|
+
--muted-foreground: var(--gray-500);
|
|
336
|
+
--card: 0 0% 100%;
|
|
337
|
+
--card-foreground: var(--gray-800);
|
|
338
|
+
--card-border: var(--gray-200);
|
|
339
|
+
--popover: 0 0% 100%;
|
|
340
|
+
--popover-foreground: var(--gray-800);
|
|
341
|
+
--border: var(--gray-200);
|
|
342
|
+
--border-hover: var(--gray-300);
|
|
343
|
+
--border-active: var(--gray-600);
|
|
344
|
+
--input: 0 0% 100%;
|
|
345
|
+
--input-border: var(--gray-200);
|
|
346
|
+
--input-focus: var(--gray-600);
|
|
347
|
+
--ring: var(--gray-600);
|
|
348
|
+
--ring-offset: var(--gray-50);
|
|
349
|
+
|
|
350
|
+
/* Shadows (bright neutral tint) */
|
|
351
|
+
--shadow-xs: 0 1px 2px 0 rgb(20 24 28 / 0.03);
|
|
352
|
+
--shadow-sm: 0 1px 3px 0 rgb(20 24 28 / 0.05), 0 1px 2px -1px rgb(20 24 28 / 0.04);
|
|
353
|
+
--shadow-md: 0 4px 6px -1px rgb(20 24 28 / 0.05), 0 2px 4px -2px rgb(20 24 28 / 0.04);
|
|
354
|
+
--shadow-lg: 0 10px 15px -3px rgb(20 24 28 / 0.06), 0 4px 6px -4px rgb(20 24 28 / 0.04);
|
|
355
|
+
--shadow-xl: 0 20px 25px -5px rgb(20 24 28 / 0.08), 0 8px 10px -6px rgb(20 24 28 / 0.04);
|
|
356
|
+
--shadow-2xl: 0 25px 50px -12px rgb(20 24 28 / 0.14);
|
|
357
|
+
--shadow-card: 0 0 8px 0 rgba(20, 24, 28, 0.04);
|
|
358
|
+
--shadow-card-hover: 0 0 16px 0 rgba(20, 24, 28, 0.06);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
:root[data-theme="work"] .nextclaw-chat-message-user {
|
|
362
|
+
background-color: hsl(var(--gray-100));
|
|
363
|
+
border-color: transparent;
|
|
364
|
+
color: hsl(var(--gray-800));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
}
|
|
368
|
+
|
|
287
369
|
@layer base {
|
|
288
370
|
:root[data-theme="warm"] {
|
|
289
371
|
/* ========================================
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { render, screen } from "@testing-library/react";
|
|
1
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
2
2
|
import userEvent from "@testing-library/user-event";
|
|
3
3
|
import { MemoryRouter } from "react-router-dom";
|
|
4
4
|
import type * as ReactRouterDom from "react-router-dom";
|
|
@@ -50,6 +50,13 @@ const mocks = vi.hoisted(() => ({
|
|
|
50
50
|
builtIn: false,
|
|
51
51
|
model: "openai/gpt-5.2",
|
|
52
52
|
runtime: "codex",
|
|
53
|
+
runtimeConfig: {
|
|
54
|
+
profile: "workspace-write",
|
|
55
|
+
},
|
|
56
|
+
thinkingDefault: "high",
|
|
57
|
+
contextTokens: 128000,
|
|
58
|
+
reservedContextTokens: 4096,
|
|
59
|
+
maxToolIterations: 64,
|
|
53
60
|
workspace: "~/.nextclaw/workspace/agents/researcher",
|
|
54
61
|
avatarUrl: null,
|
|
55
62
|
},
|
|
@@ -63,6 +70,13 @@ const mocks = vi.hoisted(() => ({
|
|
|
63
70
|
defaults: {
|
|
64
71
|
model: "openai/gpt-5.1",
|
|
65
72
|
workspace: "~/.nextclaw/workspace",
|
|
73
|
+
engine: "native",
|
|
74
|
+
engineConfig: {},
|
|
75
|
+
thinkingDefault: "off",
|
|
76
|
+
models: {},
|
|
77
|
+
contextTokens: 200000,
|
|
78
|
+
reservedContextTokens: 10000,
|
|
79
|
+
maxToolIterations: 1000,
|
|
66
80
|
},
|
|
67
81
|
},
|
|
68
82
|
providers: {
|
|
@@ -252,6 +266,7 @@ describe("AgentsPage", () => {
|
|
|
252
266
|
expect(screen.getByText("~/.nextclaw/workspace")).toBeTruthy();
|
|
253
267
|
expect(screen.getAllByRole("button", { name: "开始对话" })).toHaveLength(2);
|
|
254
268
|
expect(screen.getAllByRole("button", { name: "更多操作" })).toHaveLength(2);
|
|
269
|
+
expect(screen.queryByRole("button", { name: "查看详情" })).toBeNull();
|
|
255
270
|
expect(screen.queryByRole("button", { name: "编辑" })).toBeNull();
|
|
256
271
|
expect(screen.getByText("负责调研、信息筛选与结论提炼。")).toBeTruthy();
|
|
257
272
|
expect(
|
|
@@ -269,7 +284,8 @@ describe("AgentsPage", () => {
|
|
|
269
284
|
expect(screen.queryByText("创建新的 Agent 身份")).toBeNull();
|
|
270
285
|
|
|
271
286
|
await user.click(screen.getAllByRole("button", { name: "更多操作" })[1]);
|
|
272
|
-
|
|
287
|
+
const detailsEditButtons = screen.getAllByRole("button", { name: "编辑" });
|
|
288
|
+
await user.click(detailsEditButtons[detailsEditButtons.length - 1]);
|
|
273
289
|
|
|
274
290
|
expect(screen.getByText("编辑 Agent 身份")).toBeTruthy();
|
|
275
291
|
expect(screen.getByText("主目录保持不变")).toBeTruthy();
|
|
@@ -280,6 +296,122 @@ describe("AgentsPage", () => {
|
|
|
280
296
|
expect(screen.getByDisplayValue("gpt-5.2")).toBeTruthy();
|
|
281
297
|
});
|
|
282
298
|
|
|
299
|
+
it("separates read-only details from editing and keeps advanced config collapsed until requested", async () => {
|
|
300
|
+
const user = userEvent.setup();
|
|
301
|
+
|
|
302
|
+
renderAgentsPage();
|
|
303
|
+
|
|
304
|
+
await user.click(screen.getAllByRole("button", { name: "更多操作" })[1]);
|
|
305
|
+
await user.click(screen.getByRole("button", { name: "查看详情" }));
|
|
306
|
+
|
|
307
|
+
expect(screen.getByText("身份")).toBeTruthy();
|
|
308
|
+
expect(screen.getByText("上下文窗口大小")).toBeTruthy();
|
|
309
|
+
expect(screen.getByText("128,000")).toBeTruthy();
|
|
310
|
+
expect(screen.queryByRole("button", { name: "保存编辑" })).toBeNull();
|
|
311
|
+
const detailsDialog = screen.getByText("身份").closest("[role='dialog']");
|
|
312
|
+
expect(detailsDialog?.className).toContain("sm:max-w-2xl");
|
|
313
|
+
const detailLists = Array.from(detailsDialog?.querySelectorAll("dl") ?? []);
|
|
314
|
+
expect(detailLists.length).toBeGreaterThan(0);
|
|
315
|
+
expect(
|
|
316
|
+
detailLists.every(
|
|
317
|
+
(list) =>
|
|
318
|
+
!list.className.includes("divide-y") &&
|
|
319
|
+
!list.className.includes("border-t"),
|
|
320
|
+
),
|
|
321
|
+
).toBe(true);
|
|
322
|
+
expect(
|
|
323
|
+
Array.from(detailsDialog?.querySelectorAll("section") ?? []).every(
|
|
324
|
+
(section) =>
|
|
325
|
+
section.className.includes("space-y-2") &&
|
|
326
|
+
section.className.includes("border-t") &&
|
|
327
|
+
!section.className.includes("sm:grid-cols"),
|
|
328
|
+
),
|
|
329
|
+
).toBe(true);
|
|
330
|
+
expect(
|
|
331
|
+
detailLists.every((list) => list.className.includes("pl-5")),
|
|
332
|
+
).toBe(true);
|
|
333
|
+
expect(
|
|
334
|
+
Array.from(detailsDialog?.querySelectorAll("dt") ?? []).every(
|
|
335
|
+
(term) => {
|
|
336
|
+
const item = term.parentElement;
|
|
337
|
+
return Boolean(
|
|
338
|
+
item?.className.includes("grid-cols-[10rem_minmax(0,1fr)]") &&
|
|
339
|
+
!item.className.includes("space-y"),
|
|
340
|
+
);
|
|
341
|
+
},
|
|
342
|
+
),
|
|
343
|
+
).toBe(true);
|
|
344
|
+
expect(
|
|
345
|
+
Array.from(detailsDialog?.querySelectorAll("dt span") ?? []).every(
|
|
346
|
+
(label) => !label.className.includes("truncate"),
|
|
347
|
+
),
|
|
348
|
+
).toBe(true);
|
|
349
|
+
expect(
|
|
350
|
+
Array.from(detailsDialog?.querySelectorAll("dt") ?? []).every(
|
|
351
|
+
(term) =>
|
|
352
|
+
!term.textContent?.includes("继承默认") &&
|
|
353
|
+
!term.textContent?.includes("Agent 覆盖"),
|
|
354
|
+
),
|
|
355
|
+
).toBe(true);
|
|
356
|
+
expect(
|
|
357
|
+
Array.from(detailsDialog?.querySelectorAll("dd") ?? []).some((value) =>
|
|
358
|
+
value.textContent?.includes("128,000(Agent 覆盖)"),
|
|
359
|
+
),
|
|
360
|
+
).toBe(true);
|
|
361
|
+
expect(
|
|
362
|
+
Array.from(detailsDialog?.querySelectorAll("dd") ?? []).some((value) =>
|
|
363
|
+
value.textContent?.includes("未设置(继承默认)"),
|
|
364
|
+
),
|
|
365
|
+
).toBe(true);
|
|
366
|
+
expect(
|
|
367
|
+
Array.from(detailsDialog?.querySelectorAll("dt span, dd") ?? []).every(
|
|
368
|
+
(node) => node.className.includes("text-xs"),
|
|
369
|
+
),
|
|
370
|
+
).toBe(true);
|
|
371
|
+
expect(detailsDialog?.querySelector(".rounded-xl.bg-white.p-3")).toBeNull();
|
|
372
|
+
|
|
373
|
+
await user.click(screen.getByRole("button", { name: "编辑" }));
|
|
374
|
+
|
|
375
|
+
expect(screen.getByText("编辑 Agent 身份")).toBeTruthy();
|
|
376
|
+
const advancedDetails = screen.getByText("高级配置").closest("details");
|
|
377
|
+
expect(advancedDetails?.hasAttribute("open")).toBe(false);
|
|
378
|
+
|
|
379
|
+
await user.click(screen.getByText("高级配置"));
|
|
380
|
+
expect(advancedDetails?.hasAttribute("open")).toBe(true);
|
|
381
|
+
expect(screen.queryByLabelText("预留上下文大小")).toBeNull();
|
|
382
|
+
expect(screen.queryByLabelText("最大工具迭代次数")).toBeNull();
|
|
383
|
+
expect(screen.queryByLabelText("默认思考强度")).toBeNull();
|
|
384
|
+
expect(screen.queryByLabelText("Runtime 配置 JSON")).toBeNull();
|
|
385
|
+
expect(screen.queryByLabelText("模型覆盖 JSON")).toBeNull();
|
|
386
|
+
|
|
387
|
+
fireEvent.change(screen.getByLabelText("上下文窗口大小"), {
|
|
388
|
+
target: { value: "64000" },
|
|
389
|
+
});
|
|
390
|
+
await user.click(screen.getByRole("button", { name: "保存编辑" }));
|
|
391
|
+
|
|
392
|
+
expect(mocks.updateAgent).toHaveBeenCalledWith({
|
|
393
|
+
agentId: "researcher",
|
|
394
|
+
data: expect.objectContaining({
|
|
395
|
+
contextTokens: 64000,
|
|
396
|
+
}),
|
|
397
|
+
});
|
|
398
|
+
expect(mocks.updateAgent.mock.calls[0][0].data).not.toHaveProperty(
|
|
399
|
+
"reservedContextTokens",
|
|
400
|
+
);
|
|
401
|
+
expect(mocks.updateAgent.mock.calls[0][0].data).not.toHaveProperty(
|
|
402
|
+
"maxToolIterations",
|
|
403
|
+
);
|
|
404
|
+
expect(mocks.updateAgent.mock.calls[0][0].data).not.toHaveProperty(
|
|
405
|
+
"thinkingDefault",
|
|
406
|
+
);
|
|
407
|
+
expect(mocks.updateAgent.mock.calls[0][0].data).not.toHaveProperty(
|
|
408
|
+
"runtimeConfig",
|
|
409
|
+
);
|
|
410
|
+
expect(mocks.updateAgent.mock.calls[0][0].data).not.toHaveProperty(
|
|
411
|
+
"models",
|
|
412
|
+
);
|
|
413
|
+
});
|
|
414
|
+
|
|
283
415
|
it("uses a runtime dropdown instead of manual text input when editing an agent", async () => {
|
|
284
416
|
const user = userEvent.setup();
|
|
285
417
|
|
|
@@ -307,6 +439,7 @@ describe("AgentsPage", () => {
|
|
|
307
439
|
avatar: "",
|
|
308
440
|
model: "openai/gpt-5.2",
|
|
309
441
|
runtime: "codex",
|
|
442
|
+
contextTokens: 128000,
|
|
310
443
|
},
|
|
311
444
|
});
|
|
312
445
|
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { AgentEditFormState } from "@/features/agents/types/agent-form.types";
|
|
2
|
+
import { Input } from "@/shared/components/ui/input";
|
|
3
|
+
import { t } from "@/shared/lib/i18n";
|
|
4
|
+
import { ChevronDown, Settings2 } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
type AgentAdvancedConfigFieldsProps = {
|
|
7
|
+
form: AgentEditFormState;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
onChange: (patch: Partial<AgentEditFormState>) => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function AgentAdvancedConfigFields({
|
|
13
|
+
form,
|
|
14
|
+
disabled = false,
|
|
15
|
+
onChange,
|
|
16
|
+
}: AgentAdvancedConfigFieldsProps) {
|
|
17
|
+
return (
|
|
18
|
+
<details className="group rounded-2xl border border-gray-200 bg-white">
|
|
19
|
+
<summary className="flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-3 text-sm font-semibold text-gray-800 [&::-webkit-details-marker]:hidden">
|
|
20
|
+
<span className="flex min-w-0 items-center gap-2">
|
|
21
|
+
<Settings2 className="h-4 w-4 shrink-0 text-gray-400" />
|
|
22
|
+
<span className="truncate">{t("agentsAdvancedConfigToggle")}</span>
|
|
23
|
+
</span>
|
|
24
|
+
<ChevronDown className="h-4 w-4 shrink-0 text-gray-400 transition-transform group-open:rotate-180" />
|
|
25
|
+
</summary>
|
|
26
|
+
<div className="space-y-4 border-t border-gray-100 px-4 py-4">
|
|
27
|
+
<p className="text-xs leading-5 text-gray-500">
|
|
28
|
+
{t("agentsAdvancedConfigDescription")}
|
|
29
|
+
</p>
|
|
30
|
+
<div className="grid gap-4 md:grid-cols-2">
|
|
31
|
+
<AgentNumberField
|
|
32
|
+
label={t("agentsAdvancedContextTokensLabel")}
|
|
33
|
+
value={form.contextTokens}
|
|
34
|
+
min={1000}
|
|
35
|
+
step={1000}
|
|
36
|
+
disabled={disabled}
|
|
37
|
+
onChange={(contextTokens) => onChange({ contextTokens })}
|
|
38
|
+
/>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</details>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function AgentNumberField(props: {
|
|
46
|
+
label: string;
|
|
47
|
+
value: string;
|
|
48
|
+
min: number;
|
|
49
|
+
step: number;
|
|
50
|
+
disabled: boolean;
|
|
51
|
+
onChange: (value: string) => void;
|
|
52
|
+
}) {
|
|
53
|
+
const { label, value, min, step, disabled, onChange } = props;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<label className="space-y-2 text-sm font-medium text-gray-700">
|
|
57
|
+
<span>{label}</span>
|
|
58
|
+
<Input
|
|
59
|
+
type="number"
|
|
60
|
+
min={min}
|
|
61
|
+
step={step}
|
|
62
|
+
value={value}
|
|
63
|
+
disabled={disabled}
|
|
64
|
+
placeholder={t("agentsAdvancedInheritPlaceholder")}
|
|
65
|
+
aria-label={label}
|
|
66
|
+
onChange={(event) => onChange(event.target.value)}
|
|
67
|
+
/>
|
|
68
|
+
</label>
|
|
69
|
+
);
|
|
70
|
+
}
|