@nextclaw/ui 0.12.24 → 0.12.26
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 +136 -29
- package/dist/assets/api-DGD9_Bg4.js +15 -0
- package/dist/assets/app-manager-provider-oYdeYPSv.js +1 -0
- package/dist/assets/{book-open-DDlN5MvX.js → book-open-BcnAiKde.js} +1 -1
- package/dist/assets/channels-list-page-HgLgrEg4.js +8 -0
- package/dist/assets/chat-page-DAKMFDrS.js +1 -0
- package/dist/assets/config-split-page-CcrEUtwu.js +1 -0
- package/dist/assets/cpu-DPPwMzoC.js +3 -0
- package/dist/assets/{createLucideIcon-BLMK3QUd.js → createLucideIcon-DzY6wN61.js} +1 -1
- package/dist/assets/desktop-DVUbOWbR.js +3 -0
- package/dist/assets/desktop-update-config-CP8dFYXK.js +1 -0
- package/dist/assets/{dialog-C3D7Be0p.js → dialog-BKo0RItd.js} +1 -1
- package/dist/assets/{dist-CPlbUgwU.js → dist-CFiwgaLs.js} +1 -1
- package/dist/assets/doc-browser-CAhfnm0D.js +1 -0
- package/dist/assets/{doc-browser-context-BJuMaI3o.js → doc-browser-context-FukQHvyo.js} +1 -1
- package/dist/assets/doc-browser-p9DDNPWB.js +1 -0
- package/dist/assets/doc-browser-rZIQIjuw.js +1 -0
- package/dist/assets/download-CMM8po31.js +1 -0
- package/dist/assets/{es2015-xqN1slyW.js → es2015-BhznEEyJ.js} +1 -1
- package/dist/assets/{external-link-DwfSfTLB.js → external-link-CpEvG65F.js} +1 -1
- package/dist/assets/i18n-D1144VAA.js +1 -0
- package/dist/assets/index-Cuwst6cc.js +100 -0
- package/dist/assets/index-dlcqieQ0.css +1 -0
- package/dist/assets/{key-round-CJ5gDAAG.js → key-round-DUq47t0P.js} +1 -1
- package/dist/assets/marketplace-page-BeFbwxR-.js +105 -0
- package/dist/assets/marketplace-page-CR4xq-TM.js +1 -0
- package/dist/assets/mcp-marketplace-page-DlRrSCj3.js +1 -0
- package/dist/assets/mcp-marketplace-page-DwnaLNTx.js +40 -0
- package/dist/assets/model-config-L2l6YAlQ.js +1 -0
- package/dist/assets/{notice-card-BFDbKQDA.js → notice-card-Dr6xCwva.js} +1 -1
- package/dist/assets/play-AqrNslHI.js +1 -0
- package/dist/assets/plus-B-YHtTNC.js +1 -0
- package/dist/assets/{popover-B86Dbfhf.js → popover-BDFNiLlg.js} +1 -1
- package/dist/assets/provider-scoped-model-input-BMTp4BEH.js +1 -0
- package/dist/assets/providers-list-DYAEunOp.js +1 -0
- package/dist/assets/refresh-cw-CrbD8EkT.js +1 -0
- package/dist/assets/remote-Dr3jcfWP.js +1 -0
- package/dist/assets/{rotate-cw-BZ2JObNs.js → rotate-cw-BN9yjccP.js} +1 -1
- package/dist/assets/runtime-config-page-BdeU8PEK.js +1 -0
- package/dist/assets/{save-euRxl8pI.js → save-CO_4qf6b.js} +1 -1
- package/dist/assets/{search-CLd7m0M7.js → search-CRtQwr-h.js} +1 -1
- package/dist/assets/search-config-CQUhd5RU.js +1 -0
- package/dist/assets/secrets-config-D-NWlW9q.js +3 -0
- package/dist/assets/{select-CJ0wbo3D.js → select-BUTwE_lC.js} +1 -1
- package/dist/assets/{setting-row-D1Yygqp7.js → setting-row-BavcnXw1.js} +1 -1
- package/dist/assets/settings-MWL2SMyk.js +1 -0
- package/dist/assets/{sparkles-DVfeSVJQ.js → sparkles-BmgOD4nY.js} +1 -1
- package/dist/assets/{status-dot-ChvPCib9.js → status-dot-l3kPFdq_.js} +1 -1
- package/dist/assets/{tabs-custom-Hia_ong0.js → tabs-custom-D48zdZoc.js} +1 -1
- package/dist/assets/{tag-chip-FrkmkT8r.js → tag-chip-Dm2Lqnpu.js} +1 -1
- package/dist/assets/use-config-Cyv5IuSt.js +1 -0
- package/dist/assets/use-infinite-scroll-loader-CFVdPpNv.js +1 -0
- package/dist/assets/x-BeyYA_h6.js +1 -0
- package/dist/index.html +29 -40
- package/package.json +9 -9
- package/src/app/components/layout/sidebar.layout.test.tsx +2 -4
- package/src/app/components/theme-provider.tsx +1 -0
- package/src/app/configs/app-navigation.config.ts +0 -6
- package/src/app/index.tsx +4 -7
- package/src/features/agents/components/agents-page.test.tsx +25 -15
- package/src/features/agents/components/agents-page.tsx +133 -172
- package/src/features/channels/components/config/channel-form.test.tsx +1 -0
- package/src/features/channels/components/config/channel-form.tsx +4 -3
- package/src/features/channels/components/config/weixin-channel-auth-section.test.tsx +38 -1
- package/src/features/channels/components/config/weixin-channel-auth-section.tsx +137 -40
- package/src/features/channels/index.ts +1 -1
- package/src/features/channels/utils/channel-form-fields.utils.test.ts +26 -0
- package/src/features/channels/utils/channel-form-fields.utils.ts +32 -18
- package/src/features/chat/components/chat-session-workspace-panel-nav.tsx +23 -4
- package/src/features/chat/components/chat-session-workspace-panel.tsx +53 -35
- package/src/features/chat/components/chat-sidebar-session-item.tsx +16 -12
- package/src/features/chat/components/conversation/chat-conversation-header.test.tsx +74 -0
- package/src/features/chat/components/conversation/chat-conversation-header.tsx +8 -2
- package/src/features/chat/components/conversation/chat-conversation-panel.test.tsx +262 -114
- package/src/features/chat/components/conversation/chat-conversation-panel.tsx +210 -174
- package/src/features/chat/components/conversation/chat-input-bar.container.tsx +11 -1
- package/src/features/chat/components/conversation/session-header/chat-session-header-actions.test.tsx +24 -0
- package/src/features/chat/components/conversation/session-header/chat-session-header-actions.tsx +27 -6
- package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +174 -0
- package/src/features/chat/components/layout/chat-sidebar.test.tsx +45 -8
- package/src/features/chat/components/layout/chat-sidebar.tsx +29 -46
- package/src/features/chat/components/providers/chat-presenter.provider.tsx +4 -0
- package/src/features/chat/components/workspace/session-cron-job-content.tsx +103 -0
- package/src/features/chat/hooks/use-ncp-agent-runtime.test.tsx +153 -80
- package/src/features/chat/hooks/use-ncp-chat-page-data.test.tsx +70 -0
- package/src/features/chat/hooks/use-ncp-chat-page-data.ts +1 -1
- package/src/features/chat/hooks/use-ncp-child-session-tabs-view.ts +2 -8
- package/src/features/chat/hooks/use-ncp-session-list-view.ts +1 -2
- package/src/features/chat/managers/chat-session-list.manager.test.ts +7 -9
- package/src/features/chat/managers/chat-session-list.manager.ts +5 -10
- package/src/features/chat/managers/ncp-chat-input.manager.test.ts +20 -2
- package/src/features/chat/managers/ncp-chat-input.manager.ts +18 -0
- package/src/features/chat/managers/ncp-chat-presenter.manager.ts +7 -0
- package/src/features/chat/managers/ncp-chat-thread.manager.test.ts +52 -1
- package/src/features/chat/managers/ncp-chat-thread.manager.ts +21 -0
- package/src/features/chat/pages/ncp-chat-page.tsx +9 -5
- package/src/features/chat/stores/chat-input.store.ts +3 -1
- package/src/features/chat/stores/chat-session-list.store.ts +0 -2
- package/src/features/chat/stores/chat-thread.store.ts +4 -0
- package/src/features/chat/utils/chat-session-display.utils.test.ts +83 -1
- package/src/features/chat/utils/chat-session-display.utils.ts +73 -0
- package/src/features/chat/utils/ncp-chat-input-availability.utils.test.ts +1 -0
- package/src/features/chat/utils/ncp-session-adapter.utils.test.ts +22 -0
- package/src/features/chat/utils/ncp-session-adapter.utils.ts +32 -0
- package/src/features/marketplace/components/curated-shelves/marketplace-curated-scene-route.test.tsx +235 -0
- package/src/features/marketplace/components/curated-shelves/marketplace-curated-shelves.config.ts +162 -0
- package/src/features/marketplace/components/curated-shelves/marketplace-curated-shelves.tsx +355 -0
- package/src/features/marketplace/components/curated-shelves/marketplace-shelf-card.tsx +118 -0
- package/src/features/marketplace/components/detail-doc/marketplace-detail-doc-renderer.ts +201 -0
- package/src/features/marketplace/components/detail-doc/marketplace-detail-doc.test.ts +40 -0
- package/src/features/marketplace/components/marketplace-catalog-grid.tsx +114 -0
- package/src/features/marketplace/components/marketplace-detail-doc.ts +73 -24
- package/src/features/marketplace/components/marketplace-item-icon.tsx +45 -0
- package/src/features/marketplace/components/marketplace-list-card.tsx +177 -93
- package/src/features/marketplace/components/marketplace-page-detail.test.tsx +9 -2
- package/src/features/marketplace/components/marketplace-page-parts.tsx +1 -1
- package/src/features/marketplace/components/marketplace-page.test.tsx +25 -6
- package/src/features/marketplace/components/marketplace-page.tsx +154 -132
- package/src/features/marketplace/hooks/use-marketplace-curated-scene-route.ts +97 -0
- package/src/features/marketplace/hooks/use-marketplace.ts +59 -3
- package/src/features/system-status/components/config/runtime-agent-list-card.tsx +4 -8
- package/src/features/system-status/components/config/runtime-binding-list-card.tsx +5 -7
- package/src/features/system-status/components/config/runtime-config-editor.tsx +1 -19
- package/src/features/system-status/components/config/runtime-entry-list-card.tsx +10 -11
- package/src/features/system-status/components/config/runtime-settings-card.tsx +15 -23
- package/src/features/system-status/components/runtime-control-card.test.tsx +8 -6
- package/src/features/system-status/components/runtime-control-card.tsx +7 -6
- package/src/features/system-status/pages/runtime-config-page.test.tsx +19 -9
- package/src/features/system-status/pages/runtime-config-page.tsx +2 -3
- package/src/features/system-status/utils/runtime-config-agent.utils.ts +4 -4
- package/src/features/system-status/utils/system-status.utils.ts +31 -6
- package/src/index.css +8 -0
- package/src/platforms/desktop/components/desktop-app-shell.test.tsx +68 -0
- package/src/platforms/desktop/components/desktop-app-shell.tsx +46 -18
- package/src/platforms/desktop/components/desktop-window-chrome.tsx +30 -0
- package/src/platforms/desktop/index.ts +6 -0
- package/src/platforms/desktop/types/desktop-update.types.ts +3 -0
- package/src/platforms/desktop/utils/desktop-host.utils.ts +56 -0
- package/src/shared/components/common/brand-header.tsx +36 -16
- package/src/shared/components/config/provider-form-support.ts +2 -22
- package/src/shared/components/cron-config.tsx +12 -58
- package/src/shared/components/doc-browser/doc-browser.tsx +4 -4
- package/src/shared/components/ui/select.tsx +19 -7
- package/src/shared/lib/api/channel-auth.types.ts +1 -0
- package/src/shared/lib/api/ncp-session.types.ts +9 -0
- package/src/shared/lib/api/types.ts +12 -1
- package/src/shared/lib/api/utils/marketplace.utils.ts +7 -1
- package/src/shared/lib/cron/cron-job-view.utils.ts +59 -0
- package/src/shared/lib/cron/index.ts +1 -0
- package/src/shared/lib/i18n/{channel-auth.ts → channel-auth.constants.ts} +31 -0
- package/src/shared/lib/i18n/chat-labels.utils.ts +3 -2
- package/src/shared/lib/i18n/index.ts +20 -59
- package/src/shared/lib/i18n/{runtime-control.ts → runtime-control-labels.utils.ts} +30 -1
- package/src/shared/lib/provider-models/index.test.ts +39 -0
- package/src/shared/lib/provider-models/index.ts +1 -3
- package/src/shared/lib/ui-document-title/index.ts +0 -1
- package/tsconfig.json +1 -0
- package/vite.config.ts +1 -1
- package/vitest.config.ts +1 -1
- package/dist/assets/api-D2xRKmZd.js +0 -15
- package/dist/assets/app-manager-provider-CNaZboG4.js +0 -1
- package/dist/assets/app-navigation.config-Ihhrrt--.js +0 -1
- package/dist/assets/channels-list-page-p26lgxLk.js +0 -8
- package/dist/assets/chat-Dkh2qtuz.js +0 -61
- package/dist/assets/chat-page-DoTmE2wx.js +0 -1
- package/dist/assets/chunk-JZWAC4HX-Kydj4yEz.js +0 -3
- package/dist/assets/config-split-page-DIOCjj2Q.js +0 -1
- package/dist/assets/desktop-update-config-DlpzDfKM.js +0 -1
- package/dist/assets/doc-browser-C8FM5fC0.js +0 -1
- package/dist/assets/doc-browser-RJUOL_GO.js +0 -1
- package/dist/assets/doc-browser-p82AdNO-.js +0 -1
- package/dist/assets/folder-CeJKPx5P.js +0 -1
- package/dist/assets/hash-BqxRTZW5.js +0 -1
- package/dist/assets/i18n-DnTGDIRw.js +0 -1
- package/dist/assets/index-D8MKmXtO.css +0 -1
- package/dist/assets/index-pBvbJ5Mt.js +0 -2
- package/dist/assets/loader-circle-fd-vQKtW.js +0 -1
- package/dist/assets/logo-badge-KAe-7d8c.js +0 -1
- package/dist/assets/logos-C4sYP1Vl.js +0 -1
- package/dist/assets/marketplace-page-Cql0kDi-.js +0 -1
- package/dist/assets/marketplace-page-m4P5g_Ht.js +0 -49
- package/dist/assets/mcp-marketplace-page-9WVKl1m1.js +0 -1
- package/dist/assets/mcp-marketplace-page-ByzBQZcx.js +0 -40
- package/dist/assets/message-square-z_osm9c0.js +0 -1
- package/dist/assets/model-config-Dbr_0APb.js +0 -1
- package/dist/assets/play-Dv6Nr1Ew.js +0 -1
- package/dist/assets/plus-D8eKFY7h.js +0 -1
- package/dist/assets/provider-scoped-model-input-DFm6N2f7.js +0 -1
- package/dist/assets/providers-list-BJcLOjun.js +0 -1
- package/dist/assets/refresh-ccw-ByVwmnN_.js +0 -1
- package/dist/assets/refresh-cw-PcqoYB3K.js +0 -1
- package/dist/assets/remote-BOxo9iwd.js +0 -1
- package/dist/assets/runtime-config-page-CjLhnbSl.js +0 -1
- package/dist/assets/search-config-J4Htco-P.js +0 -1
- package/dist/assets/secrets-config-CUdERjco.js +0 -3
- package/dist/assets/sessions-config-page-DpK991fs.js +0 -2
- package/dist/assets/settings-drbWqzA4.js +0 -1
- package/dist/assets/skeleton-BK1SOSRA.js +0 -1
- package/dist/assets/theme-provider-0hxjiPc_.js +0 -2
- package/dist/assets/tooltip-Cj4yA0gH.js +0 -1
- package/dist/assets/trash-2-CBsHCfqq.js +0 -1
- package/dist/assets/use-config-38Ur-89i.js +0 -1
- package/dist/assets/use-confirm-dialog-DPQThaeU.js +0 -1
- package/dist/assets/use-infinite-scroll-loader-5Gf1xQi7.js +0 -1
- package/dist/assets/use-viewport-layout-D1XzKeip.js +0 -1
- package/dist/assets/x-CM-XDMpk.js +0 -1
- package/src/features/chat/components/config/sessions-config-detail-pane.tsx +0 -244
- package/src/features/chat/pages/sessions-config-page.test.tsx +0 -152
- package/src/features/chat/pages/sessions-config-page.tsx +0 -192
- /package/dist/assets/{config-hints-MogHYQ8G.js → config-hints-BNfpOL4J.js} +0 -0
|
@@ -7,10 +7,14 @@ const Select = SelectPrimitive.Root
|
|
|
7
7
|
const SelectGroup = SelectPrimitive.Group
|
|
8
8
|
const SelectValue = SelectPrimitive.Value
|
|
9
9
|
|
|
10
|
+
type SelectTriggerProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & {
|
|
11
|
+
indicator?: React.ReactNode
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
const SelectTrigger = React.forwardRef<
|
|
11
15
|
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
12
|
-
|
|
13
|
-
>(({ className, children, ...props }, ref) => (
|
|
16
|
+
SelectTriggerProps
|
|
17
|
+
>(({ className, children, indicator, ...props }, ref) => (
|
|
14
18
|
<SelectPrimitive.Trigger
|
|
15
19
|
ref={ref}
|
|
16
20
|
className={cn(
|
|
@@ -21,7 +25,7 @@ const SelectTrigger = React.forwardRef<
|
|
|
21
25
|
>
|
|
22
26
|
{children}
|
|
23
27
|
<SelectPrimitive.Icon asChild>
|
|
24
|
-
<ChevronDown className="h-4 w-4 opacity-50" />
|
|
28
|
+
{indicator ?? <ChevronDown className="h-4 w-4 opacity-50" />}
|
|
25
29
|
</SelectPrimitive.Icon>
|
|
26
30
|
</SelectPrimitive.Trigger>
|
|
27
31
|
))
|
|
@@ -55,15 +59,19 @@ const SelectScrollDownButton = React.forwardRef<
|
|
|
55
59
|
))
|
|
56
60
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName
|
|
57
61
|
|
|
62
|
+
type SelectContentProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {
|
|
63
|
+
viewportClassName?: string
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
const SelectContent = React.forwardRef<
|
|
59
67
|
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
60
|
-
|
|
61
|
-
>(({ className, children, position = "popper", ...props }, ref) => (
|
|
68
|
+
SelectContentProps
|
|
69
|
+
>(({ className, children, position = "popper", viewportClassName, ...props }, ref) => (
|
|
62
70
|
<SelectPrimitive.Portal>
|
|
63
71
|
<SelectPrimitive.Content
|
|
64
72
|
ref={ref}
|
|
65
73
|
className={cn(
|
|
66
|
-
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 bg-white",
|
|
74
|
+
"relative z-[var(--z-popover,50)] max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 bg-white",
|
|
67
75
|
position === "popper" &&
|
|
68
76
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
69
77
|
className
|
|
@@ -73,7 +81,11 @@ const SelectContent = React.forwardRef<
|
|
|
73
81
|
>
|
|
74
82
|
<SelectScrollUpButton />
|
|
75
83
|
<SelectPrimitive.Viewport
|
|
76
|
-
className={cn(
|
|
84
|
+
className={cn(
|
|
85
|
+
"p-1",
|
|
86
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
|
|
87
|
+
viewportClassName
|
|
88
|
+
)}
|
|
77
89
|
>
|
|
78
90
|
{children}
|
|
79
91
|
</SelectPrimitive.Viewport>
|
|
@@ -31,6 +31,13 @@ export type SessionContextWindowView = {
|
|
|
31
31
|
updatedAt: string;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
export type SessionActivityPreviewView = {
|
|
35
|
+
state: "running" | "completed" | "failed" | "idle";
|
|
36
|
+
timestamp: string;
|
|
37
|
+
statusText?: string;
|
|
38
|
+
replyText?: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
34
41
|
export type SessionEntryView = {
|
|
35
42
|
key: string;
|
|
36
43
|
createdAt: string;
|
|
@@ -52,9 +59,11 @@ export type SessionEntryView = {
|
|
|
52
59
|
parentSessionId?: string | null;
|
|
53
60
|
spawnedByRequestId?: string | null;
|
|
54
61
|
contextWindow?: SessionContextWindowView | null;
|
|
62
|
+
activityPreview?: SessionActivityPreviewView;
|
|
55
63
|
messageCount: number;
|
|
56
64
|
lastRole?: string;
|
|
57
65
|
lastTimestamp?: string;
|
|
66
|
+
status?: NcpSessionStatus;
|
|
58
67
|
};
|
|
59
68
|
|
|
60
69
|
export type SessionMessageView = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NcpSessionStatus } from '@nextclaw/ncp';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RuntimeEntryView, NcpSessionSummaryView } from './ncp-session.types';
|
|
3
3
|
export type { SessionEntryView, RuntimeEntryView, SessionTypeIconView, SessionMessageView, SessionEventView, NcpSessionSummaryView, NcpSessionsListView, NcpMessageView, NcpSessionMessagesView, SessionContextWindowView } from './ncp-session.types';
|
|
4
4
|
|
|
5
5
|
// API Types - matching backend response format
|
|
@@ -776,6 +776,17 @@ export type MarketplaceRecommendationView = {
|
|
|
776
776
|
items: MarketplaceItemSummary[];
|
|
777
777
|
};
|
|
778
778
|
|
|
779
|
+
export type MarketplaceSceneView = {
|
|
780
|
+
scene: string;
|
|
781
|
+
title: string;
|
|
782
|
+
description?: string;
|
|
783
|
+
count?: number;
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
export type MarketplaceScenesView = {
|
|
787
|
+
scenes: MarketplaceSceneView[];
|
|
788
|
+
};
|
|
789
|
+
|
|
779
790
|
export type MarketplaceInstalledRecord = {
|
|
780
791
|
type: MarketplaceItemType;
|
|
781
792
|
id?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { nextclawClient } from '
|
|
1
|
+
import { nextclawClient } from '@/shared/lib/api/managers/client.manager';
|
|
2
2
|
import type {
|
|
3
3
|
MarketplaceInstallRequest,
|
|
4
4
|
MarketplaceInstallResult,
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
MarketplaceItemView,
|
|
12
12
|
MarketplaceListView,
|
|
13
13
|
MarketplaceRecommendationView,
|
|
14
|
+
MarketplaceScenesView,
|
|
14
15
|
MarketplaceSort
|
|
15
16
|
} from '@/shared/lib/api/types';
|
|
16
17
|
|
|
@@ -18,6 +19,7 @@ export type MarketplaceListParams = {
|
|
|
18
19
|
type: MarketplaceItemType;
|
|
19
20
|
q?: string;
|
|
20
21
|
tag?: string;
|
|
22
|
+
scene?: string;
|
|
21
23
|
sort?: MarketplaceSort;
|
|
22
24
|
page?: number;
|
|
23
25
|
pageSize?: number;
|
|
@@ -49,6 +51,10 @@ export async function fetchMarketplaceRecommendations(
|
|
|
49
51
|
return await nextclawClient.marketplace.fetchRecommendations(type, params);
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
export async function fetchMarketplaceSkillScenes(): Promise<MarketplaceScenesView> {
|
|
55
|
+
return await nextclawClient.marketplace.fetchSkillScenes();
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
export async function installMarketplaceItem(request: MarketplaceInstallRequest): Promise<MarketplaceInstallResult> {
|
|
53
59
|
return await nextclawClient.marketplace.install(
|
|
54
60
|
request as Parameters<typeof nextclawClient.marketplace.install>[0]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { CronJobView } from "@/shared/lib/api";
|
|
2
|
+
import { formatDateTime } from "@/shared/lib/i18n";
|
|
3
|
+
|
|
4
|
+
export function formatCronDate(value?: string | null): string {
|
|
5
|
+
return formatDateTime(value ?? undefined);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function formatDateFromMs(value?: number | null): string {
|
|
9
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
10
|
+
return "-";
|
|
11
|
+
}
|
|
12
|
+
return formatDateTime(new Date(value));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function formatEveryDuration(ms?: number | null): string {
|
|
16
|
+
if (typeof ms !== "number" || !Number.isFinite(ms)) {
|
|
17
|
+
return "-";
|
|
18
|
+
}
|
|
19
|
+
const seconds = Math.round(ms / 1000);
|
|
20
|
+
if (seconds < 60) return `${seconds}s`;
|
|
21
|
+
const minutes = Math.round(seconds / 60);
|
|
22
|
+
if (minutes < 60) return `${minutes}m`;
|
|
23
|
+
const hours = Math.round(minutes / 60);
|
|
24
|
+
if (hours < 24) return `${hours}h`;
|
|
25
|
+
const days = Math.round(hours / 24);
|
|
26
|
+
return `${days}d`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function describeCronSchedule(job: CronJobView): string {
|
|
30
|
+
const { schedule } = job;
|
|
31
|
+
if (schedule.kind === "cron") {
|
|
32
|
+
return schedule.expr ? `cron ${schedule.expr}` : "cron";
|
|
33
|
+
}
|
|
34
|
+
if (schedule.kind === "every") {
|
|
35
|
+
return `every ${formatEveryDuration(schedule.everyMs)}`;
|
|
36
|
+
}
|
|
37
|
+
if (schedule.kind === "at") {
|
|
38
|
+
return `at ${formatDateFromMs(schedule.atMs)}`;
|
|
39
|
+
}
|
|
40
|
+
return "-";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function describeCronDelivery(job: CronJobView): string {
|
|
44
|
+
if (!job.payload.deliver) {
|
|
45
|
+
return "-";
|
|
46
|
+
}
|
|
47
|
+
const channel = job.payload.channel ?? "-";
|
|
48
|
+
const target = job.payload.to ?? "-";
|
|
49
|
+
return `${channel}:${target}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function describeCronSession(job: CronJobView): string {
|
|
53
|
+
return job.payload.sessionId?.trim() || `cron:${job.id}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function isCronJobForSession(job: CronJobView, sessionKey: string | null | undefined): boolean {
|
|
57
|
+
const normalizedSessionKey = sessionKey?.trim();
|
|
58
|
+
return Boolean(normalizedSessionKey && job.payload.sessionId?.trim() === normalizedSessionKey);
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./cron-job-view.utils";
|
|
@@ -38,5 +38,36 @@ export const CHANNEL_AUTH_LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
38
38
|
weixinAuthAdvancedDescription: {
|
|
39
39
|
zh: '仅在你需要自定义接口地址、账号映射或白名单时再展开这些字段。',
|
|
40
40
|
en: 'Expand these fields only when you need to customize the API base URL, account mapping, or allowlist.'
|
|
41
|
+
},
|
|
42
|
+
feishuAuthTitle: { zh: '扫码连接飞书', en: 'Connect Feishu by QR' },
|
|
43
|
+
feishuAuthDescription: { zh: '飞书渠道使用扫码创建自建应用,不再要求手动复制应用凭证。', en: 'Feishu uses QR-based app registration, so you no longer need to copy app credentials manually.' },
|
|
44
|
+
feishuAuthHint: {
|
|
45
|
+
zh: '点击按钮后用飞书扫码确认,连接成功后会自动保存应用凭证并启用 WebSocket 收发。',
|
|
46
|
+
en: 'Start the flow, scan with Feishu, and the app credentials will be saved automatically for WebSocket messaging.'
|
|
47
|
+
},
|
|
48
|
+
feishuAuthCapabilityHint: {
|
|
49
|
+
zh: '连接成功后,Agent 可以通过飞书自建应用收发私聊和群聊消息。',
|
|
50
|
+
en: 'After connecting, the agent can send and receive Feishu direct and group messages through the registered app.'
|
|
51
|
+
},
|
|
52
|
+
feishuAuthDisabledHint: {
|
|
53
|
+
zh: '当前飞书应用已完成扫码连接,但渠道处于未启用状态。打开 Enabled 后才会开始收发消息。',
|
|
54
|
+
en: 'This Feishu app is connected, but the channel is inactive. Turn on Enabled before it can send or receive messages.'
|
|
55
|
+
},
|
|
56
|
+
feishuAuthConnect: { zh: '扫码连接飞书', en: 'Scan QR to connect Feishu' },
|
|
57
|
+
feishuAuthQrAlt: { zh: '飞书应用注册二维码', en: 'Feishu app registration QR code' },
|
|
58
|
+
feishuAuthScanPrompt: { zh: '请用飞书扫码,并按页面提示完成应用创建授权。', en: 'Scan with Feishu and follow the prompts to finish app registration.' },
|
|
59
|
+
feishuAuthReadyTitle: { zh: '准备连接飞书', en: 'Ready to connect Feishu' },
|
|
60
|
+
feishuAuthReadyDescription: {
|
|
61
|
+
zh: '点击左侧按钮后,这里会显示应用注册二维码。首配流程默认不需要进入开放平台手动建应用。',
|
|
62
|
+
en: 'After you start the flow, the app registration QR code will appear here. First-time setup does not require manually creating an app in the developer console.'
|
|
63
|
+
},
|
|
64
|
+
feishuAuthAdvancedTitle: { zh: '高级设置', en: 'Advanced settings' },
|
|
65
|
+
feishuAuthAdvancedDescription: {
|
|
66
|
+
zh: '仅在你需要切换 Feishu/Lark 域名、指定默认账号、白名单或群聊策略时再展开这些字段。',
|
|
67
|
+
en: 'Expand these fields only when you need to switch Feishu/Lark domains, choose a default account, or adjust allowlist and group policies.'
|
|
68
|
+
},
|
|
69
|
+
feishuAuthDomain: {
|
|
70
|
+
zh: '飞书域名',
|
|
71
|
+
en: 'Feishu domain'
|
|
41
72
|
}
|
|
42
73
|
};
|
|
@@ -38,11 +38,10 @@ export const CHAT_LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
38
38
|
},
|
|
39
39
|
chatSessionLabel: { zh: '当前会话', en: 'Current Session' },
|
|
40
40
|
chatNoSession: { zh: '未选择会话', en: 'No session selected' },
|
|
41
|
-
chatNoSessionHint: { zh: '创建一个会话并发送第一条消息。', en: 'Create a session and send your first message.' },
|
|
42
41
|
chatHistoryLoading: { zh: '加载会话历史中...', en: 'Loading session history...' },
|
|
43
|
-
chatNoMessages: { zh: '暂无消息,发送一条开始对话。', en: 'No messages yet. Send one to start.' },
|
|
44
42
|
chatBackToParent: { zh: '返回父会话', en: 'Back to parent' },
|
|
45
43
|
chatSessionOpenChildSessions: { zh: '查看子会话', en: 'View child sessions' },
|
|
44
|
+
chatSessionOpenCronJobs: { zh: '查看本会话定时任务', en: 'View session cron jobs' },
|
|
46
45
|
chatChildSessionLoading: { zh: '正在加载子会话…', en: 'Loading child session…' },
|
|
47
46
|
chatChildSessionEmpty: { zh: '子会话还没有消息。', en: 'No child session messages yet.' },
|
|
48
47
|
chatWorkspaceClosePanel: { zh: '关闭工作区侧栏', en: 'Close workspace panel' },
|
|
@@ -56,6 +55,8 @@ export const CHAT_LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
56
55
|
chatWorkspacePreviewEmpty: { zh: '当前没有可显示的文件内容。', en: 'No file content is available for preview.' },
|
|
57
56
|
chatWorkspaceDiffEmpty: { zh: '当前没有可显示的 diff 内容。', en: 'No diff content is available.' },
|
|
58
57
|
chatWorkspacePreviewTruncated: { zh: '内容已截断', en: 'Preview truncated' },
|
|
58
|
+
chatWorkspaceSessionCronJobs: { zh: '本会话定时任务', en: 'Session cron jobs' },
|
|
59
|
+
chatWorkspaceCronJobEmpty: { zh: '这个会话暂无定时任务。', en: 'This session has no cron jobs.' },
|
|
59
60
|
chatSessionUnread: { zh: '会话有未读更新', en: 'Session has unread updates' },
|
|
60
61
|
chatTyping: { zh: 'Agent 正在思考...', en: 'Agent is thinking...' },
|
|
61
62
|
chatRuntimeInitializing: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AGENT_LABELS } from './agents';
|
|
2
2
|
import { CHANNEL_LABELS } from './channels';
|
|
3
|
-
import { CHANNEL_AUTH_LABELS } from './channel-auth';
|
|
3
|
+
import { CHANNEL_AUTH_LABELS } from './channel-auth.constants';
|
|
4
4
|
import { CHAT_LABELS } from './chat-labels.utils';
|
|
5
5
|
import {
|
|
6
6
|
getLanguage,
|
|
@@ -17,7 +17,7 @@ import { MARKETPLACE_LABELS } from './marketplace';
|
|
|
17
17
|
import { PATH_PICKER_LABELS } from './runtime/i18n.path-picker';
|
|
18
18
|
import { PWA_LABELS } from './pwa';
|
|
19
19
|
import { REMOTE_LABELS } from './remote';
|
|
20
|
-
import { RUNTIME_CONTROL_LABELS } from './runtime-control';
|
|
20
|
+
import { RUNTIME_CONTROL_LABELS } from './runtime-control-labels.utils';
|
|
21
21
|
import { SEARCH_LABELS } from './search';
|
|
22
22
|
export type { I18nLanguage };
|
|
23
23
|
export { getLanguage, getLocale, initializeI18n, LANGUAGE_OPTIONS, resolveInitialLanguage, setLanguage, subscribeLanguageChange };
|
|
@@ -113,7 +113,7 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
113
113
|
en: 'If the model is not listed, type a custom model ID directly.'
|
|
114
114
|
},
|
|
115
115
|
modelIdentifierHelp: {
|
|
116
|
-
zh: '
|
|
116
|
+
zh: '智能体默认模型标识,使用带提供商前缀的格式。例如:openai/gpt-5.1、anthropic/claude-opus-4-1、deepseek/deepseek-chat、minimax/MiniMax-M2.5、openrouter/openai/gpt-5.3-codex。',
|
|
117
117
|
en: 'Default model identifier used by the agent. Use provider-prefixed format. Examples: openai/gpt-5.1 · anthropic/claude-opus-4-1 · deepseek/deepseek-chat · minimax/MiniMax-M2.5 · openrouter/openai/gpt-5.3-codex.'
|
|
118
118
|
},
|
|
119
119
|
maxToolIterations: { zh: '最大工具迭代次数', en: 'Max Tool Iterations' },
|
|
@@ -132,7 +132,7 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
132
132
|
providersSelectPlaceholder: { zh: '选择提供商', en: 'Select Provider' },
|
|
133
133
|
providersSelectTitle: { zh: '选择左侧提供商开始配置', en: 'Select a provider from the left to configure' },
|
|
134
134
|
providersSelectDescription: { zh: '你可以连续切换多个提供商并逐个保存配置。', en: 'Switch between providers continuously and save each configuration.' },
|
|
135
|
-
providersDefaultDescription: { zh: '
|
|
135
|
+
providersDefaultDescription: { zh: '为你的智能体配置 AI 服务', en: 'Configure AI services for your agents' },
|
|
136
136
|
providersEmptyTitle: { zh: '尚未配置提供商', en: 'No providers configured' },
|
|
137
137
|
providersEmptyDescription: { zh: '添加一个 AI 提供商后即可开始使用。', en: 'Add an AI provider to start using the platform.' },
|
|
138
138
|
apiKey: { zh: 'API 密钥', en: 'API Key' },
|
|
@@ -346,32 +346,32 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
346
346
|
authSessionMemoryNotice: { zh: '当前版本的会话只保存在服务端内存里。NextClaw UI 进程重启后,需要重新登录。', en: 'Sessions are stored only in server memory for now. You will need to sign in again after the NextClaw UI process restarts.' },
|
|
347
347
|
dmScope: { zh: '私聊范围', en: 'DM Scope' },
|
|
348
348
|
dmScopeHelp: { zh: '控制私聊会话如何隔离。', en: 'Control how direct-message sessions are isolated.' },
|
|
349
|
-
defaultContextTokens: { zh: '
|
|
350
|
-
defaultContextTokensHelp: { zh: '
|
|
349
|
+
defaultContextTokens: { zh: '默认上下文额度', en: 'Default Context Tokens' },
|
|
350
|
+
defaultContextTokensHelp: { zh: '当智能体未设置单独值时使用该上下文预算。', en: 'Input context budget for agents when no per-agent override is set.' },
|
|
351
351
|
runtimeCompanionEnabled: { zh: '桌宠 Companion', en: 'Companion' },
|
|
352
352
|
runtimeCompanionEnabledHelp: { zh: '开启后会自动拉起悬浮 Companion;关闭后会立即停止,并在下次启动时保持关闭。', en: 'When enabled, NextClaw auto-starts the floating companion. When disabled, it stops immediately and stays off after restart.' },
|
|
353
|
-
defaultEngine: { zh: '
|
|
354
|
-
defaultEngineHelp: { zh: '
|
|
355
|
-
agentList: { zh: '
|
|
356
|
-
agentListHelp: { zh: '
|
|
353
|
+
defaultEngine: { zh: '默认运行时', en: 'Default Runtime' },
|
|
354
|
+
defaultEngineHelp: { zh: '默认使用的智能体运行时,例如 native、codex 或 claude。', en: 'Default agent runtime, for example native, codex, or claude.' },
|
|
355
|
+
agentList: { zh: '智能体列表', en: 'Agent List' },
|
|
356
|
+
agentListHelp: { zh: '在同一个网关进程中运行多个固定角色智能体。', en: 'Run multiple fixed-role agents in one gateway process.' },
|
|
357
357
|
bindings: { zh: '绑定规则', en: 'Bindings' },
|
|
358
|
-
bindingsHelp: { zh: '根据渠道 + 账号 +
|
|
358
|
+
bindingsHelp: { zh: '根据渠道 + 账号 + 对端将入站消息路由到目标智能体。', en: 'Route inbound message by channel + account + peer to target agent.' },
|
|
359
359
|
agentIdRequiredError: { zh: 'agents.list[{index}].id 必填', en: 'agents.list[{index}].id is required' },
|
|
360
|
-
duplicateAgentId: { zh: '
|
|
360
|
+
duplicateAgentId: { zh: '重复的智能体 ID', en: 'Duplicate agent id' },
|
|
361
361
|
bindingAgentIdRequired: { zh: 'bindings[{index}].agentId 必填', en: 'bindings[{index}].agentId is required' },
|
|
362
362
|
bindingAgentIdNotFound: { zh: 'bindings[{index}].agentId 未在 agents.list/main 中找到', en: "bindings[{index}].agentId not found in agents.list/main" },
|
|
363
363
|
bindingChannelRequired: { zh: 'bindings[{index}].match.channel 必填', en: 'bindings[{index}].match.channel is required' },
|
|
364
364
|
bindingPeerIdRequired: { zh: '设置 peer.kind 时,bindings[{index}].match.peer.id 必填', en: 'bindings[{index}].match.peer.id is required when peer.kind is set' },
|
|
365
|
-
agentIdPlaceholder: { zh: '
|
|
365
|
+
agentIdPlaceholder: { zh: '智能体 ID(例如 engineer)', en: 'Agent ID (e.g. engineer)' },
|
|
366
366
|
workspaceOverridePlaceholder: { zh: '工作空间覆盖(可选)', en: 'Workspace override (optional)' },
|
|
367
367
|
modelOverridePlaceholder: { zh: '模型覆盖(可选)', en: 'Model override (optional)' },
|
|
368
|
-
defaultEnginePlaceholder: { zh: '
|
|
369
|
-
engineOverridePlaceholder: { zh: '
|
|
370
|
-
contextTokensPlaceholder: { zh: '
|
|
368
|
+
defaultEnginePlaceholder: { zh: '默认运行时(如 native 或 codex)', en: 'Default runtime (e.g. native or codex)' },
|
|
369
|
+
engineOverridePlaceholder: { zh: '运行时覆盖(可选)', en: 'Runtime override (optional)' },
|
|
370
|
+
contextTokensPlaceholder: { zh: '上下文额度', en: 'Context tokens' },
|
|
371
371
|
maxToolsPlaceholder: { zh: '最大工具次数', en: 'Max tools' },
|
|
372
|
-
defaultAgent: { zh: '
|
|
373
|
-
addAgent: { zh: '
|
|
374
|
-
targetAgentIdPlaceholder: { zh: '
|
|
372
|
+
defaultAgent: { zh: '默认智能体', en: 'Default agent' },
|
|
373
|
+
addAgent: { zh: '添加智能体', en: 'Add Agent' },
|
|
374
|
+
targetAgentIdPlaceholder: { zh: '目标智能体 ID', en: 'Target agent ID' },
|
|
375
375
|
channelPlaceholder: { zh: '渠道(例如 discord)', en: 'Channel (e.g. discord)' },
|
|
376
376
|
accountIdOptionalPlaceholder: { zh: '账号 ID(可选)', en: 'Account ID (optional)' },
|
|
377
377
|
peerKindOptional: { zh: '对端类型(可选)', en: 'Peer kind (optional)' },
|
|
@@ -415,51 +415,12 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
415
415
|
secretProviderAlias: { zh: 'Provider 别名', en: 'Provider Alias' },
|
|
416
416
|
addSecretRef: { zh: '添加 Ref', en: 'Add Ref' },
|
|
417
417
|
|
|
418
|
-
//
|
|
419
|
-
sessionsPageTitle: { zh: '会话管理', en: 'Sessions' },
|
|
420
|
-
sessionsPageDescription: {
|
|
421
|
-
zh: '管理会话:筛选、按渠道分组、查看历史、改标签/偏好模型、清空和删除。',
|
|
422
|
-
en: 'Manage sessions: filter, group by channel, inspect history, edit metadata, clear, and delete.'
|
|
423
|
-
},
|
|
424
|
-
sessionsFiltersTitle: { zh: '筛选', en: 'Filters' },
|
|
425
|
-
sessionsFiltersDescription: { zh: '按关键词、活跃窗口和分组方式筛选会话。', en: 'Filter sessions by query, activity window, and grouping mode.' },
|
|
426
|
-
sessionsSearchPlaceholder: { zh: '搜索 key 或标签', en: 'Search session key or label' },
|
|
427
|
-
sessionsActiveMinutesPlaceholder: { zh: '活跃分钟(0=不限)', en: 'Active minutes (0 = no limit)' },
|
|
428
|
-
sessionsLimitPlaceholder: { zh: '展示上限', en: 'Limit' },
|
|
429
|
-
sessionsGroupModeLabel: { zh: '分组方式', en: 'Grouping' },
|
|
430
|
-
sessionsGroupModeAll: { zh: '不分组 / 全部', en: 'All (No grouping)' },
|
|
431
|
-
sessionsGroupModeByChannel: { zh: '按渠道分组', en: 'Group by channel' },
|
|
432
|
-
sessionsListTitle: { zh: '会话列表', en: 'Session list' },
|
|
433
|
-
sessionsTotalLabel: { zh: '总数', en: 'Total' },
|
|
434
|
-
sessionsCurrentLabel: { zh: '当前展示', en: 'Showing' },
|
|
418
|
+
// Session labels shared by the main chat workspace.
|
|
435
419
|
sessionsLoading: { zh: '加载会话中...', en: 'Loading sessions...' },
|
|
436
420
|
sessionsEmpty: { zh: '暂无会话。', en: 'No sessions yet.' },
|
|
437
|
-
sessionsKeyLabel: { zh: '键', en: 'Key' },
|
|
438
|
-
sessionsChannelLabel: { zh: '渠道', en: 'Channel' },
|
|
439
|
-
sessionsMessagesLabel: { zh: '消息数', en: 'Messages' },
|
|
440
|
-
sessionsUpdatedLabel: { zh: '更新时间', en: 'Updated' },
|
|
441
|
-
sessionsLastRoleLabel: { zh: '最后角色', en: 'Last Role' },
|
|
442
421
|
sessionsLabelPlaceholder: { zh: '会话标签(可选)', en: 'Session label (optional)' },
|
|
443
|
-
sessionsModelPlaceholder: { zh: '偏好模型(可选)', en: 'Preferred model (optional)' },
|
|
444
|
-
sessionsShowHistory: { zh: '查看历史', en: 'View history' },
|
|
445
|
-
sessionsHideHistory: { zh: '隐藏历史', en: 'Hide history' },
|
|
446
|
-
sessionsSaveMeta: { zh: '保存元信息', en: 'Save metadata' },
|
|
447
|
-
sessionsClearHistory: { zh: '清空历史', en: 'Clear history' },
|
|
448
|
-
sessionsDeleteConfirm: { zh: '确认删除会话', en: 'Delete session' },
|
|
449
|
-
sessionsHistoryTitle: { zh: '历史', en: 'History' },
|
|
450
|
-
sessionsHistoryDescription: { zh: '最近 200 条消息(展示窗口)。', en: 'Latest 200 messages (display window).' },
|
|
451
|
-
sessionsHistoryLoading: { zh: '加载历史中...', en: 'Loading history...' },
|
|
452
|
-
sessionsApplyingChanges: { zh: '正在应用会话变更...', en: 'Applying session changes...' },
|
|
453
|
-
sessionsUnknownChannel: { zh: '未知渠道', en: 'Unknown channel' },
|
|
454
|
-
sessionsAllChannels: { zh: '全部渠道', en: 'All Channels' },
|
|
455
422
|
sessionsRunStatusRunning: { zh: '运行中', en: 'Running' },
|
|
456
423
|
sessionsRunStatusQueued: { zh: '排队中', en: 'Queued' },
|
|
457
|
-
sessionsMetadata: { zh: '元信息', en: 'Metadata' },
|
|
458
|
-
sessionsNoSelectionTitle: { zh: '未选择会话', en: 'No Session Selected' },
|
|
459
|
-
sessionsNoSelectionDescription: {
|
|
460
|
-
zh: '从左侧列表选择一个会话以查看聊天历史并配置其元信息。',
|
|
461
|
-
en: 'Select a session from the list on the left to view its chat history and configure its metadata.'
|
|
462
|
-
},
|
|
463
424
|
// Chat
|
|
464
425
|
...AGENT_LABELS,
|
|
465
426
|
...CHAT_LABELS,
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
export const RUNTIME_CONTROL_LABELS: Record<string, { zh: string; en: string }> = {
|
|
2
2
|
runtimePageTitle: { zh: '路由与运行时', en: 'Routing & Runtime' },
|
|
3
3
|
runtimePageDescription: {
|
|
4
|
-
zh: '对齐 OpenClaw
|
|
4
|
+
zh: '对齐 OpenClaw 的多智能体路由:绑定规则、智能体池、私聊范围。',
|
|
5
5
|
en: 'Align multi-agent routing with OpenClaw: bindings, agent pool, and DM scope.'
|
|
6
6
|
},
|
|
7
|
+
dmScopeMain: { zh: '统一到主会话', en: 'Main session' },
|
|
8
|
+
dmScopePerPeer: { zh: '按对端隔离', en: 'Per peer' },
|
|
9
|
+
dmScopePerChannelPeer: { zh: '按渠道和对端隔离', en: 'Per channel and peer' },
|
|
10
|
+
dmScopePerAccountChannelPeer: { zh: '按账号、渠道和对端隔离', en: 'Per account, channel, and peer' },
|
|
11
|
+
runtimeEntries: { zh: '运行时入口', en: 'Runtime Entries' },
|
|
12
|
+
runtimeEntriesHelp: { zh: '统一管理可见的运行时入口与其配置。', en: 'Manage visible runtime entries and their configuration in one place.' },
|
|
13
|
+
runtimeEntryIdPlaceholder: { zh: '入口 ID,例如 hermes', en: 'Entry ID, for example hermes' },
|
|
14
|
+
runtimeEntryLabelPlaceholder: { zh: '展示名称,例如 Hermes', en: 'Display name, for example Hermes' },
|
|
15
|
+
runtimeEntryTypePlaceholder: { zh: '运行时类型,例如 narp-stdio', en: 'Runtime type, for example narp-stdio' },
|
|
16
|
+
runtimeEntryConfigJson: { zh: '配置 JSON', en: 'Config JSON' },
|
|
17
|
+
addRuntimeEntry: { zh: '添加运行时入口', en: 'Add Runtime Entry' },
|
|
18
|
+
runtimeEntryIdRequired: { zh: '运行时入口 ID 必填,位置:{index}', en: 'Runtime entry id is required at index {index}.' },
|
|
19
|
+
runtimeEntryTypeRequired: { zh: '运行时入口 "{id}" 的类型必填', en: 'Runtime entry type is required for "{id}".' },
|
|
20
|
+
runtimeEntryDuplicate: { zh: '重复的运行时入口 ID', en: 'Duplicate runtime entry id' },
|
|
21
|
+
runtimeEntryConfigObjectRequired: { zh: '运行时入口 "{id}" 的配置必须是 JSON 对象。', en: 'Runtime entry config for "{id}" must be a JSON object.' },
|
|
22
|
+
peerKindDirect: { zh: '私聊', en: 'Direct' },
|
|
23
|
+
peerKindGroup: { zh: '群组', en: 'Group' },
|
|
24
|
+
peerKindChannel: { zh: '频道', en: 'Channel' },
|
|
7
25
|
runtimeLoading: { zh: '加载运行时配置中...', en: 'Loading runtime settings...' },
|
|
8
26
|
runtimeControlTitle: { zh: '服务管理', en: 'Service Management' },
|
|
9
27
|
runtimeControlDescription: {
|
|
@@ -53,6 +71,17 @@ export const RUNTIME_CONTROL_LABELS: Record<string, { zh: string; en: string }>
|
|
|
53
71
|
},
|
|
54
72
|
runtimeControlLoading: { zh: '读取运行时控制能力中...', en: 'Loading runtime control capabilities...' },
|
|
55
73
|
runtimeControlLoadFailed: { zh: '读取运行时控制状态失败', en: 'Failed to load runtime control state' },
|
|
74
|
+
runtimeControlManagedLocalMessage: { zh: '使用此页面管理本地 NextClaw 服务。关闭浏览器不会停止服务。', en: 'Use this page to manage the local NextClaw service. Closing the browser does not stop the service.' },
|
|
75
|
+
runtimeControlManagedLocalHint: { zh: '此页面由正在运行的本地服务提供。关闭浏览器不会停止它。', en: 'This page is served by the running local service. Closing the browser does not stop it.' },
|
|
76
|
+
runtimeControlManagedLocalHintShort: { zh: '此页面由正在运行的本地服务提供。', en: 'This page is served by the running local service.' },
|
|
77
|
+
runtimeControlStartUnavailableHosted: { zh: '当前页面已经由运行中的本地服务托管。', en: 'This page is already hosted by the running local service.' },
|
|
78
|
+
runtimeControlRestartAppDesktopOnly: { zh: '只有桌面壳环境支持重启整个应用。', en: 'App restart is only available in the desktop shell.' },
|
|
79
|
+
runtimeControlServiceNotRunning: { zh: '本地服务未运行。', en: 'The local service is not running.' },
|
|
80
|
+
runtimeControlServiceAlreadyStopped: { zh: '本地服务已经停止。', en: 'The local service is already stopped.' },
|
|
81
|
+
runtimeControlManagedServiceStarted: { zh: '本地服务已启动。', en: 'Managed service started.' },
|
|
82
|
+
runtimeControlManagedServiceStartScheduled: { zh: '本地服务启动已安排。', en: 'Managed service start scheduled.' },
|
|
83
|
+
runtimeControlRestartScheduled: { zh: '重启已安排。此页面可能会短暂断开。', en: 'Restart scheduled. This page may disconnect for a few seconds.' },
|
|
84
|
+
runtimeControlStopScheduled: { zh: '停止已安排。此页面即将断开。', en: 'Stop scheduled. This page will disconnect shortly.' },
|
|
56
85
|
runtimeControlServiceRunning: { zh: '服务运行中', en: 'Service running' },
|
|
57
86
|
runtimeControlServiceStopped: { zh: '服务已停止', en: 'Service stopped' },
|
|
58
87
|
runtimeControlServiceStarting: { zh: '正在启动服务', en: 'Starting service' },
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { buildProviderModelCatalog } from './index';
|
|
3
|
+
|
|
4
|
+
describe('buildProviderModelCatalog', () => {
|
|
5
|
+
it('does not resurrect an OpenRouter model removed from config models', () => {
|
|
6
|
+
const catalog = buildProviderModelCatalog({
|
|
7
|
+
onlyConfigured: true,
|
|
8
|
+
meta: {
|
|
9
|
+
providers: [
|
|
10
|
+
{
|
|
11
|
+
name: 'openrouter',
|
|
12
|
+
displayName: 'OpenRouter',
|
|
13
|
+
modelPrefix: 'openrouter',
|
|
14
|
+
defaultModels: [
|
|
15
|
+
'openrouter/deepseek/deepseek-v3.2',
|
|
16
|
+
'openrouter/openai/gpt-5.3-codex'
|
|
17
|
+
],
|
|
18
|
+
keywords: [],
|
|
19
|
+
envKey: 'OPENROUTER_API_KEY'
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
search: [],
|
|
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
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(catalog).toHaveLength(1);
|
|
37
|
+
expect(catalog[0]?.models).toEqual(['openai/gpt-5.3-codex']);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -189,11 +189,9 @@ export function buildProviderModelCatalog(params: {
|
|
|
189
189
|
const providerConfig = config?.providers?.[spec.name];
|
|
190
190
|
const prefix = (spec.modelPrefix || spec.name || '').trim();
|
|
191
191
|
const aliases = normalizeStringList([spec.modelPrefix || '', spec.name || '']);
|
|
192
|
-
const
|
|
193
|
-
const customModels = normalizeStringList(
|
|
192
|
+
const models = normalizeStringList(
|
|
194
193
|
(providerConfig?.models ?? []).map((model) => toProviderLocalModel(model, aliases))
|
|
195
194
|
);
|
|
196
|
-
const models = normalizeStringList([...defaultModels, ...customModels]);
|
|
197
195
|
const modelThinking = normalizeModelThinkingMap(providerConfig?.modelThinking, aliases);
|
|
198
196
|
const configDisplayName = providerConfig?.displayName?.trim();
|
|
199
197
|
const configured = isProviderConfigured(providerConfig);
|
|
@@ -19,7 +19,6 @@ const ROUTE_TITLE_KEYS: Array<{ prefix: string; key: string }> = [
|
|
|
19
19
|
{ prefix: '/updates', key: 'runtimeUpdatesPageTitle' },
|
|
20
20
|
{ prefix: '/remote', key: 'remotePageTitle' },
|
|
21
21
|
{ prefix: '/security', key: 'authSecurityTitle' },
|
|
22
|
-
{ prefix: '/sessions', key: 'sessionsPageTitle' },
|
|
23
22
|
{ prefix: '/secrets', key: 'secretsPageTitle' }
|
|
24
23
|
];
|
|
25
24
|
|
package/tsconfig.json
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@/*": ["./src/*"],
|
|
35
35
|
"@nextclaw/agent-chat": ["../nextclaw-agent-chat/src/index.ts"],
|
|
36
36
|
"@nextclaw/agent-chat-ui": ["../nextclaw-agent-chat-ui/src/index.ts"],
|
|
37
|
+
"@agent-chat-ui/*": ["../nextclaw-agent-chat-ui/src/*"],
|
|
37
38
|
"@nextclaw/client-sdk": ["../nextclaw-client-sdk/src/index.ts"],
|
|
38
39
|
"@nextclaw/shared": ["../nextclaw-shared/src/index.ts"],
|
|
39
40
|
"@nextclaw/ncp": ["../ncp-packages/nextclaw-ncp/src/index.ts"],
|
package/vite.config.ts
CHANGED
|
@@ -19,7 +19,6 @@ export default defineConfig({
|
|
|
19
19
|
'@/components/config/SearchConfig': path.resolve(__dirname, './src/shared/components/search-config.tsx'),
|
|
20
20
|
'@/components/config/SecretsConfig': path.resolve(__dirname, './src/shared/components/config/secrets-config.tsx'),
|
|
21
21
|
'@/components/config/security-config': path.resolve(__dirname, './src/features/system-status/components/security-config.tsx'),
|
|
22
|
-
'@/components/config/SessionsConfig': path.resolve(__dirname, './src/features/chat/pages/sessions-config-page.tsx'),
|
|
23
22
|
'@/components/layout/AppLayout': path.resolve(__dirname, './src/app/components/layout/app-layout.tsx'),
|
|
24
23
|
'@/components/marketplace/marketplace-page': path.resolve(__dirname, './src/features/marketplace/components/marketplace-page.tsx'),
|
|
25
24
|
'@/components/marketplace/mcp/mcp-marketplace-page': path.resolve(__dirname, './src/features/marketplace/components/mcp/mcp-marketplace-page.tsx'),
|
|
@@ -32,6 +31,7 @@ export default defineConfig({
|
|
|
32
31
|
'@': path.resolve(__dirname, './src'),
|
|
33
32
|
'@nextclaw/agent-chat': path.resolve(__dirname, '../nextclaw-agent-chat/src/index.ts'),
|
|
34
33
|
'@nextclaw/agent-chat-ui': path.resolve(__dirname, '../nextclaw-agent-chat-ui/src/index.ts'),
|
|
34
|
+
'@agent-chat-ui': path.resolve(__dirname, '../nextclaw-agent-chat-ui/src'),
|
|
35
35
|
'@nextclaw/client-sdk': path.resolve(__dirname, '../nextclaw-client-sdk/src/index.ts'),
|
|
36
36
|
'@nextclaw/shared': path.resolve(__dirname, '../nextclaw-shared/src/index.ts')
|
|
37
37
|
}
|
package/vitest.config.ts
CHANGED
|
@@ -14,7 +14,6 @@ export default defineConfig({
|
|
|
14
14
|
'@/components/config/SearchConfig': path.resolve(__dirname, './src/shared/components/search-config.tsx'),
|
|
15
15
|
'@/components/config/SecretsConfig': path.resolve(__dirname, './src/shared/components/config/secrets-config.tsx'),
|
|
16
16
|
'@/components/config/security-config': path.resolve(__dirname, './src/features/system-status/components/security-config.tsx'),
|
|
17
|
-
'@/components/config/SessionsConfig': path.resolve(__dirname, './src/features/chat/pages/sessions-config-page.tsx'),
|
|
18
17
|
'@/components/layout/AppLayout': path.resolve(__dirname, './src/app/components/layout/app-layout.tsx'),
|
|
19
18
|
'@/components/marketplace/marketplace-page': path.resolve(__dirname, './src/features/marketplace/components/marketplace-page.tsx'),
|
|
20
19
|
'@/components/marketplace/mcp/mcp-marketplace-page': path.resolve(__dirname, './src/features/marketplace/components/mcp/mcp-marketplace-page.tsx'),
|
|
@@ -27,6 +26,7 @@ export default defineConfig({
|
|
|
27
26
|
'@': path.resolve(__dirname, './src'),
|
|
28
27
|
'@nextclaw/agent-chat': path.resolve(__dirname, '../nextclaw-agent-chat/src/index.ts'),
|
|
29
28
|
'@nextclaw/agent-chat-ui': path.resolve(__dirname, '../nextclaw-agent-chat-ui/src/index.ts'),
|
|
29
|
+
'@agent-chat-ui': path.resolve(__dirname, '../nextclaw-agent-chat-ui/src'),
|
|
30
30
|
'@nextclaw/client-sdk': path.resolve(__dirname, '../nextclaw-client-sdk/src/index.ts'),
|
|
31
31
|
'@nextclaw/shared': path.resolve(__dirname, '../nextclaw-shared/src/index.ts')
|
|
32
32
|
}
|