feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { SingleMode, type SingleModeProps } from './single-mode';
export { WorkflowMode, type WorkflowModeProps } from './workflow-mode';

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { I18n } from '@coze-arch/i18n';
import Coachmark, { StepCard } from '@coze-common/biz-components/coachmark';
import promptDiffGuideI18NPNG from '../../../assets/coachmark/prompt-diff-guide.i18n.png';
import promptDiffGuideCNPNG from '../../../assets/coachmark/prompt-diff-guide.cn.png';
import modelSelectGuideI18NPNG from '../../../assets/coachmark/model-diff-guide.i18n.png';
import modelSelectGuideCNPNG from '../../../assets/coachmark/model-diff-guide.cn.png';
export const CoachMark = () => (
<Coachmark
steps={[
{
content: (
<StepCard
imgSrc={IS_OVERSEA ? promptDiffGuideI18NPNG : promptDiffGuideCNPNG}
content={I18n.t('compare_guide_description_prompt')}
title={I18n.t('compare_guide_title_prompt')}
/>
),
target: '#prompt_diff_coachmark_target',
},
{
content: (
<StepCard
imgSrc={
IS_OVERSEA ? modelSelectGuideI18NPNG : modelSelectGuideCNPNG
}
content={I18n.t('compare_guide_description_model')}
title={I18n.t('compare_guide_title_model')}
/>
),
target: '#model_select_coachmark_target',
},
]}
caseId="singleAgentDiffGuide"
/>
);

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useShallow } from 'zustand/react/shallow';
import { useDiffTaskStore } from '@coze-studio/bot-detail-store/diff-task';
import { useBotInfoStore } from '@coze-studio/bot-detail-store/bot-info';
import { I18n } from '@coze-arch/i18n';
import { IconCozCompare } from '@coze-arch/coze-design/icons';
import { Button } from '@coze-arch/coze-design';
import { EVENT_NAMES, sendTeaEvent } from '@coze-arch/bot-tea';
export const ModelDiffButton = (props: { readonly?: boolean }) => {
const { readonly } = props;
const { enterDiffMode } = useDiffTaskStore(
useShallow(state => ({
enterDiffMode: state.enterDiffMode,
})),
);
const { botId } = useBotInfoStore(
useShallow(state => ({
botId: state.botId,
})),
);
return (
<Button
icon={<IconCozCompare />}
color="highlight"
disabled={readonly}
onClick={() => {
sendTeaEvent(EVENT_NAMES.compare_mode_front, {
bot_id: botId,
compare_type: 'models',
from: 'compare_button',
source: 'bot_detail_page',
action: 'start',
});
enterDiffMode({ diffTask: 'model' });
}}
>
{I18n.t('compare_model_compare_model')}
</Button>
);
};

View File

