feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
18
frontend/packages/agent-ide/entry/src/modes/index.ts
Normal file
18
frontend/packages/agent-ide/entry/src/modes/index.ts
Normal 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';
|
||||
@@ -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"
|
||||
/>
|
||||
);
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user