From 1ed3e113ba57e05110966bee9c46dbe82e7a5598 Mon Sep 17 00:00:00 2001 From: GCWing Date: Wed, 25 Mar 2026 21:21:01 +0800 Subject: [PATCH] feat(web-ui): scene viewport, gallery refresh, skills UI and i18n - Add useGallerySceneAutoRefresh for gallery scenes - SceneViewport, agents, assistant, miniapp gallery, profile and skills styling - Trim BasicsConfig; adjust McpToolsConfig - Update en-US and zh-CN locale strings --- .../app/hooks/useGallerySceneAutoRefresh.ts | 65 ++++++++++++++++++ src/web-ui/src/app/scenes/SceneViewport.scss | 19 ++++++ src/web-ui/src/app/scenes/SceneViewport.tsx | 14 +++- .../src/app/scenes/agents/AgentsScene.tsx | 19 ++---- .../app/scenes/assistant/AssistantScene.scss | 11 ++++ .../app/scenes/assistant/AssistantScene.tsx | 16 ++++- .../miniapps/views/MiniAppGalleryView.tsx | 32 ++++----- .../profile/views/AssistantConfigPage.tsx | 32 +-------- .../profile/views/AssistantQuickInput.scss | 22 ++++++- .../app/scenes/profile/views/NurseryView.scss | 24 ++++--- .../src/app/scenes/skills/SkillsScene.scss | 29 ++++++++ .../src/app/scenes/skills/SkillsScene.tsx | 66 +++++++++++++------ .../scenes/skills/components/SkillCard.tsx | 18 ++++- .../config/components/BasicsConfig.tsx | 27 -------- .../config/components/McpToolsConfig.tsx | 21 +++--- src/web-ui/src/locales/en-US/common.json | 3 + .../src/locales/en-US/scenes/agents.json | 3 +- .../src/locales/en-US/scenes/miniapp.json | 1 - .../src/locales/en-US/scenes/profile.json | 1 + .../src/locales/en-US/scenes/skills.json | 9 +-- src/web-ui/src/locales/zh-CN/common.json | 3 + .../src/locales/zh-CN/scenes/agents.json | 3 +- .../src/locales/zh-CN/scenes/miniapp.json | 1 - .../src/locales/zh-CN/scenes/profile.json | 1 + .../src/locales/zh-CN/scenes/skills.json | 9 +-- 25 files changed, 299 insertions(+), 150 deletions(-) create mode 100644 src/web-ui/src/app/hooks/useGallerySceneAutoRefresh.ts diff --git a/src/web-ui/src/app/hooks/useGallerySceneAutoRefresh.ts b/src/web-ui/src/app/hooks/useGallerySceneAutoRefresh.ts new file mode 100644 index 00000000..26aff541 --- /dev/null +++ b/src/web-ui/src/app/hooks/useGallerySceneAutoRefresh.ts @@ -0,0 +1,65 @@ +import { useEffect, useRef } from 'react'; +import type { SceneTabId } from '@/app/components/SceneBar/types'; +import { useSceneManager } from './useSceneManager'; + +export interface UseGallerySceneAutoRefreshOptions { + /** Tab id from SceneBar (e.g. skills, agents, miniapps). */ + sceneId: SceneTabId; + /** Reload lists; may be async. */ + refetch: () => void | Promise; + enabled?: boolean; +} + +/** + * Gallery scenes stay mounted while inactive (SceneViewport). Refresh when: + * 1. User switches back to this tab (inactive → active). + * 2. The window regains visibility while this tab is active (e.g. external edits). + * + * Initial load remains the responsibility of each feature hook (workspacePath, + * search query, etc.); this hook only covers re-entry and focus. + */ +export function useGallerySceneAutoRefresh({ + sceneId, + refetch, + enabled = true, +}: UseGallerySceneAutoRefreshOptions): void { + const { activeTabId } = useSceneManager(); + const isActive = activeTabId === sceneId; + const refetchRef = useRef(refetch); + refetchRef.current = refetch; + + /** null = not yet synced (skip first tick to avoid duplicating hook mount loads). */ + const wasActiveRef = useRef(null); + + useEffect(() => { + if (!enabled) { + return; + } + if (wasActiveRef.current === null) { + wasActiveRef.current = isActive; + return; + } + if (isActive && !wasActiveRef.current) { + void Promise.resolve(refetchRef.current()); + } + wasActiveRef.current = isActive; + }, [enabled, isActive]); + + useEffect(() => { + if (!enabled) { + return; + } + const onVisibility = () => { + if (document.visibilityState !== 'visible') { + return; + } + if (activeTabId !== sceneId) { + return; + } + void Promise.resolve(refetchRef.current()); + }; + + document.addEventListener('visibilitychange', onVisibility); + return () => document.removeEventListener('visibilitychange', onVisibility); + }, [enabled, activeTabId, sceneId]); +} diff --git a/src/web-ui/src/app/scenes/SceneViewport.scss b/src/web-ui/src/app/scenes/SceneViewport.scss index 24341371..6be09c0a 100644 --- a/src/web-ui/src/app/scenes/SceneViewport.scss +++ b/src/web-ui/src/app/scenes/SceneViewport.scss @@ -64,6 +64,25 @@ margin: 0; } + // ── Lazy chunk loading (matches flow_chat ProcessingIndicator dots) ── + + &__lazy-fallback { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; + z-index: 1; + + .processing-indicator { + max-width: none; + width: auto; + margin: 0; + padding: 0; + } + } + // ── Scene slot ──────────────────────────────────────── &__scene { diff --git a/src/web-ui/src/app/scenes/SceneViewport.tsx b/src/web-ui/src/app/scenes/SceneViewport.tsx index ecef1975..db534619 100644 --- a/src/web-ui/src/app/scenes/SceneViewport.tsx +++ b/src/web-ui/src/app/scenes/SceneViewport.tsx @@ -13,6 +13,7 @@ import type { SceneTabId } from '../components/SceneBar/types'; import { useSceneManager } from '../hooks/useSceneManager'; import { useI18n } from '@/infrastructure/i18n/hooks/useI18n'; import { useDialogCompletionNotify } from '../hooks/useDialogCompletionNotify'; +import { ProcessingIndicator } from '@/flow_chat/components/modern/ProcessingIndicator'; import './SceneViewport.scss'; const SessionScene = lazy(() => import('./session/SessionScene')); @@ -56,7 +57,18 @@ const SceneViewport: React.FC = ({ workspacePath, isEntering return (
- + + +
+ )} + > {openTabs.map(tab => (
{ t, }); + useGallerySceneAutoRefresh({ + sceneId: 'agents', + refetch: () => void loadAgents(), + }); + const coreAgentMeta = useMemo((): Record => ({ agentic: { role: t('coreAgentsZone.modes.agentic.role'), @@ -190,19 +196,6 @@ const AgentsHomeView: React.FC = () => { )} /> - )} /> diff --git a/src/web-ui/src/app/scenes/assistant/AssistantScene.scss b/src/web-ui/src/app/scenes/assistant/AssistantScene.scss index bc7ce18a..83feaeb3 100644 --- a/src/web-ui/src/app/scenes/assistant/AssistantScene.scss +++ b/src/web-ui/src/app/scenes/assistant/AssistantScene.scss @@ -7,5 +7,16 @@ &__loading { width: 100%; height: 100%; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; + + .processing-indicator { + max-width: none; + width: auto; + margin: 0; + padding: 0; + } } } diff --git a/src/web-ui/src/app/scenes/assistant/AssistantScene.tsx b/src/web-ui/src/app/scenes/assistant/AssistantScene.tsx index 0fe4995a..bb01db57 100644 --- a/src/web-ui/src/app/scenes/assistant/AssistantScene.tsx +++ b/src/web-ui/src/app/scenes/assistant/AssistantScene.tsx @@ -1,6 +1,8 @@ import React, { Suspense, lazy, useMemo, useEffect } from 'react'; import { useWorkspaceContext } from '@/infrastructure/contexts/WorkspaceContext'; +import { useI18n } from '@/infrastructure/i18n/hooks/useI18n'; import { WorkspaceKind } from '@/shared/types'; +import { ProcessingIndicator } from '@/flow_chat/components/modern/ProcessingIndicator'; import { useMyAgentStore } from '../my-agent/myAgentStore'; import './AssistantScene.scss'; @@ -11,6 +13,7 @@ interface AssistantSceneProps { } const AssistantScene: React.FC = ({ workspacePath }) => { + const { t } = useI18n('common'); const selectedAssistantWorkspaceId = useMyAgentStore((s) => s.selectedAssistantWorkspaceId); const setSelectedAssistantWorkspaceId = useMyAgentStore((s) => s.setSelectedAssistantWorkspaceId); const { currentWorkspace, assistantWorkspacesList } = useWorkspaceContext(); @@ -67,7 +70,18 @@ const AssistantScene: React.FC = ({ workspacePath }) => { return (
- }> + + +
+ )} + > { const runningWorkerIds = useMiniAppStore((state) => state.runningWorkerIds); const setApps = useMiniAppStore((state) => state.setApps); const setLoading = useMiniAppStore((state) => state.setLoading); + const setRunningWorkerIds = useMiniAppStore((state) => state.setRunningWorkerIds); const markWorkerStopped = useMiniAppStore((state) => state.markWorkerStopped); const { workspacePath } = useCurrentWorkspace(); const { openScene, activateScene, closeScene, openTabs } = useSceneManager(); @@ -134,15 +135,26 @@ const MiniAppGalleryView: React.FC = () => { } }; - const handleRefresh = async () => { + const refetchMiniAppGallery = useCallback(async () => { setLoading(true); try { - const refreshed = await miniAppAPI.listMiniApps(); + const [refreshed, running] = await Promise.all([ + miniAppAPI.listMiniApps(), + miniAppAPI.workerListRunning(), + ]); setApps(refreshed); + setRunningWorkerIds(running); + } catch (error) { + log.error('Failed to refresh miniapp gallery', error); } finally { setLoading(false); } - }; + }, [setApps, setLoading, setRunningWorkerIds]); + + useGallerySceneAutoRefresh({ + sceneId: 'miniapps', + refetch: refetchMiniAppGallery, + }); const handleAddFromFolder = async () => { try { @@ -219,18 +231,6 @@ const MiniAppGalleryView: React.FC = () => { > - )} /> diff --git a/src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx b/src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx index 904fed29..288a1ce4 100644 --- a/src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx +++ b/src/web-ui/src/app/scenes/profile/views/AssistantConfigPage.tsx @@ -12,7 +12,6 @@ import { } from 'lucide-react'; import { Button, - ConfirmDialog, IconButton, Input, } from '@/component-library'; @@ -93,7 +92,6 @@ const AssistantConfigPage: React.FC = () => { const { document: identityDocument, updateField: updateIdentityField, - resetPersonaFiles, reload: reloadIdentityDocument, } = useAgentIdentityDocument(workspacePath); @@ -111,8 +109,6 @@ const AssistantConfigPage: React.FC = () => { const [editValue, setEditValue] = useState(''); const nameInputRef = useRef(null); const metaInputRef = useRef(null); - const [isResetDialogOpen, setIsResetDialogOpen] = useState(false); - const [rightView, setRightView] = useState('info'); const [personaDoc, setPersonaDoc] = useState(null); const personaSaveTimerRef = useRef | null>(null); @@ -450,16 +446,6 @@ const AssistantConfigPage: React.FC = () => { )}
- setIsResetDialogOpen(true)} - > - - { assistantName={identityName} />
+

{t('nursery.assistant.sessionsSectionTitle')}

{ {rightView === 'personaDoc' ? renderPersonaDocPanel() : renderInfoPanel()}
- - setIsResetDialogOpen(false)} - onConfirm={() => { - setIsResetDialogOpen(false); - resetPersonaFiles() - .then(() => notificationService.success(t('identity.resetSuccess'))) - .catch(() => notificationService.error(t('identity.resetFailed'))); - }} - onCancel={() => setIsResetDialogOpen(false)} - /> ); }; diff --git a/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss b/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss index 4baee223..4fceeca9 100644 --- a/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss +++ b/src/web-ui/src/app/scenes/profile/views/AssistantQuickInput.scss @@ -1,7 +1,8 @@ @use '../../../../component-library/styles/tokens' as *; .aqi { - padding: $size-gap-4 0 $size-gap-4; + // Horizontal inset: shadow fade + align with .acp-sessions-area (var from .acp-layout__left) + padding: $size-gap-4 var(--acp-left-inline-pad, #{$size-gap-6}) $size-gap-5; &__box { display: flex; @@ -9,12 +10,29 @@ border: 1px solid var(--border-medium); border-radius: $size-radius-xl; background: color-mix(in srgb, var(--element-bg-subtle) 94%, transparent); + // Large blur + negative spread: diffuse “pool” under the card, softer at side clips + box-shadow: 0 2px 16px -6px color-mix(in srgb, var(--color-text-primary) 8%, transparent); transition: border-color $motion-fast $easing-standard, - background $motion-fast $easing-standard; + background $motion-fast $easing-standard, + box-shadow $motion-fast $easing-standard, + transform $motion-fast $easing-standard; + + &:hover:not(:has(.bitfun-textarea__field:disabled)) { + transform: translateY(-2px); + border-color: var(--border-strong, var(--border-medium)); + background: color-mix(in srgb, var(--element-bg-base) 90%, transparent); + box-shadow: + 0 20px 48px -14px color-mix(in srgb, var(--color-text-primary) 14%, transparent), + 0 10px 28px -10px color-mix(in srgb, var(--color-text-primary) 9%, transparent); + } &:focus-within { + transform: translateY(-2px); border-color: var(--border-focus, var(--color-accent-500)); background: var(--element-bg-soft); + box-shadow: + 0 22px 52px -12px color-mix(in srgb, var(--color-accent-500, #60a5fa) 18%, transparent), + 0 12px 32px -10px color-mix(in srgb, var(--color-text-primary) 10%, transparent); } } diff --git a/src/web-ui/src/app/scenes/profile/views/NurseryView.scss b/src/web-ui/src/app/scenes/profile/views/NurseryView.scss index beb315bf..f9aa7362 100644 --- a/src/web-ui/src/app/scenes/profile/views/NurseryView.scss +++ b/src/web-ui/src/app/scenes/profile/views/NurseryView.scss @@ -2798,6 +2798,8 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); flex-direction: column; overflow: hidden; padding: 0; + // Shared with AssistantQuickInput (.aqi) and .acp-sessions-area horizontal inset + --acp-left-inline-pad: #{$size-gap-6}; } &__right { @@ -2890,11 +2892,6 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); font-size: $font-size-base; max-width: 140px; } - - &__reset.icon-btn { - flex-shrink: 0; - margin-top: 4px; - } } // ── Left: quick input area — handled by AssistantQuickInput component ──────── @@ -2907,8 +2904,17 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); min-height: 0; overflow-y: auto; overflow-x: hidden; - padding-top: $size-gap-5; - padding-bottom: $size-gap-8; + padding: $size-gap-5 var(--acp-left-inline-pad) $size-gap-8; + + &__title { + margin: 0 0 $size-gap-3; + padding: 0; + font-size: $font-size-sm; + font-weight: $font-weight-semibold; + line-height: $line-height-tight; + letter-spacing: -0.01em; + color: var(--color-text-secondary); + } &::-webkit-scrollbar { width: 4px; @@ -2944,13 +2950,13 @@ $acp-content-top: clamp(40px, 4.5vh, 52px); } .bitfun-nav-panel__inline-empty { - padding: $size-gap-4 $size-gap-3; + padding: $size-gap-4 0; font-size: $font-size-sm; } .bitfun-nav-panel__inline-action { min-height: 38px; - padding: $size-gap-3 $size-gap-3; + padding: $size-gap-3 0; font-size: $font-size-sm; border-radius: $size-radius-lg; } diff --git a/src/web-ui/src/app/scenes/skills/SkillsScene.scss b/src/web-ui/src/app/scenes/skills/SkillsScene.scss index 57eb3364..4b272ac5 100644 --- a/src/web-ui/src/app/scenes/skills/SkillsScene.scss +++ b/src/web-ui/src/app/scenes/skills/SkillsScene.scss @@ -123,6 +123,35 @@ gap: 4px; } + &__detail-path-btn { + flex: 1; + min-width: 0; + margin: 0; + padding: 0; + border: none; + background: none; + font: inherit; + font-family: $font-family-mono; + font-size: 11px; + line-height: $line-height-base; + text-align: left; + word-break: break-all; + color: var(--color-accent-500); + text-decoration: underline; + text-underline-offset: 2px; + cursor: pointer; + transition: color $motion-fast $easing-standard; + + &:hover { + color: var(--color-accent-600); + } + + &:focus-visible { + outline: 2px solid var(--color-accent-500); + outline-offset: 2px; + } + } + &__detail-row { display: flex; align-items: baseline; diff --git a/src/web-ui/src/app/scenes/skills/SkillsScene.tsx b/src/web-ui/src/app/scenes/skills/SkillsScene.tsx index ebbd1ef4..46b4809f 100644 --- a/src/web-ui/src/app/scenes/skills/SkillsScene.tsx +++ b/src/web-ui/src/app/scenes/skills/SkillsScene.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { CheckCircle2, ChevronLeft, @@ -9,7 +9,6 @@ import { Package, Plus, Puzzle, - RefreshCw, Search as SearchIcon, Sparkles, Store, @@ -28,17 +27,26 @@ import { GalleryZone, } from '@/app/components'; import type { SkillInfo, SkillLevel, SkillMarketItem } from '@/infrastructure/config/types'; +import { workspaceAPI } from '@/infrastructure/api'; +import { workspaceManager } from '@/infrastructure/services/business/workspaceManager'; +import { useNotification } from '@/shared/notification-system'; +import { isRemoteWorkspace } from '@/shared/types'; +import { createLogger } from '@/shared/utils/logger'; import { getCardGradient } from '@/shared/utils/cardGradients'; import { useInstalledSkills } from './hooks/useInstalledSkills'; import { useSkillMarket } from './hooks/useSkillMarket'; import SkillCard from './components/SkillCard'; import './SkillsScene.scss'; import { useSkillsSceneStore } from './skillsSceneStore'; +import { useGallerySceneAutoRefresh } from '@/app/hooks/useGallerySceneAutoRefresh'; + +const log = createLogger('SkillsScene'); const SKILLS_SOURCE_URL = 'https://skills.sh'; const SkillsScene: React.FC = () => { const { t } = useTranslation('scenes/skills'); + const notification = useNotification(); const { searchDraft, marketQuery, @@ -76,14 +84,31 @@ const SkillsScene: React.FC = () => { }, }); - const isRefreshing = installed.loading || market.marketLoading || market.loadingMore; + const refetchSkillsScene = useCallback(async () => { + await Promise.all([installed.loadSkills(true), market.refresh()]); + }, [installed.loadSkills, market.refresh]); - const handleRefreshAll = async () => { - await Promise.all([ - installed.loadSkills(true), - market.refresh(), - ]); - }; + useGallerySceneAutoRefresh({ + sceneId: 'skills', + refetch: refetchSkillsScene, + }); + + const canRevealSkillPath = !isRemoteWorkspace(workspaceManager.getState().currentWorkspace); + + const handleRevealSkillPath = useCallback( + async (path: string) => { + if (!canRevealSkillPath || !path.trim()) { + return; + } + try { + await workspaceAPI.revealInExplorer(path); + } catch (error) { + log.error('Failed to reveal skill path in explorer', { path, error }); + notification.error(t('messages.revealPathFailed', { error: String(error) })); + } + }, + [canRevealSkillPath, notification, t], + ); const handleAddSkill = async () => { const added = await installed.handleAdd(); @@ -198,16 +223,6 @@ const SkillsScene: React.FC = () => { {t('toolbar.addTooltip')} - )} /> @@ -404,7 +419,18 @@ const SkillsScene: React.FC = () => { {selectedInstalledSkill ? (
{t('list.item.pathLabel')} - {selectedInstalledSkill.path} + {canRevealSkillPath ? ( + + ) : ( + {selectedInstalledSkill.path} + )}
) : null} diff --git a/src/web-ui/src/app/scenes/skills/components/SkillCard.tsx b/src/web-ui/src/app/scenes/skills/components/SkillCard.tsx index bb19b65d..4344f83d 100644 --- a/src/web-ui/src/app/scenes/skills/components/SkillCard.tsx +++ b/src/web-ui/src/app/scenes/skills/components/SkillCard.tsx @@ -50,9 +50,13 @@ const SkillCard: React.FC = ({ '--skill-card-color-rgb': getCardColorRgb(accentSeed ?? name), } as React.CSSProperties} onClick={openDetails} - role="button" tabIndex={0} - onKeyDown={(e) => e.key === 'Enter' && openDetails()} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + openDetails(); + } + }} aria-label={name} > {/* Header: icon + badges */} @@ -71,7 +75,15 @@ const SkillCard: React.FC = ({ {description?.trim() && (

{description.trim()}

)} - {meta &&
{meta}
} + {meta ? ( +
e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + > + {meta} +
+ ) : null} {/* Footer: action buttons */} diff --git a/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx b/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx index 5d0a3c7f..695a4a7b 100644 --- a/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx +++ b/src/web-ui/src/infrastructure/config/components/BasicsConfig.tsx @@ -8,7 +8,6 @@ import { Tooltip, ConfigPageLoading, ConfigPageMessage, - ConfigPageRefreshButton, IconButton, } from '@/component-library'; import { configAPI, workspaceAPI } from '@/infrastructure/api'; @@ -380,11 +379,6 @@ function BasicsLoggingSection() { [configLevel, showMessage, t] ); - const handleRefresh = useCallback(async () => { - await loadData(); - showMessage('info', t('logging.messages.refreshed')); - }, [loadData, showMessage, t]); - const handleOpenFolder = useCallback(async () => { const folder = runtimeInfo?.sessionLogDir; if (!folder) { @@ -415,14 +409,6 @@ function BasicsLoggingSection() { - } > { - await loadData(); - showMessage('info', t('terminal.messages.refreshed')); - }, [loadData, showMessage, t]); - const shouldShowPowerShellCoreRecommendation = useMemo(() => { const isWindows = platform === 'windows'; if (!isWindows) return false; @@ -593,14 +574,6 @@ function BasicsTerminalSection() { - } > { }; const mcpSectionExtra = ( - <> - setShowJsonEditor(!showJsonEditor)} - tooltip={showJsonEditor ? tMcp('actions.backToList') : tMcp('actions.jsonConfig')} - > - {showJsonEditor ? : } - - - - - + setShowJsonEditor(!showJsonEditor)} + tooltip={showJsonEditor ? tMcp('actions.backToList') : tMcp('actions.jsonConfig')} + > + {showJsonEditor ? : } + ); const renderServerBadge = (server: MCPServerInfo) => ( diff --git a/src/web-ui/src/locales/en-US/common.json b/src/web-ui/src/locales/en-US/common.json index 0d5db2be..dcbffc72 100644 --- a/src/web-ui/src/locales/en-US/common.json +++ b/src/web-ui/src/locales/en-US/common.json @@ -783,6 +783,9 @@ "assistant": "Assistant", "shell": "Shell" }, + "loading": { + "scenes": "Loading scene" + }, "welcomeScene": { "tabLabel": "Welcome", "welcomeBack": "Welcome back to", diff --git a/src/web-ui/src/locales/en-US/scenes/agents.json b/src/web-ui/src/locales/en-US/scenes/agents.json index 2736eb5b..86eac833 100644 --- a/src/web-ui/src/locales/en-US/scenes/agents.json +++ b/src/web-ui/src/locales/en-US/scenes/agents.json @@ -11,8 +11,7 @@ "title": "Agents", "subtitle": "Review and manage core modes, agents, and sub-agents, including tools and skills.", "searchPlaceholder": "Search agents by name or description…", - "newAgent": "New Agent", - "refresh": "Refresh" + "newAgent": "New Agent" }, "nav": { "coreAgents": "Core Agents", diff --git a/src/web-ui/src/locales/en-US/scenes/miniapp.json b/src/web-ui/src/locales/en-US/scenes/miniapp.json index 43bb408d..64808c06 100644 --- a/src/web-ui/src/locales/en-US/scenes/miniapp.json +++ b/src/web-ui/src/locales/en-US/scenes/miniapp.json @@ -3,7 +3,6 @@ "subtitle": "Instantly generated mini apps, ready to use right away. You can also continue to iterate on them.", "searchPlaceholder": "Search mini apps...", "importFromFolder": "Import from folder", - "refreshList": "Refresh list", "running": "Running", "allApps": "All Apps", "noRunningApps": "No running apps", diff --git a/src/web-ui/src/locales/en-US/scenes/profile.json b/src/web-ui/src/locales/en-US/scenes/profile.json index e972292d..3ae1723b 100644 --- a/src/web-ui/src/locales/en-US/scenes/profile.json +++ b/src/web-ui/src/locales/en-US/scenes/profile.json @@ -189,6 +189,7 @@ "inheritPrimary": "Inherit from template (primary)", "inheritFast": "Inherit from template (fast)", "personaDocsTitle": "Key documents", + "sessionsSectionTitle": "Sessions", "scheduledSessionsTitle": "Scheduled sessions", "scheduledSessionsNoWorkspace": "Select an assistant workspace to manage scheduled sessions.", "personaDocs": { diff --git a/src/web-ui/src/locales/en-US/scenes/skills.json b/src/web-ui/src/locales/en-US/scenes/skills.json index 329ed4e3..442b0e6d 100644 --- a/src/web-ui/src/locales/en-US/scenes/skills.json +++ b/src/web-ui/src/locales/en-US/scenes/skills.json @@ -36,7 +36,6 @@ }, "toolbar": { "searchPlaceholder": "Search skills...", - "refreshTooltip": "Refresh", "addTooltip": "Add Skill" }, "filters": { @@ -58,7 +57,6 @@ "subtitlePrefix": "Browse reusable skills from", "subtitleSuffix": ".", "searchPlaceholder": "Search marketplace skills...", - "refreshTooltip": "Refresh marketplace results", "loading": "Loading marketplace skills...", "errorPrefix": "Failed to load marketplace: ", "empty": { @@ -124,7 +122,9 @@ "user": "User", "project": "Project", "deleteTooltip": "Delete", - "pathLabel": "Path:" + "pathLabel": "Path:", + "openPathInExplorer": "Open this folder in file explorer", + "revealPathUnavailableRemote": "Remote workspace paths cannot be opened in the local file manager" } }, "deleteModal": { @@ -146,6 +146,7 @@ "marketDownloadSuccess": "Skill \"{{name}}\" downloaded successfully", "marketDownloadFailed": "Failed to download: {{error}}", "enabled": "enabled", - "disabled": "disabled" + "disabled": "disabled", + "revealPathFailed": "Could not open in file explorer: {{error}}" } } diff --git a/src/web-ui/src/locales/zh-CN/common.json b/src/web-ui/src/locales/zh-CN/common.json index 28583e12..d4dfb265 100644 --- a/src/web-ui/src/locales/zh-CN/common.json +++ b/src/web-ui/src/locales/zh-CN/common.json @@ -783,6 +783,9 @@ "assistant": "助理", "shell": "Shell" }, + "loading": { + "scenes": "正在加载场景" + }, "welcomeScene": { "tabLabel": "欢迎使用", "welcomeBack": "欢迎回到", diff --git a/src/web-ui/src/locales/zh-CN/scenes/agents.json b/src/web-ui/src/locales/zh-CN/scenes/agents.json index d91c9261..fee64ea8 100644 --- a/src/web-ui/src/locales/zh-CN/scenes/agents.json +++ b/src/web-ui/src/locales/zh-CN/scenes/agents.json @@ -11,8 +11,7 @@ "title": "专业智能体", "subtitle": "查看与管理核心模式、Agent 与 Sub-Agent,配置工具与 Skills。", "searchPlaceholder": "搜索 Agent 名称或描述…", - "newAgent": "新建 Agent", - "refresh": "刷新" + "newAgent": "新建 Agent" }, "nav": { "coreAgents": "核心智能体", diff --git a/src/web-ui/src/locales/zh-CN/scenes/miniapp.json b/src/web-ui/src/locales/zh-CN/scenes/miniapp.json index 1003f83c..60b61120 100644 --- a/src/web-ui/src/locales/zh-CN/scenes/miniapp.json +++ b/src/web-ui/src/locales/zh-CN/scenes/miniapp.json @@ -3,7 +3,6 @@ "subtitle": "即时生成的小应用,打开就能用,也能继续迭代。", "searchPlaceholder": "搜索小应用...", "importFromFolder": "从文件夹导入", - "refreshList": "刷新列表", "running": "已启动", "allApps": "全部应用", "noRunningApps": "暂无运行中的应用", diff --git a/src/web-ui/src/locales/zh-CN/scenes/profile.json b/src/web-ui/src/locales/zh-CN/scenes/profile.json index d00b7536..b7325c01 100644 --- a/src/web-ui/src/locales/zh-CN/scenes/profile.json +++ b/src/web-ui/src/locales/zh-CN/scenes/profile.json @@ -189,6 +189,7 @@ "inheritPrimary": "继承模板(主力)", "inheritFast": "继承模板(快速)", "personaDocsTitle": "关键文档", + "sessionsSectionTitle": "会话", "scheduledSessionsTitle": "定时会话", "scheduledSessionsNoWorkspace": "请先选择助理工作区后再管理定时会话。", "personaDocs": { diff --git a/src/web-ui/src/locales/zh-CN/scenes/skills.json b/src/web-ui/src/locales/zh-CN/scenes/skills.json index 04a19a5a..4f92743b 100644 --- a/src/web-ui/src/locales/zh-CN/scenes/skills.json +++ b/src/web-ui/src/locales/zh-CN/scenes/skills.json @@ -36,7 +36,6 @@ }, "toolbar": { "searchPlaceholder": "搜索技能...", - "refreshTooltip": "刷新", "addTooltip": "添加技能" }, "filters": { @@ -58,7 +57,6 @@ "subtitlePrefix": "从", "subtitleSuffix": "浏览和下载可复用技能。", "searchPlaceholder": "搜索市场技能...", - "refreshTooltip": "刷新市场结果", "loading": "正在加载市场技能...", "errorPrefix": "市场加载失败: ", "empty": { @@ -124,7 +122,9 @@ "user": "用户级", "project": "项目级", "deleteTooltip": "删除", - "pathLabel": "路径:" + "pathLabel": "路径:", + "openPathInExplorer": "在资源管理器中打开此文件夹", + "revealPathUnavailableRemote": "远程工作区无法在本地资源管理器中打开路径" } }, "deleteModal": { @@ -146,6 +146,7 @@ "marketDownloadSuccess": "技能 \"{{name}}\" 下载成功", "marketDownloadFailed": "下载失败: {{error}}", "enabled": "启用", - "disabled": "禁用" + "disabled": "禁用", + "revealPathFailed": "无法在资源管理器中打开: {{error}}" } }