@@ -0,0 +1,124 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type ReactNode, useState } from 'react';
import { useShallow } from 'zustand/react/shallow';
import classNames from 'classnames';
import { usePageRuntimeStore } from '@coze-studio/bot-detail-store/page-runtime';
import { useBotDetailIsReadonly } from '@coze-studio/bot-detail-store';
import { BotPageFromEnum } from '@coze-arch/bot-typings/common';
import { BotMode, TabStatus } from '@coze-arch/bot-api/developer_api';
import { AbilityAreaContainer } from '@coze-agent-ide/tool';
import { useBotPageStore } from '@coze-agent-ide/space-bot/store';
import {
ContentView,
BotDebugPanel,
} from '@coze-agent-ide/space-bot/component';
import s from '../../index.module.less';
import {
AgentConfigArea,
type AgentConfigAreaProps,
} from './section-area/agent-config-area/index';
import {
AgentChatArea,
type AgentChatAreaProps,
} from './section-area/agent-chat-area';
import { CoachMark } from './components/coach-mark';
export interface SingleModeProps
extends Omit<AgentConfigAreaProps, 'isAllToolHidden'>,
AgentChatAreaProps {
rightSheetSlot?: ReactNode;
chatAreaReadOnly?: boolean;
}
export const SingleMode: React.FC<SingleModeProps> = ({
rightSheetSlot,
renderChatTitleNode,
chatSlot,
chatHeaderClassName,
chatAreaReadOnly,
...agentConfigAreaProps
}) => {
const { isInit, historyVisible, pageFrom, defaultAllHidden } =
usePageRuntimeStore(
useShallow(state => ({
isInit: state.init,
historyVisible: state.historyVisible,
pageFrom: state.pageFrom,
defaultAllHidden: !Object.values(
state.botSkillBlockCollapsibleState,
).some(val => val !== TabStatus.Hide),
})),
);
const modeSwitching = useBotPageStore(state => state.bot.modeSwitching);
const isReadonly = useBotDetailIsReadonly();
const [isAllToolHidden, setIsAllToolHidden] = useState(defaultAllHidden);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const onAllToolHiddenStatusChange = (_isAllToolHidden: any) => {
setIsAllToolHidden(_isAllToolHidden);
};
return (
<div
className={classNames(
s.container,
historyVisible && s['playground-neat'],
pageFrom === BotPageFromEnum.Store && s.store,
)}
>
<AbilityAreaContainer
enableToolHiddenMode
eventCallbacks={{
onAllToolHiddenStatusChange,
}}
isReadonly={isReadonly}
mode={BotMode.SingleMode}
modeSwitching={modeSwitching}
isInit={isInit}
>
<ContentView
mode={BotMode.SingleMode}
className={classNames({
[s['wrapper-single-with-tool-area-hidden']]: isAllToolHidden,
})}
>
<AgentConfigArea
isAllToolHidden={isAllToolHidden}
{...agentConfigAreaProps}
/>
<AgentChatArea
renderChatTitleNode={renderChatTitleNode}
chatSlot={chatSlot}
chatHeaderClassName={chatHeaderClassName}
chatAreaReadOnly={chatAreaReadOnly}
/>
</ContentView>
{/* Debug调试台 */}
<BotDebugPanel />
{rightSheetSlot}
<CoachMark />
</AbilityAreaContainer>
</div>
);
};

View File

