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,93 @@
/*
* 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 FC, type ReactNode } from 'react';
import { useShallow } from 'zustand/react/shallow';
import { I18n } from '@coze-arch/i18n';
import { Popover } from '@coze-arch/bot-semi';
import { CollapsibleIconButton } from '@coze-studio/components/collapsible-icon-button';
import { InputSlider } from '@coze-studio/components';
import { useModelStore } from '@coze-studio/bot-detail-store/model';
import { ModelFormItem } from '@coze-agent-ide/model-manager';
import { IconCozChatSetting } from '@coze-arch/coze-design/icons';
const DialogueConfig: FC<{ tips: ReactNode }> = ({ tips }) => {
const { model, setModelByImmer } = useModelStore(
useShallow(state => ({
model: state,
setModelByImmer: state.setModelByImmer,
})),
);
const handleChange = (value: number) => {
setModelByImmer(draft => {
if (!draft.config.ShortMemPolicy) {
draft.config.ShortMemPolicy = { HistoryRound: value };
return;
}
draft.config.ShortMemPolicy.HistoryRound = value;
});
};
return (
<div className="p-[24px]">
<div className="leading-[32px] coz-fg-plus text-[20px] font-[500]">
{I18n.t('workflow_agent_dialog_set')}
</div>
{tips ? (
<div className="mt-[16px] coz-fg-secondary text-[14px] leading-[20px]">
{tips}
</div>
) : null}
<div className="mt-[16px] coz-fg-plus text-[14px] leading-[20px] font-[500]">
{I18n.t('workflow_agent_dialog_set_chathistory')}
</div>
<ModelFormItem
popoverContent={I18n.t('model_config_history_round_explain')}
label={I18n.t('model_config_history_round')}
>
<InputSlider
step={1}
min={0}
max={100}
decimalPlaces={0}
value={model.config.ShortMemPolicy?.HistoryRound}
onChange={handleChange}
/>
</ModelFormItem>
</div>
);
};
const itemKey = Symbol.for('DialogueConfigView');
export const DialogueConfigView: FC<{
tips: ReactNode;
}> = ({ tips }) => (
<Popover
className="overflow-hidden rounded-[12px] w-[600px]"
trigger="click"
autoAdjustOverflow={true}
content={<DialogueConfig tips={tips} />}
>
<CollapsibleIconButton
itemKey={itemKey}
data-testid="bot.ide.bot_creator.set_model_view_button"
icon={<IconCozChatSetting className="text-[16px]" />}
text={I18n.t('workflow_agent_dialog_set')}
/>
</Popover>
);

View File

@@ -0,0 +1,19 @@
/*
* 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 { DialogueConfigView } from './dialogue-config-view';
export { SingleAgentModelView } from './single-agent-model-view';
export { ModelConfigView } from './model-config-view';

View File

@@ -0,0 +1,49 @@
/*
* 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 { BotMode } from '@coze-arch/bot-api/playground_api';
import { useGetSingleAgentCurrentModel } from '@coze-agent-ide/model-manager';
import { SingleAgentModelView } from './single-agent-model-view';
import { DialogueConfigView } from './dialogue-config-view';
export const ModelConfigView: React.FC<{
mode: BotMode;
modelListExtraHeaderSlot?: React.ReactNode;
}> = ({ mode, modelListExtraHeaderSlot }) => {
const currentModel = useGetSingleAgentCurrentModel();
if (mode === BotMode.SingleMode) {
return currentModel?.model_type ? (
<SingleAgentModelView
modelListExtraHeaderSlot={modelListExtraHeaderSlot}
/>
) : null;
}
if (mode === BotMode.MultiMode || mode === BotMode.WorkflowMode) {
return (
<DialogueConfigView
tips={
mode === BotMode.WorkflowMode
? I18n.t('workflow_agent_dialog_set_desc')
: null
}
/>
);
}
return null;
};

View File

@@ -0,0 +1,128 @@
/*
* 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 { useEffect, useState } from 'react';
import { useShallow } from 'zustand/react/shallow';
import { useModelStore } from '@coze-studio/bot-detail-store/model';
import { useBotDetailIsReadonly } from '@coze-studio/bot-detail-store';
import { useSpaceStore } from '@coze-arch/bot-studio-store';
import { type Model } from '@coze-arch/bot-api/developer_api';
import { ModelSelect } from '@coze-agent-ide/model-manager/model-select-v2';
import {
useModelCapabilityCheckModal,
useGetSingleAgentCurrentModel,
getModelOptionList,
} from '@coze-agent-ide/model-manager';
import { useBotEditor } from '@coze-agent-ide/bot-editor-context-store';
import {
useBotCreatorContext,
BotCreatorScene,
} from '@coze-agent-ide/bot-creator-context';
export interface SingleAgentModelViewProps {
modelListExtraHeaderSlot?: React.ReactNode;
triggerRender?: (model?: Model, popoverVisible?: boolean) => React.ReactNode;
}
export function SingleAgentModelView(props: SingleAgentModelViewProps) {
const { modelListExtraHeaderSlot, triggerRender } = props;
const spaceId = useSpaceStore(store => store.space.id);
const { scene } = useBotCreatorContext();
const currentModel = useGetSingleAgentCurrentModel();
const currentModelId = currentModel?.model_type
? String(currentModel.model_type)
: undefined;
const { storeSet } = useBotEditor();
const modelStore = storeSet.useModelStore(
useShallow(state => ({
onlineModelList: state.onlineModelList,
offlineModelMap: state.offlineModelMap,
getModelPreset: state.getModelPreset,
})),
);
const [currentModelIdState, setCurrentModelIdState] = useState<
string | undefined
>(currentModelId);
const { modelConfig, setModelByImmer } = useModelStore(
useShallow(state => ({
modelConfig: state.config,
setModelByImmer: state.setModelByImmer,
})),
);
const { modalNode, checkAndOpenModal } = useModelCapabilityCheckModal({
onOk: modelId => {
setCurrentModelIdState(modelId);
},
});
const isReadonly = useBotDetailIsReadonly();
const modelList = getModelOptionList({
onlineModelList: modelStore.onlineModelList,
offlineModelMap: modelStore.offlineModelMap,
currentModelId: String(currentModel?.model_type),
});
useEffect(() => {
setCurrentModelIdState(currentModelId);
}, [currentModelId]);
return currentModelIdState ? (
<>
<ModelSelect
popoverClassName="h-auto !max-h-[70vh]"
disabled={isReadonly}
enableJumpDetail={
scene === BotCreatorScene.Bot && spaceId && !IS_OPEN_SOURCE
? { spaceId }
: undefined
}
modelListExtraHeaderSlot={modelListExtraHeaderSlot}
selectedModelId={currentModelIdState}
modelList={modelList}
onModelChange={m => {
const modelId = String(m.model_type);
const checkPassed = checkAndOpenModal(modelId);
if (checkPassed) {
setCurrentModelIdState(modelId);
}
return checkPassed;
}}
modelConfigProps={{
hideDiversityCollapseButton: true,
agentType: 'single',
currentConfig: modelConfig,
onConfigChange: v => {
setModelByImmer(draft => {
draft.config = {
model: currentModelIdState,
...v,
};
});
},
modelStore,
}}
triggerRender={triggerRender}
modalSlot={modalNode}
/>
</>
) : null;
}