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,38 @@
/*
* 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 BackgroundImageInfo } from '@coze-arch/bot-api/developer_api';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import type { BotSkillStore } from '@/store/bot-skill';
import { ItemTypeExtra } from '@/save-manager/types';
type RegisterChatBackgroundConfig = HostedObserverConfig<
BotSkillStore,
ItemTypeExtra,
BackgroundImageInfo[]
>;
export const chatBackgroundConfig: RegisterChatBackgroundConfig = {
key: ItemTypeExtra.ChatBackGround,
selector: store => store.backgroundImageInfoList,
debounce: DebounceTime.Immediate,
middleware: {
onBeforeSave: dataSource => ({
background_image_info_list: dataSource,
}),
},
};

View File

@@ -0,0 +1,48 @@
/*
* 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 HostedObserverConfig } from '@coze-studio/autosave';
import { type BotSkillStore } from '@/store/bot-skill';
import { type BizKey, type ScopeStateType } from '@/save-manager/types';
import { workflowsConfig } from './workflows';
import { voicesInfoConfig } from './voices-info';
import { variablesConfig } from './variables';
import { taskInfoConfig } from './task-info';
import { suggestionConfig } from './suggestion-config';
import { pluginConfig } from './plugin';
import { onboardingConfig } from './onboarding-content';
import { layoutInfoConfig } from './layout-info';
import { knowledgeConfig } from './knowledge';
import { chatBackgroundConfig } from './chat-background';
export const registers: HostedObserverConfig<
BotSkillStore,
BizKey,
ScopeStateType
>[] = [
pluginConfig,
chatBackgroundConfig,
onboardingConfig,
knowledgeConfig,
layoutInfoConfig,
suggestionConfig,
taskInfoConfig,
variablesConfig,
workflowsConfig,
voicesInfoConfig,
];

View File

@@ -0,0 +1,44 @@
/*
* 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 { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import type { KnowledgeConfig } from '@/types/skill';
import { type BotSkillStore, useBotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
type RegisterKnowledge = HostedObserverConfig<
BotSkillStore,
ItemType,
KnowledgeConfig
>;
export const knowledgeConfig: RegisterKnowledge = {
key: ItemType.DataSet,
selector: store => store.knowledge,
debounce: {
default: DebounceTime.Immediate,
'dataSetInfo.min_score': DebounceTime.Medium,
'dataSetInfo.top_k': DebounceTime.Medium,
},
middleware: {
onBeforeSave: dataSource => ({
knowledge: useBotSkillStore
.getState()
.transformVo2Dto.knowledge(dataSource),
}),
},
};

View File

@@ -0,0 +1,40 @@
/*
* 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 LayoutInfo } from '@coze-arch/idl/developer_api';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import { type BotSkillStore, useBotSkillStore } from '@/store/bot-skill';
import { ItemTypeExtra } from '@/save-manager/types';
type RegisterLayoutInfo = HostedObserverConfig<
BotSkillStore,
ItemTypeExtra,
LayoutInfo
>;
export const layoutInfoConfig: RegisterLayoutInfo = {
key: ItemTypeExtra.LayoutInfo,
selector: store => store.layoutInfo,
debounce: DebounceTime.Immediate,
middleware: {
onBeforeSave: layoutInfo => ({
layout_info: useBotSkillStore
.getState()
.transformVo2Dto.layoutInfo(layoutInfo),
}),
},
};

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 { type OnboardingInfo } from '@coze-arch/bot-api/playground_api';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import type { ExtendOnboardingContent } from '@/types/skill';
import { useBotSkillStore } from '@/store/bot-skill';
import type { BotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
type RegisterOnboardingContent = HostedObserverConfig<
BotSkillStore,
ItemType,
ExtendOnboardingContent
>;
export const onboardingConfig: RegisterOnboardingContent = {
key: ItemType.ONBOARDING,
selector: {
deps: [state => state.onboardingContent],
transformer: onboardingContent =>
useBotSkillStore.getState().transformVo2Dto.onboarding(onboardingContent),
},
debounce: {
default: DebounceTime.Immediate,
prologue: DebounceTime.Long,
suggested_questions: {
arrayType: true,
action: {
N: DebounceTime.Immediate,
D: DebounceTime.Immediate,
E: DebounceTime.Long,
},
},
},
middleware: {
onBeforeSave: (dataSource: OnboardingInfo) => ({
onboarding_info: dataSource,
}),
},
};

View File

@@ -0,0 +1,51 @@
/*
* 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 { cloneDeep } from 'lodash-es';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import type { EnabledPluginApi } from '@/types/skill';
import { type BotSkillStore, useBotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
type RegisterSystemContent = HostedObserverConfig<
BotSkillStore,
ItemType,
EnabledPluginApi[]
>;
export const pluginConfig: RegisterSystemContent = {
key: ItemType.APIINFO,
selector: store => store.pluginApis,
debounce: DebounceTime.Immediate,
middleware: {
onBeforeSave: dataSource => {
// 必须先深克隆,处理原数据会改动 store 的值
const clonePluginApis = cloneDeep(dataSource);
const newPluginApis = clonePluginApis.map(item => {
// ai生成动画仅生效一次请求接口时删除
delete item.autoAddCss;
return item;
});
return {
plugin_info_list: useBotSkillStore
.getState()
.transformVo2Dto.plugin(newPluginApis),
};
},
},
};

View File

@@ -0,0 +1,43 @@
/*
* 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 { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import type { BotSuggestionConfig } from '@/types/skill';
import { type BotSkillStore, useBotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
type RegisterSuggestionConfig = HostedObserverConfig<
BotSkillStore,
ItemType,
BotSuggestionConfig
>;
export const suggestionConfig: RegisterSuggestionConfig = {
key: ItemType.SUGGESTREPLY,
selector: store => store.suggestionConfig,
debounce: {
default: DebounceTime.Immediate,
customized_suggest_prompt: DebounceTime.Long,
},
middleware: {
onBeforeSave: dataSource => ({
suggest_reply_info: useBotSkillStore
.getState()
.transformVo2Dto.suggestionConfig(dataSource),
}),
},
};

View File

@@ -0,0 +1,35 @@
/*
* 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 { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import { type BotSkillStore, useBotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
type RegisterTaskInfo = HostedObserverConfig<BotSkillStore, ItemType, boolean>;
export const taskInfoConfig: RegisterTaskInfo = {
key: ItemType.TASK,
selector: store => store.taskInfo.user_task_allowed,
debounce: DebounceTime.Immediate,
middleware: {
onBeforeSave: dataSource => ({
task_info: useBotSkillStore.getState().transformVo2Dto.task({
user_task_allowed: dataSource,
}),
}),
},
};

View File

@@ -0,0 +1,60 @@
/*
* 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 { REPORT_EVENTS as ReportEventNames } from '@coze-arch/report-events';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import { CustomError } from '@coze-arch/bot-error';
import { uniqMemoryList } from '@/utils/uniq-memory-list';
import { type VariableItem, VariableKeyErrType } from '@/types/skill';
import { usePageRuntimeStore } from '@/store/page-runtime';
import { type BotSkillStore, useBotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
type RegisterVariables = HostedObserverConfig<
BotSkillStore,
ItemType,
VariableItem[]
>;
export const variablesConfig: RegisterVariables = {
key: ItemType.PROFILEMEMORY,
selector: store => store.variables,
debounce: DebounceTime.Immediate,
middleware: {
onBeforeSave: dataSource => {
const { editable } = usePageRuntimeStore.getState();
const filteredVariables = uniqMemoryList(dataSource).filter(i => {
const errType = i?.errType || VariableKeyErrType.KEY_CHECK_PASS;
return errType > VariableKeyErrType.KEY_CHECK_PASS;
});
if (!filteredVariables.length && editable) {
return {
variable_list: useBotSkillStore
.getState()
.transformVo2Dto.variables(dataSource),
};
}
throw new CustomError(
ReportEventNames.parmasValidation,
'botSkill.variables return nothing',
);
},
},
};

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 { merge } from 'lodash-es';
import { type BotInfoForUpdate } from '@coze-arch/idl/playground_api';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import { type TTSInfo, type VoicesInfo } from '@/types/skill';
import { transformVo2Dto } from '@/store/bot-skill/transform';
import { type BotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
interface Values {
voicesInfo: VoicesInfo;
tts: TTSInfo;
}
type RegisterVariables = HostedObserverConfig<BotSkillStore, ItemType, Values>;
export const voicesInfoConfig: RegisterVariables = {
key: ItemType.PROFILEMEMORY,
selector: store => ({ voicesInfo: store.voicesInfo, tts: store.tts }),
debounce: DebounceTime.Immediate,
middleware: {
// ! any warning 改动的时候要仔细
onBeforeSave: (
values: Values,
): Pick<Required<BotInfoForUpdate>, 'voices_info'> => ({
voices_info: merge(
{},
transformVo2Dto.tts(values.tts),
transformVo2Dto.voicesInfo(values.voicesInfo),
),
}),
},
};

View File

@@ -0,0 +1,50 @@
/*
* 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 { cloneDeep, uniqBy } from 'lodash-es';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import type { WorkFlowItemType } from '@/types/skill';
import { type BotSkillStore, useBotSkillStore } from '@/store/bot-skill';
import { ItemType } from '@/save-manager/types';
type RegisterWorkflows = HostedObserverConfig<
BotSkillStore,
ItemType,
WorkFlowItemType[]
>;
export const workflowsConfig: RegisterWorkflows = {
key: ItemType.WORKFLOW,
selector: store => store.workflows,
debounce: DebounceTime.Immediate,
middleware: {
onBeforeSave: (dataSource: WorkFlowItemType[]) => {
const workflowsToBackend = cloneDeep(dataSource);
const filterList = uniqBy(workflowsToBackend, 'workflow_id').map(v => {
// 解决加载图标的时候由于图标链接失效而报错不在这里保存会失效的workflow的plugin_icon而是每次都拉取最新的有效的图标链接
v.plugin_icon = '';
return v;
});
return {
workflow_info_list: useBotSkillStore
.getState()
.transformVo2Dto.workflow(filterList),
};
},
},
};

View File

@@ -0,0 +1,33 @@
/*
* 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 { AutosaveManager } from '@coze-studio/autosave';
import { useBotSkillStore, type BotSkillStore } from '@/store/bot-skill';
import { type BizKey, type ScopeStateType } from '@/save-manager/types';
import { saveRequest } from '../request';
import { registers } from './configs';
export const botSkillSaveManager = new AutosaveManager<
BotSkillStore,
BizKey,
ScopeStateType
>({
store: useBotSkillStore,
registers,
saveRequest,
});

View File

@@ -0,0 +1,36 @@
/*
* 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 { personaSaveManager } from './persona';
import { modelSaveManager } from './model';
import { botSkillSaveManager } from './bot-skill';
const managers = [personaSaveManager, botSkillSaveManager, modelSaveManager];
export const autosaveManager = {
start: () => {
console.log('start:>>');
managers.forEach(manager => {
manager.start();
});
},
close: () => {
console.log('close:>>');
managers.forEach(manager => {
manager.close();
});
},
};

View File

@@ -0,0 +1,43 @@
/*
* 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 ModelInfo } from '@coze-arch/bot-api/developer_api';
import { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import { type ModelStore, useModelStore } from '@/store/model';
import { ItemType } from '@/save-manager/types';
type RegisterSystemContent = HostedObserverConfig<
ModelStore,
ItemType,
ModelInfo
>;
export const modelConfig: RegisterSystemContent = {
key: ItemType.OTHERINFO,
selector: store => store.config,
debounce: {
default: DebounceTime.Immediate,
temperature: DebounceTime.Medium,
max_tokens: DebounceTime.Medium,
'ShortMemPolicy.HistoryRound': DebounceTime.Medium,
},
middleware: {
onBeforeSave: dataSource => ({
model_info: useModelStore.getState().transformVo2Dto(dataSource),
}),
},
};

View File

@@ -0,0 +1,34 @@
/*
* 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 ModelInfo } from '@coze-arch/bot-api/developer_api';
import { AutosaveManager } from '@coze-studio/autosave';
import { useModelStore, type ModelStore } from '@/store/model';
import { type BizKey } from '@/save-manager/types';
import { saveRequest } from '../request';
import { modelConfig } from './config';
export const modelSaveManager = new AutosaveManager<
ModelStore,
BizKey,
ModelInfo
>({
store: useModelStore,
registers: [modelConfig],
saveRequest,
});

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 { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import { ItemTypeExtra } from '../../types';
import type { Agent } from '../../../types/agent';
import { type MultiAgentStore } from '../../../store/multi-agent/store';
type RegisterSystemContent = HostedObserverConfig<
MultiAgentStore,
ItemTypeExtra,
Agent
>;
export const registerMultiAgentConfig: RegisterSystemContent = {
key: ItemTypeExtra.MultiAgent,
selector: state => state.agents?.[0],
debounce: {
default: DebounceTime.Immediate,
description: DebounceTime.Long,
'position.x': DebounceTime.Medium,
'position.y': DebounceTime.Medium,
'skills.knowledge.dataSetInfo.min_score': DebounceTime.Medium,
'skills.knowledge.dataSetInfo.top_k': DebounceTime.Medium,
'skills.knowledge.dataSetInfo.no_recall_reply_customize_prompt':
DebounceTime.Long,
'model.temperature': DebounceTime.Medium,
'model.max_tokens': DebounceTime.Medium,
'model.top_p': DebounceTime.Medium,
'model.ShortMemPolicy.HistoryRound': DebounceTime.Medium,
prompt: DebounceTime.Long, // agent 提示词
'suggestion.customized_suggest_prompt': DebounceTime.Long,
intents: { arrayType: true, action: { E: DebounceTime.Long } },
},
};

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 { useSpaceStore } from '@coze-arch/bot-studio-store';
import { PlaygroundApi } from '@coze-arch/bot-api';
import { AutosaveManager, type SaveRequest } from '@coze-studio/autosave';
import { storage } from '@/utils/storage';
import type { Agent } from '@/types/agent';
import {
type MultiAgentStore,
useMultiAgentStore,
} from '@/store/multi-agent/store';
import { useBotInfoStore } from '@/store/bot-info';
import { saveFetcher } from '../../utils/save-fetcher';
import { ItemTypeExtra } from '../../types';
import { registerMultiAgentConfig } from './config';
const saveRequestAgent: SaveRequest<Agent, ItemTypeExtra> = async (
payload: Agent,
) =>
await saveFetcher(() => {
const params = useMultiAgentStore.getState().transformVo2Dto.agent(payload);
return PlaygroundApi.UpdateAgentV2({
...params,
id: payload.id,
bot_id: useBotInfoStore.getState().botId,
space_id: useSpaceStore.getState().getSpaceId(),
base_commit_version: storage.baseVersion,
});
}, ItemTypeExtra.MultiAgent);
export const multiAgentSaveManager = new AutosaveManager<
MultiAgentStore,
ItemTypeExtra,
Agent
>({
store: useMultiAgentStore,
registers: [registerMultiAgentConfig],
saveRequest: saveRequestAgent,
});

View File

@@ -0,0 +1,51 @@
/*
* 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 { DebounceTime, type HostedObserverConfig } from '@coze-studio/autosave';
import {
usePersonaStore,
type PersonaStore,
type RequiredBotPrompt,
} from '@/store/persona';
import { ItemType } from '@/save-manager/types';
type RegisterSystemContent = HostedObserverConfig<
PersonaStore,
ItemType,
RequiredBotPrompt
>;
export const personaConfig: RegisterSystemContent = {
key: ItemType.SYSTEMINFO,
selector: state => state.systemMessage,
debounce: () => {
const { systemMessage } = usePersonaStore.getState();
const { isOptimize } = systemMessage;
console.log('systemMessage:>>', systemMessage);
console.log('isOptimize:>>', isOptimize);
if (isOptimize) {
return DebounceTime.Immediate;
}
return DebounceTime.Long;
},
middleware: {
onBeforeSave: nextState => ({
prompt_info: usePersonaStore.getState().transformVo2Dto(nextState),
}),
},
};

View File

@@ -0,0 +1,37 @@
/*
* 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 { AutosaveManager } from '@coze-studio/autosave';
import {
usePersonaStore,
type PersonaStore,
type RequiredBotPrompt,
} from '@/store/persona';
import { type ItemType } from '@/save-manager/types';
import { saveRequest } from '../request';
import { personaConfig } from './config';
export const personaSaveManager = new AutosaveManager<
PersonaStore,
ItemType,
RequiredBotPrompt
>({
store: usePersonaStore,
registers: [personaConfig],
saveRequest,
});

View File

@@ -0,0 +1,46 @@
/*
* 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 { PlaygroundApi } from '@coze-arch/bot-api';
import { type SaveRequest } from '@coze-studio/autosave';
import { storage } from '@/utils/storage';
import { useBotInfoStore } from '@/store/bot-info';
import { type BizKey, type ScopeStateType } from '@/save-manager/types';
import { saveFetcher } from '../utils/save-fetcher';
/**
* 自动保存统一请求方法
*/
export const saveRequest: SaveRequest<ScopeStateType, BizKey> = async (
payload: ScopeStateType,
itemType: BizKey,
) => {
const { botId } = useBotInfoStore.getState();
await saveFetcher(
async () =>
await PlaygroundApi.UpdateDraftBotInfoAgw({
bot_info: {
bot_id: botId,
...payload,
},
base_commit_version: storage.baseVersion,
}),
itemType,
);
};