@@ -0,0 +1,97 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type ReactNode } from 'react';
import { useShallow } from 'zustand/react/shallow';
import classNames from 'classnames';
import { SingleSheet } from '@coze-agent-ide/space-bot/component';
import { I18n } from '@coze-arch/i18n';
import { type BotPageFromEnum } from '@coze-arch/bot-typings/common';
import { usePageRuntimeStore } from '@coze-studio/bot-detail-store/page-runtime';
import { useBotSkillStore } from '@coze-studio/bot-detail-store/bot-skill';
import { BotDebugChatArea } from '@coze-agent-ide/chat-debug-area';
import s from '../../../index.module.less';
export interface AgentChatAreaProps {
renderChatTitleNode?: (params: {
pageFrom: BotPageFromEnum | undefined;
showBackground: boolean;
}) => ReactNode;
chatSlot?: ReactNode;
chatHeaderClassName?: string;
chatAreaReadOnly?: boolean;
}
export const AgentChatArea: React.FC<AgentChatAreaProps> = ({
renderChatTitleNode,
chatSlot,
chatHeaderClassName,
chatAreaReadOnly,
}) => {
const { showBackground } = useBotSkillStore(
useShallow(({ backgroundImageInfoList }) => ({
showBackground: Boolean(
backgroundImageInfoList?.[0]?.mobile_background_image?.origin_image_url,
),
})),
);
const { pageFrom } = usePageRuntimeStore(
useShallow(state => ({
pageFrom: state.pageFrom,
})),
);
return (
<SingleSheet
title={I18n.t('bot_preview_debug_title')}
titleClassName={classNames(
showBackground ? '!coz-fg-images-white' : '',
'!text-[16px]',
)}
containerClassName={classNames(
s['bj-cover'],
showBackground && `${s['bj-img-cover']}`,
'flex-none !h-12',
)}
headerSlotClassName="!h-12"
headerClassName={classNames(
s['debug-chat-header-padding'],
'!h-12 !text-[16px] !border-0',
`${s['border-cover']}`,
{
'!bg-transparent': showBackground,
},
chatHeaderClassName,
)}
titleNode={renderChatTitleNode?.({
pageFrom,
showBackground,
})}
renderContent={headerNode => (
<div className={classNames(s['message-area'])}>
<BotDebugChatArea
headerNode={headerNode}
readOnly={chatAreaReadOnly}
/>
{chatSlot}
</div>
)}
/>
);
};

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useShallow } from 'zustand/react/shallow';
import classNames from 'classnames';
import { SingleSheet } from '@coze-agent-ide/space-bot/component';
import { usePageRuntimeStore } from '@coze-studio/bot-detail-store/page-runtime';
import { I18n } from '@coze-arch/i18n';
import { LayoutContext, PlacementEnum } from '@coze-arch/bot-hooks';
import { PromptView } from '@coze-agent-ide/prompt-adapter';
import { BotConfigArea } from '@coze-agent-ide/bot-config-area-adapter';
// eslint-disable-next-line @coze-arch/no-deep-relative-import
import s from '../../../../index.module.less';
import { ToolArea, type ToolAreaProps } from './tool-area';
export type AgentConfigAreaProps = ToolAreaProps & {
modelListExtraHeaderSlot?: React.ReactNode;
};
export const AgentConfigArea: React.FC<AgentConfigAreaProps> = props => {
const { editable, pageFrom } = usePageRuntimeStore(
useShallow(state => ({
editable: state.editable,
pageFrom: state.pageFrom,
})),
);
return (
<SingleSheet
headerClassName={classNames([
'coz-bg-plus',
'coz-fg-secondary',
'!h-12',
'!px-4',
'!py-0',
])}
title={I18n.t('bot_build_title')}
titleClassName="!text-[16px]"
titleNode={
<div className={s['sheet-title-node-cover']}>
<BotConfigArea
pageFrom={pageFrom}
editable={editable}
modelListExtraHeaderSlot={props.modelListExtraHeaderSlot}
/>
</div>
}
>
<div className={s['tool-card']}>
<LayoutContext value={{ placement: PlacementEnum.LEFT }}>
<PromptView />
</LayoutContext>
<ToolArea {...props} />
</div>
</SingleSheet>
);
};

View File

