dashboard-nanobot/frontend/src/modules/dashboard/BotDashboardModule.tsx

508 lines
22 KiB
TypeScript
Raw Normal View History

2026-03-31 04:31:47 +00:00
import { BotDashboardView } from './components/BotDashboardView';
import { useBotDashboardModule } from './hooks/useBotDashboardModule';
import type { BotDashboardModuleProps } from './types';
2026-03-17 20:53:49 +00:00
import {
2026-03-31 04:31:47 +00:00
formatBytes,
formatWorkspaceTime,
} from './utils';
import './BotDashboardModule.css';
import './components/DashboardShared.css';
2026-03-01 16:26:03 +00:00
2026-03-31 04:31:47 +00:00
export function BotDashboardModule({
onOpenImageFactory,
forcedBotId,
compactMode = false,
compactPanelTab: compactPanelTabProp,
onCompactPanelTabChange,
}: BotDashboardModuleProps) {
const dashboard = useBotDashboardModule({
forcedBotId,
compactMode,
compactPanelTab: compactPanelTabProp,
onCompactPanelTabChange,
});
const runtimeMoreLabel = dashboard.isZh ? '更多' : 'More';
const botListPanelProps = {
bots: dashboard.bots,
filteredBots: dashboard.filteredBots,
pagedBots: dashboard.pagedBots,
selectedBotId: dashboard.selectedBotId,
normalizedBotListQuery: dashboard.normalizedBotListQuery,
botListQuery: dashboard.botListQuery,
botListPageSizeReady: dashboard.botListPageSizeReady,
botListPage: dashboard.botListPage,
botListTotalPages: dashboard.botListTotalPages,
botListMenuOpen: dashboard.botListMenuOpen,
controlStateByBot: dashboard.controlStateByBot,
operatingBotId: dashboard.operatingBotId,
compactMode: dashboard.compactMode,
isZh: dashboard.isZh,
isLoadingTemplates: dashboard.isLoadingTemplates,
isBatchOperating: dashboard.isBatchOperating,
labels: {
batchStart: dashboard.t.batchStart,
batchStop: dashboard.t.batchStop,
botSearchNoResult: dashboard.t.botSearchNoResult,
botSearchPlaceholder: dashboard.t.botSearchPlaceholder,
clearSearch: dashboard.t.clearSearch,
delete: dashboard.t.delete,
disable: dashboard.t.disable,
disabled: dashboard.t.disabled,
enable: dashboard.t.enable,
extensions: dashboard.t.extensions,
image: dashboard.t.image,
manageImages: dashboard.t.manageImages,
newBot: dashboard.t.newBot,
paginationNext: dashboard.t.paginationNext,
paginationPage: dashboard.t.paginationPage,
paginationPrev: dashboard.t.paginationPrev,
searchAction: dashboard.t.searchAction,
start: dashboard.t.start,
stop: dashboard.t.stop,
syncingPageSize: dashboard.t.syncingPageSize,
templateManager: dashboard.t.templateManager,
titleBots: dashboard.t.titleBots,
2026-03-13 06:40:54 +00:00
},
2026-03-31 04:31:47 +00:00
botSearchInputName: dashboard.botSearchInputName,
botListMenuRef: dashboard.botListMenuRef,
onOpenCreateWizard: () => dashboard.setShowCreateBotModal(true),
onOpenImageFactory,
onToggleMenu: () => dashboard.setBotListMenuOpen((prev) => !prev),
onCloseMenu: () => dashboard.setBotListMenuOpen(false),
onOpenTemplateManager: dashboard.openTemplateManager,
onBatchStartBots: dashboard.batchStartBots,
onBatchStopBots: dashboard.batchStopBots,
onBotListQueryChange: dashboard.setBotListQuery,
onBotListPageChange: dashboard.setBotListPage,
onSelectBot: dashboard.setSelectedBotId,
onSetCompactPanelTab: (tab: 'chat' | 'runtime') => dashboard.setCompactPanelTab(tab),
onSetBotEnabled: dashboard.setBotEnabled,
onStartBot: dashboard.startBot,
onStopBot: dashboard.stopBot,
onOpenResourceMonitor: dashboard.openResourceMonitor,
onRemoveBot: dashboard.removeBot,
};
const topicFeedPanelProps = {
isZh: dashboard.isZh,
topicKey: dashboard.topicFeedTopicKey,
topicOptions: dashboard.activeTopicOptions,
topicState: dashboard.topicPanelState,
items: dashboard.topicFeedItems,
loading: dashboard.topicFeedLoading,
loadingMore: dashboard.topicFeedLoadingMore,
nextCursor: dashboard.topicFeedNextCursor,
error: dashboard.topicFeedError,
readSavingById: dashboard.topicFeedReadSavingById,
deleteSavingById: dashboard.topicFeedDeleteSavingById,
onTopicChange: dashboard.setTopicFeedTopicKey,
onRefresh: () => void dashboard.loadTopicFeed({ append: false, topicKey: dashboard.topicFeedTopicKey }),
onMarkRead: (itemId: number) => void dashboard.markTopicFeedItemRead(itemId),
onDeleteItem: (item: (typeof dashboard.topicFeedItems)[number]) => void dashboard.deleteTopicFeedItem(item),
onLoadMore: () => void dashboard.loadTopicFeed({ append: true, cursor: dashboard.topicFeedNextCursor, topicKey: dashboard.topicFeedTopicKey }),
onOpenWorkspacePath: (path: string) => void dashboard.openWorkspacePathFromChat(path),
resolveWorkspaceMediaSrc: dashboard.resolveWorkspaceMediaSrc,
onOpenTopicSettings: dashboard.openTopicConfigModal,
onDetailOpenChange: dashboard.setTopicDetailOpen,
layout: 'panel' as const,
};
const dashboardChatPanelProps = {
conversation: dashboard.conversation,
isZh: dashboard.isZh,
labels: {
badReply: dashboard.t.badReply,
botDisabledHint: dashboard.t.botDisabledHint,
botStarting: dashboard.t.botStarting,
botStopping: dashboard.t.botStopping,
chatDisabled: dashboard.t.chatDisabled,
controlCommandsHide: dashboard.t.controlCommandsHide,
controlCommandsShow: dashboard.t.controlCommandsShow,
copyPrompt: dashboard.t.copyPrompt,
copyReply: dashboard.t.copyReply,
2026-04-02 04:14:08 +00:00
deleteMessage: dashboard.t.deleteMessage,
2026-03-31 04:31:47 +00:00
disabledPlaceholder: dashboard.t.disabledPlaceholder,
download: dashboard.t.download,
editPrompt: dashboard.t.editPrompt,
fileNotPreviewable: dashboard.t.fileNotPreviewable,
goodReply: dashboard.t.goodReply,
inputPlaceholder: dashboard.t.inputPlaceholder,
interrupt: dashboard.t.interrupt,
noConversation: dashboard.t.noConversation,
previewTitle: dashboard.t.previewTitle,
2026-04-02 12:27:06 +00:00
stagedSubmissionAttachmentCount: dashboard.t.stagedSubmissionAttachmentCount,
stagedSubmissionEmpty: dashboard.t.stagedSubmissionEmpty,
stagedSubmissionRestore: dashboard.t.stagedSubmissionRestore,
stagedSubmissionRemove: dashboard.t.stagedSubmissionRemove,
2026-03-31 04:31:47 +00:00
quoteReply: dashboard.t.quoteReply,
quotedReplyLabel: dashboard.t.quotedReplyLabel,
send: dashboard.t.send,
thinking: dashboard.t.thinking,
uploadFile: dashboard.t.uploadFile,
uploadingFile: dashboard.t.uploadingFile,
user: dashboard.t.user,
voiceStart: dashboard.t.voiceStart,
voiceStop: dashboard.t.voiceStop,
voiceTranscribing: dashboard.t.voiceTranscribing,
you: dashboard.t.you,
2026-03-13 06:40:54 +00:00
},
2026-03-31 04:31:47 +00:00
chatScrollRef: dashboard.chatScrollRef,
onChatScroll: dashboard.onChatScroll,
expandedProgressByKey: dashboard.expandedProgressByKey,
expandedUserByKey: dashboard.expandedUserByKey,
2026-04-02 04:14:08 +00:00
deletingMessageIdMap: dashboard.deletingMessageIdMap,
2026-03-31 04:31:47 +00:00
feedbackSavingByMessageId: dashboard.feedbackSavingByMessageId,
markdownComponents: dashboard.markdownComponents,
workspaceDownloadExtensionSet: dashboard.workspaceDownloadExtensionSet,
onToggleProgressExpand: dashboard.toggleProgressExpanded,
onToggleUserExpand: dashboard.toggleUserExpanded,
onEditUserPrompt: dashboard.editUserPrompt,
onCopyUserPrompt: dashboard.copyUserPrompt,
2026-04-02 04:14:08 +00:00
onDeleteConversationMessage: dashboard.deleteConversationMessage,
2026-03-31 04:31:47 +00:00
onOpenWorkspacePath: dashboard.openWorkspacePathFromChat,
onSubmitAssistantFeedback: dashboard.submitAssistantFeedback,
onQuoteAssistantReply: dashboard.quoteAssistantReply,
onCopyAssistantReply: dashboard.copyAssistantReply,
isThinking: dashboard.isThinking,
canChat: dashboard.canChat,
isChatEnabled: dashboard.isChatEnabled,
2026-04-02 04:14:08 +00:00
speechEnabled: dashboard.speechEnabled,
2026-03-31 04:31:47 +00:00
selectedBotEnabled: dashboard.selectedBotEnabled,
selectedBotControlState: dashboard.selectedBotControlState,
quotedReply: dashboard.quotedReply,
onClearQuotedReply: () => dashboard.setQuotedReply(null),
2026-04-02 12:27:06 +00:00
stagedSubmissions: dashboard.selectedBotStagedSubmissions,
onRestoreStagedSubmission: dashboard.restoreStagedSubmission,
onRemoveStagedSubmission: dashboard.removeStagedSubmission,
2026-03-31 04:31:47 +00:00
pendingAttachments: dashboard.pendingAttachments,
onRemovePendingAttachment: (path: string) =>
dashboard.setPendingAttachments((prev) => prev.filter((value) => value !== path)),
attachmentUploadPercent: dashboard.attachmentUploadPercent,
isUploadingAttachments: dashboard.isUploadingAttachments,
filePickerRef: dashboard.filePickerRef,
allowedAttachmentExtensions: dashboard.allowedAttachmentExtensions,
onPickAttachments: dashboard.onPickAttachments,
controlCommandPanelOpen: dashboard.controlCommandPanelOpen,
controlCommandPanelRef: dashboard.controlCommandPanelRef,
onToggleControlCommandPanel: () => {
dashboard.setChatDatePickerOpen(false);
dashboard.setControlCommandPanelOpen((prev) => !prev);
2026-03-13 06:40:54 +00:00
},
2026-03-31 04:31:47 +00:00
activeControlCommand: dashboard.activeControlCommand,
canSendControlCommand: dashboard.canSendControlCommand,
isInterrupting: dashboard.isInterrupting,
onSendControlCommand: dashboard.sendControlCommand,
onInterruptExecution: dashboard.interruptExecution,
chatDateTriggerRef: dashboard.chatDateTriggerRef,
hasSelectedBot: Boolean(dashboard.selectedBotId),
chatDateJumping: dashboard.chatDateJumping,
onToggleChatDatePicker: dashboard.toggleChatDatePicker,
chatDatePickerOpen: dashboard.chatDatePickerOpen,
chatDatePanelPosition: dashboard.chatDatePanelPosition,
chatDateValue: dashboard.chatDateValue,
onChatDateValueChange: dashboard.setChatDateValue,
onCloseChatDatePicker: () => dashboard.setChatDatePickerOpen(false),
onJumpConversationToDate: dashboard.jumpConversationToDate,
command: dashboard.command,
onCommandChange: dashboard.setCommand,
composerTextareaRef: dashboard.composerTextareaRef,
onComposerKeyDown: dashboard.onComposerKeyDown,
isVoiceRecording: dashboard.isVoiceRecording,
isVoiceTranscribing: dashboard.isVoiceTranscribing,
isCompactMobile: dashboard.isCompactMobile,
voiceCountdown: dashboard.voiceCountdown,
onVoiceInput: dashboard.onVoiceInput,
onTriggerPickAttachments: dashboard.triggerPickAttachments,
2026-04-02 12:27:06 +00:00
submitActionMode: dashboard.submitActionMode,
onSubmitAction: dashboard.handlePrimarySubmitAction,
2026-03-31 04:31:47 +00:00
};
const runtimePanelProps = {
selectedBot: dashboard.selectedBot,
selectedBotEnabled: dashboard.selectedBotEnabled,
operatingBotId: dashboard.operatingBotId,
runtimeMenuOpen: dashboard.runtimeMenuOpen,
runtimeMenuRef: dashboard.runtimeMenuRef,
displayState: dashboard.displayState,
workspaceError: dashboard.workspaceError,
workspacePathDisplay: dashboard.workspacePathDisplay,
workspaceLoading: dashboard.workspaceLoading,
workspaceQuery: dashboard.workspaceQuery,
workspaceSearchInputName: dashboard.workspaceSearchInputName,
workspaceSearchLoading: dashboard.workspaceSearchLoading,
filteredWorkspaceEntries: dashboard.filteredWorkspaceEntries,
workspaceParentPath: dashboard.workspaceParentPath,
workspaceFileLoading: dashboard.workspaceFileLoading,
workspaceDownloadExtensionSet: dashboard.workspaceDownloadExtensionSet,
workspaceAutoRefresh: dashboard.workspaceAutoRefresh,
isCompactHidden: dashboard.compactMode && (dashboard.isCompactListPage || dashboard.compactPanelTab !== 'runtime'),
showCompactSurface: dashboard.showCompactBotPageClose,
emptyStateText: dashboard.forcedBotMissing ? `${dashboard.t.noTelemetry}: ${String(dashboard.forcedBotId).trim()}` : dashboard.t.noTelemetry,
labels: {
agent: dashboard.t.agent,
autoRefresh: dashboard.lc.autoRefresh,
base: dashboard.t.base,
channels: dashboard.t.channels,
clearHistory: dashboard.t.clearHistory,
clearSearch: dashboard.t.clearSearch,
cronViewer: dashboard.t.cronViewer,
download: dashboard.t.download,
emptyDir: dashboard.t.emptyDir,
envParams: dashboard.t.envParams,
exportHistory: dashboard.t.exportHistory,
fileNotPreviewable: dashboard.t.fileNotPreviewable,
folder: dashboard.t.folder,
goUp: dashboard.t.goUp,
goUpTitle: dashboard.t.goUpTitle,
loadingDir: dashboard.t.loadingDir,
mcp: dashboard.t.mcp,
more: runtimeMoreLabel,
noPreviewFile: dashboard.t.noPreviewFile,
openingPreview: dashboard.t.openingPreview,
openFolderTitle: dashboard.t.openFolderTitle,
params: dashboard.t.params,
previewTitle: dashboard.t.previewTitle,
refreshHint: dashboard.lc.refreshHint,
restart: dashboard.t.restart,
runtime: dashboard.t.runtime,
searchAction: dashboard.t.searchAction,
skills: dashboard.t.skills,
topic: dashboard.t.topic,
workspaceHint: dashboard.t.workspaceHint,
workspaceOutputs: dashboard.t.workspaceOutputs,
workspaceSearchNoResult: dashboard.t.workspaceSearchNoResult,
workspaceSearchPlaceholder: dashboard.t.workspaceSearchPlaceholder,
2026-03-01 16:26:03 +00:00
},
2026-03-31 04:31:47 +00:00
onRestartBot: dashboard.restartBot,
onToggleRuntimeMenu: () => dashboard.setRuntimeMenuOpen((prev) => !prev),
onOpenBaseConfig: dashboard.openBaseConfigModal,
onOpenParamConfig: dashboard.openParamConfigModal,
onOpenChannelConfig: dashboard.openChannelConfigModal,
onOpenTopicConfig: dashboard.openTopicConfigModal,
onOpenEnvParams: dashboard.openEnvParamsConfigModal,
onOpenSkills: dashboard.openSkillsConfigModal,
onOpenMcpConfig: dashboard.openMcpConfigModal,
onOpenCronJobs: dashboard.openCronJobsModal,
onOpenAgentFiles: dashboard.openAgentFilesModal,
onExportHistory: () => {
dashboard.setRuntimeMenuOpen(false);
dashboard.exportConversationJson();
2026-03-01 16:26:03 +00:00
},
2026-03-31 04:31:47 +00:00
onClearHistory: async () => {
dashboard.setRuntimeMenuOpen(false);
await dashboard.clearConversationHistory();
2026-03-01 16:26:03 +00:00
},
2026-03-31 04:31:47 +00:00
onRefreshWorkspace: () => dashboard.selectedBot ? dashboard.loadWorkspaceTree(dashboard.selectedBot.id, dashboard.workspaceCurrentPath) : undefined,
onWorkspaceQueryChange: dashboard.setWorkspaceQuery,
onWorkspaceQueryClear: () => dashboard.setWorkspaceQuery(''),
onWorkspaceQuerySearch: () => dashboard.setWorkspaceQuery((value) => value.trim()),
onToggleWorkspaceAutoRefresh: () => dashboard.setWorkspaceAutoRefresh((prev) => !prev),
onLoadWorkspaceTree: dashboard.loadWorkspaceTree,
onOpenWorkspaceFilePreview: dashboard.openWorkspaceFilePreview,
onShowWorkspaceHoverCard: dashboard.showWorkspaceHoverCard,
onHideWorkspaceHoverCard: dashboard.hideWorkspaceHoverCard,
};
const dashboardModalStackProps = {
resourceMonitorModal: {
open: dashboard.showResourceModal,
botId: dashboard.resourceBotId,
resourceBot: dashboard.resourceBot,
resourceSnapshot: dashboard.resourceSnapshot,
resourceLoading: dashboard.resourceLoading,
resourceError: dashboard.resourceError,
isZh: dashboard.isZh,
closeLabel: dashboard.t.close,
onClose: () => dashboard.setShowResourceModal(false),
onRefresh: dashboard.loadResourceSnapshot,
2026-03-26 18:09:25 +00:00
},
2026-03-31 04:31:47 +00:00
baseConfigModal: {
open: dashboard.showBaseModal,
selectedBotId: dashboard.selectedBot?.id || '',
editForm: dashboard.editForm,
paramDraft: dashboard.paramDraft,
baseImageOptions: dashboard.baseImageOptions,
systemTimezoneOptions: dashboard.systemTimezoneOptions,
defaultSystemTimezone: dashboard.defaultSystemTimezone,
passwordToggleLabels: dashboard.passwordToggleLabels,
isSaving: dashboard.isSaving,
isZh: dashboard.isZh,
labels: {
accessPassword: dashboard.t.accessPassword,
accessPasswordPlaceholder: dashboard.t.accessPasswordPlaceholder,
baseConfig: dashboard.t.baseConfig,
baseImageReadonly: dashboard.t.baseImageReadonly,
botIdReadonly: dashboard.t.botIdReadonly,
botName: dashboard.t.botName,
botNamePlaceholder: dashboard.t.botNamePlaceholder,
cancel: dashboard.t.cancel,
close: dashboard.t.close,
save: dashboard.t.save,
},
onClose: () => dashboard.setShowBaseModal(false),
onEditFormChange: dashboard.updateEditForm,
onParamDraftChange: dashboard.updateParamDraft,
onSave: () => dashboard.saveBot('base'),
2026-03-01 16:26:03 +00:00
},
2026-03-31 04:31:47 +00:00
paramConfigModal: {
open: dashboard.showParamModal,
editForm: dashboard.editForm,
paramDraft: dashboard.paramDraft,
passwordToggleLabels: dashboard.passwordToggleLabels,
isZh: dashboard.isZh,
isTestingProvider: dashboard.isTestingProvider,
providerTestResult: dashboard.providerTestResult,
isSaving: dashboard.isSaving,
labels: {
cancel: dashboard.t.cancel,
close: dashboard.t.close,
modelName: dashboard.t.modelName,
modelNamePlaceholder: dashboard.t.modelNamePlaceholder,
modelParams: dashboard.t.modelParams,
newApiKey: dashboard.t.newApiKey,
newApiKeyPlaceholder: dashboard.t.newApiKeyPlaceholder,
saveParams: dashboard.t.saveParams,
testModelConnection: dashboard.t.testModelConnection,
testing: dashboard.t.testing,
},
onClose: () => dashboard.setShowParamModal(false),
onEditFormChange: dashboard.updateEditForm,
onParamDraftChange: dashboard.updateParamDraft,
onProviderChange: dashboard.onBaseProviderChange,
onTestProviderConnection: dashboard.testProviderConnection,
onSave: () => dashboard.saveBot('params'),
2026-03-01 16:26:03 +00:00
},
2026-03-31 04:31:47 +00:00
channelConfigModal: dashboard.channelConfigModalProps,
topicConfigModal: dashboard.topicConfigModalProps,
skillsModal: dashboard.skillsModalProps,
skillMarketInstallModal: dashboard.skillMarketInstallModalProps,
mcpConfigModal: dashboard.mcpConfigModalProps,
envParamsModal: dashboard.envParamsModalProps,
cronJobsModal: dashboard.cronJobsModalProps,
templateManagerModal: {
open: dashboard.showTemplateModal,
templateTab: dashboard.templateTab,
templateAgentCount: dashboard.templateAgentCount,
templateTopicCount: dashboard.templateTopicCount,
templateAgentText: dashboard.templateAgentText,
templateTopicText: dashboard.templateTopicText,
isSavingTemplates: dashboard.isSavingTemplates,
labels: {
cancel: dashboard.t.cancel,
close: dashboard.t.close,
processing: dashboard.t.processing,
save: dashboard.t.save,
templateManagerTitle: dashboard.t.templateManagerTitle,
templateTabAgent: dashboard.t.templateTabAgent,
templateTabTopic: dashboard.t.templateTabTopic,
},
onClose: () => dashboard.setShowTemplateModal(false),
onTemplateTabChange: dashboard.setTemplateTab,
onTemplateAgentTextChange: dashboard.setTemplateAgentText,
onTemplateTopicTextChange: dashboard.setTemplateTopicText,
onSave: dashboard.saveTemplateManager,
2026-03-01 16:26:03 +00:00
},
2026-03-31 04:31:47 +00:00
agentFilesModal: {
open: dashboard.showAgentModal,
agentTab: dashboard.agentTab,
tabValue: String(dashboard.editForm[dashboard.agentFieldByTab[dashboard.agentTab]]),
isSaving: dashboard.isSaving,
labels: {
agentFiles: dashboard.t.agentFiles,
cancel: dashboard.t.cancel,
close: dashboard.t.close,
saveFiles: dashboard.t.saveFiles,
},
onClose: () => dashboard.setShowAgentModal(false),
onAgentTabChange: dashboard.setAgentTab,
onTabValueChange: (nextValue: string) => dashboard.updateAgentTabValue(dashboard.agentTab, nextValue),
onSave: () => dashboard.saveBot('agent'),
2026-03-15 07:14:01 +00:00
},
2026-03-31 04:31:47 +00:00
runtimeActionModal: {
open: dashboard.showRuntimeActionModal,
runtimeAction: dashboard.runtimeAction,
labels: {
close: dashboard.t.close,
lastAction: dashboard.t.lastAction,
2026-03-01 16:26:03 +00:00
},
2026-03-31 04:31:47 +00:00
onClose: () => dashboard.setShowRuntimeActionModal(false),
},
workspacePreviewModal: {
isZh: dashboard.isZh,
labels: {
cancel: dashboard.t.cancel,
close: dashboard.t.close,
copyAddress: dashboard.t.copyAddress,
download: dashboard.t.download,
editFile: dashboard.t.editFile,
filePreview: dashboard.t.filePreview,
fileTruncated: dashboard.t.fileTruncated,
save: dashboard.t.save,
2026-03-16 03:08:25 +00:00
},
2026-03-31 04:31:47 +00:00
preview: dashboard.workspacePreview,
previewFullscreen: dashboard.workspacePreviewFullscreen,
previewEditorEnabled: dashboard.workspacePreviewEditorEnabled,
previewCanEdit: dashboard.workspacePreviewCanEdit,
previewDraft: dashboard.workspacePreviewDraft,
previewSaving: dashboard.workspacePreviewSaving,
markdownComponents: dashboard.workspacePreviewMarkdownComponents,
onClose: dashboard.closeWorkspacePreview,
onToggleFullscreen: () => dashboard.setWorkspacePreviewFullscreen((prev) => !prev),
onCopyPreviewPath: dashboard.copyWorkspacePreviewPath,
onCopyPreviewUrl: dashboard.copyWorkspacePreviewUrl,
onPreviewDraftChange: dashboard.setWorkspacePreviewDraft,
onSavePreviewMarkdown: dashboard.saveWorkspacePreviewMarkdown,
onEnterEditMode: () => dashboard.setWorkspacePreviewMode('edit'),
onExitEditMode: () => {
dashboard.setWorkspacePreviewDraft(dashboard.workspacePreview?.content || '');
dashboard.setWorkspacePreviewMode('preview');
2026-03-26 18:09:25 +00:00
},
2026-03-31 04:31:47 +00:00
getWorkspaceDownloadHref: dashboard.getWorkspaceDownloadHref,
getWorkspaceRawHref: dashboard.getWorkspaceRawHref,
},
workspaceHoverCard: {
state: dashboard.workspaceHoverCard,
isZh: dashboard.isZh,
formatWorkspaceTime,
formatBytes,
},
2026-03-05 02:42:39 +00:00
};
2026-03-31 04:31:47 +00:00
const createBotModalProps = {
open: dashboard.showCreateBotModal,
onClose: () => dashboard.setShowCreateBotModal(false),
onCreated: () => {
void dashboard.refresh();
},
2026-03-01 16:26:03 +00:00
};
return (
2026-03-31 04:31:47 +00:00
<BotDashboardView
compactMode={dashboard.compactMode}
hasForcedBot={dashboard.hasForcedBot}
showBotListPanel={dashboard.showBotListPanel}
botListPanelProps={botListPanelProps}
hasSelectedBot={Boolean(dashboard.selectedBot)}
isCompactListPage={dashboard.isCompactListPage}
compactPanelTab={dashboard.compactPanelTab}
showCompactBotPageClose={dashboard.showCompactBotPageClose}
forcedBotId={dashboard.forcedBotId}
selectBotText={dashboard.forcedBotMissing ? `${dashboard.t.selectBot}: ${String(dashboard.forcedBotId).trim()}` : dashboard.t.selectBot}
isZh={dashboard.isZh}
runtimeViewMode={dashboard.runtimeViewMode}
hasTopicUnread={dashboard.hasTopicUnread}
onRuntimeViewModeChange={dashboard.setRuntimeViewMode}
topicFeedPanelProps={topicFeedPanelProps}
dashboardChatPanelProps={dashboardChatPanelProps}
runtimePanelProps={runtimePanelProps}
onCompactClose={() => {
dashboard.setSelectedBotId('');
dashboard.setCompactPanelTab('chat');
}}
dashboardModalStackProps={dashboardModalStackProps}
createBotModalProps={createBotModalProps}
/>
2026-03-01 16:26:03 +00:00
);
}