@nextclaw/ui 0.9.2 → 0.9.4
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 +12 -0
- package/dist/assets/ChannelsList-DDfZIiJa.js +1 -0
- package/dist/assets/ChatPage-FpRraTxm.js +38 -0
- package/dist/assets/{DocBrowser-CVwUDJMO.js → DocBrowser-Kndx8OJj.js} +1 -1
- package/dist/assets/LogoBadge-hKHoLH9n.js +1 -0
- package/dist/assets/MarketplacePage-CZIJyfjK.js +49 -0
- package/dist/assets/McpMarketplacePage-BGrAMA37.js +40 -0
- package/dist/assets/{ModelConfig-CsX-_fyy.js → ModelConfig-BpKQeGfb.js} +1 -1
- package/dist/assets/ProvidersList-qfUL6mrW.js +1 -0
- package/dist/assets/RemoteAccessPage-BQuMsngI.js +1 -0
- package/dist/assets/{RuntimeConfig-CX2TGEG1.js → RuntimeConfig-CVlqNWKO.js} +1 -1
- package/dist/assets/{SearchConfig-C-WBTcWi.js → SearchConfig-DXFV6Mvx.js} +1 -1
- package/dist/assets/{SecretsConfig-9kbR0ZCB.js → SecretsConfig-BGW9aUqv.js} +2 -2
- package/dist/assets/{SessionsConfig-Bohn3P1q.js → SessionsConfig-BByfa1ke.js} +2 -2
- package/dist/assets/{chat-message-AWIcksDK.js → chat-message-ZwnDwDuQ.js} +1 -1
- package/dist/assets/index-BWvap_iq.js +8 -0
- package/dist/assets/index-COrhpAdh.css +1 -0
- package/dist/assets/{index-CPDASUXh.js → index-Ct7FQpxN.js} +1 -1
- package/dist/assets/{label-DD61y-4v.js → label-Bklr3fXc.js} +1 -1
- package/dist/assets/marketplace-localization-Dk31LJJJ.js +1 -0
- package/dist/assets/{page-layout-CfnoVycc.js → page-layout-sNhcbwtm.js} +1 -1
- package/dist/assets/{popover-DsugZ6rp.js → popover-C3rJrJJG.js} +1 -1
- package/dist/assets/{security-config-DIrf2Z0O.js → security-config-BueosYw1.js} +1 -1
- package/dist/assets/skeleton-CiG6msbm.js +1 -0
- package/dist/assets/status-dot-CsIV5YrS.js +1 -0
- package/dist/assets/{switch-NX5OmUXQ.js → switch-DSdHSIsC.js} +1 -1
- package/dist/assets/{tabs-custom-9ihB5Jem.js → tabs-custom-BB-VjdL2.js} +1 -1
- package/dist/assets/{useConfirmDialog-BuQnVTeR.js → useConfirmDialog-BL5s8KDC.js} +2 -2
- package/dist/assets/{vendor-DKBNiC31.js → vendor-CwsIoNvJ.js} +128 -93
- package/dist/index.html +3 -3
- package/package.json +3 -3
- package/src/App.tsx +4 -0
- package/src/api/auth.types.ts +24 -0
- package/src/api/chat-session-type.types.ts +21 -0
- package/src/api/marketplace.ts +8 -2
- package/src/api/mcp-marketplace.ts +138 -0
- package/src/api/remote.ts +77 -0
- package/src/api/remote.types.ts +104 -0
- package/src/api/types.ts +28 -34
- package/src/components/chat/ChatSidebar.test.tsx +31 -2
- package/src/components/chat/ChatSidebar.tsx +26 -2
- package/src/components/chat/chat-page-data.ts +36 -38
- package/src/components/chat/chat-page-runtime.test.ts +96 -2
- package/src/components/chat/chat-page-runtime.ts +1 -135
- package/src/components/chat/chat-session-preference-governance.ts +303 -0
- package/src/components/chat/legacy/LegacyChatPage.tsx +4 -19
- package/src/components/chat/ncp/NcpChatPage.tsx +4 -19
- package/src/components/chat/ncp/ncp-chat-page-data.test.ts +36 -0
- package/src/components/chat/ncp/ncp-chat-page-data.ts +62 -21
- package/src/components/chat/ncp/ncp-session-adapter.test.ts +2 -0
- package/src/components/chat/ncp/ncp-session-adapter.ts +2 -0
- package/src/components/chat/stores/chat-input.store.ts +14 -1
- package/src/components/chat/useChatSessionTypeState.test.tsx +29 -0
- package/src/components/chat/useChatSessionTypeState.ts +55 -12
- package/src/components/layout/Sidebar.tsx +11 -1
- package/src/components/marketplace/MarketplacePage.test.tsx +152 -0
- package/src/components/marketplace/MarketplacePage.tsx +52 -199
- package/src/components/marketplace/marketplace-installed-cache.test.ts +110 -0
- package/src/components/marketplace/marketplace-installed-cache.ts +149 -0
- package/src/components/marketplace/marketplace-localization.ts +77 -0
- package/src/components/marketplace/marketplace-page-parts.tsx +102 -0
- package/src/components/marketplace/mcp/McpMarketplacePage.test.tsx +208 -0
- package/src/components/marketplace/mcp/McpMarketplacePage.tsx +578 -0
- package/src/components/remote/RemoteAccessPage.tsx +396 -0
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/label.tsx +1 -1
- package/src/hooks/useMarketplace.ts +36 -7
- package/src/hooks/useMcpMarketplace.ts +99 -0
- package/src/hooks/useRemoteAccess.ts +120 -0
- package/src/hooks/useWebSocket.ts +25 -16
- package/src/lib/i18n.marketplace.ts +91 -0
- package/src/lib/i18n.remote.ts +142 -0
- package/src/lib/i18n.ts +10 -68
- package/dist/assets/ChannelsList-DKD6Llid.js +0 -1
- package/dist/assets/ChatPage-BK9X4Tin.js +0 -38
- package/dist/assets/LogoBadge-CYQ_b7jk.js +0 -1
- package/dist/assets/MarketplacePage-B_2z3ii_.js +0 -49
- package/dist/assets/ProvidersList-CZstsyv7.js +0 -1
- package/dist/assets/index-BEgClaDH.js +0 -8
- package/dist/assets/index-C8GsgIUn.css +0 -1
- package/dist/assets/skeleton-DJ-Wen2o.js +0 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import {
|
|
3
|
+
controlRemoteService,
|
|
4
|
+
fetchRemoteStatus,
|
|
5
|
+
fetchRemoteDoctor,
|
|
6
|
+
loginRemote,
|
|
7
|
+
logoutRemote,
|
|
8
|
+
pollRemoteBrowserAuth,
|
|
9
|
+
startRemoteBrowserAuth,
|
|
10
|
+
updateRemoteSettings
|
|
11
|
+
} from '@/api/remote';
|
|
12
|
+
import { t } from '@/lib/i18n';
|
|
13
|
+
import { toast } from 'sonner';
|
|
14
|
+
|
|
15
|
+
export function useRemoteStatus() {
|
|
16
|
+
return useQuery({
|
|
17
|
+
queryKey: ['remote-status'],
|
|
18
|
+
queryFn: fetchRemoteStatus,
|
|
19
|
+
staleTime: 5000,
|
|
20
|
+
refetchOnWindowFocus: true
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useRemoteLogin() {
|
|
25
|
+
const queryClient = useQueryClient();
|
|
26
|
+
|
|
27
|
+
return useMutation({
|
|
28
|
+
mutationFn: loginRemote,
|
|
29
|
+
onSuccess: () => {
|
|
30
|
+
queryClient.invalidateQueries({ queryKey: ['remote-status'] });
|
|
31
|
+
toast.success(t('remoteLoginSuccess'));
|
|
32
|
+
},
|
|
33
|
+
onError: (error: Error) => {
|
|
34
|
+
toast.error(`${t('remoteLoginFailed')}: ${error.message}`);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function useRemoteBrowserAuthStart() {
|
|
40
|
+
return useMutation({
|
|
41
|
+
mutationFn: startRemoteBrowserAuth,
|
|
42
|
+
onError: (error: Error) => {
|
|
43
|
+
toast.error(`${t('remoteBrowserAuthStartFailed')}: ${error.message}`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function useRemoteBrowserAuthPoll() {
|
|
49
|
+
const queryClient = useQueryClient();
|
|
50
|
+
|
|
51
|
+
return useMutation({
|
|
52
|
+
mutationFn: pollRemoteBrowserAuth,
|
|
53
|
+
onSuccess: (result) => {
|
|
54
|
+
if (result.status === 'authorized') {
|
|
55
|
+
queryClient.invalidateQueries({ queryKey: ['remote-status'] });
|
|
56
|
+
toast.success(t('remoteLoginSuccess'));
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
onError: (error: Error) => {
|
|
60
|
+
toast.error(`${t('remoteBrowserAuthPollFailed')}: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function useRemoteLogout() {
|
|
66
|
+
const queryClient = useQueryClient();
|
|
67
|
+
|
|
68
|
+
return useMutation({
|
|
69
|
+
mutationFn: logoutRemote,
|
|
70
|
+
onSuccess: () => {
|
|
71
|
+
queryClient.invalidateQueries({ queryKey: ['remote-status'] });
|
|
72
|
+
toast.success(t('remoteLogoutSuccess'));
|
|
73
|
+
},
|
|
74
|
+
onError: (error: Error) => {
|
|
75
|
+
toast.error(`${t('remoteLogoutFailed')}: ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function useRemoteSettings() {
|
|
81
|
+
const queryClient = useQueryClient();
|
|
82
|
+
|
|
83
|
+
return useMutation({
|
|
84
|
+
mutationFn: updateRemoteSettings,
|
|
85
|
+
onSuccess: () => {
|
|
86
|
+
queryClient.invalidateQueries({ queryKey: ['remote-status'] });
|
|
87
|
+
toast.success(t('remoteSettingsSaved'));
|
|
88
|
+
},
|
|
89
|
+
onError: (error: Error) => {
|
|
90
|
+
toast.error(`${t('remoteSettingsSaveFailed')}: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function useRemoteDoctor() {
|
|
96
|
+
return useMutation({
|
|
97
|
+
mutationFn: fetchRemoteDoctor,
|
|
98
|
+
onSuccess: () => {
|
|
99
|
+
toast.success(t('remoteDoctorCompleted'));
|
|
100
|
+
},
|
|
101
|
+
onError: (error: Error) => {
|
|
102
|
+
toast.error(`${t('remoteDoctorFailed')}: ${error.message}`);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function useRemoteServiceControl() {
|
|
108
|
+
const queryClient = useQueryClient();
|
|
109
|
+
|
|
110
|
+
return useMutation({
|
|
111
|
+
mutationFn: controlRemoteService,
|
|
112
|
+
onSuccess: (result) => {
|
|
113
|
+
queryClient.invalidateQueries({ queryKey: ['remote-status'] });
|
|
114
|
+
toast.success(result.message);
|
|
115
|
+
},
|
|
116
|
+
onError: (error: Error) => {
|
|
117
|
+
toast.error(`${t('remoteServiceActionFailed')}: ${error.message}`);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
@@ -4,6 +4,30 @@ import { API_BASE } from '@/api/client';
|
|
|
4
4
|
import { useUiStore } from '@/stores/ui.store';
|
|
5
5
|
import type { QueryClient } from '@tanstack/react-query';
|
|
6
6
|
|
|
7
|
+
function shouldInvalidateConfigQuery(configPath: string) {
|
|
8
|
+
const normalized = configPath.trim().toLowerCase();
|
|
9
|
+
if (!normalized) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
if (normalized.startsWith('plugins') || normalized.startsWith('skills')) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function invalidateMarketplaceQueries(queryClient: QueryClient | undefined, configPath: string): void {
|
|
19
|
+
if (configPath.startsWith('plugins')) {
|
|
20
|
+
queryClient?.invalidateQueries({ queryKey: ['ncp-session-types'] });
|
|
21
|
+
queryClient?.invalidateQueries({ queryKey: ['marketplace-installed', 'plugin'] });
|
|
22
|
+
queryClient?.invalidateQueries({ queryKey: ['marketplace-items'] });
|
|
23
|
+
}
|
|
24
|
+
if (configPath.startsWith('mcp')) {
|
|
25
|
+
queryClient?.invalidateQueries({ queryKey: ['marketplace-mcp-installed'] });
|
|
26
|
+
queryClient?.invalidateQueries({ queryKey: ['marketplace-mcp-items'] });
|
|
27
|
+
queryClient?.invalidateQueries({ queryKey: ['marketplace-mcp-doctor'] });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
7
31
|
export function useWebSocket(queryClient?: QueryClient) {
|
|
8
32
|
const [ws, setWs] = useState<ConfigWebSocket | null>(null);
|
|
9
33
|
const { setConnectionStatus } = useUiStore();
|
|
@@ -83,17 +107,6 @@ export function useWebSocket(queryClient?: QueryClient) {
|
|
|
83
107
|
queryClient.invalidateQueries({ queryKey: ['ncp-session-messages'] });
|
|
84
108
|
};
|
|
85
109
|
|
|
86
|
-
const shouldInvalidateConfigQuery = (configPath: string) => {
|
|
87
|
-
const normalized = configPath.trim().toLowerCase();
|
|
88
|
-
if (!normalized) {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
if (normalized.startsWith('plugins') || normalized.startsWith('skills')) {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
return true;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
110
|
setConnectionStatus('connecting');
|
|
98
111
|
|
|
99
112
|
client.on('connection.open', () => {
|
|
@@ -121,11 +134,7 @@ export function useWebSocket(queryClient?: QueryClient) {
|
|
|
121
134
|
if (configPath.startsWith('session')) {
|
|
122
135
|
invalidateSessionQueries();
|
|
123
136
|
}
|
|
124
|
-
|
|
125
|
-
queryClient?.invalidateQueries({ queryKey: ['ncp-session-types'] });
|
|
126
|
-
queryClient?.invalidateQueries({ queryKey: ['marketplace-installed', 'plugin'] });
|
|
127
|
-
queryClient?.invalidateQueries({ queryKey: ['marketplace-items'] });
|
|
128
|
-
}
|
|
137
|
+
invalidateMarketplaceQueries(queryClient, configPath);
|
|
129
138
|
});
|
|
130
139
|
|
|
131
140
|
client.on('run.updated', (event) => {
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export const MARKETPLACE_LABELS = {
|
|
2
|
+
marketplacePluginsPageTitle: { zh: '插件市场', en: 'Plugin Marketplace' },
|
|
3
|
+
marketplacePluginsPageDescription: { zh: '安装、启用与管理插件。', en: 'Install, enable, and manage plugins.' },
|
|
4
|
+
marketplaceSkillsPageTitle: { zh: '技能市场', en: 'Skill Marketplace' },
|
|
5
|
+
marketplaceSkillsPageDescription: { zh: '安装与管理技能。', en: 'Install and manage skills.' },
|
|
6
|
+
marketplaceMcpPageTitle: { zh: 'MCP 市场', en: 'MCP Marketplace' },
|
|
7
|
+
marketplaceMcpPageDescription: { zh: '发现、安装、诊断并管理 MCP servers。', en: 'Discover, install, diagnose, and manage MCP servers.' },
|
|
8
|
+
marketplaceTabMarketplacePlugins: { zh: '插件市场', en: 'Plugin Market' },
|
|
9
|
+
marketplaceTabMarketplaceSkills: { zh: '技能市场', en: 'Skill Market' },
|
|
10
|
+
marketplaceMcpTabCatalog: { zh: 'MCP 市场', en: 'MCP Market' },
|
|
11
|
+
marketplaceMcpTabInstalled: { zh: '已安装 MCP', en: 'Installed MCP' },
|
|
12
|
+
marketplaceTabInstalledPlugins: { zh: '已安装插件', en: 'Installed Plugins' },
|
|
13
|
+
marketplaceTabInstalledSkills: { zh: '已安装技能', en: 'Installed Skills' },
|
|
14
|
+
marketplaceSearchPlaceholderPlugins: { zh: '搜索插件...', en: 'Search plugins...' },
|
|
15
|
+
marketplaceSearchPlaceholderSkills: { zh: '搜索技能...', en: 'Search skills...' },
|
|
16
|
+
marketplaceMcpSearchPlaceholder: { zh: '搜索 MCP servers...', en: 'Search MCP servers...' },
|
|
17
|
+
marketplaceFilterPlugins: { zh: '插件', en: 'Plugins' },
|
|
18
|
+
marketplaceFilterSkills: { zh: '技能', en: 'Skills' },
|
|
19
|
+
marketplaceFilterMcp: { zh: 'MCP', en: 'MCP' },
|
|
20
|
+
marketplaceSortRelevance: { zh: '相关性', en: 'Relevance' },
|
|
21
|
+
marketplaceSortUpdated: { zh: '最近更新', en: 'Recently Updated' },
|
|
22
|
+
marketplaceUnknownItem: { zh: '未知项目', en: 'Unknown Item' },
|
|
23
|
+
marketplaceInstalledLocalSummary: { zh: '已在本地安装,市场暂无详情。', en: 'Installed locally. Details are currently unavailable from marketplace.' },
|
|
24
|
+
marketplaceTypePlugin: { zh: '插件', en: 'Plugin' },
|
|
25
|
+
marketplaceTypeSkill: { zh: '技能', en: 'Skill' },
|
|
26
|
+
marketplaceTypeMcp: { zh: 'MCP', en: 'MCP' },
|
|
27
|
+
marketplaceTypeExtension: { zh: '扩展', en: 'Extension' },
|
|
28
|
+
marketplaceInstall: { zh: '安装', en: 'Install' },
|
|
29
|
+
marketplaceInstalling: { zh: '安装中...', en: 'Installing...' },
|
|
30
|
+
marketplaceEnable: { zh: '启用', en: 'Enable' },
|
|
31
|
+
marketplaceDisable: { zh: '禁用', en: 'Disable' },
|
|
32
|
+
marketplaceEnabling: { zh: '启用中...', en: 'Enabling...' },
|
|
33
|
+
marketplaceDisabling: { zh: '禁用中...', en: 'Disabling...' },
|
|
34
|
+
marketplaceUninstall: { zh: '卸载', en: 'Uninstall' },
|
|
35
|
+
marketplaceRemoving: { zh: '卸载中...', en: 'Removing...' },
|
|
36
|
+
marketplaceSectionPlugins: { zh: '插件列表', en: 'Plugin Catalog' },
|
|
37
|
+
marketplaceSectionSkills: { zh: '技能列表', en: 'Skill Catalog' },
|
|
38
|
+
marketplaceMcpSectionCatalog: { zh: 'MCP 列表', en: 'MCP Catalog' },
|
|
39
|
+
marketplaceMcpSectionInstalled: { zh: '已安装 MCP', en: 'Installed MCP' },
|
|
40
|
+
marketplaceSectionInstalledPlugins: { zh: '已安装插件', en: 'Installed Plugins' },
|
|
41
|
+
marketplaceSectionInstalledSkills: { zh: '已安装技能', en: 'Installed Skills' },
|
|
42
|
+
marketplaceErrorLoadingPluginsData: { zh: '加载插件市场数据失败', en: 'Failed to load plugin marketplace data' },
|
|
43
|
+
marketplaceErrorLoadingSkillsData: { zh: '加载技能市场数据失败', en: 'Failed to load skill marketplace data' },
|
|
44
|
+
marketplaceErrorLoadingInstalledPlugins: { zh: '加载已安装插件失败', en: 'Failed to load installed plugins' },
|
|
45
|
+
marketplaceErrorLoadingInstalledSkills: { zh: '加载已安装技能失败', en: 'Failed to load installed skills' },
|
|
46
|
+
marketplaceNoPlugins: { zh: '未找到插件。', en: 'No plugins found.' },
|
|
47
|
+
marketplaceNoSkills: { zh: '未找到技能。', en: 'No skills found.' },
|
|
48
|
+
marketplaceNoMcp: { zh: '未找到 MCP server。', en: 'No MCP servers found.' },
|
|
49
|
+
marketplaceNoInstalledPlugins: { zh: '未找到已安装插件。', en: 'No installed plugins found.' },
|
|
50
|
+
marketplaceNoInstalledSkills: { zh: '未找到已安装技能。', en: 'No installed skills found.' },
|
|
51
|
+
marketplaceNoInstalledMcp: { zh: '未找到已安装 MCP server。', en: 'No installed MCP servers found.' },
|
|
52
|
+
marketplaceUninstallTitle: { zh: '确认卸载', en: 'Uninstall' },
|
|
53
|
+
marketplaceUninstallDescription: {
|
|
54
|
+
zh: '该操作会移除扩展,后续可在市场中重新安装。',
|
|
55
|
+
en: 'This will remove the extension. You can install it again from the marketplace.'
|
|
56
|
+
},
|
|
57
|
+
marketplaceInstallSuccessPlugin: { zh: '插件安装成功', en: 'Plugin installed successfully' },
|
|
58
|
+
marketplaceInstallSuccessSkill: { zh: '技能安装成功', en: 'Skill installed successfully' },
|
|
59
|
+
marketplaceInstallSuccessMcp: { zh: 'MCP 安装成功', en: 'MCP installed successfully' },
|
|
60
|
+
marketplaceEnableSuccess: { zh: '启用成功', en: 'Enabled successfully' },
|
|
61
|
+
marketplaceDisableSuccess: { zh: '禁用成功', en: 'Disabled successfully' },
|
|
62
|
+
marketplaceUninstallSuccess: { zh: '卸载成功', en: 'Uninstalled successfully' },
|
|
63
|
+
marketplaceMcpManageSuccess: { zh: 'MCP 操作成功', en: 'MCP operation completed' },
|
|
64
|
+
marketplaceInstallFailed: { zh: '安装失败', en: 'Install failed' },
|
|
65
|
+
marketplaceOperationFailed: { zh: '操作失败', en: 'Operation failed' },
|
|
66
|
+
marketplaceInstalledPluginsCountSuffix: { zh: '个已安装插件', en: 'installed plugins' },
|
|
67
|
+
marketplaceInstalledSkillsCountSuffix: { zh: '个已安装技能', en: 'installed skills' },
|
|
68
|
+
marketplaceDetailPanelTitle: { zh: '详情预览', en: 'Detail Preview' },
|
|
69
|
+
marketplaceDetailPanelEmpty: { zh: '点击左侧任意插件/技能,在这里查看详情。', en: 'Click an item on the left to preview details here.' },
|
|
70
|
+
marketplaceDetailSummary: { zh: '摘要', en: 'Summary' },
|
|
71
|
+
marketplaceDetailDescription: { zh: '描述', en: 'Description' },
|
|
72
|
+
marketplaceOpenInDocBrowserTab: { zh: '新标签打开', en: 'Open in New Tab' },
|
|
73
|
+
marketplaceMcpInstallDialogTitle: { zh: '安装 MCP Server', en: 'Install MCP Server' },
|
|
74
|
+
marketplaceMcpServerName: { zh: 'Server 名称', en: 'Server Name' },
|
|
75
|
+
marketplaceMcpAllAgents: { zh: '默认对全部 Agent 可用', en: 'Available to All Agents' },
|
|
76
|
+
marketplaceMcpAllAgentsDescription: {
|
|
77
|
+
zh: '默认作为公共资源池接入,不做 runtime 级限制。',
|
|
78
|
+
en: 'Use the server as a shared tool source by default instead of scoping it per runtime.'
|
|
79
|
+
},
|
|
80
|
+
marketplaceMcpDoctor: { zh: 'Doctor', en: 'Doctor' },
|
|
81
|
+
marketplaceMcpDoctorTitle: { zh: 'MCP Doctor', en: 'MCP Doctor' },
|
|
82
|
+
marketplaceMcpDoctorAccessible: { zh: '可访问', en: 'Accessible' },
|
|
83
|
+
marketplaceMcpDoctorTransport: { zh: '传输方式', en: 'Transport' },
|
|
84
|
+
marketplaceMcpDoctorTools: { zh: '工具数', en: 'Tools' },
|
|
85
|
+
marketplaceMcpRemove: { zh: '移除', en: 'Remove' },
|
|
86
|
+
marketplaceMcpRemoveTitle: { zh: '确认移除', en: 'Remove MCP Server' },
|
|
87
|
+
marketplaceMcpRemoveDescription: {
|
|
88
|
+
zh: '该操作会删除 MCP server 配置,并通过热插拔立即从工具源中移除。',
|
|
89
|
+
en: 'This removes the MCP server config and hot-unplugs it from the tool source immediately.'
|
|
90
|
+
}
|
|
91
|
+
} as const;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
export const REMOTE_LABELS: Record<string, { zh: string; en: string }> = {
|
|
2
|
+
remotePageTitle: { zh: '远程访问', en: 'Remote Access' },
|
|
3
|
+
remotePageDescription: {
|
|
4
|
+
zh: '直接在界面内完成平台登录、设备配置、后台服务控制与诊断。',
|
|
5
|
+
en: 'Handle platform login, device settings, managed service control, and diagnostics directly in the UI.'
|
|
6
|
+
},
|
|
7
|
+
remoteLoading: { zh: '正在加载远程访问状态...', en: 'Loading remote access status...' },
|
|
8
|
+
remoteOverviewTitle: { zh: '连接总览', en: 'Connection Overview' },
|
|
9
|
+
remoteOverviewDescription: {
|
|
10
|
+
zh: '快速确认平台账号、托管服务和远程连接器状态。',
|
|
11
|
+
en: 'Quickly verify platform account, managed service, and connector state.'
|
|
12
|
+
},
|
|
13
|
+
remoteAccountConnected: { zh: '平台已登录', en: 'Platform Connected' },
|
|
14
|
+
remoteAccountNotConnected: { zh: '平台未登录', en: 'Platform Not Connected' },
|
|
15
|
+
remoteRuntimeMissing: { zh: '连接器未运行', en: 'Connector Not Running' },
|
|
16
|
+
remoteStateConnected: { zh: '已连接', en: 'Connected' },
|
|
17
|
+
remoteStateConnecting: { zh: '连接中', en: 'Connecting' },
|
|
18
|
+
remoteStateError: { zh: '连接异常', en: 'Error' },
|
|
19
|
+
remoteStateDisconnected: { zh: '已断开', en: 'Disconnected' },
|
|
20
|
+
remoteStateDisabled: { zh: '未启用', en: 'Disabled' },
|
|
21
|
+
remoteLocalOrigin: { zh: '本地服务地址', en: 'Local Origin' },
|
|
22
|
+
remotePublicPlatform: { zh: '平台地址', en: 'Platform Base' },
|
|
23
|
+
remoteDeviceId: { zh: '设备 ID', en: 'Device ID' },
|
|
24
|
+
remoteLastConnectedAt: { zh: '上次连接时间', en: 'Last Connected At' },
|
|
25
|
+
remoteLastError: { zh: '最近错误', en: 'Last Error' },
|
|
26
|
+
remoteDeviceTitle: { zh: '设备配置', en: 'Device Settings' },
|
|
27
|
+
remoteDeviceDescription: {
|
|
28
|
+
zh: '保存远程访问开关、设备名和平台 API Base。',
|
|
29
|
+
en: 'Save remote access state, device name, and platform API base.'
|
|
30
|
+
},
|
|
31
|
+
remoteEnabled: { zh: '启用远程访问', en: 'Enable Remote Access' },
|
|
32
|
+
remoteEnabledHelp: {
|
|
33
|
+
zh: '保存后需要启动或重启后台服务,新的远程配置才会真正生效。',
|
|
34
|
+
en: 'After saving, start or restart the managed service to apply the new remote configuration.'
|
|
35
|
+
},
|
|
36
|
+
remoteDeviceName: { zh: '设备名称', en: 'Device Name' },
|
|
37
|
+
remoteDeviceNamePlaceholder: { zh: '例如:PeideMacBook-Pro', en: 'For example: PeideMacBook-Pro' },
|
|
38
|
+
remotePlatformApiBase: { zh: '平台 API Base', en: 'Platform API Base' },
|
|
39
|
+
remotePlatformApiBaseHelp: {
|
|
40
|
+
zh: '留空可回退到登录时写入的 providers.nextclaw.apiBase。',
|
|
41
|
+
en: 'Leave empty to fall back to providers.nextclaw.apiBase saved at login time.'
|
|
42
|
+
},
|
|
43
|
+
remoteSaveSettings: { zh: '保存设置', en: 'Save Settings' },
|
|
44
|
+
remoteSettingsSaved: { zh: '远程设置已保存', en: 'Remote settings saved' },
|
|
45
|
+
remoteSettingsSaveFailed: { zh: '远程设置保存失败', en: 'Failed to save remote settings' },
|
|
46
|
+
remoteSaveHint: {
|
|
47
|
+
zh: '推荐流程:先保存设置,再启动或重启服务,最后运行诊断确认。',
|
|
48
|
+
en: 'Recommended flow: save settings, start or restart the service, then run diagnostics.'
|
|
49
|
+
},
|
|
50
|
+
remoteAccountTitle: { zh: '平台账号', en: 'Platform Account' },
|
|
51
|
+
remoteAccountDescription: {
|
|
52
|
+
zh: '通过浏览器授权把当前设备安全连接到 NextClaw 平台。',
|
|
53
|
+
en: 'Authorize this device in your browser and connect it to the NextClaw platform.'
|
|
54
|
+
},
|
|
55
|
+
remoteAccountEmail: { zh: '邮箱', en: 'Email' },
|
|
56
|
+
remoteAccountRole: { zh: '角色', en: 'Role' },
|
|
57
|
+
remoteApiBase: { zh: 'API Base', en: 'API Base' },
|
|
58
|
+
remoteBrowserAuthTitle: { zh: '浏览器授权登录', en: 'Browser Authorization' },
|
|
59
|
+
remoteBrowserAuthDescription: {
|
|
60
|
+
zh: '点击后会打开平台授权页,在浏览器内登录或注册并授权当前设备。',
|
|
61
|
+
en: 'Open the platform authorization page in your browser, then sign in or create an account there.'
|
|
62
|
+
},
|
|
63
|
+
remoteBrowserAuthAction: { zh: '前往浏览器授权', en: 'Continue in Browser' },
|
|
64
|
+
remoteBrowserAuthResume: { zh: '重新打开授权页', en: 'Reopen Authorization Page' },
|
|
65
|
+
remoteBrowserAuthStarting: { zh: '正在创建授权会话...', en: 'Starting authorization...' },
|
|
66
|
+
remoteBrowserAuthAuthorizing: { zh: '等待浏览器完成授权...', en: 'Waiting for browser authorization...' },
|
|
67
|
+
remoteBrowserAuthWaiting: {
|
|
68
|
+
zh: '浏览器授权页已打开。请在网页中完成登录或注册,然后此页面会自动接入。',
|
|
69
|
+
en: 'The authorization page is open. Complete sign in or registration there and this page will connect automatically.'
|
|
70
|
+
},
|
|
71
|
+
remoteBrowserAuthCompleted: { zh: '浏览器授权完成,正在刷新登录状态。', en: 'Authorization completed. Refreshing account status.' },
|
|
72
|
+
remoteBrowserAuthExpired: { zh: '授权会话已过期,请重新发起。', en: 'Authorization session expired. Start again.' },
|
|
73
|
+
remoteBrowserAuthPopupBlocked: {
|
|
74
|
+
zh: '浏览器没有自动打开,请点击“重新打开授权页”。',
|
|
75
|
+
en: 'Your browser did not open automatically. Use "Reopen Authorization Page".'
|
|
76
|
+
},
|
|
77
|
+
remoteBrowserAuthSession: { zh: '授权会话', en: 'Auth Session' },
|
|
78
|
+
remoteBrowserAuthExpiresAt: { zh: '授权过期时间', en: 'Auth Expires At' },
|
|
79
|
+
remoteBrowserAuthHint: {
|
|
80
|
+
zh: '如果你刚修改了上方 Platform API Base,建议先保存设置;未保存时当前页面也会沿用你输入的新地址发起授权。',
|
|
81
|
+
en: 'If you just changed the Platform API Base above, saving settings is recommended. This page will still use the current value for browser authorization.'
|
|
82
|
+
},
|
|
83
|
+
remoteBrowserAuthStartFailed: { zh: '启动浏览器授权失败', en: 'Failed to start browser authorization' },
|
|
84
|
+
remoteBrowserAuthPollFailed: { zh: '浏览器授权状态检查失败', en: 'Failed to check browser authorization status' },
|
|
85
|
+
remoteEmail: { zh: '邮箱', en: 'Email' },
|
|
86
|
+
remotePassword: { zh: '密码', en: 'Password' },
|
|
87
|
+
remotePasswordPlaceholder: { zh: '请输入你的平台密码', en: 'Enter your platform password' },
|
|
88
|
+
remoteRegisterIfNeeded: { zh: '如果账号不存在则注册', en: 'Register If Needed' },
|
|
89
|
+
remoteRegisterIfNeededHelp: {
|
|
90
|
+
zh: '开启后会走平台注册接口,然后自动保存登录态。',
|
|
91
|
+
en: 'When enabled, the UI will register first and then save the resulting login token.'
|
|
92
|
+
},
|
|
93
|
+
remoteLogin: { zh: '登录平台', en: 'Login to Platform' },
|
|
94
|
+
remoteCreateAccount: { zh: '注册并登录', en: 'Create Account & Login' },
|
|
95
|
+
remoteLoggingIn: { zh: '登录中...', en: 'Logging in...' },
|
|
96
|
+
remoteLoginSuccess: { zh: '平台登录成功', en: 'Platform login succeeded' },
|
|
97
|
+
remoteLoginFailed: { zh: '平台登录失败', en: 'Platform login failed' },
|
|
98
|
+
remoteLogout: { zh: '退出登录', en: 'Logout' },
|
|
99
|
+
remoteLoggingOut: { zh: '退出中...', en: 'Logging out...' },
|
|
100
|
+
remoteLogoutSuccess: { zh: '已退出平台登录', en: 'Logged out from platform' },
|
|
101
|
+
remoteLogoutFailed: { zh: '退出登录失败', en: 'Failed to logout' },
|
|
102
|
+
remoteServiceTitle: { zh: '后台服务', en: 'Managed Service' },
|
|
103
|
+
remoteServiceDescription: {
|
|
104
|
+
zh: '直接控制托管当前 UI 的后台服务。',
|
|
105
|
+
en: 'Directly control the managed service that hosts the current UI.'
|
|
106
|
+
},
|
|
107
|
+
remoteServiceRunning: { zh: '服务运行中', en: 'Service Running' },
|
|
108
|
+
remoteServiceManagedRunning: { zh: '当前就是托管服务', en: 'Current Managed Service' },
|
|
109
|
+
remoteServiceStopped: { zh: '服务未运行', en: 'Service Stopped' },
|
|
110
|
+
remoteServicePid: { zh: '进程 PID', en: 'Process PID' },
|
|
111
|
+
remoteServiceUiUrl: { zh: 'UI 地址', en: 'UI URL' },
|
|
112
|
+
remoteServiceCurrentProcess: { zh: '当前页面是否由该服务提供', en: 'Current Page Served By It' },
|
|
113
|
+
remoteStartService: { zh: '启动服务', en: 'Start Service' },
|
|
114
|
+
remoteRestartService: { zh: '重启服务', en: 'Restart Service' },
|
|
115
|
+
remoteStopService: { zh: '停止服务', en: 'Stop Service' },
|
|
116
|
+
remoteServiceHint: {
|
|
117
|
+
zh: '如果当前页面本身就是托管服务,停止或重启时页面会短暂断开,这是预期行为。',
|
|
118
|
+
en: 'If this page is served by the managed service itself, stop/restart may briefly disconnect the page.'
|
|
119
|
+
},
|
|
120
|
+
remoteServiceActionFailed: { zh: '服务操作失败', en: 'Service action failed' },
|
|
121
|
+
remoteDoctorTitle: { zh: '远程诊断', en: 'Remote Diagnostics' },
|
|
122
|
+
remoteDoctorDescription: {
|
|
123
|
+
zh: '检查开关、平台登录、本地 UI 健康和连接器状态。',
|
|
124
|
+
en: 'Check config state, platform login, local UI health, and connector status.'
|
|
125
|
+
},
|
|
126
|
+
remoteRunDoctor: { zh: '运行诊断', en: 'Run Diagnostics' },
|
|
127
|
+
remoteDoctorRunning: { zh: '诊断中...', en: 'Running diagnostics...' },
|
|
128
|
+
remoteDoctorCompleted: { zh: '诊断完成', en: 'Diagnostics completed' },
|
|
129
|
+
remoteDoctorFailed: { zh: '诊断失败', en: 'Diagnostics failed' },
|
|
130
|
+
remoteDoctorGeneratedAt: { zh: '生成时间', en: 'Generated At' },
|
|
131
|
+
remoteDoctorEmpty: { zh: '点击上方按钮运行一次诊断。', en: 'Run diagnostics to see the latest checks here.' },
|
|
132
|
+
remoteCheckPassed: { zh: '通过', en: 'Passed' },
|
|
133
|
+
remoteCheckFailed: { zh: '失败', en: 'Failed' },
|
|
134
|
+
connected: { zh: '已连接', en: 'Connected' },
|
|
135
|
+
disconnected: { zh: '未连接', en: 'Disconnected' },
|
|
136
|
+
connecting: { zh: '连接中...', en: 'Connecting...' },
|
|
137
|
+
feishuConnecting: { zh: '验证 / 连接中...', en: 'Verifying / connecting...' },
|
|
138
|
+
statusReady: { zh: '就绪', en: 'Ready' },
|
|
139
|
+
statusSetup: { zh: '待配置', en: 'Setup' },
|
|
140
|
+
statusActive: { zh: '活跃', en: 'Active' },
|
|
141
|
+
statusInactive: { zh: '未启用', en: 'Inactive' }
|
|
142
|
+
};
|
package/src/lib/i18n.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { MARKETPLACE_LABELS } from './i18n.marketplace';
|
|
2
|
+
import { REMOTE_LABELS } from './i18n.remote';
|
|
3
|
+
|
|
1
4
|
export type I18nLanguage = 'zh' | 'en';
|
|
2
5
|
|
|
3
6
|
const I18N_STORAGE_KEY = 'nextclaw.ui.language';
|
|
@@ -131,6 +134,7 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
131
134
|
cron: { zh: '定时任务', en: 'Cron Jobs' },
|
|
132
135
|
secrets: { zh: '密钥管理', en: 'Secrets' },
|
|
133
136
|
runtime: { zh: '路由与运行时', en: 'Routing & Runtime' },
|
|
137
|
+
remote: { zh: '远程访问', en: 'Remote Access' },
|
|
134
138
|
marketplace: { zh: '市场', en: 'Marketplace' },
|
|
135
139
|
advanced: { zh: '高级', en: 'Advanced' },
|
|
136
140
|
settings: { zh: '设置', en: 'Settings' },
|
|
@@ -153,6 +157,8 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
153
157
|
saving: { zh: '保存中...', en: 'Saving...' },
|
|
154
158
|
remove: { zh: '移除', en: 'Remove' },
|
|
155
159
|
all: { zh: '全部', en: 'All' },
|
|
160
|
+
yes: { zh: '是', en: 'Yes' },
|
|
161
|
+
no: { zh: '否', en: 'No' },
|
|
156
162
|
prev: { zh: '上一页', en: 'Prev' },
|
|
157
163
|
next: { zh: '下一页', en: 'Next' },
|
|
158
164
|
noneOption: { zh: '无', en: 'None' },
|
|
@@ -735,74 +741,10 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
735
741
|
cronRunForceConfirm: { zh: '任务已禁用,仍要立即执行', en: 'Cron job disabled. Force run now' },
|
|
736
742
|
|
|
737
743
|
// Marketplace
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
marketplaceTabMarketplacePlugins: { zh: '插件市场', en: 'Plugin Market' },
|
|
743
|
-
marketplaceTabMarketplaceSkills: { zh: '技能市场', en: 'Skill Market' },
|
|
744
|
-
marketplaceTabInstalledPlugins: { zh: '已安装插件', en: 'Installed Plugins' },
|
|
745
|
-
marketplaceTabInstalledSkills: { zh: '已安装技能', en: 'Installed Skills' },
|
|
746
|
-
marketplaceSearchPlaceholderPlugins: { zh: '搜索插件...', en: 'Search plugins...' },
|
|
747
|
-
marketplaceSearchPlaceholderSkills: { zh: '搜索技能...', en: 'Search skills...' },
|
|
748
|
-
marketplaceFilterPlugins: { zh: '插件', en: 'Plugins' },
|
|
749
|
-
marketplaceFilterSkills: { zh: '技能', en: 'Skills' },
|
|
750
|
-
marketplaceSortRelevance: { zh: '相关性', en: 'Relevance' },
|
|
751
|
-
marketplaceSortUpdated: { zh: '最近更新', en: 'Recently Updated' },
|
|
752
|
-
marketplaceUnknownItem: { zh: '未知项目', en: 'Unknown Item' },
|
|
753
|
-
marketplaceInstalledLocalSummary: { zh: '已在本地安装,市场暂无详情。', en: 'Installed locally. Details are currently unavailable from marketplace.' },
|
|
754
|
-
marketplaceTypePlugin: { zh: '插件', en: 'Plugin' },
|
|
755
|
-
marketplaceTypeSkill: { zh: '技能', en: 'Skill' },
|
|
756
|
-
marketplaceTypeExtension: { zh: '扩展', en: 'Extension' },
|
|
757
|
-
marketplaceInstall: { zh: '安装', en: 'Install' },
|
|
758
|
-
marketplaceInstalling: { zh: '安装中...', en: 'Installing...' },
|
|
759
|
-
marketplaceEnable: { zh: '启用', en: 'Enable' },
|
|
760
|
-
marketplaceDisable: { zh: '禁用', en: 'Disable' },
|
|
761
|
-
marketplaceEnabling: { zh: '启用中...', en: 'Enabling...' },
|
|
762
|
-
marketplaceDisabling: { zh: '禁用中...', en: 'Disabling...' },
|
|
763
|
-
marketplaceUninstall: { zh: '卸载', en: 'Uninstall' },
|
|
764
|
-
marketplaceRemoving: { zh: '卸载中...', en: 'Removing...' },
|
|
765
|
-
marketplaceSectionPlugins: { zh: '插件列表', en: 'Plugin Catalog' },
|
|
766
|
-
marketplaceSectionSkills: { zh: '技能列表', en: 'Skill Catalog' },
|
|
767
|
-
marketplaceSectionInstalledPlugins: { zh: '已安装插件', en: 'Installed Plugins' },
|
|
768
|
-
marketplaceSectionInstalledSkills: { zh: '已安装技能', en: 'Installed Skills' },
|
|
769
|
-
marketplaceErrorLoadingPluginsData: { zh: '加载插件市场数据失败', en: 'Failed to load plugin marketplace data' },
|
|
770
|
-
marketplaceErrorLoadingSkillsData: { zh: '加载技能市场数据失败', en: 'Failed to load skill marketplace data' },
|
|
771
|
-
marketplaceErrorLoadingInstalledPlugins: { zh: '加载已安装插件失败', en: 'Failed to load installed plugins' },
|
|
772
|
-
marketplaceErrorLoadingInstalledSkills: { zh: '加载已安装技能失败', en: 'Failed to load installed skills' },
|
|
773
|
-
marketplaceNoPlugins: { zh: '未找到插件。', en: 'No plugins found.' },
|
|
774
|
-
marketplaceNoSkills: { zh: '未找到技能。', en: 'No skills found.' },
|
|
775
|
-
marketplaceNoInstalledPlugins: { zh: '未找到已安装插件。', en: 'No installed plugins found.' },
|
|
776
|
-
marketplaceNoInstalledSkills: { zh: '未找到已安装技能。', en: 'No installed skills found.' },
|
|
777
|
-
marketplaceUninstallTitle: { zh: '确认卸载', en: 'Uninstall' },
|
|
778
|
-
marketplaceUninstallDescription: {
|
|
779
|
-
zh: '该操作会移除扩展,后续可在市场中重新安装。',
|
|
780
|
-
en: 'This will remove the extension. You can install it again from the marketplace.'
|
|
781
|
-
},
|
|
782
|
-
marketplaceInstallSuccessPlugin: { zh: '插件安装成功', en: 'Plugin installed successfully' },
|
|
783
|
-
marketplaceInstallSuccessSkill: { zh: '技能安装成功', en: 'Skill installed successfully' },
|
|
784
|
-
marketplaceEnableSuccess: { zh: '启用成功', en: 'Enabled successfully' },
|
|
785
|
-
marketplaceDisableSuccess: { zh: '禁用成功', en: 'Disabled successfully' },
|
|
786
|
-
marketplaceUninstallSuccess: { zh: '卸载成功', en: 'Uninstalled successfully' },
|
|
787
|
-
marketplaceInstallFailed: { zh: '安装失败', en: 'Install failed' },
|
|
788
|
-
marketplaceOperationFailed: { zh: '操作失败', en: 'Operation failed' },
|
|
789
|
-
marketplaceInstalledPluginsCountSuffix: { zh: '个已安装插件', en: 'installed plugins' },
|
|
790
|
-
marketplaceInstalledSkillsCountSuffix: { zh: '个已安装技能', en: 'installed skills' },
|
|
791
|
-
marketplaceDetailPanelTitle: { zh: '详情预览', en: 'Detail Preview' },
|
|
792
|
-
marketplaceDetailPanelEmpty: { zh: '点击左侧任意插件/技能,在这里查看详情。', en: 'Click an item on the left to preview details here.' },
|
|
793
|
-
marketplaceDetailSummary: { zh: '摘要', en: 'Summary' },
|
|
794
|
-
marketplaceDetailDescription: { zh: '描述', en: 'Description' },
|
|
795
|
-
marketplaceOpenInDocBrowserTab: { zh: '新标签打开', en: 'Open in New Tab' },
|
|
796
|
-
|
|
797
|
-
// Status
|
|
798
|
-
connected: { zh: '已连接', en: 'Connected' },
|
|
799
|
-
disconnected: { zh: '未连接', en: 'Disconnected' },
|
|
800
|
-
connecting: { zh: '连接中...', en: 'Connecting...' },
|
|
801
|
-
feishuConnecting: { zh: '验证 / 连接中...', en: 'Verifying / connecting...' },
|
|
802
|
-
statusReady: { zh: '就绪', en: 'Ready' },
|
|
803
|
-
statusSetup: { zh: '待配置', en: 'Setup' },
|
|
804
|
-
statusActive: { zh: '活跃', en: 'Active' },
|
|
805
|
-
statusInactive: { zh: '未启用', en: 'Inactive' },
|
|
744
|
+
...MARKETPLACE_LABELS,
|
|
745
|
+
|
|
746
|
+
// Remote & Status
|
|
747
|
+
...REMOTE_LABELS,
|
|
806
748
|
|
|
807
749
|
// Action labels
|
|
808
750
|
actionConfigure: { zh: '配置', en: 'Configure' },
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as v,j as a,aw as Z,F as ee,e as T,K as ae,ae as te,aR as se,aS as ne,aT as le,z as re,s as oe,a5 as ce,v as ie}from"./vendor-DKBNiC31.js";import{t as e,c as I,_ as me,u as q,a as $,b as H,a0 as pe,a1 as de,I as D,S as be,e as ue,f as xe,g as ye,h as ge,B as E}from"./index-BEgClaDH.js";import{L as he}from"./label-DD61y-4v.js";import{S as fe}from"./switch-NX5OmUXQ.js";import{L as K,S as J}from"./LogoBadge-CYQ_b7jk.js";import{h as _}from"./config-hints-CApS3K_7.js";import{c as we,b as ve,a as je,C as ke}from"./config-layout-BHnOoweL.js";import{T as Se}from"./tabs-custom-9ihB5Jem.js";import{P as Ce,a as Ne}from"./page-layout-CfnoVycc.js";function Pe({value:t,onChange:m,className:i,placeholder:r=""}){const[o,u]=v.useState(""),d=x=>{x.key==="Enter"&&o.trim()?(x.preventDefault(),m([...t,o.trim()]),u("")):x.key==="Backspace"&&!o&&t.length>0&&m(t.slice(0,-1))},g=x=>{m(t.filter((j,h)=>h!==x))};return a.jsxs("div",{className:I("flex flex-wrap gap-2 p-2 border rounded-md min-h-[42px]",i),children:[t.map((x,j)=>a.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 bg-primary text-primary-foreground rounded text-sm",children:[x,a.jsx("button",{type:"button",onClick:()=>g(j),className:"hover:text-red-300 transition-colors",children:a.jsx(Z,{className:"h-3 w-3"})})]},j)),a.jsx("input",{type:"text",value:o,onChange:x=>u(x.target.value),onKeyDown:d,className:"flex-1 outline-none min-w-[100px] bg-transparent text-sm",placeholder:r||e("enterTag")})]})}function z(t){var r,o;const m=me();return((r=t.tutorialUrls)==null?void 0:r[m])||((o=t.tutorialUrls)==null?void 0:o.default)||t.tutorialUrl}const Ie={telegram:"telegram.svg",slack:"slack.svg",discord:"discord.svg",whatsapp:"whatsapp.svg",qq:"qq.svg",feishu:"feishu.svg",dingtalk:"dingtalk.svg",wecom:"wecom.svg",mochat:"mochat.svg",email:"email.svg"};function Fe(t,m){const i=m.toLowerCase(),r=t[i];return r?`/logos/${r}`:null}function Y(t){return Fe(Ie,t)}const R=[{value:"pairing",label:"pairing"},{value:"allowlist",label:"allowlist"},{value:"open",label:"open"},{value:"disabled",label:"disabled"}],B=[{value:"open",label:"open"},{value:"allowlist",label:"allowlist"},{value:"disabled",label:"disabled"}],Te=[{value:"off",label:"off"},{value:"partial",label:"partial"},{value:"block",label:"block"},{value:"progress",label:"progress"}],De=t=>t.includes("token")||t.includes("secret")||t.includes("password")?a.jsx(ae,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("url")||t.includes("host")?a.jsx(te,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("email")||t.includes("mail")?a.jsx(se,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("id")||t.includes("from")?a.jsx(ne,{className:"h-3.5 w-3.5 text-gray-500"}):t==="enabled"||t==="consentGranted"?a.jsx(le,{className:"h-3.5 w-3.5 text-gray-500"}):a.jsx(re,{className:"h-3.5 w-3.5 text-gray-500"});function G(){return{telegram:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"proxy",type:"text",label:e("proxy")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:R},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:B},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],discord:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"gatewayUrl",type:"text",label:e("gatewayUrl")},{name:"intents",type:"number",label:e("intents")},{name:"proxy",type:"text",label:e("proxy")},{name:"mediaMaxMb",type:"number",label:e("attachmentMaxSizeMb")},{name:"streaming",type:"select",label:e("streamingMode"),options:Te},{name:"draftChunk",type:"json",label:e("draftChunkingJson")},{name:"textChunkLimit",type:"number",label:e("textChunkLimit")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:R},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:B},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],whatsapp:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"bridgeUrl",type:"text",label:e("bridgeUrl")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],feishu:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"appSecret",type:"password",label:e("appSecret")},{name:"encryptKey",type:"password",label:e("encryptKey")},{name:"verificationToken",type:"password",label:e("verificationToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],dingtalk:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"clientId",type:"text",label:e("clientId")},{name:"clientSecret",type:"password",label:e("clientSecret")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],wecom:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"corpId",type:"text",label:e("corpId")},{name:"agentId",type:"text",label:e("agentId")},{name:"secret",type:"password",label:e("secret")},{name:"token",type:"password",label:e("token")},{name:"callbackPort",type:"number",label:e("callbackPort")},{name:"callbackPath",type:"text",label:e("callbackPath")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],slack:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"mode",type:"text",label:e("mode")},{name:"webhookPath",type:"text",label:e("webhookPath")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"botToken",type:"password",label:e("botToken")},{name:"appToken",type:"password",label:e("appToken")}],email:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"consentGranted",type:"boolean",label:e("consentGranted")},{name:"imapHost",type:"text",label:e("imapHost")},{name:"imapPort",type:"number",label:e("imapPort")},{name:"imapUsername",type:"text",label:e("imapUsername")},{name:"imapPassword",type:"password",label:e("imapPassword")},{name:"fromAddress",type:"email",label:e("fromAddress")}],mochat:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"baseUrl",type:"text",label:e("baseUrl")},{name:"clawToken",type:"password",label:e("clawToken")},{name:"agentUserId",type:"text",label:e("agentUserId")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],qq:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"secret",type:"password",label:e("appSecret")},{name:"markdownSupport",type:"boolean",label:e("markdownSupport")},{name:"allowFrom",type:"tags",label:e("allowFrom")}]}}function A(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function V(t,m){const i={...t};for(const[r,o]of Object.entries(m)){const u=i[r];if(A(u)&&A(o)){i[r]=V(u,o);continue}i[r]=o}return i}function Ae(t,m){const i=t.split("."),r={};let o=r;for(let u=0;u<i.length-1;u+=1){const d=i[u];o[d]={},o=o[d]}return o[i[i.length-1]]=m,r}function Le({channelName:t}){var O,U;const{data:m}=q(),{data:i}=$(),{data:r}=H(),o=pe(),u=de(),[d,g]=v.useState({}),[x,j]=v.useState({}),[h,f]=v.useState(null),k=t?m==null?void 0:m.channels[t]:null,w=t?G()[t]??[]:[],c=r==null?void 0:r.uiHints,p=t?`channels.${t}`:null,S=((O=r==null?void 0:r.actions)==null?void 0:O.filter(s=>s.scope===p))??[],C=t&&(((U=_(`channels.${t}`,c))==null?void 0:U.label)??t),P=i==null?void 0:i.channels.find(s=>s.name===t),F=P?z(P):void 0;v.useEffect(()=>{if(k){g({...k});const s={};(t?G()[t]??[]:[]).filter(l=>l.type==="json").forEach(l=>{const y=k[l.name];s[l.name]=JSON.stringify(y??{},null,2)}),j(s)}else g({}),j({})},[k,t]);const N=(s,n)=>{g(l=>({...l,[s]:n}))},L=s=>{if(s.preventDefault(),!t)return;const n={...d};for(const l of w){if(l.type!=="password")continue;const y=n[l.name];(typeof y!="string"||y.length===0)&&delete n[l.name]}for(const l of w){if(l.type!=="json")continue;const y=x[l.name]??"";try{n[l.name]=y.trim()?JSON.parse(y):{}}catch{T.error(`${e("invalidJson")}: ${l.name}`);return}}o.mutate({channel:t,data:n})},Q=s=>{if(!s||!t)return;const n=s.channels;if(!A(n))return;const l=n[t];A(l)&&g(y=>V(y,l))},W=async s=>{if(!(!t||!p)){f(s.id);try{let n={...d};s.saveBeforeRun&&(n={...n,...s.savePatch??{}},g(n),await o.mutateAsync({channel:t,data:n}));const l=await u.mutateAsync({actionId:s.id,data:{scope:p,draftConfig:Ae(p,n)}});Q(l.patch),l.ok?T.success(l.message||e("success")):T.error(l.message||e("error"))}catch(n){const l=n instanceof Error?n.message:String(n);T.error(`${e("error")}: ${l}`)}finally{f(null)}}};if(!t||!P||!k)return a.jsx("div",{className:we,children:a.jsxs("div",{children:[a.jsx("h3",{className:"text-base font-semibold text-gray-900",children:e("channelsSelectTitle")}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsSelectDescription")})]})});const M=!!k.enabled;return a.jsxs("div",{className:ve,children:[a.jsx("div",{className:"border-b border-gray-100 px-6 py-5",children:a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[a.jsxs("div",{className:"min-w-0",children:[a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx(K,{name:t,src:Y(t),className:I("h-9 w-9 rounded-lg border",M?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:t[0]})}),a.jsx("h3",{className:"truncate text-lg font-semibold text-gray-900 capitalize",children:C})]}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsFormDescription")}),F&&a.jsxs("a",{href:F,className:"mt-2 inline-flex items-center gap-1.5 text-xs text-primary transition-colors hover:text-primary-hover",children:[a.jsx(ee,{className:"h-3.5 w-3.5"}),e("channelsGuideTitle")]})]}),a.jsx(J,{status:M?"active":"inactive",label:M?e("statusActive"):e("statusInactive")})]})}),a.jsxs("form",{onSubmit:L,className:"flex min-h-0 flex-1 flex-col",children:[a.jsx("div",{className:"min-h-0 flex-1 space-y-6 overflow-y-auto overscroll-contain px-6 py-5",children:w.map(s=>{const n=t?_(`channels.${t}.${s.name}`,c):void 0,l=(n==null?void 0:n.label)??s.label,y=n==null?void 0:n.placeholder;return a.jsxs("div",{className:"space-y-2.5",children:[a.jsxs(he,{htmlFor:s.name,className:"flex items-center gap-2 text-sm font-medium text-gray-900",children:[De(s.name),l]}),s.type==="boolean"&&a.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-3",children:[a.jsx("span",{className:"text-sm text-gray-500",children:d[s.name]?e("enabled"):e("disabled")}),a.jsx(fe,{id:s.name,checked:d[s.name]||!1,onCheckedChange:b=>N(s.name,b),className:"data-[state=checked]:bg-emerald-500"})]}),(s.type==="text"||s.type==="email")&&a.jsx(D,{id:s.name,type:s.type,value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y,className:"rounded-xl"}),s.type==="password"&&a.jsx(D,{id:s.name,type:"password",value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y??e("leaveBlankToKeepUnchanged"),className:"rounded-xl"}),s.type==="number"&&a.jsx(D,{id:s.name,type:"number",value:d[s.name]||0,onChange:b=>N(s.name,parseInt(b.target.value,10)||0),placeholder:y,className:"rounded-xl"}),s.type==="tags"&&a.jsx(Pe,{value:d[s.name]||[],onChange:b=>N(s.name,b)}),s.type==="select"&&a.jsxs(be,{value:d[s.name]||"",onValueChange:b=>N(s.name,b),children:[a.jsx(ue,{className:"rounded-xl",children:a.jsx(xe,{})}),a.jsx(ye,{children:(s.options??[]).map(b=>a.jsx(ge,{value:b.value,children:b.label},b.value))})]}),s.type==="json"&&a.jsx("textarea",{id:s.name,value:x[s.name]??"{}",onChange:b=>j(X=>({...X,[s.name]:b.target.value})),className:"min-h-[120px] w-full resize-none rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs font-mono"})]},s.name)})}),a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-t border-gray-100 px-6 py-4",children:[a.jsx("div",{className:"flex flex-wrap items-center gap-2",children:S.filter(s=>s.trigger==="manual").map(s=>a.jsx(E,{type:"button",onClick:()=>W(s),disabled:o.isPending||!!h,variant:"secondary",children:h===s.id?e("connecting"):s.title},s.id))}),a.jsx(E,{type:"submit",disabled:o.isPending||!!h,children:o.isPending?e("saving"):e("save")})]})]})]})}const Me={telegram:"channelDescTelegram",slack:"channelDescSlack",email:"channelDescEmail",webhook:"channelDescWebhook",discord:"channelDescDiscord",feishu:"channelDescFeishu"};function He(){const{data:t}=q(),{data:m}=$(),{data:i}=H(),[r,o]=v.useState("enabled"),[u,d]=v.useState(),[g,x]=v.useState(""),j=i==null?void 0:i.uiHints,h=m==null?void 0:m.channels,f=t==null?void 0:t.channels,k=[{id:"enabled",label:e("channelsTabEnabled"),count:(h??[]).filter(c=>{var p;return(p=f==null?void 0:f[c.name])==null?void 0:p.enabled}).length},{id:"all",label:e("channelsTabAll"),count:(h??[]).length}],w=v.useMemo(()=>{const c=g.trim().toLowerCase();return(h??[]).filter(p=>{var C;const S=((C=f==null?void 0:f[p.name])==null?void 0:C.enabled)||!1;return r==="enabled"?S:!0}).filter(p=>c?(p.displayName||p.name).toLowerCase().includes(c)||p.name.toLowerCase().includes(c):!0)},[r,f,h,g]);return v.useEffect(()=>{if(w.length===0){d(void 0);return}w.some(p=>p.name===u)||d(w[0].name)},[w,u]),!t||!m?a.jsx("div",{className:"p-8 text-gray-400",children:e("channelsLoading")}):a.jsxs(Ce,{className:"xl:flex xl:h-full xl:min-h-0 xl:flex-col xl:pb-0",children:[a.jsx(Ne,{title:e("channelsPageTitle"),description:e("channelsPageDescription")}),a.jsxs("div",{className:I(ke,"xl:min-h-0 xl:flex-1"),children:[a.jsxs("section",{className:je,children:[a.jsx("div",{className:"border-b border-gray-100 px-4 pt-4",children:a.jsx(Se,{tabs:k,activeTab:r,onChange:o,className:"mb-0"})}),a.jsx("div",{className:"border-b border-gray-100 px-4 py-3",children:a.jsxs("div",{className:"relative",children:[a.jsx(oe,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400"}),a.jsx(D,{value:g,onChange:c=>x(c.target.value),placeholder:e("channelsFilterPlaceholder"),className:"h-10 rounded-xl pl-9"})]})}),a.jsxs("div",{className:"min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain p-3",children:[w.map(c=>{const p=t.channels[c.name],S=(p==null?void 0:p.enabled)||!1,C=_(`channels.${c.name}`,j),P=z(c),F=(C==null?void 0:C.help)||e(Me[c.name]||"channelDescriptionDefault"),N=u===c.name;return a.jsx("button",{type:"button",onClick:()=>d(c.name),className:I("w-full rounded-xl border p-2.5 text-left transition-all",N?"border-primary/30 bg-primary-50/40 shadow-sm":"border-gray-200/70 bg-white hover:border-gray-300 hover:bg-gray-50/70"),children:a.jsxs("div",{className:"flex items-start justify-between gap-3",children:[a.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[a.jsx(K,{name:c.name,src:Y(c.name),className:I("h-10 w-10 rounded-lg border",S?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:c.name[0]})}),a.jsxs("div",{className:"min-w-0",children:[a.jsx("p",{className:"truncate text-sm font-semibold text-gray-900",children:c.displayName||c.name}),a.jsx("p",{className:"line-clamp-1 text-[11px] text-gray-500",children:F})]})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[P&&a.jsx("a",{href:P,onClick:L=>L.stopPropagation(),className:"inline-flex h-7 w-7 items-center justify-center rounded-md text-gray-300 transition-colors hover:bg-gray-100/70 hover:text-gray-500",title:e("channelsGuideTitle"),children:a.jsx(ce,{className:"h-3.5 w-3.5"})}),a.jsx(J,{status:S?"active":"inactive",label:S?e("statusActive"):e("statusInactive"),className:"min-w-[56px] justify-center"})]})]})},c.name)}),w.length===0&&a.jsxs("div",{className:"flex h-full min-h-[220px] flex-col items-center justify-center rounded-xl border border-dashed border-gray-200 bg-gray-50/70 py-10 text-center",children:[a.jsx("div",{className:"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-white",children:a.jsx(ie,{className:"h-5 w-5 text-gray-300"})}),a.jsx("p",{className:"text-sm font-medium text-gray-700",children:e("channelsNoMatch")})]})]})]}),a.jsx(Le,{channelName:u})]})]})}export{He as ChannelsList};
|