@@ -0,0 +1,169 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable @coze-arch/no-deep-relative-import */
import classNames from 'classnames';
import { useModelStore } from '@coze-studio/bot-detail-store/model';
import { ShortcutToolConfig } from '@coze-common/chat-area-plugins-chat-shortcuts/shortcut-tool';
import { I18n } from '@coze-arch/i18n';
import { LayoutContext, PlacementEnum } from '@coze-arch/bot-hooks';
import { FormatType } from '@coze-arch/bot-api/knowledge';
import { BotMode, WorkflowMode } from '@coze-arch/bot-api/developer_api';
import {
WorkflowCard,
WorkflowModalFrom,
} from '@coze-agent-ide/workflow-card-adapter';
import { ToolGroupKey } from '@coze-agent-ide/tool-config';
import { GroupingContainer, ToolKey, ToolView } from '@coze-agent-ide/tool';
import { useDataSetArea } from '@coze-agent-ide/space-bot/hook';
import {
ChatBackground,
DataMemory,
Setting as DataSetSetting,
settingAreaScrollId,
SuggestionBlock,
} from '@coze-agent-ide/space-bot/component';
import { PluginApisArea } from '@coze-agent-ide/plugin-area-adapter';
import { OnboardingMessage } from '@coze-agent-ide/onboarding-message-adapter';
import s from '../../../../index.module.less';
import { SkillsModal } from '../../../../components/shortcut-skills-modal';
export interface ToolAreaProps {
isAllToolHidden: boolean;
skillToolSlot?: React.ReactNode;
knowledgeToolSlot?: React.ReactNode;
memoryToolSlot?: React.ReactNode;
dialogToolSlot?: React.ReactNode;
debugToolSlot?: React.ReactNode;
extraToolSlot?: React.ReactNode;
}
export const ToolArea: React.FC<ToolAreaProps> = props => {
const {
isAllToolHidden,
skillToolSlot,
knowledgeToolSlot,
memoryToolSlot,
dialogToolSlot,
extraToolSlot,
} = props;
const { node: DataSetArea, initRef: DataSetAreaRef } = useDataSetArea();
const modelId = useModelStore(state => state.config.model);
return (
<LayoutContext value={{ placement: PlacementEnum.CENTER }}>
<div
className={classNames(s['setting-area'], 'coz-bg-plus', {
[s['tool-hidden']]: isAllToolHidden,
})}
>
<div className="p-[12px] overflow-auto flex-1" id={settingAreaScrollId}>
<ToolView>
<GroupingContainer
title={I18n.t('bot_edit_type_skills')}
toolGroupKey={ToolGroupKey.SKILL}
>
{/* 工具 */}
<PluginApisArea
toolKey={ToolKey.PLUGIN}
title={I18n.t('Plugins')}
/>
{/* Workflow */}
<WorkflowCard
flowMode={WorkflowMode.Workflow}
toolKey={ToolKey.WORKFLOW}
title={I18n.t('Workflows')}
from={WorkflowModalFrom.BotSkills}
/>
{skillToolSlot}
</GroupingContainer>
<GroupingContainer
toolGroupKey={ToolGroupKey.KNOWLEDGE}
title={I18n.t('bot_edit_type_knowledge')}
actionNodes={<DataSetSetting modelId={modelId ?? ''} />}
>
{/* 知识库 */}
<DataSetArea
initRef={DataSetAreaRef}
toolKey={ToolKey.DOCUMENT}
title={I18n.t('dataset_detail_type_text')}
desc={I18n.t('bot_ide_knowledge_text_desc')}
formatType={FormatType.Text}
/>
<DataSetArea
initRef={DataSetAreaRef}
toolKey={ToolKey.TABLE}
title={I18n.t('dataset_detail_type_table')}
formatType={FormatType.Table}
desc={I18n.t('bot_ide_knowledge_table_desc')}
/>
<DataSetArea
initRef={DataSetAreaRef}
toolKey={ToolKey.PHOTO}
title={I18n.t('knowledge_photo_025')}
formatType={FormatType.Image}
desc={I18n.t('knowledge_photo_027')}
/>
{knowledgeToolSlot}
</GroupingContainer>
<GroupingContainer
toolGroupKey={ToolGroupKey.MEMORY}
title={I18n.t('bot_edit_type_memory')}
>
{/* 变量存储 */}
<DataMemory
toolKey={ToolKey.VARIABLE}
title={I18n.t('user_profile')}
/>
{memoryToolSlot}
</GroupingContainer>
<GroupingContainer
toolGroupKey={ToolGroupKey.DIALOG}
title={I18n.t('bot_edit_type_dialog')}
>
{/* 开场白 */}
<OnboardingMessage
toolKey={ToolKey.ONBOARDING}
title={I18n.t('bot_preview_opening_remarks')}
/>
{/* suggestion 开关 */}
<SuggestionBlock
toolKey={ToolKey.SUGGEST}
title={I18n.t('bot_edit_suggestion')}
/>
{/* 快捷键shortcut */}
<ShortcutToolConfig
skillModal={SkillsModal}
toolKey={ToolKey.SHORTCUT}
botMode={BotMode.SingleMode}
title={I18n.t('bot_ide_shortcut')}
/>
{/* 聊天背景图片 */}
<ChatBackground
toolKey={ToolKey.BACKGROUND}
title={I18n.t('bgi_title')}
/>
{dialogToolSlot}
</GroupingContainer>
{extraToolSlot}
</ToolView>
</div>
</div>
</LayoutContext>
);
};