View File

@@ -0,0 +1,39 @@
/*
* 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 { autosaveManager } from './auto-save/index';
export { personaSaveManager } from './auto-save/persona';
export { botSkillSaveManager } from './auto-save/bot-skill';
export { multiAgentSaveManager } from './auto-save/multi-agent';
export { modelSaveManager } from './auto-save/model';
export { registerMultiAgentConfig } from './auto-save/multi-agent/config';
export { updateBotRequest } from './utils/save-fetcher';
export { saveFileboxMode } from './manual-save/filebox';
export {
saveConnectorType,
saveDeleteAgents,
saveUpdateAgents,
saveMultiAgentData,
} from './manual-save/multi-agent';
export { saveTableMemory } from './manual-save/memory-table';
export { saveTTSConfig } from './manual-save/tts';
export { saveDevHooksConfig } from './manual-save/dev-hooks';
export { updateShortcutSort } from './manual-save/shortcuts';
export { updateQueryCollect } from './manual-save/query-collect';
export { saveTimeCapsule } from './manual-save/time-capsule';
export { getBotDetailDtoInfo } from './utils/bot-dto-info';
export { ItemTypeExtra } from './types';

View File

@@ -0,0 +1,29 @@
/*
* 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 HookInfo } from '@coze-arch/idl/playground_api';
import { ItemType } from '@coze-arch/bot-api/developer_api';
import { saveFetcher, updateBotRequest } from '../utils/save-fetcher';
export const saveDevHooksConfig = async (hooksInfo: HookInfo) =>
saveFetcher(
() =>
updateBotRequest({
hook_info: hooksInfo,
}),
ItemType.HOOKINFO,
);

View File

@@ -0,0 +1,41 @@
/*
* 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 FileboxInfoMode,
ItemType,
} from '@coze-arch/bot-api/developer_api';
import { useBotSkillStore } from '@/store/bot-skill';
import { saveFetcher, updateBotRequest } from '../utils/save-fetcher';
export const saveFileboxMode = async (nextMode: FileboxInfoMode) => {
const { filebox: fileboxConfig } = useBotSkillStore.getState();
return await saveFetcher(
() =>
updateBotRequest({
filebox_info: useBotSkillStore
.getState()
.transformVo2Dto.filebox(
fileboxConfig?.mode ? fileboxConfig : { mode: nextMode },
),
}),
ItemType.TABLE,
);
};

View File

@@ -0,0 +1,35 @@
/*
* 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 { ItemType } from '@coze-arch/bot-api/developer_api';
import { useBotSkillStore } from '@/store/bot-skill';
import { saveFetcher, updateBotRequest } from '../utils/save-fetcher';
export async function saveTableMemory() {
const { databaseList } = useBotSkillStore.getState();
return await saveFetcher(
() =>
updateBotRequest({
database_list: useBotSkillStore
.getState()
.transformVo2Dto.databaseList(databaseList),
}),
ItemType.TABLE,
);
}

View File

@@ -0,0 +1,96 @@
/*
* 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 { useSpaceStore } from '@coze-arch/bot-studio-store';
import { type MultiAgentConnectorType } from '@coze-arch/bot-api/playground_api';
import { PlaygroundApi } from '@coze-arch/bot-api';
import { type LineType } from '@flowgram-adapter/free-layout-editor';
import { storage } from '@/utils/storage';
import type { Agent } from '@/types/agent';
import { useMultiAgentStore } from '@/store/multi-agent';
import { useBotInfoStore } from '@/store/bot-info';
import { saveFetcher } from '../utils/save-fetcher';
import { ItemTypeExtra } from '../types';
// skill结构化的接口
export async function saveUpdateAgents(agent: Agent) {
return await saveFetcher(
() =>
PlaygroundApi.UpdateAgentV2({
...useMultiAgentStore.getState().transformVo2Dto.agent(agent),
bot_id: useBotInfoStore.getState().botId,
space_id: useSpaceStore.getState().getSpaceId(),
base_commit_version: storage.baseVersion,
}),
ItemTypeExtra.MultiAgent,
);
}
export async function saveDeleteAgents(deleteAgentId: string) {
return await saveFetcher(
() =>
PlaygroundApi.UpdateAgentV2({
bot_id: useBotInfoStore.getState().botId,
space_id: useSpaceStore.getState().getSpaceId(),
id: deleteAgentId,
is_delete: true,
base_commit_version: storage.baseVersion,
}),
ItemTypeExtra.MultiAgent,
);
}
export function saveDeleteAgentsV3(deleteAgentId: string) {
return saveFetcher(
() =>
PlaygroundApi.UpdateAgentV2({
bot_id: useBotInfoStore.getState().botId,
space_id: useSpaceStore.getState().getSpaceId(),
id: deleteAgentId,
is_delete: true,
base_commit_version: storage.baseVersion,
}),
ItemTypeExtra.MultiAgent,
);
}
export async function saveMultiAgentData() {
return await saveFetcher(
() =>
PlaygroundApi.UpdateMultiAgent({
space_id: useSpaceStore.getState().getSpaceId(),
bot_id: useBotInfoStore.getState().botId,
session_type: useMultiAgentStore.getState().chatModeConfig.type,
base_commit_version: storage.baseVersion,
}),
ItemTypeExtra.MultiAgent,
);
}
export async function saveConnectorType(connectorType: LineType) {
return await saveFetcher(
() =>
PlaygroundApi.UpdateMultiAgent({
space_id: useSpaceStore.getState().getSpaceId(),
bot_id: useBotInfoStore.getState().botId,
connector_type: connectorType as unknown as MultiAgentConnectorType,
base_commit_version: storage.baseVersion,
}),
ItemTypeExtra.ConnectorType,
);
}

View File

@@ -0,0 +1,38 @@
/*
* 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 UpdateDraftBotInfoAgwResponse } from '@coze-arch/idl/playground_api';
import { type UserQueryCollectConf } from '@coze-arch/bot-api/developer_api';
import { saveFetcher, updateBotRequest } from '../utils/save-fetcher';
import { ItemTypeExtra } from '../types';
export const updateQueryCollect = async (
queryCollectConf: UserQueryCollectConf,
) => {
// @ts-expect-error -- linter-disable-autofix
let updateResult: UpdateDraftBotInfoAgwResponse = null;
await saveFetcher(async () => {
const res = await updateBotRequest({
user_query_collect_conf: queryCollectConf,
});
updateResult = res;
return res;
}, ItemTypeExtra.QueryCollect);
return updateResult;
};

View File

@@ -0,0 +1,28 @@
/*
* 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 { saveFetcher, updateBotRequest } from '../utils/save-fetcher';
import { ItemTypeExtra } from '../types';
export const updateShortcutSort = async (shortcutSort: string[]) =>
await saveFetcher(
() =>
updateBotRequest({
shortcut_sort: shortcutSort,
}),
ItemTypeExtra.Shortcut,
);

View File

@@ -0,0 +1,36 @@
/*
* 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 { useBotSkillStore } from '@/store/bot-skill';
import { saveFetcher, updateBotRequest } from '../utils/save-fetcher';
import { ItemTypeExtra } from '../types';
export async function saveTimeCapsule() {
const { timeCapsule, transformVo2Dto } = useBotSkillStore.getState();
return await saveFetcher(
() =>
updateBotRequest({
bot_tag_info: transformVo2Dto.timeCapsule({
time_capsule_mode: timeCapsule.time_capsule_mode,
disable_prompt_calling: timeCapsule.disable_prompt_calling,
time_capsule_time_to_live: timeCapsule.time_capsule_time_to_live,
}),
}),
ItemTypeExtra.TimeCapsule,
);
}

View File

@@ -0,0 +1,56 @@
/*
* 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 { cloneDeep, merge } from 'lodash-es';
import { useBotSkillStore } from '@/store/bot-skill';
import { saveFetcher, updateBotRequest } from '../utils/save-fetcher';
import { ItemTypeExtra } from '../types';
export const saveTTSConfig = async () => {
const { tts, transformVo2Dto, voicesInfo } = useBotSkillStore.getState();
const {
muted = false,
close_voice_call = false,
i18n_lang_voice = {},
autoplay = false,
autoplay_voice = {},
i18n_lang_voice_str,
} = tts;
const cloneVoiceInfo = {
muted,
close_voice_call,
i18n_lang_voice: cloneDeep(i18n_lang_voice),
autoplay,
autoplay_voice: cloneDeep(autoplay_voice),
i18n_lang_voice_str: cloneDeep(i18n_lang_voice_str),
};
return await saveFetcher(
() =>
updateBotRequest({
voices_info: merge(
{},
transformVo2Dto.tts(cloneVoiceInfo),
transformVo2Dto.voicesInfo(voicesInfo),
),
}),
ItemTypeExtra.TTS,
);
};

View File

@@ -0,0 +1,35 @@
/*
* 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 @typescript-eslint/no-explicit-any */
import { ItemType } from '@coze-arch/bot-api/developer_api';
// 走自动保存update接口的scope服务端会维护ItemType其他scope前端维护在ItemTypeExtra中
export enum ItemTypeExtra {
MultiAgent = 1024,
TTS = 1025,
ConnectorType = 1026,
ChatBackGround = 1027,
Shortcut = 1028,
QueryCollect = 1029,
LayoutInfo = 1030,
TaskInfo = 1031,
TimeCapsule = 1032,
}
export type BizKey = ItemType | ItemTypeExtra | undefined;
export type ScopeStateType = any;
export { ItemType };