View File

@@ -0,0 +1,249 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type ReactNode } from 'react';
import { useShallow } from 'zustand/react/shallow';
import classNames from 'classnames';
import { ResizableLayout } from '@coze-studio/components';
import { usePageRuntimeStore } from '@coze-studio/bot-detail-store/page-runtime';
import { useBotSkillStore } from '@coze-studio/bot-detail-store/bot-skill';
import { useBotDetailIsReadonly } from '@coze-studio/bot-detail-store';
import { I18n } from '@coze-arch/i18n';
import { BotPageFromEnum } from '@coze-arch/bot-typings/common';
import {
IconBotMultiLeftBtnIcon,
IconBotMultiRightBtnIcon,
} from '@coze-arch/bot-icons';
import { LayoutContext, PlacementEnum } from '@coze-arch/bot-hooks';
import { BotMode, TabStatus } from '@coze-arch/bot-api/developer_api';
import { WorkflowConfigArea } from '@coze-agent-ide/workflow';
import { ToolGroupKey } from '@coze-agent-ide/tool-config';
import {
GroupingContainer,
AbilityAreaContainer,
ToolKey,
ToolView,
} from '@coze-agent-ide/tool';
import { useBotPageStore } from '@coze-agent-ide/space-bot/store';
import {
DataMemory,
settingAreaScrollId,
ChatBackground,
SheetView,
ContentView,
BotDebugPanel,
} from '@coze-agent-ide/space-bot/component';
import { OnboardingMessage } from '@coze-agent-ide/onboarding-message-adapter';
import { BotDebugChatArea } from '@coze-agent-ide/chat-debug-area';
import { BotConfigArea } from '@coze-agent-ide/bot-config-area-adapter';
import s from '../../index.module.less';
export interface WorkflowModeProps {
rightSheetSlot?: ReactNode;
memoryToolSlot?: ReactNode;
dialogToolSlot?: ReactNode;
renderChatTitleNode?: (params: {
pageFrom: BotPageFromEnum | undefined;
showBackground: boolean;
}) => ReactNode;
chatSlot?: ReactNode;
chatHeaderClassName?: string;
chatAreaReadOnly?: boolean;
}
// eslint-disable-next-line @coze-arch/max-line-per-function
export const WorkflowMode: React.FC<WorkflowModeProps> = ({
rightSheetSlot,
memoryToolSlot,
dialogToolSlot,
renderChatTitleNode,
chatSlot,
chatHeaderClassName,
chatAreaReadOnly,
}) => {
const { isInit, editable, historyVisible, pageFrom, defaultAllHidden } =
usePageRuntimeStore(
useShallow(state => ({
editable: state.editable,
isInit: state.init,
historyVisible: state.historyVisible,
pageFrom: state.pageFrom,
defaultAllHidden: !Object.values(
state.botSkillBlockCollapsibleState,
).some(val => val !== TabStatus.Hide),
})),
);
const { showBackground } = useBotSkillStore(
useShallow(({ backgroundImageInfoList }) => ({
showBackground: Boolean(
backgroundImageInfoList?.[0]?.mobile_background_image?.origin_image_url,
),
})),
);
const modeSwitching = useBotPageStore(state => state.bot.modeSwitching);
const isReadonly = useBotDetailIsReadonly();
const toolArea = (
<div className="overflow-hidden h-full flex">
<LayoutContext value={{ placement: PlacementEnum.CENTER }}>
<div
className={classNames(s['setting-area'], 'coz-bg-plus', {
[s['tool-hidden']]: defaultAllHidden,
})}
>
<div
className="px-[28px] py-[16px] overflow-auto flex-1"
id={settingAreaScrollId}
>
<ToolView>
<WorkflowConfigArea />
<div className="mx-[-28px] my-[16px] border-0 border-b border-solid coz-stroke-primary" />
<GroupingContainer
toolGroupKey={ToolGroupKey.MEMORY}
title={I18n.t('bot_edit_type_memory')}
>
{/* 变量存储 */}
<DataMemory
toolKey={ToolKey.VARIABLE}
title={I18n.t('user_profile')}
/>
{memoryToolSlot}
</GroupingContainer>
<GroupingContainer
toolGroupKey={ToolGroupKey.DIALOG}
title={I18n.t('bot_edit_type_dialog')}
>
{/* 开场白 */}
<OnboardingMessage
toolKey={ToolKey.ONBOARDING}
title={I18n.t('bot_preview_opening_remarks')}
/>
{/* 聊天背景图片 */}
<ChatBackground
toolKey={ToolKey.BACKGROUND}
title={I18n.t('bgi_title')}
/>
{dialogToolSlot}
</GroupingContainer>
</ToolView>
</div>
</div>
</LayoutContext>
</div>
);
const leftSheet = (
<SheetView
headerClassName={classNames([
'coz-bg-plus',
'coz-fg-secondary',
s['sheet-view-left-header'],
s['sheet-view-new-header'],
])}
mode={BotMode.WorkflowMode}
title={I18n.t('bot_build_title')}
titleNode={
<div className={s['sheet-title-node-cover']}>
<BotConfigArea pageFrom={pageFrom} editable={editable} />
</div>
}
slideProps={{
placement: 'left',
closeBtnTooltip: I18n.t('chatflow_develop_tooltip_hide'),
openBtnTooltip: I18n.t('chatflow_develop_tooltip_show'),
width: 400,
visible: true,
btnNode: <IconBotMultiLeftBtnIcon />,
}}
>
{toolArea}
</SheetView>
);
const rightSheet = (
<SheetView
mode={BotMode.WorkflowMode}
title={I18n.t('bot_preview_debug_title')}
titleClassName={showBackground ? '!coz-fg-images-white' : ''}
containerClassName={classNames(
s['bj-cover'],
showBackground && `${s['bj-img-cover']} `,
s['bj-single-cover'],
)}
headerClassName={classNames(
s['debug-chat-header-padding'],
`${s['border-cover']}`,
{
'!bg-transparent': showBackground,
},
chatHeaderClassName,
)}
slideProps={{
placement: 'right',
closeBtnTooltip: I18n.t('chatflow_preview_tooltip_hide'),
openBtnTooltip: I18n.t('chatflow_preview_tooltip_show'),
width: 400,
visible: true,
btnNode: <IconBotMultiRightBtnIcon />,
}}
titleNode={renderChatTitleNode?.({ pageFrom, showBackground })}
renderContent={headerNode => (
<div className={classNames(s['message-area'])}>
<BotDebugChatArea
headerNode={headerNode}
readOnly={chatAreaReadOnly}
/>
{chatSlot}
</div>
)}
/>
);
return (
<div
className={classNames(
s.container,
historyVisible && s['playground-neat'],
pageFrom === BotPageFromEnum.Store && s.store,
)}
>
<AbilityAreaContainer
enableToolHiddenMode
isReadonly={isReadonly}
mode={BotMode.WorkflowMode}
modeSwitching={modeSwitching}
isInit={isInit}
>
<ContentView mode={BotMode.WorkflowMode}>
<ResizableLayout
className="h-full"
hotZoneClassName={s['layout-hotzone']}
>
<div className="w-1/2 min-w-[610px]">{leftSheet}</div>
<div className="w-1/2 min-w-[480px]">{rightSheet}</div>
</ResizableLayout>
</ContentView>
{/* Debug调试台 */}
<BotDebugPanel />
{rightSheetSlot}
</AbilityAreaContainer>
</div>
);
};