View File

@@ -0,0 +1,114 @@
/*
* 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 { merge } from 'lodash-es';
import {
REPORT_EVENTS as ReportEventNames,
createReportEvent,
} from '@coze-arch/report-events';
import {
type VoicesInfo,
type BotInfoForUpdate,
} from '@coze-arch/idl/playground_api';
import { BotMode } from '@coze-arch/bot-api/developer_api';
import { type RemoveOptional, type UnionUndefined } from '@/types/utils';
import { useQueryCollectStore } from '@/store/query-collect';
import { usePersonaStore } from '@/store/persona';
import { useMultiAgentStore } from '@/store/multi-agent';
import { useModelStore } from '@/store/model';
import { useBotSkillStore } from '@/store/bot-skill';
import { useBotInfoStore } from '@/store/bot-info';
export const getBotDetailDtoInfo = () => {
const { mode } = useBotInfoStore.getState();
const botSkill = useBotSkillStore.getState();
const multiAgent = useMultiAgentStore.getState();
const model = useModelStore.getState();
const persona = usePersonaStore.getState();
const queryCollect = useQueryCollectStore.getState();
const isMulti = mode === BotMode.MultiMode;
const {
knowledge,
variables,
workflows,
taskInfo,
suggestionConfig,
onboardingContent,
pluginApis,
backgroundImageInfoList,
shortcut,
tts,
timeCapsule,
filebox,
devHooks,
voicesInfo,
} = botSkill;
const { agents } = multiAgent;
const reportEvent = createReportEvent({
eventName: ReportEventNames.botDebugSaveAll,
});
try {
const botSkillInfo: Omit<BotInfoForUpdate, 'voices_info'> & {
voices_info: UnionUndefined<RemoveOptional<VoicesInfo>>;
} = {
prompt_info: persona.transformVo2Dto(persona.systemMessage),
model_info: model.transformVo2Dto(model.config),
plugin_info_list: isMulti
? undefined
: botSkill.transformVo2Dto.plugin(pluginApis),
workflow_info_list: isMulti
? undefined
: botSkill.transformVo2Dto.workflow(workflows),
knowledge: isMulti
? undefined
: botSkill.transformVo2Dto.knowledge(knowledge),
variable_list: botSkill.transformVo2Dto.variables(variables),
task_info: botSkill.transformVo2Dto.task(taskInfo),
suggest_reply_info:
botSkill.transformVo2Dto.suggestionConfig(suggestionConfig),
onboarding_info: botSkill.transformVo2Dto.onboarding(onboardingContent),
background_image_info_list: backgroundImageInfoList,
shortcut_sort: botSkill.transformVo2Dto.shortcut(shortcut),
voices_info: merge(
{},
botSkill.transformVo2Dto.tts(tts),
botSkill.transformVo2Dto.voicesInfo(voicesInfo),
),
bot_tag_info: botSkill.transformVo2Dto.timeCapsule(timeCapsule),
filebox_info: botSkill.transformVo2Dto.filebox(filebox),
hook_info: isMulti ? undefined : devHooks,
user_query_collect_conf: queryCollect.transformVo2Dto(queryCollect),
agents: isMulti
? agents.map(item => multiAgent.transformVo2Dto.agent(item))
: undefined,
};
reportEvent.success();
return { botSkillInfo };
} catch (e) {
reportEvent.error({
reason: 'bot debug save all fail',
error: e instanceof Error ? e : void 0,
});
return {};
}
};

View File

@@ -0,0 +1,99 @@
/*
* 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 dayjs from 'dayjs';
import { REPORT_EVENTS as ReportEventNames } from '@coze-arch/report-events';
import { reporter } from '@coze-arch/logger';
import { type BotInfoForUpdate } from '@coze-arch/idl/playground_api';
import { BotPageFromEnum } from '@coze-arch/bot-typings/common';
import { type UpdateDraftBotResponse } from '@coze-arch/bot-api/developer_api';
import { PlaygroundApi } from '@coze-arch/bot-api';
import { useBotInfoStore } from '@/store/bot-info';
import { type BizKey } from '../types';
import { storage } from '../../utils/storage';
import { usePageRuntimeStore } from '../../store/page-runtime';
import { useCollaborationStore } from '../../store/collaboration';
export async function saveFetcher(
saveRequest: () => Promise<UpdateDraftBotResponse>,
scopeKey: BizKey,
) {
const { editable, isPreview, pageFrom, init, setPageRuntimeByImmer } =
usePageRuntimeStore.getState();
const { setCollaborationByImmer } = useCollaborationStore.getState();
const isReadonly = () =>
!editable || isPreview || pageFrom === BotPageFromEnum.Explore;
if (isReadonly() || !init) {
return;
}
try {
setPageRuntimeByImmer(state => {
state.savingInfo.saving = true;
state.savingInfo.scopeKey = scopeKey ? String(scopeKey) : '';
});
const res = await saveRequest();
setPageRuntimeByImmer(state => {
state.savingInfo = {
saving: false,
time: dayjs().format('HH:mm:ss'),
};
});
if (res) {
setPageRuntimeByImmer(state => {
state.hasUnpublishChange = res.data.has_change ?? false;
});
setCollaborationByImmer(state => {
state.sameWithOnline = res.data.same_with_online ?? false;
if (state.branch && res.data.branch) {
state.branch = res.data.branch;
}
});
}
reporter.successEvent({
eventName: ReportEventNames.AutosaveSuccess,
meta: { itemType: scopeKey },
});
} catch (e) {
reporter.errorEvent({
eventName: ReportEventNames.AutosaveError,
error: e as Error,
meta: { itemType: scopeKey },
});
}
}
/**
* 更新bot草稿信息的结构
* @returns 根据标记返回使用不同请求体的更新bot
*/
export function updateBotRequest(structPayload: BotInfoForUpdate) {
const { botId } = useBotInfoStore.getState();
return PlaygroundApi.UpdateDraftBotInfoAgw({
bot_info: {
bot_id: botId,
...structPayload,
},
base_commit_version: storage.baseVersion,
});
}