feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
17
frontend/packages/studio/stores/bot-detail/src/global.d.ts
vendored
Normal file
17
frontend/packages/studio/stores/bot-detail/src/global.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/// <reference types='@coze-arch/bot-typings' />
|
||||
@@ -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 { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import { getBotDetailIsReadonlyByState } from '../utils/get-read-only';
|
||||
import { usePageRuntimeStore } from '../store/page-runtime';
|
||||
import { useCollaborationStore } from '../store/collaboration';
|
||||
|
||||
export const useBotDetailIsReadonly = (): boolean => {
|
||||
const { editable, isPreview } = usePageRuntimeStore(
|
||||
useShallow(state => ({
|
||||
editable: state.editable,
|
||||
isPreview: state.isPreview,
|
||||
})),
|
||||
);
|
||||
const editLockStatus = useCollaborationStore(state => state.editLockStatus);
|
||||
return getBotDetailIsReadonlyByState({
|
||||
editable,
|
||||
isPreview,
|
||||
editLockStatus,
|
||||
});
|
||||
};
|
||||
@@ -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';
|
||||
|
||||
export const useChatBackgroundState = () => {
|
||||
const backgroundState = useBotSkillStore(s => s.backgroundImageInfoList);
|
||||
|
||||
const showBackground =
|
||||
!!backgroundState?.[0]?.mobile_background_image?.origin_image_url;
|
||||
const mobileBackGround =
|
||||
backgroundState?.[0]?.web_background_image?.origin_image_url;
|
||||
|
||||
const pcBackground =
|
||||
backgroundState?.[0]?.web_background_image?.origin_image_url;
|
||||
|
||||
return {
|
||||
showBackground,
|
||||
mobileBackGround,
|
||||
pcBackground,
|
||||
backgroundModeClassName: showBackground ? '!coz-fg-images-white' : '',
|
||||
};
|
||||
};
|
||||
80
frontend/packages/studio/stores/bot-detail/src/index.ts
Normal file
80
frontend/packages/studio/stores/bot-detail/src/index.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 { avatarBackgroundWebSocket } from './utils/avatar-background-socket';
|
||||
|
||||
export { useBotDetailIsReadonly } from './hooks/use-bot-detail-readonly';
|
||||
export {
|
||||
TTSInfo,
|
||||
type VariableItem,
|
||||
VariableKeyErrType,
|
||||
type TableMemoryItem,
|
||||
type SuggestQuestionMessage,
|
||||
type BotDetailSkill,
|
||||
type WorkFlowItemType,
|
||||
type DatabaseInfo,
|
||||
type DatabaseList,
|
||||
type KnowledgeConfig,
|
||||
type TagListType,
|
||||
type ExtendOnboardingContent,
|
||||
TimeCapsuleOptionsEnum,
|
||||
} from './types/skill';
|
||||
|
||||
export { updateHeaderStatus } from './utils/handle-status';
|
||||
export { initBotDetailStore } from './init/init-bot-detail-store';
|
||||
export { useBotDetailStoreSet } from './store/index';
|
||||
|
||||
export {
|
||||
autosaveManager,
|
||||
personaSaveManager,
|
||||
botSkillSaveManager,
|
||||
multiAgentSaveManager,
|
||||
registerMultiAgentConfig,
|
||||
getBotDetailDtoInfo,
|
||||
saveConnectorType,
|
||||
saveDeleteAgents,
|
||||
saveUpdateAgents,
|
||||
saveMultiAgentData,
|
||||
saveFileboxMode,
|
||||
saveTableMemory,
|
||||
saveTTSConfig,
|
||||
saveTimeCapsule,
|
||||
saveDevHooksConfig,
|
||||
updateShortcutSort,
|
||||
updateBotRequest,
|
||||
} from './save-manager';
|
||||
export { getBotDetailIsReadonly } from './utils/get-read-only';
|
||||
export { uniqMemoryList } from './utils/uniq-memory-list';
|
||||
|
||||
export { verifyBracesAndToast } from './utils/submit';
|
||||
export { storage } from './utils/storage';
|
||||
|
||||
export { findTargetAgent, findFirstAgentId } from './utils/find-agent';
|
||||
export { manuallySwitchAgent, deleteAgent } from './utils/handle-agent';
|
||||
export { type Agent, type BotMultiAgent, type DraftBotVo } from './types/agent';
|
||||
export { getReplacedBotPrompt } from './utils/save';
|
||||
export { getExecuteDraftBotRequestId } from './utils/execute-draft-bot-request-id';
|
||||
export { useManuallySwitchAgentStore } from './store/manually-switch-agent-store';
|
||||
export { useChatBackgroundState } from './hooks/use-chat-background-state';
|
||||
|
||||
export {
|
||||
DotStatus,
|
||||
GenerateAvatarModal,
|
||||
GenerateType,
|
||||
} from './types/generate-image';
|
||||
export { useGenerateImageStore } from './store/generate-image-store';
|
||||
export { initGenerateImageStore } from './init/init-generate-image';
|
||||
export { useMonetizeConfigStore } from './store/monetize-config-store';
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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,
|
||||
createReportEvent,
|
||||
} from '@coze-arch/report-events';
|
||||
import { type BotMonetizationConfigData } from '@coze-arch/idl/benefit';
|
||||
import { type GetDraftBotInfoAgwData } from '@coze-arch/bot-api/playground_api';
|
||||
import { type HistoryInfo } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import { useQueryCollectStore } from '../store/query-collect';
|
||||
import { usePersonaStore } from '../store/persona';
|
||||
import { usePageRuntimeStore } from '../store/page-runtime';
|
||||
import { useMultiAgentStore } from '../store/multi-agent';
|
||||
import { useMonetizeConfigStore } from '../store/monetize-config-store';
|
||||
import { useModelStore } from '../store/model';
|
||||
import { useBotDetailStoreSet } from '../store/index';
|
||||
import { useCollaborationStore } from '../store/collaboration';
|
||||
import { useBotSkillStore } from '../store/bot-skill';
|
||||
import { useBotInfoStore } from '../store/bot-info';
|
||||
import { useAuditInfoStore } from '../store/audit-info';
|
||||
import { getBotDataService } from '../services/get-bot-data-service';
|
||||
|
||||
export async function initBotDetailStore(params?: {
|
||||
version?: HistoryInfo['version'];
|
||||
scene?: 'bot' | 'market';
|
||||
}) {
|
||||
const { version, scene = 'bot' } = params ?? {};
|
||||
const getRecordEvent = createReportEvent({
|
||||
eventName: ReportEventNames.botDebugGetRecord,
|
||||
});
|
||||
const { botId, version: botInfoVersion } = useBotInfoStore.getState();
|
||||
const { setPageRuntimeBotInfo } = usePageRuntimeStore.getState();
|
||||
const { clear } = useBotDetailStoreSet;
|
||||
try {
|
||||
setPageRuntimeBotInfo({ init: false });
|
||||
const getBotInfoEvent = createReportEvent({
|
||||
eventName: ReportEventNames.botGetDraftBotInfo,
|
||||
});
|
||||
try {
|
||||
const { botData, monetizeConfig = {} } = await getBotDataService({
|
||||
scene,
|
||||
botId,
|
||||
customVersion: version,
|
||||
botInfoVersion,
|
||||
});
|
||||
// 处理bot草稿页特有字段
|
||||
if (scene === 'bot') {
|
||||
initBotSceneStore(botData, version);
|
||||
}
|
||||
// 初始化store set
|
||||
initBotDetailStoreSet(botData, monetizeConfig);
|
||||
getBotInfoEvent.success();
|
||||
} catch (e) {
|
||||
clear();
|
||||
getBotInfoEvent.error({
|
||||
reason: 'get new draft bot info fail',
|
||||
error: e instanceof Error ? e : void 0,
|
||||
});
|
||||
throw e;
|
||||
}
|
||||
|
||||
getRecordEvent.success();
|
||||
} catch (e) {
|
||||
getRecordEvent.error({
|
||||
reason: 'init fail',
|
||||
error: e instanceof Error ? e : void 0,
|
||||
});
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
const initBotSceneStore = (info: GetDraftBotInfoAgwData, version?: string) => {
|
||||
const { initStore: initPageRuntimeStore } = usePageRuntimeStore.getState();
|
||||
const { initStore: initCollaborationStore } =
|
||||
useCollaborationStore.getState();
|
||||
initPageRuntimeStore({
|
||||
...info,
|
||||
customVersion: version,
|
||||
});
|
||||
initCollaborationStore(info);
|
||||
};
|
||||
|
||||
const initBotDetailStoreSet = (
|
||||
botData: GetDraftBotInfoAgwData,
|
||||
monetizeConfig: BotMonetizationConfigData,
|
||||
) => {
|
||||
const { initStore: initBotInfoStore } = useBotInfoStore.getState();
|
||||
const { initStore: initPersonaStore } = usePersonaStore.getState();
|
||||
const { initStore: initModelStore } = useModelStore.getState();
|
||||
const { initStore: initBotSkillStore } = useBotSkillStore.getState();
|
||||
const { initStore: initMultiAgentStore } = useMultiAgentStore.getState();
|
||||
const { initStore: initMonetizeConfigStore } =
|
||||
useMonetizeConfigStore.getState();
|
||||
const { initStore: initQueryCollectStore } = useQueryCollectStore.getState();
|
||||
const { initStore: initAuditInfoStore } = useAuditInfoStore.getState();
|
||||
initBotInfoStore(botData);
|
||||
initPersonaStore(botData);
|
||||
initModelStore(botData);
|
||||
initBotSkillStore(botData);
|
||||
initMultiAgentStore(botData);
|
||||
// 设置信息付费信息
|
||||
initMonetizeConfigStore(monetizeConfig);
|
||||
initQueryCollectStore(botData);
|
||||
initAuditInfoStore(botData);
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 { logger } from '@coze-arch/logger';
|
||||
import { getFlags } from '@coze-arch/bot-flags';
|
||||
import { PlaygroundApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { getBotDetailIsReadonly } from '../utils/get-read-only';
|
||||
import {
|
||||
getInitAvatarInfo,
|
||||
getInitBackgroundInfo,
|
||||
} from '../utils/generate-image';
|
||||
import { initAvatarBackgroundWebSocket } from '../utils/avatar-background-socket';
|
||||
import { useGenerateImageStore } from '../store/generate-image-store';
|
||||
import { useBotInfoStore } from '../store/bot-info';
|
||||
|
||||
export const initGenerateImageStore = async () => {
|
||||
try {
|
||||
const {
|
||||
updateImageList,
|
||||
updateNoticeList,
|
||||
setGenerateAvatarModalByImmer,
|
||||
setGenerateBackgroundModalByImmer,
|
||||
clearGenerateImageStore,
|
||||
} = useGenerateImageStore.getState();
|
||||
const { botId } = useBotInfoStore.getState();
|
||||
|
||||
const isReadOnly = getBotDetailIsReadonly();
|
||||
const FLAGS = getFlags();
|
||||
|
||||
if (isReadOnly || !FLAGS['bot.studio.gif_avater_background']) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化一下,防止从创建页跳到编辑页把创建页的状态带过来
|
||||
clearGenerateImageStore();
|
||||
|
||||
const resp = await PlaygroundApi.GetPicTask({
|
||||
bot_id: botId,
|
||||
});
|
||||
const respData = resp?.data ?? {};
|
||||
const { tasks = [], notices = [] } = respData;
|
||||
updateImageList(tasks);
|
||||
updateNoticeList(notices);
|
||||
setGenerateAvatarModalByImmer(state => {
|
||||
getInitAvatarInfo(respData, state);
|
||||
});
|
||||
|
||||
setGenerateBackgroundModalByImmer(state => {
|
||||
getInitBackgroundInfo(respData, state);
|
||||
});
|
||||
|
||||
initAvatarBackgroundWebSocket();
|
||||
} catch (error) {
|
||||
const e = error instanceof Error ? error : new Error(error as string);
|
||||
logger.error({ error: e });
|
||||
}
|
||||
};
|
||||
@@ -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,
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
];
|
||||
@@ -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),
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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),
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -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),
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
}),
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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',
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -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),
|
||||
),
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -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),
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
});
|
||||
@@ -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 } },
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
});
|
||||
@@ -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),
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
});
|
||||
@@ -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,
|
||||
);
|
||||
};
|
||||
@@ -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';
|
||||
@@ -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,
|
||||
);
|
||||
@@ -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,
|
||||
);
|
||||
};
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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,
|
||||
);
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
@@ -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,
|
||||
);
|
||||
};
|
||||
@@ -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 };
|
||||
@@ -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 {};
|
||||
}
|
||||
};
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 GetBotVersionInfoData,
|
||||
GetBotVersionScene,
|
||||
type GetDraftBotInfoAgwData,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
import {
|
||||
MonetizationEntityType,
|
||||
type BotMonetizationConfigData,
|
||||
} from '@coze-arch/bot-api/benefit';
|
||||
import { benefitApi, PlaygroundApi } from '@coze-arch/bot-api';
|
||||
|
||||
export const getBotDataService = async (params: {
|
||||
scene: 'bot' | 'market';
|
||||
botId: string;
|
||||
customVersion?: string;
|
||||
botInfoVersion: string;
|
||||
}): Promise<{
|
||||
botData: GetDraftBotInfoAgwData;
|
||||
monetizeConfig: BotMonetizationConfigData | undefined;
|
||||
}> => {
|
||||
const { scene, botId, customVersion, botInfoVersion } = params;
|
||||
if (scene === 'bot') {
|
||||
const [botInfoResp, monetizeConfigResp] = await getBotSceneData({
|
||||
botId,
|
||||
version: customVersion ?? '',
|
||||
});
|
||||
return {
|
||||
botData: getCommonBotData(botInfoResp?.data ?? {}),
|
||||
monetizeConfig: monetizeConfigResp?.data,
|
||||
};
|
||||
}
|
||||
const botInfoResp = await getMarketSceneData({
|
||||
botId,
|
||||
version: botInfoVersion,
|
||||
});
|
||||
return {
|
||||
botData: getCommonBotData(botInfoResp?.data ?? {}),
|
||||
monetizeConfig: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const getBotSceneData = async (params: { botId: string; version: string }) => {
|
||||
const { botId, version } = params;
|
||||
return await Promise.all([
|
||||
PlaygroundApi.GetDraftBotInfoAgw({
|
||||
bot_id: botId,
|
||||
version,
|
||||
}),
|
||||
IS_OVERSEA
|
||||
? benefitApi.PublicGetBotMonetizationConfig({
|
||||
entity_id: botId,
|
||||
entity_type: MonetizationEntityType.Bot,
|
||||
})
|
||||
: Promise.resolve(undefined),
|
||||
]);
|
||||
};
|
||||
|
||||
const getMarketSceneData = async (params: {
|
||||
botId: string;
|
||||
version: string;
|
||||
}) => {
|
||||
const { botId, version } = params;
|
||||
return await PlaygroundApi.GetBotVersionInfo({
|
||||
bot_id: botId,
|
||||
version: version ?? '',
|
||||
scene: GetBotVersionScene.BotStore,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCommonBotData = (
|
||||
botData: GetDraftBotInfoAgwData | GetBotVersionInfoData,
|
||||
): GetDraftBotInfoAgwData => {
|
||||
let commonBotData: GetDraftBotInfoAgwData = {
|
||||
bot_info: {},
|
||||
};
|
||||
if ('bot_info' in botData) {
|
||||
commonBotData = botData;
|
||||
}
|
||||
if ('bot_version_info' in botData) {
|
||||
commonBotData = {
|
||||
bot_info: botData.bot_version_info?.common_bot_info ?? {},
|
||||
};
|
||||
}
|
||||
return commonBotData;
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
import { type AuditInfo } from '@coze-arch/idl/playground_api';
|
||||
import { type GetDraftBotInfoAgwData } from '@coze-arch/bot-api/playground_api';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../utils/setter-factory';
|
||||
|
||||
export const getDefaultAuditInfoStore = (): AuditInfoStore => ({
|
||||
audit_status: 1,
|
||||
});
|
||||
|
||||
export type AuditInfoStore = AuditInfo;
|
||||
|
||||
export interface AuditInfoAction {
|
||||
setAuditInfo: SetterAction<AuditInfoStore>;
|
||||
setAuditInfoByImmer: (update: (state: AuditInfoStore) => void) => void;
|
||||
initStore: (botData: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useAuditInfoStore = create<AuditInfoStore & AuditInfoAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultAuditInfoStore(),
|
||||
setAuditInfo: setterActionFactory<AuditInfoStore>(set),
|
||||
setAuditInfoByImmer: update =>
|
||||
set(produce<AuditInfoStore>(auditInfo => update(auditInfo))),
|
||||
initStore: botData => {
|
||||
const { setAuditInfo } = get();
|
||||
botData && setAuditInfo(botData?.latest_audit_info ?? {});
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultAuditInfoStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.auditInfo',
|
||||
},
|
||||
),
|
||||
);
|
||||
160
frontend/packages/studio/stores/bot-detail/src/store/bot-info.ts
Normal file
160
frontend/packages/studio/stores/bot-detail/src/store/bot-info.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
import {
|
||||
type BotInfo,
|
||||
type GetDraftBotInfoAgwData,
|
||||
type UserInfo,
|
||||
type BusinessType,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
import {
|
||||
BotMarketStatus,
|
||||
BotMode,
|
||||
type ConnectorInfo,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../utils/setter-factory';
|
||||
|
||||
export const getDefaultBotInfoStore = (): BotInfoStore => ({
|
||||
botId: '',
|
||||
mode: BotMode.SingleMode,
|
||||
botMarketStatus: BotMarketStatus.Offline,
|
||||
name: '',
|
||||
description: '',
|
||||
icon_uri: '',
|
||||
icon_url: '',
|
||||
create_time: '',
|
||||
creator_id: '',
|
||||
update_time: '',
|
||||
connector_id: '',
|
||||
publisher: {},
|
||||
has_publish: false,
|
||||
connectors: [],
|
||||
publish_time: '',
|
||||
space_id: '',
|
||||
version: '',
|
||||
raw: {},
|
||||
});
|
||||
|
||||
/** 定义bot的基础信息*/
|
||||
export interface BotInfoStore {
|
||||
botId: string;
|
||||
/** 发布的业务线详情 */
|
||||
connectors: Array<ConnectorInfo>;
|
||||
/** for前端,发布时间 */
|
||||
publish_time: string;
|
||||
/** 空间id */
|
||||
space_id: string;
|
||||
/** 是否已发布 */
|
||||
has_publish: boolean;
|
||||
mode: BotMode;
|
||||
/** 最新发布版本时传发布人 */
|
||||
publisher: UserInfo;
|
||||
/** bot上架后的商品状态 */
|
||||
botMarketStatus: BotMarketStatus;
|
||||
/** bot名称 */
|
||||
name: string;
|
||||
/** bot描述 */
|
||||
description: string;
|
||||
/** bot 图标uri */
|
||||
icon_uri: string;
|
||||
/** bot 图标url */
|
||||
icon_url: string;
|
||||
/** 创建时间 */
|
||||
create_time: string;
|
||||
/** 创建人id */
|
||||
creator_id: string;
|
||||
/** 更新时间 */
|
||||
update_time: string;
|
||||
/** 业务线 */
|
||||
connector_id: string;
|
||||
/** multi agent mode agent信息 */
|
||||
// agents?: Array<Agent>;
|
||||
/** 版本,毫秒 */
|
||||
version: string;
|
||||
/** multi_agent结构体 */
|
||||
// multi_agent_info?: MultiAgentInfo;
|
||||
/** @ 保存了原始bot数据, readonly **/
|
||||
raw: BotInfo;
|
||||
/** 抖音分身应用id */
|
||||
appId?: string;
|
||||
/** 业务类型 默认0 分身业务1 */
|
||||
businessType?: BusinessType;
|
||||
}
|
||||
|
||||
export interface BotInfoAction {
|
||||
setBotInfo: SetterAction<BotInfoStore>;
|
||||
setBotInfoByImmer: (update: (state: BotInfoStore) => void) => void;
|
||||
transformVo2Dto: (data: GetDraftBotInfoAgwData) => BotInfoStore;
|
||||
initStore: (data: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useBotInfoStore = create<BotInfoStore & BotInfoAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultBotInfoStore(),
|
||||
setBotInfo: setterActionFactory<BotInfoStore>(set),
|
||||
setBotInfoByImmer: update =>
|
||||
set(produce<BotInfoStore>(state => update(state))),
|
||||
// eslint-disable-next-line complexity
|
||||
transformVo2Dto: data => {
|
||||
// 将botData转化为botInfoStore, 只取BotInfoStore中的固定字段
|
||||
const botInfo = data.bot_info ?? {};
|
||||
return {
|
||||
botId: botInfo?.bot_id ?? '',
|
||||
mode: botInfo?.bot_mode ?? BotMode.SingleMode,
|
||||
botMarketStatus: data.bot_market_status ?? BotMarketStatus.Offline,
|
||||
name: botInfo.name ?? '',
|
||||
description: botInfo.description ?? '',
|
||||
icon_uri: botInfo.icon_uri ?? '',
|
||||
icon_url: botInfo.icon_url ?? '',
|
||||
create_time: botInfo.create_time ?? '',
|
||||
creator_id: botInfo.creator_id ?? '',
|
||||
update_time: botInfo.update_time ?? '',
|
||||
connector_id: botInfo.connector_id ?? '',
|
||||
version: botInfo.version ?? '',
|
||||
publisher: data.publisher ?? {},
|
||||
has_publish: data.has_publish ?? false,
|
||||
connectors: data.connectors ?? [],
|
||||
publish_time: data.publish_time ?? '',
|
||||
space_id: data.space_id ?? '',
|
||||
businessType: botInfo.business_type,
|
||||
appId: data.app_id ?? '',
|
||||
raw: botInfo,
|
||||
};
|
||||
},
|
||||
initStore: data => {
|
||||
const { transformVo2Dto } = get();
|
||||
const transformedData = transformVo2Dto(data);
|
||||
set(transformedData);
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultBotInfoStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.botInfo',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -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 { I18n } from '@coze-arch/i18n';
|
||||
import { BotTableRWMode } from '@coze-arch/bot-api/memory';
|
||||
import {
|
||||
type BackgroundImageInfo,
|
||||
SuggestedQuestionsShowMode,
|
||||
SuggestReplyMode,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import {
|
||||
type VoicesInfo,
|
||||
type BotSuggestionConfig,
|
||||
type DatabaseInfo,
|
||||
type ExtendOnboardingContent,
|
||||
type TimeCapsuleConfig,
|
||||
type TTSInfo,
|
||||
} from '../../types/skill';
|
||||
|
||||
export const DEFAULT_KNOWLEDGE_CONFIG = () => {
|
||||
const baseConfig = {
|
||||
top_k: 3,
|
||||
min_score: 0.5,
|
||||
auto: true,
|
||||
search_strategy: 0,
|
||||
show_source: false,
|
||||
};
|
||||
return baseConfig;
|
||||
};
|
||||
|
||||
export const DEFAULT_BOT_NODE_SUGGESTION_CONFIG = (): BotSuggestionConfig => ({
|
||||
suggest_reply_mode: SuggestReplyMode.UseOriginBotMode,
|
||||
customized_suggest_prompt: '',
|
||||
});
|
||||
|
||||
export const DEFAULT_SUGGESTION_PROMPT = () =>
|
||||
IS_OVERSEA
|
||||
? I18n.t('bot_suggestion_customize_default_gpt')
|
||||
: I18n.t('bot_suggestion_customize_default_seed');
|
||||
|
||||
export const DEFAULT_ONBOARDING_CONFIG = (): ExtendOnboardingContent => ({
|
||||
prologue: '',
|
||||
suggested_questions: [],
|
||||
suggested_questions_show_mode: SuggestedQuestionsShowMode.Random,
|
||||
});
|
||||
|
||||
export const DEFAULT_SUGGESTION_CONFIG = (): BotSuggestionConfig => ({
|
||||
suggest_reply_mode: SuggestReplyMode.WithDefaultPrompt,
|
||||
customized_suggest_prompt: '',
|
||||
});
|
||||
|
||||
export const DEFAULT_BACKGROUND_IMAGE_LIST = (): BackgroundImageInfo[] => [];
|
||||
export const DEFAULT_DATABASE = (): DatabaseInfo => ({
|
||||
tableId: '',
|
||||
name: '',
|
||||
desc: '',
|
||||
icon_uri: '',
|
||||
readAndWriteMode: BotTableRWMode.LimitedReadWrite,
|
||||
tableMemoryList: [],
|
||||
});
|
||||
export const DEFAULT_TTS_CONFIG = (): TTSInfo => ({
|
||||
muted: false,
|
||||
close_voice_call: false,
|
||||
i18n_lang_voice: {},
|
||||
autoplay: false,
|
||||
autoplay_voice: {},
|
||||
tag_list: [],
|
||||
debugVoice: [],
|
||||
i18n_lang_voice_str: {},
|
||||
});
|
||||
|
||||
export const DEFAULT_TIME_CAPSULE_CONFIG = (): TimeCapsuleConfig => ({
|
||||
time_capsule_mode: 0,
|
||||
disable_prompt_calling: 0, // 默认支持在prompt调用
|
||||
time_capsule_time_to_live: '0',
|
||||
});
|
||||
|
||||
export const DEFAULT_SHORTCUT_CONFIG = () => ({
|
||||
shortcut_list: [],
|
||||
shortcut_sort: [],
|
||||
});
|
||||
|
||||
export const DEFAULT_VOICES_INFO: () => VoicesInfo = () => ({
|
||||
defaultUserInputType: undefined,
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 {
|
||||
useBotSkillStore,
|
||||
getDefaultBotSkillStore,
|
||||
type BotSkillStore,
|
||||
type BotSkillAction,
|
||||
} from './store';
|
||||
export {
|
||||
DEFAULT_SUGGESTION_PROMPT,
|
||||
DEFAULT_KNOWLEDGE_CONFIG,
|
||||
} from './defaults';
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { isFunction } from 'lodash-es';
|
||||
import { produce } from 'immer';
|
||||
import { type ShortCutStruct } from '@coze-agent-ide/tool-config';
|
||||
import {
|
||||
type HookInfo,
|
||||
type LayoutInfo,
|
||||
type BackgroundImageInfo,
|
||||
type GetDraftBotInfoAgwData,
|
||||
} from '@coze-arch/bot-api/playground_api';
|
||||
import {
|
||||
type DefaultUserInputType,
|
||||
FileboxInfoMode,
|
||||
type PluginApi,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
import { botInputLengthService } from '@coze-agent-ide/bot-input-length-limit';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../../utils/setter-factory';
|
||||
import { getPluginApisFilterExample } from '../../utils/plugin-apis';
|
||||
import {
|
||||
type VoicesInfo,
|
||||
type BotSuggestionConfig,
|
||||
type DatabaseInfo,
|
||||
type DatabaseList,
|
||||
type EnabledPluginApi,
|
||||
type ExtendOnboardingContent,
|
||||
type FileboxConfig,
|
||||
type KnowledgeConfig,
|
||||
type TaskManageInfo,
|
||||
type TimeCapsuleConfig,
|
||||
type TTSInfo,
|
||||
type VariableItem,
|
||||
type WorkFlowItemType,
|
||||
} from '../../types/skill';
|
||||
import { transformDto2Vo, transformVo2Dto } from './transform';
|
||||
import {
|
||||
DEFAULT_BACKGROUND_IMAGE_LIST,
|
||||
DEFAULT_DATABASE,
|
||||
DEFAULT_KNOWLEDGE_CONFIG,
|
||||
DEFAULT_ONBOARDING_CONFIG,
|
||||
DEFAULT_SHORTCUT_CONFIG,
|
||||
DEFAULT_SUGGESTION_CONFIG,
|
||||
DEFAULT_TIME_CAPSULE_CONFIG,
|
||||
DEFAULT_TTS_CONFIG,
|
||||
DEFAULT_VOICES_INFO,
|
||||
} from './defaults';
|
||||
|
||||
export const getDefaultBotSkillStore = (): BotSkillStore => ({
|
||||
pluginApis: [],
|
||||
workflows: [],
|
||||
knowledge: {
|
||||
dataSetList: [],
|
||||
dataSetInfo: DEFAULT_KNOWLEDGE_CONFIG(),
|
||||
},
|
||||
|
||||
taskInfo: {
|
||||
user_task_allowed: false,
|
||||
data: [],
|
||||
task_list: [],
|
||||
loading: false,
|
||||
},
|
||||
variables: [],
|
||||
database: DEFAULT_DATABASE(),
|
||||
databaseList: [],
|
||||
onboardingContent: DEFAULT_ONBOARDING_CONFIG(),
|
||||
suggestionConfig: DEFAULT_SUGGESTION_CONFIG(),
|
||||
tts: DEFAULT_TTS_CONFIG(),
|
||||
voicesInfo: DEFAULT_VOICES_INFO(),
|
||||
timeCapsule: DEFAULT_TIME_CAPSULE_CONFIG(),
|
||||
filebox: {
|
||||
mode: FileboxInfoMode.Off,
|
||||
},
|
||||
backgroundImageInfoList: DEFAULT_BACKGROUND_IMAGE_LIST(),
|
||||
shortcut: DEFAULT_SHORTCUT_CONFIG(),
|
||||
layoutInfo: {},
|
||||
devHooks: {},
|
||||
});
|
||||
|
||||
/** Persona & Prompt 区域 */
|
||||
export interface BotSkillStore {
|
||||
// region Bot 和 Agent 维度共有 skills
|
||||
/** 已选的 plugin api */
|
||||
pluginApis: EnabledPluginApi[];
|
||||
/** 已选 workflow */
|
||||
workflows: WorkFlowItemType[];
|
||||
/** Knowledge 配置 */
|
||||
knowledge: KnowledgeConfig;
|
||||
// endregion
|
||||
|
||||
// region Bot 维度独有 skills
|
||||
/**
|
||||
* task 配置
|
||||
*
|
||||
* 不含已添加的 task,已添加的在组件内独立管理
|
||||
*/
|
||||
taskInfo: TaskManageInfo;
|
||||
/**
|
||||
* variable 默认值配置
|
||||
*
|
||||
* 不含右上角现值,现值为打开弹窗后请求获得的组件状态
|
||||
*/
|
||||
variables: VariableItem[];
|
||||
/**
|
||||
* database 默认值配置
|
||||
*
|
||||
* 不含右上角现值,现值为打开弹窗后请求获得的组件状态
|
||||
*/
|
||||
database: DatabaseInfo;
|
||||
/**
|
||||
* database 多表默认值配置
|
||||
*
|
||||
* 不含右上角现值,现值为打开弹窗后请求获得的组件状态
|
||||
*/
|
||||
databaseList: DatabaseList;
|
||||
/** 开场白配置 */
|
||||
onboardingContent: ExtendOnboardingContent;
|
||||
/** 用户问题建议配置 */
|
||||
suggestionConfig: BotSuggestionConfig;
|
||||
// endregion
|
||||
/** 文字转语音 */
|
||||
tts: TTSInfo;
|
||||
/** 语音设置 上面 tts 在命名和含义划分上已经不准确了 但是牵扯甚广 */
|
||||
voicesInfo: VoicesInfo;
|
||||
// 时间胶囊
|
||||
timeCapsule: TimeCapsuleConfig;
|
||||
filebox: FileboxConfig;
|
||||
// 聊天背景图
|
||||
backgroundImageInfoList: BackgroundImageInfo[];
|
||||
// 快捷指令
|
||||
shortcut: ShortCutStruct;
|
||||
// hooks
|
||||
devHooks?: HookInfo;
|
||||
layoutInfo: LayoutInfo;
|
||||
}
|
||||
|
||||
export interface BotSkillAction {
|
||||
setBotSkill: SetterAction<BotSkillStore>;
|
||||
setBotSkillByImmer: (update: (state: BotSkillStore) => void) => void;
|
||||
updateSkillPluginApis: (pluginApis: PluginApi[]) => void;
|
||||
updateSkillWorkflows: (workflows: WorkFlowItemType[]) => void;
|
||||
updateSkillKnowledgeDatasetList: (
|
||||
dataSetList: KnowledgeConfig['dataSetList'],
|
||||
) => void;
|
||||
updateSkillKnowledgeDatasetInfo: (
|
||||
dataSetInfo: KnowledgeConfig['dataSetInfo'],
|
||||
) => void;
|
||||
updateSkillTaskInfo: (taskInfo: Partial<TaskManageInfo>) => void;
|
||||
updateSkillDatabase: (database: Partial<DatabaseInfo>) => void;
|
||||
updateSkillDatabaseList: (database: DatabaseList) => void;
|
||||
updateSkillOnboarding: (
|
||||
onboarding:
|
||||
| Partial<ExtendOnboardingContent>
|
||||
| ((prev: ExtendOnboardingContent) => Partial<ExtendOnboardingContent>),
|
||||
) => void;
|
||||
updateSkillLayoutInfo: (layoutInfo: LayoutInfo) => void;
|
||||
setBackgroundImageInfoList: (params: BackgroundImageInfo[]) => void;
|
||||
setSuggestionConfig: (config: Partial<BotSuggestionConfig>) => void;
|
||||
setDefaultUserInputType: (type: DefaultUserInputType) => void;
|
||||
transformDto2Vo: typeof transformDto2Vo;
|
||||
transformVo2Dto: typeof transformVo2Dto;
|
||||
initStore: (botData: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useBotSkillStore = create<BotSkillStore & BotSkillAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultBotSkillStore(),
|
||||
|
||||
setBotSkill: setterActionFactory<BotSkillStore>(set),
|
||||
setBotSkillByImmer: update =>
|
||||
set(produce<BotSkillStore>(botSkill => update(botSkill))),
|
||||
updateSkillPluginApis: (pluginApis: PluginApi[]) => {
|
||||
set(s => ({
|
||||
...s,
|
||||
pluginApis: getPluginApisFilterExample(pluginApis),
|
||||
}));
|
||||
},
|
||||
updateSkillWorkflows: workflows => set(s => ({ ...s, workflows })),
|
||||
updateSkillKnowledgeDatasetList: dataSetList =>
|
||||
set(
|
||||
produce<BotSkillStore>(s => {
|
||||
s.knowledge.dataSetList = dataSetList;
|
||||
}),
|
||||
),
|
||||
updateSkillKnowledgeDatasetInfo: dataSetInfo =>
|
||||
set(
|
||||
produce<BotSkillStore>(s => {
|
||||
s.knowledge.dataSetInfo = dataSetInfo;
|
||||
}),
|
||||
),
|
||||
updateSkillTaskInfo: taskInfo =>
|
||||
set(s => ({
|
||||
...s,
|
||||
taskInfo: { ...s.taskInfo, ...taskInfo },
|
||||
})),
|
||||
updateSkillDatabase: database =>
|
||||
set(s => ({
|
||||
...s,
|
||||
database: { ...s.database, ...database },
|
||||
})),
|
||||
updateSkillDatabaseList: databaseList =>
|
||||
set(
|
||||
produce<BotSkillStore>(s => {
|
||||
s.databaseList = databaseList;
|
||||
}),
|
||||
),
|
||||
updateSkillOnboarding: update =>
|
||||
set(s => ({
|
||||
...s,
|
||||
onboardingContent: {
|
||||
...s.onboardingContent,
|
||||
...(isFunction(update) ? update(s.onboardingContent) : update),
|
||||
},
|
||||
})),
|
||||
updateSkillLayoutInfo: layoutInfo => {
|
||||
set(s => ({
|
||||
...s,
|
||||
layoutInfo,
|
||||
}));
|
||||
},
|
||||
setSuggestionConfig: config =>
|
||||
set(s => ({
|
||||
...s,
|
||||
suggestionConfig: { ...s.suggestionConfig, ...config },
|
||||
})),
|
||||
setBackgroundImageInfoList: config =>
|
||||
set(s => ({
|
||||
...s,
|
||||
backgroundImageInfoList: [...config],
|
||||
})),
|
||||
setDefaultUserInputType: inputType =>
|
||||
set(
|
||||
state =>
|
||||
produce(state, draft => {
|
||||
draft.voicesInfo.defaultUserInputType = inputType;
|
||||
}),
|
||||
false,
|
||||
'setDefaultUserInputType',
|
||||
),
|
||||
transformDto2Vo,
|
||||
transformVo2Dto,
|
||||
initStore: botData => {
|
||||
const { bot_info: botInfo, bot_option_data: optionData } = botData;
|
||||
set({
|
||||
pluginApis: transformDto2Vo.plugin(
|
||||
botInfo?.plugin_info_list,
|
||||
optionData?.plugin_detail_map,
|
||||
optionData?.plugin_api_detail_map,
|
||||
),
|
||||
workflows: transformDto2Vo.workflow(
|
||||
botInfo?.workflow_info_list,
|
||||
optionData?.workflow_detail_map,
|
||||
),
|
||||
knowledge: transformDto2Vo.knowledge(
|
||||
botInfo?.knowledge,
|
||||
optionData?.knowledge_detail_map,
|
||||
),
|
||||
taskInfo: transformDto2Vo.task(botInfo?.task_info),
|
||||
variables: transformDto2Vo.variables(botInfo?.variable_list),
|
||||
databaseList: transformDto2Vo.databaseList(botInfo?.database_list),
|
||||
timeCapsule: transformDto2Vo.timeCapsule(
|
||||
botInfo?.bot_tag_info?.time_capsule_info,
|
||||
),
|
||||
filebox: transformDto2Vo.filebox(botInfo?.filebox_info),
|
||||
|
||||
onboardingContent:
|
||||
botInputLengthService.sliceWorkInfoOnboardingByMaxLength(
|
||||
transformDto2Vo.onboarding(botInfo?.onboarding_info),
|
||||
),
|
||||
suggestionConfig: transformDto2Vo.suggestionConfig(
|
||||
botInfo?.suggest_reply_info,
|
||||
),
|
||||
tts: transformDto2Vo.tts(botInfo?.voices_info),
|
||||
voicesInfo: transformDto2Vo.voicesInfo(botInfo.voices_info),
|
||||
backgroundImageInfoList: botInfo?.background_image_info_list ?? [],
|
||||
shortcut: transformDto2Vo.shortcut(
|
||||
botInfo?.shortcut_sort ?? [],
|
||||
optionData?.shortcut_command_list,
|
||||
),
|
||||
devHooks: transformDto2Vo.hookInfo(botInfo?.hook_info),
|
||||
layoutInfo: transformDto2Vo.layoutInfo(botInfo?.layout_info),
|
||||
});
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultBotSkillStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.botSkill',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* 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 { nanoid } from 'nanoid';
|
||||
import { isNumber, mapValues } from 'lodash-es';
|
||||
import { type ShortCutStruct } from '@coze-agent-ide/tool-config';
|
||||
import {
|
||||
type PluginStatus,
|
||||
type PluginType,
|
||||
} from '@coze-arch/idl/plugin_develop';
|
||||
import { BotTableRWMode } from '@coze-arch/idl/memory';
|
||||
import {
|
||||
type Int64,
|
||||
type PluginInfo,
|
||||
type PluginDetal,
|
||||
type PluginAPIDetal,
|
||||
type WorkflowInfo,
|
||||
type WorkflowDetail,
|
||||
type Knowledge,
|
||||
type KnowledgeDetail,
|
||||
type TaskInfo,
|
||||
type Variable,
|
||||
type Database,
|
||||
type TimeCapsuleInfo,
|
||||
type OnboardingInfo,
|
||||
type SuggestReplyInfo,
|
||||
type VoicesInfo as IDLVoicesInfo,
|
||||
type FileboxInfo,
|
||||
FileboxInfoMode,
|
||||
TimeCapsuleMode,
|
||||
type ShortcutCommand,
|
||||
type BotInfoForUpdate,
|
||||
type SuggestReplyMode as SuggestReplyModeFromPlayground,
|
||||
type HookInfo,
|
||||
SuggestedQuestionsShowMode,
|
||||
type LayoutInfo,
|
||||
DisablePromptCalling,
|
||||
} from '@coze-arch/bot-api/playground_api';
|
||||
import { SuggestReplyMode } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import {
|
||||
type WorkFlowItemType,
|
||||
type EnabledPluginApi,
|
||||
type KnowledgeConfig,
|
||||
type TaskManageInfo,
|
||||
type VariableItem,
|
||||
type TimeCapsuleConfig,
|
||||
type ExtendOnboardingContent,
|
||||
type BotSuggestionConfig,
|
||||
type TTSInfo,
|
||||
type FileboxConfig,
|
||||
type DatabaseList,
|
||||
type TableMemoryItem,
|
||||
type VoicesInfo,
|
||||
} from '../../types/skill';
|
||||
import {
|
||||
DEFAULT_BOT_NODE_SUGGESTION_CONFIG,
|
||||
DEFAULT_KNOWLEDGE_CONFIG,
|
||||
DEFAULT_SUGGESTION_CONFIG,
|
||||
DEFAULT_SUGGESTION_PROMPT,
|
||||
DEFAULT_TTS_CONFIG,
|
||||
} from './defaults';
|
||||
|
||||
// 结构化 BotInfo 接口后的 数据转换
|
||||
export const transformDto2Vo = {
|
||||
plugin: (
|
||||
data?: PluginInfo[],
|
||||
plugins?: Record<Int64, PluginDetal>,
|
||||
pluginsAPIs?: Record<Int64, PluginAPIDetal>,
|
||||
): EnabledPluginApi[] =>
|
||||
data
|
||||
?.filter(i => i.plugin_id && i.api_id && plugins?.[i.plugin_id as string])
|
||||
?.map(item => {
|
||||
const plugin = plugins?.[item.plugin_id as string];
|
||||
const api = pluginsAPIs?.[item.api_id as string];
|
||||
return {
|
||||
plugin_icon: plugin?.icon_url,
|
||||
name: api?.name,
|
||||
desc: api?.description,
|
||||
plugin_id: item.plugin_id,
|
||||
plugin_name: plugin?.name,
|
||||
api_id: item.api_id,
|
||||
parameters:
|
||||
api?.parameters?.map(i => ({
|
||||
...i,
|
||||
// 兼容开源页接口字段命名不同
|
||||
desc: i.description,
|
||||
required: i.is_required,
|
||||
})) || [],
|
||||
is_official: plugin?.is_official,
|
||||
// 这个类型历史原因 在服务端侧各服务不统一,实际业务使用为 枚举类型
|
||||
plugin_type: plugin?.plugin_type as unknown as PluginType,
|
||||
status: plugin?.plugin_status as unknown as PluginStatus,
|
||||
};
|
||||
}) ?? [],
|
||||
|
||||
workflow: (
|
||||
data?: WorkflowInfo[],
|
||||
config?: Record<Int64, WorkflowDetail>,
|
||||
): WorkFlowItemType[] =>
|
||||
data
|
||||
?.filter(i => i.workflow_id && config?.[i.workflow_id])
|
||||
?.map(item => {
|
||||
const w = config?.[item.workflow_id as string];
|
||||
return {
|
||||
workflow_id: w?.id ?? '',
|
||||
plugin_id: w?.plugin_id ?? '',
|
||||
name: w?.name ?? '',
|
||||
desc: w?.description ?? '',
|
||||
plugin_icon: w?.icon_url ?? '',
|
||||
flow_mode: item?.flow_mode,
|
||||
parameters:
|
||||
w?.api_detail?.parameters?.map(i => ({
|
||||
...i,
|
||||
desc: i.description,
|
||||
required: i.is_required,
|
||||
})) || [],
|
||||
};
|
||||
}) ?? [],
|
||||
// 知识库
|
||||
knowledge: (
|
||||
data?: Knowledge,
|
||||
config?: Record<string, KnowledgeDetail>,
|
||||
): KnowledgeConfig => {
|
||||
if (!data) {
|
||||
return {
|
||||
dataSetList: [],
|
||||
dataSetInfo: DEFAULT_KNOWLEDGE_CONFIG(),
|
||||
};
|
||||
} else {
|
||||
const dataSetList =
|
||||
data?.knowledge_info
|
||||
?.filter(i => i.id && config?.[i.id as string])
|
||||
?.map(item => {
|
||||
const k = config?.[item.id as string];
|
||||
return {
|
||||
id: k?.id,
|
||||
name: k?.name,
|
||||
avatar_url: k?.icon_url,
|
||||
icon_url: k?.icon_url,
|
||||
dataset_id: k?.id,
|
||||
};
|
||||
}) ?? [];
|
||||
|
||||
return {
|
||||
dataSetList,
|
||||
dataSetInfo: {
|
||||
min_score: data?.min_score ?? 0,
|
||||
top_k: Number(data?.top_k ?? 0),
|
||||
auto: Boolean(data?.auto),
|
||||
|
||||
search_strategy: data?.search_strategy,
|
||||
no_recall_reply_mode: data?.no_recall_reply_mode,
|
||||
no_recall_reply_customize_prompt:
|
||||
data?.no_recall_reply_customize_prompt,
|
||||
show_source: data?.show_source,
|
||||
show_source_mode: data?.show_source_mode,
|
||||
recall_strategy: data.recall_strategy,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
task: (data?: TaskInfo): TaskManageInfo => ({
|
||||
user_task_allowed: Boolean(data?.user_task_allowed),
|
||||
task_list: [],
|
||||
loading: false,
|
||||
data: [],
|
||||
}),
|
||||
|
||||
variables: (data?: Variable[]): VariableItem[] =>
|
||||
data?.map(item => ({
|
||||
id: nanoid(),
|
||||
key: item.key ?? '',
|
||||
description: item.description,
|
||||
default_value: item.default_value,
|
||||
is_system: !!item.is_system,
|
||||
prompt_disabled: !!item.prompt_disabled,
|
||||
is_disabled: !!item.is_disabled,
|
||||
})) ?? [],
|
||||
|
||||
databaseList: (data?: Database[]): DatabaseList => {
|
||||
const res: DatabaseList = [];
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
data.forEach(target => {
|
||||
if (target?.table_id && target.field_list?.length) {
|
||||
res.push({
|
||||
tableId: target.table_id as string,
|
||||
name: target.table_name as string,
|
||||
desc: target.table_desc as string,
|
||||
extra_info: {
|
||||
prompt_disabled: String(target.prompt_disabled),
|
||||
},
|
||||
readAndWriteMode:
|
||||
(target.rw_mode as BotTableRWMode) ||
|
||||
BotTableRWMode.LimitedReadWrite,
|
||||
tableMemoryList: (target.field_list as TableMemoryItem[])?.map(
|
||||
i => ({
|
||||
...i,
|
||||
nanoid: nanoid(),
|
||||
// 服务端 rpc 已使用 string 的 id 难以修改,这里兼容一下后续链路需要的 number
|
||||
id: Number(i.id),
|
||||
}),
|
||||
),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return res;
|
||||
},
|
||||
|
||||
timeCapsule: (data?: TimeCapsuleInfo): TimeCapsuleConfig => ({
|
||||
//@ts-expect-error 接口枚举类型取值重定义
|
||||
time_capsule_mode: data?.time_capsule_mode ?? TimeCapsuleMode.Off,
|
||||
disable_prompt_calling:
|
||||
data?.disable_prompt_calling ?? DisablePromptCalling.Off,
|
||||
time_capsule_time_to_live: data?.time_capsule_time_to_live ?? '0',
|
||||
}),
|
||||
|
||||
filebox: (data?: FileboxInfo): FileboxConfig => ({
|
||||
mode: data?.Mode ?? FileboxInfoMode.Off,
|
||||
}),
|
||||
|
||||
onboarding: (data?: OnboardingInfo): ExtendOnboardingContent => ({
|
||||
prologue: data?.prologue ?? '',
|
||||
suggested_questions_show_mode:
|
||||
data?.suggested_questions_show_mode ?? SuggestedQuestionsShowMode.Random,
|
||||
suggested_questions:
|
||||
data?.suggested_questions?.map(item => ({
|
||||
id: item,
|
||||
content: item,
|
||||
})) ?? [],
|
||||
}),
|
||||
|
||||
suggestionConfig: (
|
||||
data?: SuggestReplyInfo,
|
||||
isBotNode = false,
|
||||
): BotSuggestionConfig => {
|
||||
const defaultSuggestionConfig: BotSuggestionConfig = isBotNode
|
||||
? DEFAULT_BOT_NODE_SUGGESTION_CONFIG()
|
||||
: DEFAULT_SUGGESTION_CONFIG();
|
||||
//@ts-expect-error xxxxxxxxxxxxx SuggestReplyMode 两个文件定义不一致
|
||||
const suggestionConfig: BotSuggestionConfig = isNumber(
|
||||
data?.suggest_reply_mode,
|
||||
)
|
||||
? {
|
||||
suggest_reply_mode: data?.suggest_reply_mode,
|
||||
customized_suggest_prompt: data?.customized_suggest_prompt,
|
||||
}
|
||||
: defaultSuggestionConfig;
|
||||
|
||||
if (
|
||||
!suggestionConfig.customized_suggest_prompt &&
|
||||
suggestionConfig.suggest_reply_mode ===
|
||||
SuggestReplyMode.WithCustomizedPrompt
|
||||
) {
|
||||
suggestionConfig.customized_suggest_prompt = DEFAULT_SUGGESTION_PROMPT();
|
||||
}
|
||||
return suggestionConfig;
|
||||
},
|
||||
|
||||
tts: (ttsConfig?: IDLVoicesInfo): TTSInfo => {
|
||||
if (!ttsConfig || typeof ttsConfig !== 'object') {
|
||||
return DEFAULT_TTS_CONFIG();
|
||||
}
|
||||
if (!('muted' in ttsConfig && 'i18n_lang_voice' in ttsConfig)) {
|
||||
return DEFAULT_TTS_CONFIG();
|
||||
}
|
||||
const isValidObject = (obj: unknown): Record<string, number> =>
|
||||
obj && typeof obj === 'object' ? (obj as Record<string, number>) : {};
|
||||
|
||||
return {
|
||||
muted: !!ttsConfig.muted,
|
||||
close_voice_call: !!ttsConfig.voice_call,
|
||||
i18n_lang_voice: isValidObject(ttsConfig?.i18n_lang_voice),
|
||||
i18n_lang_voice_str: ttsConfig.i18n_lang_voice_str ?? {},
|
||||
autoplay: !!ttsConfig.autoplay,
|
||||
autoplay_voice: isValidObject(ttsConfig?.autoplay_voice),
|
||||
debugVoice: [],
|
||||
};
|
||||
},
|
||||
voicesInfo: (idlVoicesInfo: IDLVoicesInfo | undefined): VoicesInfo => ({
|
||||
defaultUserInputType: idlVoicesInfo?.default_user_input_type,
|
||||
}),
|
||||
shortcut: (
|
||||
shortcutSortList: string[],
|
||||
config?: ShortcutCommand[],
|
||||
): ShortCutStruct => ({
|
||||
shortcut_sort: shortcutSortList,
|
||||
//@ts-expect-error ShortCutCommand 前后端定义不一致,前端分化做了类型约束
|
||||
shortcut_list: config,
|
||||
}),
|
||||
|
||||
hookInfo: (data?: HookInfo): HookInfo | undefined => data,
|
||||
layoutInfo: (layoutInfoFromService?: LayoutInfo): LayoutInfo => ({
|
||||
workflow_id: layoutInfoFromService?.workflow_id,
|
||||
plugin_id: layoutInfoFromService?.plugin_id,
|
||||
}),
|
||||
};
|
||||
|
||||
export const transformVo2Dto = {
|
||||
plugin: (plugins: EnabledPluginApi[]): BotInfoForUpdate['plugin_info_list'] =>
|
||||
plugins.map(plugin => ({
|
||||
api_id: plugin.api_id,
|
||||
plugin_id: plugin.plugin_id,
|
||||
api_name: plugin.name,
|
||||
})),
|
||||
|
||||
workflow: (
|
||||
workflows: WorkFlowItemType[],
|
||||
): BotInfoForUpdate['workflow_info_list'] =>
|
||||
workflows.map(
|
||||
w =>
|
||||
({
|
||||
workflow_id: w.workflow_id,
|
||||
plugin_id: w.plugin_id,
|
||||
flow_mode: w.flow_mode,
|
||||
workflow_name: w.name,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
}) as any,
|
||||
),
|
||||
|
||||
knowledge: (knowledge: KnowledgeConfig): BotInfoForUpdate['knowledge'] => ({
|
||||
...knowledge.dataSetInfo,
|
||||
knowledge_info: knowledge.dataSetList
|
||||
.filter(i => !!i.dataset_id)
|
||||
.map(dataset => ({
|
||||
id: dataset.dataset_id,
|
||||
name: dataset.name,
|
||||
})),
|
||||
}),
|
||||
|
||||
task: (task: Partial<TaskManageInfo>): BotInfoForUpdate['task_info'] => ({
|
||||
user_task_allowed: task.user_task_allowed,
|
||||
}),
|
||||
|
||||
suggestionConfig: (
|
||||
suggestion: BotSuggestionConfig,
|
||||
): BotInfoForUpdate['suggest_reply_info'] => ({
|
||||
suggest_reply_mode:
|
||||
suggestion.suggest_reply_mode as unknown as SuggestReplyModeFromPlayground,
|
||||
customized_suggest_prompt: suggestion.customized_suggest_prompt,
|
||||
}),
|
||||
|
||||
variables: (variables: VariableItem[]): BotInfoForUpdate['variable_list'] =>
|
||||
variables.map(v => ({
|
||||
key: v.key,
|
||||
description: v.description,
|
||||
default_value: v.default_value,
|
||||
is_system: v.is_system,
|
||||
prompt_disabled: v.prompt_disabled,
|
||||
is_disabled: v.is_disabled,
|
||||
})),
|
||||
|
||||
databaseList: (
|
||||
databaseList: DatabaseList,
|
||||
): BotInfoForUpdate['database_list'] =>
|
||||
databaseList.map(d => ({
|
||||
table_id: d.tableId,
|
||||
table_name: d.name,
|
||||
table_desc: d.desc,
|
||||
rw_mode: d.readAndWriteMode,
|
||||
field_list: d.tableMemoryList.map(f => ({
|
||||
name: f.name,
|
||||
desc: f.desc,
|
||||
type: f.type,
|
||||
must_required: f.must_required,
|
||||
id: f.id?.toString(),
|
||||
})),
|
||||
})),
|
||||
|
||||
timeCapsule: (
|
||||
timeCapsule: TimeCapsuleConfig,
|
||||
): BotInfoForUpdate['bot_tag_info'] => ({
|
||||
time_capsule_info: {
|
||||
time_capsule_mode:
|
||||
timeCapsule.time_capsule_mode as unknown as TimeCapsuleMode,
|
||||
disable_prompt_calling:
|
||||
timeCapsule.disable_prompt_calling as unknown as DisablePromptCalling,
|
||||
time_capsule_time_to_live: timeCapsule.time_capsule_time_to_live,
|
||||
},
|
||||
}),
|
||||
|
||||
filebox: (filebox: FileboxConfig): BotInfoForUpdate['filebox_info'] => ({
|
||||
Mode: filebox.mode,
|
||||
}),
|
||||
|
||||
onboarding: (
|
||||
data: ExtendOnboardingContent,
|
||||
): BotInfoForUpdate['onboarding_info'] => ({
|
||||
prologue: data.prologue,
|
||||
suggested_questions_show_mode: data.suggested_questions_show_mode,
|
||||
suggested_questions: data.suggested_questions
|
||||
.map(i => i.content?.trim())
|
||||
.filter(c => !!c),
|
||||
}),
|
||||
|
||||
tts: (tts: Partial<TTSInfo>) => ({
|
||||
muted: tts.muted,
|
||||
i18n_lang_voice: tts.i18n_lang_voice,
|
||||
autoplay: tts.autoplay,
|
||||
autoplay_voice: tts.autoplay_voice,
|
||||
voice_call: tts.close_voice_call,
|
||||
i18n_lang_voice_str: tts.i18n_lang_voice_str,
|
||||
}),
|
||||
|
||||
voicesInfo: (voicesInfo: VoicesInfo) => ({
|
||||
default_user_input_type: voicesInfo.defaultUserInputType,
|
||||
}),
|
||||
|
||||
shortcut: (shortcut: ShortCutStruct): BotInfoForUpdate['shortcut_sort'] =>
|
||||
shortcut.shortcut_sort,
|
||||
|
||||
layoutInfo: (info: LayoutInfo): BotInfoForUpdate['layout_info'] =>
|
||||
// undefined 会被 axios 过滤,这里后端需要有 key
|
||||
mapValues(info, (val?: string) => val ?? ''),
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 { logger } from '@coze-arch/logger';
|
||||
import { useSpaceStore } from '@coze-arch/bot-studio-store';
|
||||
import { SpaceType } from '@coze-arch/bot-api/developer_api';
|
||||
import { PlaygroundApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { getBotDetailIsReadonly } from '../utils/get-read-only';
|
||||
import { useBotInfoStore } from '../store/bot-info';
|
||||
import { useCollaborationStore } from './collaboration';
|
||||
|
||||
export const collaborateQuota = async () => {
|
||||
try {
|
||||
const { botId } = useBotInfoStore.getState();
|
||||
const { inCollaboration, setCollaboration } =
|
||||
useCollaborationStore.getState();
|
||||
const {
|
||||
space: { space_type },
|
||||
} = useSpaceStore.getState();
|
||||
const isPersonal = space_type === SpaceType.Personal;
|
||||
|
||||
const isReadOnly = getBotDetailIsReadonly();
|
||||
if (isReadOnly || isPersonal) {
|
||||
return;
|
||||
}
|
||||
const { data: collaborationQuota } =
|
||||
await PlaygroundApi.GetBotCollaborationQuota({
|
||||
bot_id: botId,
|
||||
});
|
||||
setCollaboration({
|
||||
// 多人协作模式,或非多人协作模式有额度时可启用
|
||||
openCollaboratorsEnable:
|
||||
(!inCollaboration && collaborationQuota?.open_collaborators_enable) ||
|
||||
inCollaboration,
|
||||
// 非多人协作模式 && 可以升级套餐,则展示升级套餐按钮
|
||||
canUpgrade: collaborationQuota?.can_upgrade || false,
|
||||
// 用户最大开启多人协作bot的数量限制
|
||||
maxCollaborationBotCount:
|
||||
collaborationQuota?.max_collaboration_bot_count || 0,
|
||||
maxCollaboratorsCount: collaborationQuota?.max_collaborators_count || 0,
|
||||
currentCollaborationBotCount:
|
||||
collaborationQuota.current_collaboration_bot_count || 0,
|
||||
});
|
||||
} catch (error) {
|
||||
const e = error instanceof Error ? error : new Error(error as string);
|
||||
logger.error({ error: e });
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
import {
|
||||
Branch,
|
||||
type GetDraftBotInfoAgwData,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
import { type BotCollaboratorStatus } from '@coze-arch/idl/developer_api';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../utils/setter-factory';
|
||||
|
||||
export const getDefaultCollaborationStore = (): CollaborationStore => ({
|
||||
inCollaboration: false,
|
||||
sameWithOnline: false,
|
||||
committer_name: '',
|
||||
editLockStatus: EditLockStatus.Offline,
|
||||
collaboratorStatus: {
|
||||
commitable: false,
|
||||
operateable: false,
|
||||
manageable: false,
|
||||
},
|
||||
baseVersion: '',
|
||||
branch: Branch.Base,
|
||||
commit_time: '',
|
||||
commit_version: '',
|
||||
openCollaboratorsEnable: false,
|
||||
canUpgrade: false,
|
||||
currentCollaborationBotCount: 0,
|
||||
maxCollaborationBotCount: 0,
|
||||
maxCollaboratorsCount: 0,
|
||||
});
|
||||
export enum EditLockStatus {
|
||||
Lose, // 无编辑锁
|
||||
Holder, // 有编辑锁
|
||||
Offline, // 断网状态,可编辑,但是不可保存。避免联网后覆盖掉断网期间其他页面的编辑
|
||||
}
|
||||
/**多人协作*/
|
||||
export interface CollaborationStore {
|
||||
editLockStatus: EditLockStatus;
|
||||
inCollaboration: boolean;
|
||||
collaboratorStatus: BotCollaboratorStatus;
|
||||
sameWithOnline: boolean;
|
||||
baseVersion: string;
|
||||
/** for前端,最近一次的提交人 */
|
||||
committer_name: string;
|
||||
/** 获取的是什么分支的内容 */
|
||||
branch?: Branch;
|
||||
/** for前端,提交时间 */
|
||||
commit_time: string;
|
||||
commit_version: string;
|
||||
/** 能否开启协作开关 false不可开启 */
|
||||
openCollaboratorsEnable: boolean;
|
||||
/** 是否可升级套餐 顶级付费账号不可升级 */
|
||||
canUpgrade: boolean;
|
||||
// 当前开启的协作bot数量
|
||||
currentCollaborationBotCount: number;
|
||||
/** 用户最大开启多人协作bot的数量限制 */
|
||||
maxCollaborationBotCount: number;
|
||||
/** 协作者数量上限 */
|
||||
maxCollaboratorsCount: number;
|
||||
}
|
||||
|
||||
export interface CollaborationAction {
|
||||
setCollaboration: SetterAction<CollaborationStore>;
|
||||
setCollaborationByImmer: (
|
||||
update: (state: CollaborationStore) => void,
|
||||
) => void;
|
||||
getBaseVersion: () => string | undefined;
|
||||
initStore: (data: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useCollaborationStore = create<
|
||||
CollaborationStore & CollaborationAction
|
||||
>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultCollaborationStore(),
|
||||
setCollaboration: setterActionFactory<CollaborationStore>(set),
|
||||
setCollaborationByImmer: update =>
|
||||
set(produce<CollaborationStore>(state => update(state))),
|
||||
getBaseVersion: () => {
|
||||
const { baseVersion, inCollaboration } = get();
|
||||
// FG开启且单人模式下,不提供 base_version
|
||||
if (!inCollaboration) {
|
||||
return undefined;
|
||||
}
|
||||
return baseVersion;
|
||||
},
|
||||
initStore: info => {
|
||||
set({
|
||||
collaboratorStatus: info?.collaborator_status,
|
||||
inCollaboration: info.in_collaboration,
|
||||
baseVersion: info.commit_version,
|
||||
sameWithOnline: info?.same_with_online,
|
||||
committer_name: info?.committer_name,
|
||||
commit_version: info?.commit_version,
|
||||
branch: info?.branch,
|
||||
commit_time: info?.commit_time,
|
||||
});
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultCollaborationStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.collaboration',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../utils/setter-factory';
|
||||
|
||||
export type DiffTaskType = 'prompt' | 'model' | '';
|
||||
|
||||
export const getDefaultDiffTaskStore = (): DiffTaskStore => ({
|
||||
diffTask: '',
|
||||
hasContinueTask: false,
|
||||
continueTask: '',
|
||||
promptDiffInfo: {
|
||||
diffPromptResourceId: '',
|
||||
diffMode: 'draft',
|
||||
diffPrompt: '',
|
||||
},
|
||||
});
|
||||
|
||||
/** diff任务相关信息 */
|
||||
export interface DiffTaskStore {
|
||||
/** 当前diff任务类型 */
|
||||
diffTask: DiffTaskType;
|
||||
/** 是否有继续任务 */
|
||||
hasContinueTask: boolean;
|
||||
/** 继续任务信息 */
|
||||
continueTask: DiffTaskType;
|
||||
/** 当前diff任务信息 */
|
||||
promptDiffInfo: {
|
||||
diffPromptResourceId: string;
|
||||
diffPrompt: string;
|
||||
diffMode: 'draft' | 'new-diff';
|
||||
};
|
||||
}
|
||||
|
||||
export interface DiffTaskAction {
|
||||
setDiffTask: SetterAction<DiffTaskStore>;
|
||||
setDiffTaskByImmer: (update: (state: DiffTaskStore) => void) => void;
|
||||
enterDiffMode: (props: {
|
||||
diffTask: DiffTaskType;
|
||||
promptDiffInfo?: {
|
||||
diffPromptResourceId: string;
|
||||
diffMode: 'draft' | 'new-diff';
|
||||
diffPrompt: string;
|
||||
};
|
||||
}) => void;
|
||||
exitDiffMode: () => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useDiffTaskStore = create<DiffTaskStore & DiffTaskAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultDiffTaskStore(),
|
||||
setDiffTask: setterActionFactory<DiffTaskStore>(set),
|
||||
setDiffTaskByImmer: update =>
|
||||
set(produce<DiffTaskStore>(state => update(state))),
|
||||
enterDiffMode: ({ diffTask, promptDiffInfo }) => {
|
||||
set(
|
||||
produce<DiffTaskStore>(state => {
|
||||
state.diffTask = diffTask;
|
||||
}),
|
||||
false,
|
||||
'enterDiffMode',
|
||||
);
|
||||
if (diffTask === 'prompt' && promptDiffInfo) {
|
||||
get().setDiffTaskByImmer(state => {
|
||||
state.promptDiffInfo = promptDiffInfo;
|
||||
});
|
||||
}
|
||||
},
|
||||
exitDiffMode: () => {
|
||||
get().clear();
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultDiffTaskStore() }, false, 'clear');
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.diffTask',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
import { type TaskNotice, type PicTask } from '@coze-arch/idl/playground_api';
|
||||
|
||||
import {
|
||||
type GenerateImageState,
|
||||
type GenerateImageAction,
|
||||
type GenerateAvatarModal,
|
||||
GenerateType,
|
||||
DotStatus,
|
||||
type GenerateBackGroundModal,
|
||||
} from '../types/generate-image';
|
||||
|
||||
export const DEFAULT_BOT_GENERATE_AVATAR_MODAL = (): GenerateAvatarModal => ({
|
||||
visible: false,
|
||||
activeKey: GenerateType.Static,
|
||||
selectedImage: { id: '', img_info: {} },
|
||||
gif: {
|
||||
loading: false,
|
||||
dotStatus: DotStatus.None,
|
||||
text: '',
|
||||
image: { id: '', img_info: {} },
|
||||
},
|
||||
image: {
|
||||
loading: false,
|
||||
dotStatus: DotStatus.None,
|
||||
text: '',
|
||||
textCustomizable: false,
|
||||
},
|
||||
});
|
||||
|
||||
export const DEFAULT_BOT_GENERATE_BACKGROUND_MODAL =
|
||||
(): GenerateBackGroundModal => ({
|
||||
activeKey: GenerateType.Static,
|
||||
selectedImage: { id: '', img_info: {} },
|
||||
gif: {
|
||||
loading: false,
|
||||
dotStatus: DotStatus.None,
|
||||
text: '',
|
||||
image: { id: '', img_info: {} },
|
||||
},
|
||||
image: {
|
||||
loading: false,
|
||||
dotStatus: DotStatus.None,
|
||||
promptInfo: {},
|
||||
},
|
||||
});
|
||||
|
||||
export const useGenerateImageStore = create<
|
||||
GenerateImageState & GenerateImageAction
|
||||
>()(
|
||||
devtools(
|
||||
subscribeWithSelector(set => ({
|
||||
imageList: [],
|
||||
noticeList: [],
|
||||
generateAvatarModal: DEFAULT_BOT_GENERATE_AVATAR_MODAL(),
|
||||
generateBackGroundModal: DEFAULT_BOT_GENERATE_BACKGROUND_MODAL(),
|
||||
clearGenerateImageStore: () => {
|
||||
set({
|
||||
imageList: [],
|
||||
noticeList: [],
|
||||
generateAvatarModal: DEFAULT_BOT_GENERATE_AVATAR_MODAL(),
|
||||
generateBackGroundModal: DEFAULT_BOT_GENERATE_BACKGROUND_MODAL(),
|
||||
});
|
||||
},
|
||||
updateImageList: (imageList: PicTask[]) => {
|
||||
set(s => ({
|
||||
...s,
|
||||
imageList,
|
||||
}));
|
||||
},
|
||||
pushImageList: (image: PicTask) => {
|
||||
set(s => ({
|
||||
...s,
|
||||
imageList: [...s.imageList, image],
|
||||
}));
|
||||
},
|
||||
updateNoticeList: (notices: TaskNotice[]) => {
|
||||
set(s => ({ ...s, notices }));
|
||||
},
|
||||
setGenerateAvatarModal: generateAvatarModal => {
|
||||
set({ generateAvatarModal });
|
||||
},
|
||||
resetGenerateAvatarModal: () => {
|
||||
set({ generateAvatarModal: DEFAULT_BOT_GENERATE_AVATAR_MODAL() });
|
||||
},
|
||||
setGenerateAvatarModalByImmer: update =>
|
||||
set(
|
||||
produce<GenerateImageState>(({ generateAvatarModal }) =>
|
||||
update(generateAvatarModal),
|
||||
),
|
||||
),
|
||||
setGenerateBackgroundModalByImmer: update =>
|
||||
set(
|
||||
produce<GenerateImageState>(({ generateBackGroundModal }) =>
|
||||
update(generateBackGroundModal),
|
||||
),
|
||||
),
|
||||
})),
|
||||
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.botGenerateImage',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 { useAuditInfoStore } from '@/store/audit-info';
|
||||
|
||||
import { useQueryCollectStore } from './query-collect';
|
||||
import { usePersonaStore } from './persona';
|
||||
import { usePageRuntimeStore } from './page-runtime';
|
||||
import { useMultiAgentStore } from './multi-agent';
|
||||
import { useMonetizeConfigStore } from './monetize-config-store';
|
||||
import { useModelStore } from './model';
|
||||
import { useManuallySwitchAgentStore } from './manually-switch-agent-store';
|
||||
import { useDiffTaskStore } from './diff-task';
|
||||
import { useCollaborationStore } from './collaboration';
|
||||
import { useBotSkillStore } from './bot-skill';
|
||||
import { useBotInfoStore } from './bot-info';
|
||||
|
||||
export interface BotDetailStoreSet {
|
||||
usePersonaStore: typeof usePersonaStore;
|
||||
useQueryCollectStore: typeof useQueryCollectStore;
|
||||
useMultiAgentStore: typeof useMultiAgentStore;
|
||||
useModelStore: typeof useModelStore;
|
||||
useBotSkillStore: typeof useBotSkillStore;
|
||||
useBotInfoStore: typeof useBotInfoStore;
|
||||
useCollaborationStore: typeof useCollaborationStore;
|
||||
usePageRuntimeStore: typeof usePageRuntimeStore;
|
||||
useMonetizeConfigStore: typeof useMonetizeConfigStore;
|
||||
useManuallySwitchAgentStore: typeof useManuallySwitchAgentStore;
|
||||
useDiffTaskStore: typeof useDiffTaskStore;
|
||||
}
|
||||
|
||||
interface UseBotDetailStoreSet {
|
||||
getStore: () => BotDetailStoreSet;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useBotDetailStoreSet: UseBotDetailStoreSet = {
|
||||
getStore() {
|
||||
return {
|
||||
usePersonaStore,
|
||||
useQueryCollectStore,
|
||||
useMultiAgentStore,
|
||||
useModelStore,
|
||||
useBotSkillStore,
|
||||
useBotInfoStore,
|
||||
useCollaborationStore,
|
||||
usePageRuntimeStore,
|
||||
useMonetizeConfigStore,
|
||||
useManuallySwitchAgentStore,
|
||||
useAuditInfoStore,
|
||||
useDiffTaskStore,
|
||||
};
|
||||
},
|
||||
clear() {
|
||||
usePersonaStore.getState().clear();
|
||||
useQueryCollectStore.getState().clear();
|
||||
useMultiAgentStore.getState().clear();
|
||||
useModelStore.getState().clear();
|
||||
useBotSkillStore.getState().clear();
|
||||
useBotInfoStore.getState().clear();
|
||||
useCollaborationStore.getState().clear();
|
||||
usePageRuntimeStore.getState().clear();
|
||||
useMonetizeConfigStore.getState().reset();
|
||||
useManuallySwitchAgentStore.getState().clearAgentId();
|
||||
useAuditInfoStore.getState().clear();
|
||||
useDiffTaskStore.getState().clear();
|
||||
},
|
||||
};
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用来满足一个神奇的功能
|
||||
* multi agent 模式下 正在回复中
|
||||
* 用户手动切换了 agent
|
||||
* 基于新的 agent 重新生成对话
|
||||
* 需要记录 agent 的切换是「手动」|「自动」
|
||||
*/
|
||||
|
||||
/**
|
||||
* !! 不和 Bot Detail 搅合在一起了。
|
||||
*/
|
||||
|
||||
import { devtools } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
|
||||
export interface ManuallySwitchAgentState {
|
||||
agentId: string | null;
|
||||
}
|
||||
|
||||
export interface ManuallySwitchAgentAction {
|
||||
recordAgentIdOnManuallySwitchAgent: (agentId: string) => void;
|
||||
clearAgentId: () => void;
|
||||
}
|
||||
|
||||
export const useManuallySwitchAgentStore = create<
|
||||
ManuallySwitchAgentAction & ManuallySwitchAgentState
|
||||
>()(
|
||||
devtools(
|
||||
set => ({
|
||||
agentId: null,
|
||||
recordAgentIdOnManuallySwitchAgent: agentId => {
|
||||
set({ agentId }, false, 'recordAgentIdOnManuallySwitchAgent');
|
||||
},
|
||||
clearAgentId: () => {
|
||||
set({ agentId: null }, false, 'clearAgentId');
|
||||
},
|
||||
}),
|
||||
{ enabled: IS_DEV_MODE, name: 'botStudio.manuallySwitchAgentStore' },
|
||||
),
|
||||
);
|
||||
158
frontend/packages/studio/stores/bot-detail/src/store/model.ts
Normal file
158
frontend/packages/studio/stores/bot-detail/src/store/model.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
import {
|
||||
type BotInfoForUpdate,
|
||||
type ContextMode,
|
||||
type GetDraftBotInfoAgwData,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
import {
|
||||
ContextContentType,
|
||||
type Model,
|
||||
type ModelInfo,
|
||||
type ModelInfo as ModelInfoConfig,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../utils/setter-factory';
|
||||
import type { BotDetailModel } from '../types/model';
|
||||
export const DEFAULT_MODEL_INFO = (): ModelInfo => ({
|
||||
model: '',
|
||||
temperature: 0,
|
||||
max_tokens: 4096,
|
||||
top_p: 0,
|
||||
frequency_penalty: 0,
|
||||
presence_penalty: 0,
|
||||
prompt_id: 0,
|
||||
ShortMemPolicy: {
|
||||
ContextContentType: ContextContentType.USER_RES,
|
||||
},
|
||||
card_ids: [],
|
||||
});
|
||||
export const getDefaultModelStore = (): ModelStore => ({
|
||||
config: {
|
||||
model: '',
|
||||
temperature: 0,
|
||||
max_tokens: 4096,
|
||||
top_p: 0,
|
||||
frequency_penalty: 0,
|
||||
presence_penalty: 0,
|
||||
prompt_id: 0,
|
||||
ShortMemPolicy: {
|
||||
ContextContentType: ContextContentType.USER_RES,
|
||||
},
|
||||
card_ids: [],
|
||||
},
|
||||
modelList: [],
|
||||
});
|
||||
|
||||
/** Persona & Prompt 区域 */
|
||||
export interface ModelStore {
|
||||
config: ModelInfoConfig;
|
||||
/** 全部可选模型 */
|
||||
modelList: Model[];
|
||||
}
|
||||
|
||||
export interface ModelAction {
|
||||
setModel: SetterAction<ModelStore>;
|
||||
setModelByImmer: (update: (state: ModelStore) => void) => void;
|
||||
transformDto2Vo: (
|
||||
botData: GetDraftBotInfoAgwData,
|
||||
) => BotDetailModel['config'];
|
||||
transformVo2Dto: (
|
||||
model: BotDetailModel['config'],
|
||||
) => BotInfoForUpdate['model_info'];
|
||||
initStore: (botData: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useModelStore = create<ModelStore & ModelAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultModelStore(),
|
||||
setModel: setterActionFactory<ModelStore>(set),
|
||||
setModelByImmer: update =>
|
||||
set(
|
||||
produce<ModelStore>(model => update(model)),
|
||||
false,
|
||||
'setModelByImmer',
|
||||
),
|
||||
transformDto2Vo: botData => {
|
||||
const modelInfo = botData.bot_info.model_info;
|
||||
const config = botData.bot_option_data?.model_detail_map;
|
||||
return {
|
||||
model: modelInfo?.model_id,
|
||||
temperature: modelInfo?.temperature,
|
||||
max_tokens: modelInfo?.max_tokens,
|
||||
top_p: modelInfo?.top_p,
|
||||
frequency_penalty: modelInfo?.frequency_penalty,
|
||||
presence_penalty: modelInfo?.presence_penalty,
|
||||
ShortMemPolicy: {
|
||||
ContextContentType: modelInfo?.short_memory_policy
|
||||
?.context_mode as unknown as ContextContentType,
|
||||
HistoryRound: modelInfo?.short_memory_policy?.history_round,
|
||||
},
|
||||
model_name:
|
||||
modelInfo?.model_id && config
|
||||
? config[modelInfo.model_id]?.model_name
|
||||
: '',
|
||||
|
||||
model_style: modelInfo?.model_style,
|
||||
response_format: modelInfo?.response_format,
|
||||
};
|
||||
},
|
||||
transformVo2Dto: model =>
|
||||
model?.model
|
||||
? {
|
||||
model_id: model.model,
|
||||
temperature: model.temperature,
|
||||
max_tokens: model.max_tokens,
|
||||
top_p: model.top_p,
|
||||
presence_penalty: model.presence_penalty,
|
||||
frequency_penalty: model.frequency_penalty,
|
||||
short_memory_policy: {
|
||||
history_round: model?.ShortMemPolicy?.HistoryRound,
|
||||
context_mode: model?.ShortMemPolicy
|
||||
?.ContextContentType as unknown as ContextMode,
|
||||
},
|
||||
response_format: model.response_format,
|
||||
model_style: model.model_style,
|
||||
}
|
||||
: {},
|
||||
initStore: botData => {
|
||||
const { transformDto2Vo } = get();
|
||||
const { bot_info, bot_option_data } = botData;
|
||||
bot_info?.model_info && bot_option_data?.model_detail_map
|
||||
? set({
|
||||
config: transformDto2Vo(botData),
|
||||
})
|
||||
: set({ config: DEFAULT_MODEL_INFO() });
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultModelStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.model',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 { devtools } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { isNil } from 'lodash-es';
|
||||
import {
|
||||
type BotMonetizationConfigData,
|
||||
BotMonetizationRefreshPeriod,
|
||||
} from '@coze-arch/idl/benefit';
|
||||
|
||||
export interface MonetizeConfigState {
|
||||
/** 是否开启付费 */
|
||||
isOn: boolean;
|
||||
/** 开启付费后,用户免费体验的次数 */
|
||||
freeCount: number;
|
||||
/** 刷新周期 */
|
||||
refreshCycle: BotMonetizationRefreshPeriod;
|
||||
}
|
||||
|
||||
export interface MonetizeConfigAction {
|
||||
setIsOn: (isOn: boolean) => void;
|
||||
setFreeCount: (freeCount: number) => void;
|
||||
setRefreshCycle: (refreshCycle: BotMonetizationRefreshPeriod) => void;
|
||||
initStore: (data: BotMonetizationConfigData) => void;
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
const DEFAULT_STATE: () => MonetizeConfigState = () => ({
|
||||
isOn: false,
|
||||
freeCount: 0,
|
||||
refreshCycle: 1,
|
||||
});
|
||||
|
||||
export type MonetizeConfigStore = MonetizeConfigState & MonetizeConfigAction;
|
||||
|
||||
export const useMonetizeConfigStore = create<MonetizeConfigStore>()(
|
||||
devtools(
|
||||
(set, get) => ({
|
||||
...DEFAULT_STATE(),
|
||||
|
||||
setIsOn: isOn => set({ isOn }),
|
||||
setFreeCount: freeCount => set({ freeCount }),
|
||||
setRefreshCycle: refreshCycle => set({ refreshCycle }),
|
||||
initStore: data => {
|
||||
const { setIsOn, setFreeCount, setRefreshCycle } = get();
|
||||
setIsOn(isNil(data?.is_enable) ? true : data.is_enable);
|
||||
setFreeCount(
|
||||
isNil(data?.free_chat_allowance_count)
|
||||
? 0
|
||||
: data.free_chat_allowance_count,
|
||||
);
|
||||
setRefreshCycle(
|
||||
data?.refresh_period ?? BotMonetizationRefreshPeriod.Never,
|
||||
);
|
||||
},
|
||||
reset: () => set(DEFAULT_STATE()),
|
||||
}),
|
||||
{ enabled: IS_DEV_MODE, name: 'botStudio.monetizeConfig' },
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 type { AgentBizInfo } from '../../types/agent';
|
||||
|
||||
export const DEFAULT_AGENT_BIZ_INFO = (): AgentBizInfo => ({});
|
||||
export const DEFAULT_AGENT_DESCRIPTION = () =>
|
||||
I18n.t('multiagent_node_scenarios_context_default');
|
||||
@@ -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 { useMultiAgentStore, type MultiAgentStore } from './store';
|
||||
export { DEFAULT_AGENT_BIZ_INFO } from './defaults';
|
||||
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { isEqual, uniqWith } from 'lodash-es';
|
||||
import { produce } from 'immer';
|
||||
import { withSlardarIdButton } from '@coze-studio/bot-utils';
|
||||
import {
|
||||
type BotOptionData,
|
||||
type bot_common,
|
||||
type AgentReferenceInfo,
|
||||
type Agent as AgentFromPlayground,
|
||||
BotMode,
|
||||
type GetDraftBotInfoAgwData,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { useSpaceStore } from '@coze-arch/bot-studio-store';
|
||||
import { SpaceApiV2 } from '@coze-arch/bot-space-api';
|
||||
import { UIToast } from '@coze-arch/bot-semi';
|
||||
import {
|
||||
AgentType,
|
||||
AgentVersionCompat,
|
||||
MultiAgentSessionType,
|
||||
type PluginApi,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
import { PlaygroundApi } from '@coze-arch/bot-api';
|
||||
import { LineType } from '@flowgram-adapter/free-layout-editor';
|
||||
import type { WorkflowEdgeJSON } from '@flowgram-adapter/free-layout-editor';
|
||||
import type { IPoint } from '@flowgram-adapter/common';
|
||||
|
||||
import { type SetterAction, setterActionFactory } from '@/utils/setter-factory';
|
||||
import { getPluginApisFilterExample } from '@/utils/plugin-apis';
|
||||
import {
|
||||
findAgentByNextIntentID,
|
||||
findFirstAgent,
|
||||
findFirstAgentId,
|
||||
findTargetAgent,
|
||||
} from '@/utils/find-agent';
|
||||
import type { BotDetailSkill, KnowledgeConfig } from '@/types/skill';
|
||||
|
||||
import { useManuallySwitchAgentStore } from '../manually-switch-agent-store';
|
||||
import { useCollaborationStore } from '../collaboration';
|
||||
import { useBotInfoStore } from '../bot-info';
|
||||
import {
|
||||
type Agent,
|
||||
type ChatModeConfig,
|
||||
type DraftBotVo,
|
||||
type MultiSheetViewOpenState,
|
||||
} from '../../types/agent';
|
||||
import { transformDto2Vo, transformVo2Dto } from './transform';
|
||||
|
||||
export interface MultiAgentStore {
|
||||
agents: Agent[];
|
||||
edges: WorkflowEdgeJSON[];
|
||||
connector_type: LineType;
|
||||
/** 用于保存 bot 类型节点的 bot 信息 */
|
||||
botAgentInfos: DraftBotVo[];
|
||||
/**
|
||||
* 会话接管方式配置
|
||||
* 默认为 flow 模式
|
||||
*/
|
||||
chatModeConfig: ChatModeConfig;
|
||||
/** 当前agent id **/
|
||||
currentAgentID: string;
|
||||
/**muti 左右展开状态**/
|
||||
multiSheetViewOpen: MultiSheetViewOpenState;
|
||||
}
|
||||
|
||||
export const getDefaultMultiAgentStore = (): MultiAgentStore => ({
|
||||
agents: [],
|
||||
edges: [],
|
||||
connector_type: LineType.BEZIER,
|
||||
currentAgentID: '',
|
||||
botAgentInfos: [],
|
||||
multiSheetViewOpen: {
|
||||
left: true,
|
||||
right: true,
|
||||
},
|
||||
chatModeConfig: {
|
||||
type: MultiAgentSessionType.Host,
|
||||
currentHostId: '',
|
||||
},
|
||||
});
|
||||
|
||||
export interface MultiAgentAction {
|
||||
setMultiAgent: SetterAction<MultiAgentStore>;
|
||||
setMultiAgentByImmer: (update: (state: MultiAgentStore) => void) => void;
|
||||
setMultiSheetViewOpen: (state: Partial<MultiSheetViewOpenState>) => void;
|
||||
updatedCurrentAgentIdWithConnectStart: () => void;
|
||||
/** 重置 host 节点为 start 相连的节点 */
|
||||
resetHostAgent: () => void;
|
||||
/**
|
||||
* 设置sourceAgentId的portId的intent的next_agent_id为nextAgentId
|
||||
*
|
||||
* @deprecated 这是旧版画布的方法,新版为 addAgentIntent
|
||||
*/
|
||||
setAgentIntentNextID: (
|
||||
sourceAgentId?: string,
|
||||
portId?: string,
|
||||
agentId?: string,
|
||||
) => void;
|
||||
addAgentIntent: (sourceAgentId: string, targetAgentId: string) => void;
|
||||
deleteAgentIntent: (sourceAgentId: string, targetAgentId: string) => void;
|
||||
/**
|
||||
* 根据agentId找到当前agent的source的agent,也就是上游agent
|
||||
* 将上游agent中找到某个intent,next_agent_id === agentId。将该intent的next_agent_id清空
|
||||
*/
|
||||
clearEdgesByTargetAgentId: (agentId?: string) => void;
|
||||
updateAgentSkillKnowledgeDatasetInfo: (
|
||||
agentId: string,
|
||||
dataSetInfo: KnowledgeConfig['dataSetInfo'],
|
||||
) => void;
|
||||
updateAgentSkillPluginApis: (
|
||||
agentId: string,
|
||||
pluginApis: Array<PluginApi>,
|
||||
) => void;
|
||||
addAgent2Store: (
|
||||
agentInfo: bot_common.Agent,
|
||||
optionData?: BotOptionData,
|
||||
) => Agent;
|
||||
addAgent: (config: {
|
||||
/** @default AgentType.LLM_Agent */
|
||||
type?: AgentType;
|
||||
position?: IPoint;
|
||||
/** 是否使用struct版本 - 便于写单测即将删除*/
|
||||
structFlag?: boolean;
|
||||
}) => Promise<Agent | undefined>;
|
||||
batchAddBotAgent: (config: {
|
||||
bots: AgentReferenceInfo[];
|
||||
positions: IPoint[];
|
||||
/** 是否使用struct版本 - 便于写单测即将删除*/
|
||||
structFlag?: boolean;
|
||||
}) => Promise<Agent[]>;
|
||||
updateBotNodeInfo: (
|
||||
agents: AgentFromPlayground[],
|
||||
) => Promise<void> | undefined;
|
||||
copyAgent: (agentId: string) => Promise<Agent | undefined>;
|
||||
removeAgentSkillItem: (
|
||||
agentId: string,
|
||||
type: keyof Pick<BotDetailSkill, 'pluginApis' | 'workflows' | 'knowledge'>,
|
||||
apiId?: string,
|
||||
) => void;
|
||||
/**
|
||||
* 清除一条 intent 的 next_id(也就是 edge)
|
||||
*
|
||||
* - Q1:为什么不直接使用 intent id 来找 intent?
|
||||
* - A1:将一条已有的连线拖拽连接到另一个节点时,SDK 会先触发这个 intent 的 addEdge 事件,随后再触发 deleteEdge 事件。
|
||||
* 导致 deleteEdge 事件会通过 intent id 覆盖 addEdge 刚刚更新过的 intent。
|
||||
*
|
||||
* - Q2:那通过 targetAgentId 来找 intent 不够吗,为什么还需要 intent id?
|
||||
* - A2:当同一个节点的两个 intent 都指向同一个目标,这时删除其中一条连线,无法确定删除的是哪条,必须配合 intent id 来判断
|
||||
*
|
||||
* @deprecated 旧版画布的方法,新版为 deleteAgentIntent
|
||||
*/
|
||||
clearIntentNextId: (
|
||||
sourceAgentId: string,
|
||||
targetAgentId: string,
|
||||
intentId: string,
|
||||
) => void;
|
||||
transformDto2Vo: typeof transformDto2Vo;
|
||||
transformVo2Dto: typeof transformVo2Dto;
|
||||
initStore: (botData: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useMultiAgentStore = create<MultiAgentStore & MultiAgentAction>()(
|
||||
devtools(
|
||||
// eslint-disable-next-line @coze-arch/max-line-per-function
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultMultiAgentStore(),
|
||||
setMultiAgent: setterActionFactory<MultiAgentStore>(set),
|
||||
setMultiAgentByImmer: update =>
|
||||
set(produce<MultiAgentStore>(multiAgent => update(multiAgent))),
|
||||
setMultiSheetViewOpen: (state: Partial<MultiSheetViewOpenState>) => {
|
||||
set(s => ({
|
||||
...s,
|
||||
multiSheetViewOpen: {
|
||||
...s.multiSheetViewOpen,
|
||||
...state,
|
||||
},
|
||||
}));
|
||||
},
|
||||
updatedCurrentAgentIdWithConnectStart: () => {
|
||||
const firstAgent = findFirstAgent(get());
|
||||
const newAgentId = firstAgent?.id;
|
||||
useManuallySwitchAgentStore.getState().clearAgentId();
|
||||
if (newAgentId) {
|
||||
set(
|
||||
produce<MultiAgentStore>(state => {
|
||||
state.currentAgentID = newAgentId;
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
resetHostAgent: () => {
|
||||
const firstAgentId = findFirstAgentId(get());
|
||||
if (!firstAgentId) {
|
||||
return;
|
||||
}
|
||||
set(
|
||||
produce<MultiAgentStore>(multiAgent => {
|
||||
if (multiAgent.chatModeConfig.type !== MultiAgentSessionType.Host) {
|
||||
return;
|
||||
}
|
||||
multiAgent.chatModeConfig.currentHostId = firstAgentId;
|
||||
}),
|
||||
);
|
||||
},
|
||||
setAgentIntentNextID: (
|
||||
sourceAgentId?: string,
|
||||
portId?: string,
|
||||
agentId?: string,
|
||||
) => {
|
||||
set(
|
||||
produce<MultiAgentStore>(state => {
|
||||
const { agents } = state;
|
||||
const sourceAgent = findTargetAgent(agents, sourceAgentId);
|
||||
if (sourceAgent) {
|
||||
const targetIntent = sourceAgent.intents?.find(
|
||||
item => item.intent_id === portId,
|
||||
);
|
||||
if (targetIntent && agentId) {
|
||||
targetIntent.next_agent_id = agentId;
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
clearIntentNextId: (
|
||||
sourceAgentId: string,
|
||||
targetAgentId: string,
|
||||
intentId: string,
|
||||
) => {
|
||||
set(
|
||||
produce<MultiAgentStore>(state => {
|
||||
const sourceAgent = findTargetAgent(state.agents, sourceAgentId);
|
||||
const sourceIntent = sourceAgent?.intents?.find(
|
||||
i =>
|
||||
i.next_agent_id === targetAgentId && i.intent_id === intentId,
|
||||
);
|
||||
if (!sourceIntent) {
|
||||
return;
|
||||
}
|
||||
sourceIntent.next_agent_id = undefined;
|
||||
}),
|
||||
);
|
||||
},
|
||||
addAgentIntent: (sourceAgentId, targetAgentId) => {
|
||||
set(
|
||||
produce<MultiAgentStore>(({ agents }) => {
|
||||
const sourceAgent = findTargetAgent(agents, sourceAgentId);
|
||||
if (!sourceAgent) {
|
||||
return;
|
||||
}
|
||||
const newIntent = {
|
||||
intent_id: nanoid(),
|
||||
next_agent_id: targetAgentId,
|
||||
};
|
||||
switch (sourceAgent.agent_type) {
|
||||
case AgentType.Global_Agent:
|
||||
if (sourceAgent.intents?.[0]) {
|
||||
sourceAgent.intents[0].next_agent_id = targetAgentId;
|
||||
} else {
|
||||
sourceAgent.intents = [newIntent];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (sourceAgent.intents) {
|
||||
sourceAgent.intents.push(newIntent);
|
||||
} else {
|
||||
sourceAgent.intents = [newIntent];
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
deleteAgentIntent: (sourceAgentId, targetAgentId) =>
|
||||
set(
|
||||
produce<MultiAgentStore>(({ agents }) => {
|
||||
const sourceAgent = findTargetAgent(agents, sourceAgentId);
|
||||
if (!sourceAgent) {
|
||||
return;
|
||||
}
|
||||
switch (sourceAgent.agent_type) {
|
||||
case AgentType.Global_Agent:
|
||||
if (sourceAgent.intents?.[0]) {
|
||||
sourceAgent.intents[0].next_agent_id = undefined;
|
||||
} else {
|
||||
sourceAgent.intents = [{ intent_id: nanoid() }];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sourceAgent.intents =
|
||||
sourceAgent.intents?.filter(
|
||||
intent => intent.next_agent_id !== targetAgentId,
|
||||
) || [];
|
||||
}
|
||||
}),
|
||||
),
|
||||
clearEdgesByTargetAgentId: (targetAgentId?: string) => {
|
||||
set(
|
||||
produce<MultiAgentStore>(state => {
|
||||
const { agents } = state;
|
||||
const sourceAgent = findAgentByNextIntentID(agents, targetAgentId);
|
||||
|
||||
if (sourceAgent) {
|
||||
const { intents } = sourceAgent;
|
||||
|
||||
// 执行第一步指令。将上游agent的next_agent_id清空
|
||||
intents?.forEach(item => {
|
||||
if (item.next_agent_id === targetAgentId) {
|
||||
item.next_agent_id = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
updateAgentSkillKnowledgeDatasetInfo: (agentId, dataSetInfo) => {
|
||||
set(
|
||||
produce<MultiAgentStore>(state => {
|
||||
const findAgent = findTargetAgent(state.agents, agentId);
|
||||
if (findAgent) {
|
||||
findAgent.skills.knowledge.dataSetInfo = dataSetInfo;
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
updateAgentSkillPluginApis: (agentId, pluginApis) => {
|
||||
set(
|
||||
produce<MultiAgentStore>(state => {
|
||||
const findAgent = findTargetAgent(state.agents, agentId);
|
||||
if (findAgent) {
|
||||
findAgent.skills.pluginApis =
|
||||
getPluginApisFilterExample(pluginApis);
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
addAgent2Store: (
|
||||
agentInfo: bot_common.Agent,
|
||||
optionData?: BotOptionData,
|
||||
) => {
|
||||
const agent = transformDto2Vo.agent(optionData, agentInfo);
|
||||
set(
|
||||
produce<MultiAgentStore>(state => {
|
||||
state.agents.push(agent);
|
||||
}),
|
||||
);
|
||||
return agent;
|
||||
},
|
||||
addAgent: async ({ type = AgentType.LLM_Agent, position }) => {
|
||||
const { botId } = useBotInfoStore.getState();
|
||||
const { getBaseVersion, setCollaborationByImmer } =
|
||||
useCollaborationStore.getState();
|
||||
const createAgentParams = {
|
||||
agent_type: type,
|
||||
bot_id: botId,
|
||||
position,
|
||||
base_commit_version: getBaseVersion(),
|
||||
version_compat: AgentVersionCompat.NewVersion,
|
||||
};
|
||||
const { data, same_with_online, branch } =
|
||||
await PlaygroundApi.CreateAgentV2(createAgentParams);
|
||||
if (!data) {
|
||||
UIToast.error({
|
||||
content: withSlardarIdButton(
|
||||
I18n.t('chatflow_error_create_failed'),
|
||||
),
|
||||
});
|
||||
return;
|
||||
}
|
||||
setCollaborationByImmer(state => {
|
||||
state.sameWithOnline = same_with_online ?? false;
|
||||
state.branch = branch;
|
||||
});
|
||||
return get().addAgent2Store(data);
|
||||
},
|
||||
batchAddBotAgent: async ({ bots, positions }) => {
|
||||
const spaceId = useSpaceStore.getState().space.id as string;
|
||||
const { botId } = useBotInfoStore.getState();
|
||||
const { getBaseVersion, setCollaborationByImmer } =
|
||||
useCollaborationStore.getState();
|
||||
const { botAgentInfos } = get();
|
||||
const batchCreateAgentParams = {
|
||||
bot_id: botId,
|
||||
agent_type: AgentType.Bot_Agent,
|
||||
position: positions,
|
||||
references: bots,
|
||||
agent_cnt: bots.length,
|
||||
base_commit_version: getBaseVersion(),
|
||||
};
|
||||
const [
|
||||
{ data: agentInfos, same_with_online, branch },
|
||||
{ data: botInfos },
|
||||
] = await Promise.all([
|
||||
PlaygroundApi.BatchCreateAgentV2(batchCreateAgentParams),
|
||||
PlaygroundApi.MGetBotByVersion({
|
||||
space_id: spaceId,
|
||||
bot_versions: bots?.map(e => ({
|
||||
bot_id: e.ReferenceId,
|
||||
version: e.Version,
|
||||
})),
|
||||
}),
|
||||
]);
|
||||
|
||||
if (
|
||||
!Array.isArray(agentInfos) ||
|
||||
agentInfos.length === 0 ||
|
||||
!Array.isArray(botInfos) ||
|
||||
botInfos.length === 0
|
||||
) {
|
||||
UIToast.error({
|
||||
content: withSlardarIdButton(
|
||||
I18n.t('chatflow_error_create_failed'),
|
||||
),
|
||||
});
|
||||
return [] as Agent[];
|
||||
}
|
||||
const botInfosVo = botInfos.map(transformDto2Vo.botNodeInfo);
|
||||
setCollaborationByImmer(store => {
|
||||
store.sameWithOnline = same_with_online ?? false;
|
||||
store.branch = branch;
|
||||
});
|
||||
set(
|
||||
produce<MultiAgentStore>(store => {
|
||||
store.botAgentInfos = uniqWith(
|
||||
[...botAgentInfos, ...botInfosVo],
|
||||
isEqual,
|
||||
);
|
||||
}),
|
||||
);
|
||||
return agentInfos.map(e => {
|
||||
const botInfo = botInfosVo.find(b => b.id === e.reference_id);
|
||||
return get().addAgent2Store({
|
||||
...e,
|
||||
agent_name: botInfo?.name,
|
||||
icon_uri: botInfo?.icon_url,
|
||||
});
|
||||
});
|
||||
},
|
||||
copyAgent: async (agentId: string) => {
|
||||
const { botId } = useBotInfoStore.getState();
|
||||
const { getBaseVersion } = useCollaborationStore.getState();
|
||||
const copyAgentParams = {
|
||||
space_id: useSpaceStore.getState().getSpaceId(),
|
||||
bot_id: botId,
|
||||
base_commit_version: getBaseVersion(),
|
||||
agent_id: agentId,
|
||||
};
|
||||
const { data, bot_option_data = {} } = await PlaygroundApi.CopyAgentV2(
|
||||
copyAgentParams,
|
||||
);
|
||||
if (!data) {
|
||||
UIToast.error({
|
||||
content: withSlardarIdButton(
|
||||
I18n.t('chatflow_error_create_failed'),
|
||||
),
|
||||
});
|
||||
return;
|
||||
}
|
||||
return get().addAgent2Store(data, bot_option_data);
|
||||
},
|
||||
removeAgentSkillItem: (agentId, type, apiId) => {
|
||||
set(
|
||||
produce<MultiAgentStore>(s => {
|
||||
const findAgent = findTargetAgent(s.agents, agentId);
|
||||
if (findAgent?.skills) {
|
||||
switch (type) {
|
||||
case 'pluginApis': {
|
||||
findAgent.skills.pluginApis =
|
||||
findAgent.skills.pluginApis.filter(
|
||||
item => item.api_id !== apiId,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'workflows': {
|
||||
findAgent.skills.workflows =
|
||||
findAgent.skills.workflows.filter(
|
||||
item => item.workflow_id !== apiId,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'knowledge': {
|
||||
findAgent.skills.knowledge.dataSetList =
|
||||
findAgent.skills.knowledge.dataSetList.filter(
|
||||
item => item.dataset_id !== apiId,
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.warn('[removeAgentSkillItem]: ?');
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
updateBotNodeInfo: agents => {
|
||||
const { setMultiAgentByImmer } = get();
|
||||
const botAgents = agents.filter(
|
||||
e => e.agent_type === AgentType.Bot_Agent,
|
||||
);
|
||||
if (Array.isArray(botAgents) && botAgents.length > 0) {
|
||||
return SpaceApiV2.MGetBotByVersion({
|
||||
bot_versions: botAgents?.map(e => ({
|
||||
bot_id: e.reference_id,
|
||||
version: e.current_version,
|
||||
})),
|
||||
}).then(botInfos => {
|
||||
setMultiAgentByImmer(s => {
|
||||
s.botAgentInfos = (botInfos.data ?? []).map(
|
||||
transformDto2Vo.botNodeInfo,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
transformDto2Vo,
|
||||
transformVo2Dto,
|
||||
initStore: botData => {
|
||||
const { bot_info: botInfo } = botData;
|
||||
const {
|
||||
transformDto2Vo: transformDto2Vo4Multi,
|
||||
updatedCurrentAgentIdWithConnectStart,
|
||||
updateBotNodeInfo,
|
||||
} = get();
|
||||
|
||||
const {
|
||||
bot_info: { agents, multi_agent_info: multiInfo },
|
||||
bot_option_data: botOpts,
|
||||
} = botData;
|
||||
|
||||
set(
|
||||
transformDto2Vo4Multi.multiAgent({
|
||||
agents,
|
||||
multiInfo,
|
||||
botOpts,
|
||||
}),
|
||||
);
|
||||
const isMultiAgent = botInfo?.bot_mode === BotMode.MultiMode;
|
||||
if (isMultiAgent) {
|
||||
// 设置初始的对话agent id
|
||||
updatedCurrentAgentIdWithConnectStart();
|
||||
// 获取agent节点为子bot的子bot信息,并赋值入store
|
||||
updateBotNodeInfo(botInfo?.agents || []);
|
||||
}
|
||||
},
|
||||
clear: () => {
|
||||
// eslint-disable-next-line max-lines
|
||||
set({ ...getDefaultMultiAgentStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.multiAgent',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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 { nanoid } from 'nanoid';
|
||||
import { omit } from 'lodash-es';
|
||||
import {
|
||||
type Agent as AgentFromPlayground,
|
||||
type BotOptionData,
|
||||
AgentType,
|
||||
type DraftBotApi,
|
||||
type MultiAgentInfo,
|
||||
MultiAgentSessionType,
|
||||
type UpdateAgentV2Request,
|
||||
ReferenceUpdateType,
|
||||
} from '@coze-arch/bot-api/playground_api';
|
||||
import { LineType } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { useModelStore } from '../model';
|
||||
import { useBotSkillStore } from '../bot-skill';
|
||||
import { findFirstAgentId } from '../../utils/find-agent';
|
||||
import type { BotSuggestionConfig } from '../../types/skill';
|
||||
import type { Agent, BotMultiAgent, DraftBotVo } from '../../types/agent';
|
||||
import { DEFAULT_AGENT_BIZ_INFO, DEFAULT_AGENT_DESCRIPTION } from './defaults';
|
||||
export const transformDto2Vo = {
|
||||
agent: (botOpts?: BotOptionData, data?: AgentFromPlayground): Agent => {
|
||||
const { transformDto2Vo: transformDto2Vo4BotSkill } =
|
||||
useBotSkillStore.getState();
|
||||
const { transformDto2Vo: transformDto2Vo4Model } = useModelStore.getState();
|
||||
const model = transformDto2Vo4Model({
|
||||
bot_info: {
|
||||
model_info: data?.model_info,
|
||||
},
|
||||
bot_option_data: botOpts,
|
||||
});
|
||||
|
||||
const prompt = data?.prompt_info?.prompt ?? '';
|
||||
|
||||
const pluginApis = transformDto2Vo4BotSkill.plugin(
|
||||
data?.plugin_info_list,
|
||||
botOpts?.plugin_detail_map,
|
||||
botOpts?.plugin_api_detail_map,
|
||||
);
|
||||
|
||||
const workflows = transformDto2Vo4BotSkill.workflow(
|
||||
data?.workflow_info_list,
|
||||
botOpts?.workflow_detail_map,
|
||||
);
|
||||
const knowledge = transformDto2Vo4BotSkill.knowledge(
|
||||
data?.knowledge,
|
||||
botOpts?.knowledge_detail_map,
|
||||
);
|
||||
|
||||
const devHooks = transformDto2Vo4BotSkill.hookInfo(data?.hook_info);
|
||||
|
||||
return {
|
||||
id: data?.agent_id ?? '',
|
||||
reference_id: data?.reference_id,
|
||||
reference_info_status: data?.reference_info_status,
|
||||
update_type: data?.update_type,
|
||||
agent_type: data?.agent_type,
|
||||
name: data?.agent_name,
|
||||
position: data?.agent_position,
|
||||
model,
|
||||
prompt,
|
||||
description: data?.description || DEFAULT_AGENT_DESCRIPTION(),
|
||||
// 默认的业务状态bizInfo
|
||||
bizInfo: DEFAULT_AGENT_BIZ_INFO(),
|
||||
system_info_all: [],
|
||||
skills: {
|
||||
pluginApis,
|
||||
workflows,
|
||||
knowledge,
|
||||
...(devHooks ? { devHooks } : {}),
|
||||
},
|
||||
current_version: data?.current_version,
|
||||
suggestion: data?.suggest_reply_info as unknown as BotSuggestionConfig,
|
||||
intents: data?.intents || [],
|
||||
jump_config: data?.jump_config || {},
|
||||
...(data?.agent_type === AgentType.Global_Agent && {
|
||||
intents: data.intents?.length
|
||||
? data.intents
|
||||
: [{ intent_id: nanoid() }],
|
||||
}),
|
||||
};
|
||||
},
|
||||
botNodeInfo: (bot: DraftBotApi): DraftBotVo => {
|
||||
const { transformDto2Vo: transformDto2Vo4BotSkill } =
|
||||
useBotSkillStore.getState();
|
||||
return {
|
||||
...bot,
|
||||
work_info: {
|
||||
suggest_reply: transformDto2Vo4BotSkill.suggestionConfig(
|
||||
bot.suggest_reply,
|
||||
true,
|
||||
),
|
||||
},
|
||||
};
|
||||
},
|
||||
multiAgent: ({
|
||||
agents,
|
||||
multiInfo,
|
||||
botOpts,
|
||||
}: {
|
||||
agents?: AgentFromPlayground[];
|
||||
multiInfo?: MultiAgentInfo;
|
||||
botOpts?: BotOptionData;
|
||||
}): BotMultiAgent => {
|
||||
const transformedAgents =
|
||||
agents?.map(item => transformDto2Vo.agent(botOpts, item)) || [];
|
||||
|
||||
const tempEdges = transformedAgents?.flatMap(
|
||||
agent =>
|
||||
agent.intents?.map(intent => ({
|
||||
sourceNodeID: agent.id,
|
||||
targetNodeID: intent.next_agent_id || '',
|
||||
sourcePortID: intent.intent_id,
|
||||
})) || [],
|
||||
);
|
||||
|
||||
return {
|
||||
edges: tempEdges,
|
||||
connector_type: (multiInfo?.connector_type ??
|
||||
LineType.BEZIER) as LineType,
|
||||
agents: transformedAgents,
|
||||
botAgentInfos: [],
|
||||
chatModeConfig:
|
||||
multiInfo?.session_type === MultiAgentSessionType.Host
|
||||
? {
|
||||
type: multiInfo.session_type,
|
||||
currentHostId:
|
||||
findFirstAgentId({
|
||||
agents: transformedAgents,
|
||||
}) || '',
|
||||
}
|
||||
: { type: MultiAgentSessionType.Flow },
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const transformVo2Dto = {
|
||||
agent: (targetAgent: Agent): Omit<UpdateAgentV2Request, 'bot_id'> => {
|
||||
const { transformVo2Dto: transformVo2Dto4BotSkill } =
|
||||
useBotSkillStore.getState();
|
||||
const { transformVo2Dto: transformVo2Dto4Model } = useModelStore.getState();
|
||||
|
||||
return {
|
||||
...omit(targetAgent, [
|
||||
'skills',
|
||||
'system_info_all',
|
||||
'prompt',
|
||||
'bizInfo',
|
||||
'jump_config',
|
||||
'model',
|
||||
'suggestion',
|
||||
]),
|
||||
|
||||
plugin_info_list: transformVo2Dto4BotSkill.plugin(
|
||||
targetAgent?.skills?.pluginApis,
|
||||
),
|
||||
workflow_info_list: transformVo2Dto4BotSkill.workflow(
|
||||
targetAgent?.skills?.workflows,
|
||||
),
|
||||
knowledge: transformVo2Dto4BotSkill.knowledge(
|
||||
targetAgent?.skills?.knowledge,
|
||||
),
|
||||
suggest_reply_info: transformVo2Dto4BotSkill.suggestionConfig(
|
||||
targetAgent?.suggestion,
|
||||
),
|
||||
hook_info: targetAgent?.skills?.devHooks,
|
||||
model_info: transformVo2Dto4Model(targetAgent?.model),
|
||||
prompt_info: {
|
||||
prompt: targetAgent.prompt,
|
||||
},
|
||||
jump_config: targetAgent.jump_config,
|
||||
|
||||
current_version:
|
||||
targetAgent.update_type === ReferenceUpdateType.AutoUpdate
|
||||
? // 如果当前agent是自动更新,则将current_version置为"0"
|
||||
'0'
|
||||
: targetAgent.current_version,
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -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 TabDisplayItems, TabStatus } from '@coze-arch/idl/developer_api';
|
||||
|
||||
export const DEFAULT_BOT_SKILL_BLOCK_COLLAPSIBLE_STATE =
|
||||
(): TabDisplayItems => ({
|
||||
plugin_tab_status: TabStatus.Default,
|
||||
workflow_tab_status: TabStatus.Default,
|
||||
imageflow_tab_status: TabStatus.Default,
|
||||
knowledge_tab_status: TabStatus.Default,
|
||||
database_tab_status: TabStatus.Default,
|
||||
variable_tab_status: TabStatus.Default,
|
||||
opening_dialog_tab_status: TabStatus.Default,
|
||||
scheduled_task_tab_status: TabStatus.Default,
|
||||
suggestion_tab_status: TabStatus.Default,
|
||||
tts_tab_status: TabStatus.Default,
|
||||
filebox_tab_status: TabStatus.Default,
|
||||
background_image_tab_status: TabStatus.Default,
|
||||
shortcut_tab_status: TabStatus.Default,
|
||||
});
|
||||
@@ -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 { usePageRuntimeStore, type PageRuntime } from './store';
|
||||
export { DEFAULT_BOT_SKILL_BLOCK_COLLAPSIBLE_STATE } from './defaults';
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { size } from 'lodash-es';
|
||||
import { produce } from 'immer';
|
||||
import dayjs from 'dayjs';
|
||||
import { type GetDraftBotInfoAgwData } from '@coze-arch/idl/playground_api';
|
||||
import { type BotPageFromEnum } from '@coze-arch/bot-typings/common';
|
||||
import { SpaceApi } from '@coze-arch/bot-space-api';
|
||||
import {
|
||||
type GetDraftBotDisplayInfoResponse,
|
||||
type TabDisplayItems,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
import { DeveloperApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { useBotInfoStore } from '../bot-info';
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../../utils/setter-factory';
|
||||
import { DEFAULT_BOT_SKILL_BLOCK_COLLAPSIBLE_STATE } from './defaults';
|
||||
|
||||
interface SavingInfo {
|
||||
saving: boolean;
|
||||
time: string;
|
||||
debouncing?: boolean;
|
||||
scopeKey?: string;
|
||||
triggerType?: string;
|
||||
}
|
||||
export const getDefaultPageRuntimeStore = (): PageRuntime => ({
|
||||
init: false,
|
||||
isSelf: false,
|
||||
isPreview: false,
|
||||
editable: false,
|
||||
savingInfo: {
|
||||
saving: false,
|
||||
time: dayjs().format('HH:mm:ss'),
|
||||
debouncing: false,
|
||||
scopeKey: '',
|
||||
triggerType: '',
|
||||
},
|
||||
historyVisible: false,
|
||||
botSkillBlockCollapsibleState: {},
|
||||
grabPluginId: '',
|
||||
hasUnpublishChange: false,
|
||||
});
|
||||
|
||||
// bot的编辑器状态控制
|
||||
export interface PageRuntime {
|
||||
/** 初始化 **/
|
||||
init: boolean;
|
||||
/** 当前用户是否是bot的创建者 **/
|
||||
isSelf: boolean;
|
||||
/** 是否是预览状态isPreview = typeof version !== 'undefined'; **/
|
||||
isPreview: boolean;
|
||||
/** 服务端透传 **/
|
||||
editable: boolean;
|
||||
/**控制bot 历史版本展示 **/
|
||||
historyVisible?: boolean;
|
||||
|
||||
/** 记录用户主动展开/收起bot能力模块的状态 **/
|
||||
botSkillBlockCollapsibleState: TabDisplayItems;
|
||||
/** 页面来源 **/
|
||||
pageFrom?: BotPageFromEnum;
|
||||
/** 保存信息 **/
|
||||
savingInfo: SavingInfo;
|
||||
/** 划词插件id, 一个chat-area一个 **/
|
||||
grabPluginId: string;
|
||||
/** 是否有未发布的修改, header头部展示**/
|
||||
hasUnpublishChange: boolean;
|
||||
}
|
||||
|
||||
export type InitStoreData = GetDraftBotInfoAgwData & { customVersion?: string };
|
||||
export interface PageRuntimeAction {
|
||||
setPageRuntimeBotInfo: SetterAction<PageRuntime>;
|
||||
setPageRuntimeByImmer: (update: (state: PageRuntime) => void) => void;
|
||||
getBotSkillBlockCollapsibleState: () => Promise<void>;
|
||||
setBotSkillBlockCollapsibleState: (
|
||||
$params: TabDisplayItems,
|
||||
disableUpdateService?: boolean,
|
||||
) => void;
|
||||
getIsPreview: (version?: string) => boolean;
|
||||
initStore: (data: InitStoreData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const usePageRuntimeStore = create<PageRuntime & PageRuntimeAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultPageRuntimeStore(),
|
||||
setPageRuntimeBotInfo: setterActionFactory<PageRuntime>(set),
|
||||
setPageRuntimeByImmer: update =>
|
||||
set(produce<PageRuntime>(state => update(state))),
|
||||
|
||||
/**
|
||||
* 获取用户主动展开/收起bot能力模块的状态
|
||||
* ⚠️ 仅在首次打开本人 bot 编辑页时调用
|
||||
* @see
|
||||
*/
|
||||
getBotSkillBlockCollapsibleState: async () => {
|
||||
try {
|
||||
const resp: GetDraftBotDisplayInfoResponse =
|
||||
await SpaceApi.GetDraftBotDisplayInfo({
|
||||
bot_id: useBotInfoStore.getState().botId,
|
||||
});
|
||||
const botSkillBlockCollapsibleState =
|
||||
resp.data?.tab_display_info ??
|
||||
DEFAULT_BOT_SKILL_BLOCK_COLLAPSIBLE_STATE();
|
||||
|
||||
set(prevState => ({
|
||||
...prevState,
|
||||
botSkillBlockCollapsibleState,
|
||||
}));
|
||||
} catch (error) {
|
||||
set(prevState => ({
|
||||
...prevState,
|
||||
botSkillBlockCollapsibleState:
|
||||
DEFAULT_BOT_SKILL_BLOCK_COLLAPSIBLE_STATE(),
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 存储用户主动展开/收起bot能力模块的状态
|
||||
* ⚠️ 仅限主动操作时记录
|
||||
* @see
|
||||
*/
|
||||
setBotSkillBlockCollapsibleState: (
|
||||
$params: TabDisplayItems,
|
||||
disableUpdateService?: boolean,
|
||||
) => {
|
||||
if (size($params) > 0) {
|
||||
// 记录到本地状态机
|
||||
set({
|
||||
...get(),
|
||||
botSkillBlockCollapsibleState: {
|
||||
...get().botSkillBlockCollapsibleState,
|
||||
...$params,
|
||||
},
|
||||
});
|
||||
|
||||
if (disableUpdateService) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 同步到服务端
|
||||
DeveloperApi.UpdateDraftBotDisplayInfo({
|
||||
bot_id: useBotInfoStore.getState().botId,
|
||||
display_info: { tab_display_info: $params },
|
||||
space_id: useBotInfoStore.getState().space_id,
|
||||
});
|
||||
}
|
||||
},
|
||||
getIsPreview: version => typeof version !== 'undefined',
|
||||
initStore: info => {
|
||||
const { getIsPreview } = get();
|
||||
set({
|
||||
init: true,
|
||||
isPreview: getIsPreview(info?.customVersion),
|
||||
editable: info?.editable,
|
||||
savingInfo: { saving: false, time: dayjs().format('HH:mm:ss') },
|
||||
hasUnpublishChange: Boolean(info.has_unpublished_change),
|
||||
});
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultPageRuntimeStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.pageRuntime',
|
||||
},
|
||||
),
|
||||
);
|
||||
103
frontend/packages/studio/stores/bot-detail/src/store/persona.ts
Normal file
103
frontend/packages/studio/stores/bot-detail/src/store/persona.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
import {
|
||||
type BotInfoForUpdate,
|
||||
type GetDraftBotInfoAgwData,
|
||||
} from '@coze-arch/bot-api/playground_api';
|
||||
import { type BotPrompt, PromptType } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../utils/setter-factory';
|
||||
|
||||
export const getDefaultPersonaStore = (): PersonaStore => ({
|
||||
systemMessage: {
|
||||
data: '',
|
||||
prompt_type: PromptType.SYSTEM,
|
||||
isOptimize: false,
|
||||
record_id: '',
|
||||
},
|
||||
optimizePrompt: '',
|
||||
promptOptimizeUuid: '',
|
||||
promptOptimizeStatus: 'waitForRespond',
|
||||
});
|
||||
|
||||
export interface RequiredBotPrompt extends BotPrompt {
|
||||
prompt_type: PromptType;
|
||||
data: string;
|
||||
isOptimize: boolean;
|
||||
record_id?: string;
|
||||
}
|
||||
|
||||
/** Persona & Prompt 区域 */
|
||||
export interface PersonaStore {
|
||||
systemMessage: RequiredBotPrompt;
|
||||
optimizePrompt: string;
|
||||
promptOptimizeUuid: string;
|
||||
promptOptimizeStatus: 'responding' | 'waitForRespond' | 'endResponse';
|
||||
}
|
||||
|
||||
export interface PersonaAction {
|
||||
setPersona: SetterAction<PersonaStore>;
|
||||
setPersonaByImmer: (update: (state: PersonaStore) => void) => void;
|
||||
transformDto2Vo: (data: GetDraftBotInfoAgwData) => RequiredBotPrompt;
|
||||
transformVo2Dto: (
|
||||
persona: Partial<RequiredBotPrompt>,
|
||||
) => BotInfoForUpdate['prompt_info'];
|
||||
initStore: (botData: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const usePersonaStore = create<PersonaStore & PersonaAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultPersonaStore(),
|
||||
setPersona: setterActionFactory<PersonaStore>(set),
|
||||
setPersonaByImmer: update =>
|
||||
set(produce<PersonaStore>(persona => update(persona))),
|
||||
transformDto2Vo: botData =>
|
||||
({
|
||||
data: botData.bot_info?.prompt_info?.prompt ?? '',
|
||||
prompt_type: PromptType.SYSTEM,
|
||||
isOptimize: false,
|
||||
record_id: '',
|
||||
}) as unknown as RequiredBotPrompt,
|
||||
transformVo2Dto: persona =>
|
||||
({
|
||||
prompt: persona?.data || '',
|
||||
}) as unknown as BotInfoForUpdate['prompt_info'],
|
||||
initStore: botData => {
|
||||
const { setPersonaByImmer, transformDto2Vo } = get();
|
||||
botData &&
|
||||
setPersonaByImmer(store => {
|
||||
store.systemMessage = transformDto2Vo(botData);
|
||||
});
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultPersonaStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.persona',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import {
|
||||
type BotInfoForUpdate,
|
||||
type GetDraftBotInfoAgwData,
|
||||
type UserQueryCollectConf,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
|
||||
import {
|
||||
type SetterAction,
|
||||
setterActionFactory,
|
||||
} from '../utils/setter-factory';
|
||||
export interface QueryCollectStore {
|
||||
is_collected: boolean;
|
||||
private_policy: string;
|
||||
}
|
||||
|
||||
export const getDefaultQueryCollectStore = (): QueryCollectStore => ({
|
||||
is_collected: false,
|
||||
private_policy: '',
|
||||
});
|
||||
|
||||
export interface QueryCollectAction {
|
||||
setQueryCollect: SetterAction<QueryCollectStore>;
|
||||
transformDto2Vo: (data: GetDraftBotInfoAgwData) => UserQueryCollectConf;
|
||||
transformVo2Dto: (
|
||||
queryCollectConf: UserQueryCollectConf,
|
||||
) => BotInfoForUpdate['user_query_collect_conf'];
|
||||
initStore: (data: GetDraftBotInfoAgwData) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
|
||||
export const useQueryCollectStore = create<
|
||||
QueryCollectStore & QueryCollectAction
|
||||
>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...getDefaultQueryCollectStore(),
|
||||
setQueryCollect: setterActionFactory<QueryCollectStore>(set),
|
||||
transformDto2Vo: botData => {
|
||||
const data = botData.bot_info?.user_query_collect_conf;
|
||||
return {
|
||||
is_collected: data?.is_collected,
|
||||
private_policy: data?.private_policy,
|
||||
};
|
||||
},
|
||||
transformVo2Dto: info => info,
|
||||
initStore: botData => {
|
||||
const { transformDto2Vo } = get();
|
||||
set(transformDto2Vo(botData));
|
||||
},
|
||||
clear: () => {
|
||||
set({ ...getDefaultQueryCollectStore() });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botDetail.queryCollect',
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 PartialRequired } from '@coze-arch/bot-typings/common';
|
||||
import type { DraftBotApi } from '@coze-arch/bot-api/playground_api';
|
||||
import type {
|
||||
AgentInfo,
|
||||
ModelInfo,
|
||||
JumpConfig,
|
||||
MultiAgentSessionType,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
import type {
|
||||
LineType,
|
||||
WorkflowEdgeJSON,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import type { BotDetailSkill, BotSuggestionConfig } from './skill';
|
||||
import type { RequiredBotPrompt } from './persona';
|
||||
|
||||
/** multi agent 相关数据 */
|
||||
export interface BotMultiAgent {
|
||||
agents: Agent[];
|
||||
edges: WorkflowEdgeJSON[];
|
||||
connector_type: LineType;
|
||||
/** 用于保存 bot 类型节点的 bot 信息 */
|
||||
botAgentInfos: DraftBotVo[];
|
||||
/**
|
||||
* 会话接管方式配置
|
||||
* 默认为 flow 模式
|
||||
*/
|
||||
chatModeConfig: ChatModeConfig;
|
||||
}
|
||||
/** 业务用到的 */
|
||||
export interface AgentBizInfo {
|
||||
focused?: boolean;
|
||||
}
|
||||
|
||||
export type Agent = PartialRequired<Omit<AgentInfo, 'work_info'>, 'id'> & {
|
||||
prompt: string;
|
||||
model: ModelInfo;
|
||||
skills: Pick<
|
||||
BotDetailSkill,
|
||||
'pluginApis' | 'workflows' | 'knowledge' | 'devHooks'
|
||||
>;
|
||||
system_info_all: Array<RequiredBotPrompt>;
|
||||
bizInfo: AgentBizInfo;
|
||||
jump_config: JumpConfig;
|
||||
suggestion: BotSuggestionConfig;
|
||||
};
|
||||
|
||||
/** api 返回的 bot 信息中,部分字段是 json,本类型是 parse 后的类型 */
|
||||
export type DraftBotVo = Omit<DraftBotApi, 'work_info'> & {
|
||||
work_info: {
|
||||
suggest_reply: BotSuggestionConfig;
|
||||
};
|
||||
};
|
||||
|
||||
export type ChatModeConfig =
|
||||
| {
|
||||
/** 会话接管方式 */
|
||||
type: MultiAgentSessionType.Flow;
|
||||
}
|
||||
| {
|
||||
/** 会话接管方式 */
|
||||
type: MultiAgentSessionType.Host;
|
||||
/** 当前的 host 节点 id */
|
||||
currentHostId: string;
|
||||
};
|
||||
|
||||
export interface MultiSheetViewOpenState {
|
||||
left: boolean;
|
||||
right: boolean;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 TaskNotice,
|
||||
type PicTask,
|
||||
type GeneratePicPrompt,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
|
||||
export enum GenerateType {
|
||||
Static = 'static',
|
||||
Gif = 'gif',
|
||||
}
|
||||
export enum DotStatus {
|
||||
Generating = 1,
|
||||
Success,
|
||||
Fail,
|
||||
Cancel,
|
||||
None,
|
||||
}
|
||||
|
||||
export interface GenerateGifInfo {
|
||||
loading: boolean;
|
||||
dotStatus: DotStatus;
|
||||
text: string;
|
||||
image: PicTask;
|
||||
}
|
||||
|
||||
export interface GenerateAvatarModal {
|
||||
visible: boolean;
|
||||
activeKey: GenerateType;
|
||||
selectedImage: PicTask;
|
||||
generatingTaskId?: string;
|
||||
gif: GenerateGifInfo;
|
||||
image: {
|
||||
loading: boolean;
|
||||
dotStatus: DotStatus;
|
||||
text: string;
|
||||
textCustomizable: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface GenerateBackGroundModal {
|
||||
activeKey: GenerateType;
|
||||
selectedImage: PicTask;
|
||||
generatingTaskId?: string;
|
||||
gif: GenerateGifInfo;
|
||||
image: {
|
||||
loading: boolean;
|
||||
dotStatus: DotStatus;
|
||||
promptInfo: GeneratePicPrompt;
|
||||
};
|
||||
}
|
||||
|
||||
// 异步生成图片的状态
|
||||
export interface GenerateImageState {
|
||||
// 候选图列表信息
|
||||
imageList: PicTask[];
|
||||
// 生成图片消息信息
|
||||
noticeList: TaskNotice[];
|
||||
// 头像弹窗内生成图片的状态
|
||||
generateAvatarModal: GenerateAvatarModal;
|
||||
// 背景图弹窗内生成图片的状态
|
||||
generateBackGroundModal: GenerateBackGroundModal;
|
||||
}
|
||||
|
||||
export interface GenerateImageAction {
|
||||
updateImageList: (list: PicTask[]) => void;
|
||||
pushImageList: (image: PicTask) => void;
|
||||
// updateImageList: (update: (state: PicTask[]) => void) => void;
|
||||
updateNoticeList: (list: TaskNotice[]) => void;
|
||||
setGenerateAvatarModal: (state: GenerateAvatarModal) => void;
|
||||
resetGenerateAvatarModal: () => void;
|
||||
setGenerateAvatarModalByImmer: (
|
||||
update: (state: GenerateAvatarModal) => void,
|
||||
) => void;
|
||||
setGenerateBackgroundModalByImmer: (
|
||||
update: (state: GenerateBackGroundModal) => void,
|
||||
) => void;
|
||||
clearGenerateImageStore: () => void;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 { Model, ModelInfo } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
/** 模型设置 */
|
||||
export interface BotDetailModel {
|
||||
config: ModelInfo;
|
||||
/** 全部可选模型 */
|
||||
modelList: Model[];
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 { BotPrompt, PromptType } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
export interface RequiredBotPrompt extends BotPrompt {
|
||||
prompt_type: PromptType;
|
||||
data: string;
|
||||
isOptimize: boolean;
|
||||
record_id?: string;
|
||||
}
|
||||
260
frontend/packages/studio/stores/bot-detail/src/types/skill.ts
Normal file
260
frontend/packages/studio/stores/bot-detail/src/types/skill.ts
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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 ShortCutStruct } from '@coze-agent-ide/tool-config/src/shortcut-config/type';
|
||||
import {
|
||||
type PluginStatus,
|
||||
type PluginType,
|
||||
} from '@coze-arch/idl/plugin_develop';
|
||||
import { type WorkflowMode } from '@coze-arch/bot-api/workflow_api';
|
||||
import {
|
||||
type HookInfo,
|
||||
type LayoutInfo,
|
||||
type BackgroundImageInfo,
|
||||
type SuggestedQuestionsShowMode,
|
||||
type DisablePromptCalling,
|
||||
type RecallStrategy,
|
||||
type DefaultUserInputType,
|
||||
} from '@coze-arch/bot-api/playground_api';
|
||||
import {
|
||||
type BotTableRWMode,
|
||||
type FieldItem,
|
||||
} from '@coze-arch/bot-api/memory';
|
||||
import { type Dataset } from '@coze-arch/bot-api/knowledge';
|
||||
import type {
|
||||
FileboxInfo,
|
||||
PluginApi,
|
||||
PluginParameter,
|
||||
TaskInfoData,
|
||||
TaskInfo,
|
||||
SuggestReplyMode,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
interface DefaultPluginApi extends PluginApi {
|
||||
isAuto?: boolean;
|
||||
autoAddCss?: boolean;
|
||||
// #region api所在的 plugin 维度字段
|
||||
plugin_type?: PluginType;
|
||||
is_official?: boolean;
|
||||
plugin_icon?: string;
|
||||
status?: PluginStatus;
|
||||
// #endregion
|
||||
}
|
||||
export type EnabledPluginApi = Omit<DefaultPluginApi, 'debug_example'>;
|
||||
|
||||
export interface BotDetailSkill {
|
||||
// region Bot 和 Agent 维度共有 skills
|
||||
/** 已选的 plugin api */
|
||||
pluginApis: EnabledPluginApi[];
|
||||
/** 已选 workflow */
|
||||
workflows: WorkFlowItemType[];
|
||||
/** Knowledge 配置 */
|
||||
knowledge: KnowledgeConfig;
|
||||
// endregion
|
||||
|
||||
// region Bot 维度独有 skills
|
||||
/**
|
||||
* task 配置
|
||||
*
|
||||
* 不含已添加的 task,已添加的在组件内独立管理
|
||||
*/
|
||||
taskInfo: TaskManageInfo;
|
||||
/**
|
||||
* variable 默认值配置
|
||||
*
|
||||
* 不含右上角现值,现值为打开弹窗后请求获得的组件状态
|
||||
*/
|
||||
variables: VariableItem[];
|
||||
/**
|
||||
* database 默认值配置
|
||||
*
|
||||
* 不含右上角现值,现值为打开弹窗后请求获得的组件状态
|
||||
*/
|
||||
database: DatabaseInfo;
|
||||
/**
|
||||
* database 多表默认值配置
|
||||
*
|
||||
* 不含右上角现值,现值为打开弹窗后请求获得的组件状态
|
||||
*/
|
||||
databaseList: DatabaseList;
|
||||
/** 开场白配置 */
|
||||
onboardingContent: ExtendOnboardingContent;
|
||||
/** 用户问题建议配置 */
|
||||
suggestionConfig: BotSuggestionConfig;
|
||||
// endregion
|
||||
/** 文字转语音 */
|
||||
tts: TTSInfo;
|
||||
// 时间胶囊
|
||||
timeCapsule: TimeCapsuleConfig;
|
||||
filebox: FileboxConfig;
|
||||
// 聊天背景图
|
||||
backgroundImageInfoList: BackgroundImageInfo[];
|
||||
// 快捷指令
|
||||
shortcut: ShortCutStruct;
|
||||
// hooks
|
||||
devHooks?: HookInfo;
|
||||
layoutInfo: LayoutInfo;
|
||||
}
|
||||
|
||||
export interface TaskManageInfo {
|
||||
user_task_allowed: boolean;
|
||||
/** 请求task loading状态,业务使用 */
|
||||
loading: boolean;
|
||||
/** task接口数据,业务使用 */
|
||||
data: TaskInfoData[];
|
||||
/** 新版task接口数据,业务使用 */
|
||||
task_list: TaskInfo[];
|
||||
}
|
||||
|
||||
export enum VariableKeyErrType {
|
||||
KEY_CHECK_PASS = 0, // 检查通过
|
||||
KEY_NAME_USED = 1, // 名称被占用
|
||||
|
||||
KEY_IS_NULL = 2, // 为空值
|
||||
}
|
||||
|
||||
export interface TableMemoryItem extends FieldItem {
|
||||
errorMapper?: Record<string, string[]>;
|
||||
disableMustRequired?: boolean;
|
||||
nanoid?: string;
|
||||
/**
|
||||
* 是否是内置字段
|
||||
* @description 内置字段: 仅作展示用,用户不可修改,不可创建同名字段
|
||||
*/
|
||||
isSystemField?: boolean;
|
||||
}
|
||||
|
||||
export interface DatabaseInfo {
|
||||
tableId: string;
|
||||
name: string;
|
||||
desc: string;
|
||||
icon_uri?: string;
|
||||
extra_info?: Record<string, string>;
|
||||
readAndWriteMode: BotTableRWMode;
|
||||
tableMemoryList: TableMemoryItem[];
|
||||
}
|
||||
export type DatabaseList = DatabaseInfo[];
|
||||
|
||||
export interface VariableItem {
|
||||
id?: string;
|
||||
key?: string;
|
||||
description?: string;
|
||||
enable?: boolean;
|
||||
channel?: string;
|
||||
default_value?: string;
|
||||
errType?: VariableKeyErrType;
|
||||
is_system?: boolean;
|
||||
prompt_disabled?: boolean;
|
||||
is_disabled?: boolean;
|
||||
}
|
||||
|
||||
export interface TagListType {
|
||||
tagName: string;
|
||||
key: string;
|
||||
id: string;
|
||||
name: string;
|
||||
style_id: string;
|
||||
language_code: string;
|
||||
language_name: string;
|
||||
}
|
||||
|
||||
export interface ChatVoiceType {
|
||||
key?: string;
|
||||
id: string;
|
||||
name?: string;
|
||||
style_id: string;
|
||||
language_code: string;
|
||||
language_name?: string;
|
||||
}
|
||||
export interface DebugStateType {
|
||||
bot_id: string;
|
||||
voice_id?: string;
|
||||
enable?: boolean;
|
||||
style_id?: string;
|
||||
}
|
||||
export interface TTSInfo {
|
||||
muted: boolean;
|
||||
close_voice_call: boolean;
|
||||
i18n_lang_voice: Record<string, number>;
|
||||
i18n_lang_voice_str: Record<string, string>;
|
||||
autoplay: boolean;
|
||||
autoplay_voice: Record<string, number>;
|
||||
tag_list?: TagListType[];
|
||||
chatVoiceList?: ChatVoiceType[];
|
||||
debugVoice: DebugStateType[];
|
||||
}
|
||||
|
||||
export enum TimeCapsuleOptionsEnum {
|
||||
ON = 1,
|
||||
OFF = 0,
|
||||
}
|
||||
|
||||
export interface TimeCapsuleConfig {
|
||||
time_capsule_mode: TimeCapsuleOptionsEnum;
|
||||
disable_prompt_calling: DisablePromptCalling;
|
||||
time_capsule_time_to_live: string;
|
||||
}
|
||||
|
||||
export interface WorkFlowItemType {
|
||||
workflow_id: string;
|
||||
plugin_id: string;
|
||||
name: string;
|
||||
desc: string;
|
||||
parameters: Array<PluginParameter>;
|
||||
plugin_icon: string;
|
||||
flow_mode?: WorkflowMode;
|
||||
}
|
||||
|
||||
export interface KnowledgeConfig {
|
||||
/** 已选的 knowledge */
|
||||
dataSetList: Array<Dataset>;
|
||||
dataSetInfo: {
|
||||
min_score: number;
|
||||
search_strategy?: number;
|
||||
top_k: number;
|
||||
auto: boolean;
|
||||
show_source?: boolean;
|
||||
no_recall_reply_mode?: number;
|
||||
no_recall_reply_customize_prompt?: string;
|
||||
show_source_mode?: number;
|
||||
recall_strategy?: RecallStrategy;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SuggestQuestionMessage {
|
||||
id: string;
|
||||
content: string;
|
||||
highlight?: boolean;
|
||||
}
|
||||
export interface ExtendOnboardingContent {
|
||||
prologue: string;
|
||||
suggested_questions: SuggestQuestionMessage[];
|
||||
suggested_questions_show_mode: SuggestedQuestionsShowMode;
|
||||
}
|
||||
|
||||
export interface BotSuggestionConfig {
|
||||
/** 0 开启; 1 自定义; 2 关闭; 3 跟随 bot(仅 agentflow bot 节点) */
|
||||
suggest_reply_mode: SuggestReplyMode;
|
||||
customized_suggest_prompt: string;
|
||||
}
|
||||
|
||||
export interface FileboxConfig {
|
||||
mode: FileboxInfo['mode'];
|
||||
}
|
||||
|
||||
export interface VoicesInfo {
|
||||
defaultUserInputType: DefaultUserInputType | undefined;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 type RemoveOptional<T> = {
|
||||
[K in keyof T]-?: T[K];
|
||||
};
|
||||
|
||||
export type UnionUndefined<T> = {
|
||||
[K in keyof T]: T[K] | undefined;
|
||||
};
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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 { withSlardarIdButton } from '@coze-studio/bot-utils';
|
||||
import { logger } from '@coze-arch/logger';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { arrayBufferToObject } from '@coze-arch/bot-utils';
|
||||
import {
|
||||
type GenPicMessage,
|
||||
PicType,
|
||||
} from '@coze-arch/bot-api/playground_api';
|
||||
import { PlaygroundApi } from '@coze-arch/bot-api';
|
||||
import webSocketManager, {
|
||||
type Connection,
|
||||
type FrontierEventMap,
|
||||
} from '@coze-common/websocket-manager-adapter';
|
||||
import { Toast } from '@coze-arch/coze-design';
|
||||
|
||||
import { getBotDetailIsReadonly } from '../get-read-only';
|
||||
import { DotStatus } from '../../types/generate-image';
|
||||
import { useGenerateImageStore } from '../../store/generate-image-store';
|
||||
import { useBotInfoStore } from '../../store/bot-info';
|
||||
|
||||
class AvatarBackgroundWebSocket {
|
||||
private connection: Connection | undefined;
|
||||
private eventListenerList:
|
||||
| Array<{
|
||||
key: keyof FrontierEventMap;
|
||||
listener: (event) => void;
|
||||
}>
|
||||
| undefined;
|
||||
private biz: string;
|
||||
private service: number | undefined;
|
||||
private taskSet = new Set();
|
||||
|
||||
constructor(biz: string, service: number) {
|
||||
this.biz = biz;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
createConnection(retry = true) {
|
||||
if (this.connection) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.connection = webSocketManager.createConnection({
|
||||
biz: this.biz,
|
||||
service: this.service,
|
||||
});
|
||||
this.addWSEventListener();
|
||||
} catch (error) {
|
||||
// 重试一次
|
||||
if (retry) {
|
||||
this.createConnection(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.connection) {
|
||||
this.eventListenerList?.forEach(({ key, listener }) => {
|
||||
this.connection?.removeEventListener(key, listener);
|
||||
});
|
||||
this.connection?.close();
|
||||
this.connection = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private addWSEventListener() {
|
||||
this.eventListenerList = [
|
||||
{ key: 'message', listener: this.onSocketMessage },
|
||||
{ key: 'error', listener: this.onSocketError },
|
||||
];
|
||||
this.eventListenerList?.forEach(({ key, listener }) => {
|
||||
this.connection?.addEventListener(key, listener);
|
||||
});
|
||||
}
|
||||
|
||||
private onSocketMessage = event => {
|
||||
const payload = arrayBufferToObject(
|
||||
event?.message?.payload,
|
||||
) as GenPicMessage;
|
||||
const task = payload?.pic_task;
|
||||
const taskId = task?.id || '';
|
||||
if (this.taskSet.has(taskId)) {
|
||||
logger.info({
|
||||
message: 'duplicate task',
|
||||
meta: { taskId },
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.taskSet.add(taskId);
|
||||
const botId = useBotInfoStore.getState().botId || '0';
|
||||
|
||||
if (botId !== '0' && getBotDetailIsReadonly()) {
|
||||
return;
|
||||
}
|
||||
const taskBotId = task?.bot_id || '0';
|
||||
if (task && taskBotId === botId) {
|
||||
const {
|
||||
generateAvatarModal,
|
||||
generateBackGroundModal,
|
||||
setGenerateAvatarModalByImmer,
|
||||
setGenerateBackgroundModalByImmer,
|
||||
pushImageList,
|
||||
} = useGenerateImageStore.getState();
|
||||
const {
|
||||
gif: { dotStatus: avatarGifDotStatus },
|
||||
image: { dotStatus: avatarStaticImageDotStatus },
|
||||
} = generateAvatarModal;
|
||||
const {
|
||||
gif: { dotStatus: backgroundGifDotStatus },
|
||||
image: { dotStatus: backgroundStaticImageDotStatus },
|
||||
} = generateBackGroundModal;
|
||||
const { status } = task;
|
||||
// 收到消息后更新头像或背景
|
||||
const updateState = (
|
||||
key: string,
|
||||
setImmer:
|
||||
| typeof setGenerateAvatarModalByImmer
|
||||
| typeof setGenerateBackgroundModalByImmer,
|
||||
currentDotStatus: DotStatus,
|
||||
) => {
|
||||
let dotStatus = DotStatus.None;
|
||||
if (currentDotStatus === DotStatus.Generating) {
|
||||
dotStatus =
|
||||
(status as number) === DotStatus.Success
|
||||
? DotStatus.Success
|
||||
: DotStatus.Fail;
|
||||
} else {
|
||||
// 标为已读
|
||||
if (taskBotId !== '0') {
|
||||
PlaygroundApi.MarkReadNotice({
|
||||
bot_id: taskBotId,
|
||||
pic_type: task.type,
|
||||
});
|
||||
}
|
||||
if ((status as number) === DotStatus.Fail) {
|
||||
Toast.error({
|
||||
content: withSlardarIdButton(
|
||||
payload?.err_msg || I18n.t('profilepicture_toast_failed'),
|
||||
),
|
||||
});
|
||||
} else if ((status as number) === DotStatus.Success) {
|
||||
Toast.success(I18n.t('profilepicture_toast_generated'));
|
||||
}
|
||||
}
|
||||
setImmer(state => {
|
||||
state[key] = {
|
||||
...state[key],
|
||||
loading: false,
|
||||
dotStatus,
|
||||
generateTaskId: '',
|
||||
};
|
||||
if ((status as number) === DotStatus.Success) {
|
||||
state.selectedImage = task;
|
||||
}
|
||||
});
|
||||
if ((status as number) === DotStatus.Success) {
|
||||
pushImageList(task);
|
||||
}
|
||||
};
|
||||
switch (task.type) {
|
||||
case PicType.IconGif: {
|
||||
updateState('gif', setGenerateAvatarModalByImmer, avatarGifDotStatus);
|
||||
break;
|
||||
}
|
||||
case PicType.IconStatic: {
|
||||
updateState(
|
||||
'image',
|
||||
setGenerateAvatarModalByImmer,
|
||||
avatarStaticImageDotStatus,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case PicType.BackgroundGif: {
|
||||
updateState(
|
||||
'gif',
|
||||
setGenerateBackgroundModalByImmer,
|
||||
backgroundGifDotStatus,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case PicType.BackgroundStatic: {
|
||||
updateState(
|
||||
'image',
|
||||
setGenerateBackgroundModalByImmer,
|
||||
backgroundStaticImageDotStatus,
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private onSocketError = event => {
|
||||
// TODO
|
||||
};
|
||||
}
|
||||
|
||||
const getPluginServiceId = () => {
|
||||
// region/service_id映射
|
||||
const regionServiceIdMap = {
|
||||
boe: 16778137,
|
||||
cn: 33554636,
|
||||
sg: 67108932,
|
||||
va: 67108932,
|
||||
};
|
||||
return regionServiceIdMap[IS_BOE ? 'boe' : REGION];
|
||||
};
|
||||
const serviceID = getPluginServiceId();
|
||||
|
||||
export const avatarBackgroundWebSocket = new AvatarBackgroundWebSocket(
|
||||
'EditorPic',
|
||||
serviceID,
|
||||
);
|
||||
|
||||
export function initAvatarBackgroundWebSocket() {
|
||||
// 创建连接
|
||||
setTimeout(() => {
|
||||
const {
|
||||
generateAvatarModal: {
|
||||
gif: { dotStatus: avatarGifDotStatus },
|
||||
image: { dotStatus: avatarStaticImageDotStatus },
|
||||
},
|
||||
generateBackGroundModal: {
|
||||
gif: { dotStatus: backgroundGifDotStatus },
|
||||
image: { dotStatus: backgroundStaticImageDotStatus },
|
||||
},
|
||||
} = useGenerateImageStore.getState();
|
||||
if (
|
||||
[
|
||||
avatarGifDotStatus,
|
||||
avatarStaticImageDotStatus,
|
||||
backgroundGifDotStatus,
|
||||
backgroundStaticImageDotStatus,
|
||||
].includes(DotStatus.Generating)
|
||||
) {
|
||||
avatarBackgroundWebSocket.createConnection();
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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 { globalVars } from '@coze-arch/web-context';
|
||||
|
||||
export const getExecuteDraftBotRequestId = (): string =>
|
||||
globalVars.LAST_EXECUTE_ID;
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 { withSlardarIdButton } from '@coze-studio/bot-utils';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Toast } from '@coze-arch/bot-semi';
|
||||
import { AgentType } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import type { BotMultiAgent, Agent } from '../types/agent';
|
||||
|
||||
export const findFirstAgent = (
|
||||
multiAgent: BotMultiAgent,
|
||||
): Agent | undefined => {
|
||||
const startNode = multiAgent.agents.find(
|
||||
agent => agent.agent_type === AgentType.Start_Agent,
|
||||
);
|
||||
if (!startNode) {
|
||||
Toast.error({
|
||||
content: withSlardarIdButton(I18n.t('chatflow_error_miss_start')),
|
||||
});
|
||||
return;
|
||||
}
|
||||
const firstAgentId = multiAgent.edges.find(
|
||||
edge => edge.sourceNodeID === startNode.id,
|
||||
)?.targetNodeID;
|
||||
if (!firstAgentId) {
|
||||
Toast.error({
|
||||
content: withSlardarIdButton(I18n.t('chatflow_error_miss_start_agent')),
|
||||
});
|
||||
return;
|
||||
}
|
||||
return findTargetAgent(multiAgent.agents, firstAgentId);
|
||||
};
|
||||
|
||||
export const findTargetAgent = (agents: Agent[], agentId?: string) => {
|
||||
if (!agentId) {
|
||||
return;
|
||||
}
|
||||
return agents.find(item => item.id === agentId);
|
||||
};
|
||||
|
||||
/** 寻找某个agent,其中该agent的intent的next_agent_id是当前的agent id */
|
||||
export const findAgentByNextIntentID = (
|
||||
agents: Agent[],
|
||||
nextAgentID?: string,
|
||||
) => {
|
||||
if (!nextAgentID) {
|
||||
return;
|
||||
}
|
||||
return agents.find(item =>
|
||||
(item.intents || []).some(intent => intent.next_agent_id === nextAgentID),
|
||||
);
|
||||
};
|
||||
|
||||
export const findTargetAgentIndex = (agents: Agent[], agentId?: string) => {
|
||||
if (!agentId) {
|
||||
return -1;
|
||||
}
|
||||
return agents.findIndex(item => item.id === agentId);
|
||||
};
|
||||
|
||||
/**
|
||||
* start 节点指向的节点 id
|
||||
*/
|
||||
export const findFirstAgentId = ({
|
||||
agents,
|
||||
}: Pick<BotMultiAgent, 'agents'>): string | undefined => {
|
||||
const startNode = agents.find(
|
||||
agent => agent.agent_type === AgentType.Start_Agent,
|
||||
);
|
||||
return startNode?.intents?.at(0)?.next_agent_id;
|
||||
};
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 {
|
||||
GenPicStatus,
|
||||
PicType,
|
||||
type GetPicTaskData,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
|
||||
import {
|
||||
type GenerateBackGroundModal,
|
||||
type GenerateAvatarModal,
|
||||
DotStatus,
|
||||
GenerateType,
|
||||
} from '../types/generate-image';
|
||||
import { useBotSkillStore } from '../store/bot-skill';
|
||||
import getDotStatus from './get-dot-status';
|
||||
|
||||
export const getInitBackgroundInfo = (
|
||||
data: GetPicTaskData,
|
||||
state: GenerateBackGroundModal,
|
||||
) => {
|
||||
const { tasks = [] } = data;
|
||||
const { backgroundImageInfoList = [] } = useBotSkillStore.getState();
|
||||
// 当前渲染的背景图
|
||||
const uri =
|
||||
backgroundImageInfoList[0]?.mobile_background_image?.origin_image_uri;
|
||||
|
||||
const backgroundGifList = tasks.filter(
|
||||
item => item.type && [PicType.BackgroundGif].includes(item.type),
|
||||
);
|
||||
const backgroundStaticList = tasks.filter(
|
||||
item => item.type && [PicType.BackgroundStatic].includes(item.type),
|
||||
);
|
||||
const imageDotStatus = getDotStatus(
|
||||
data,
|
||||
PicType.BackgroundStatic,
|
||||
) as DotStatus;
|
||||
const gifDotStatus = getDotStatus(data, PicType.BackgroundGif) as DotStatus;
|
||||
|
||||
// 动图相关state
|
||||
state.gif.loading = backgroundGifList.some(
|
||||
item => item.status === GenPicStatus.Generating,
|
||||
);
|
||||
state.gif.text =
|
||||
backgroundGifList.find(item => item?.img_info?.prompt)?.img_info?.prompt
|
||||
?.ori_prompt ?? '';
|
||||
|
||||
state.gif.dotStatus = gifDotStatus;
|
||||
const image = backgroundGifList.find(item => item.img_info?.ori_url);
|
||||
// 第一帧信息
|
||||
if (image) {
|
||||
state.gif.image = {
|
||||
img_info: {
|
||||
tar_uri: image.img_info?.ori_uri,
|
||||
tar_url: image.img_info?.ori_url,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// 静图相关state
|
||||
state.image.loading = backgroundStaticList.some(
|
||||
item => item.status === GenPicStatus.Generating,
|
||||
);
|
||||
state.image.dotStatus = imageDotStatus;
|
||||
state.image.promptInfo =
|
||||
backgroundStaticList.find(item => item?.img_info?.prompt?.ori_prompt)
|
||||
?.img_info?.prompt ?? {};
|
||||
|
||||
const lastImageTask =
|
||||
tasks.find(item => item.type === PicType.BackgroundStatic) ?? {};
|
||||
const lastGifTask =
|
||||
tasks.find(item => item.type === PicType.BackgroundGif) ?? {};
|
||||
// 当前选中的图片: 生成成功的 展示 成功的那个图, 否则找 背景图一致的
|
||||
if (gifDotStatus === DotStatus.Success) {
|
||||
state.selectedImage = lastGifTask;
|
||||
} else if (imageDotStatus === DotStatus.Success) {
|
||||
state.selectedImage = lastImageTask;
|
||||
} else {
|
||||
// 手动上传的 找不到
|
||||
state.selectedImage =
|
||||
tasks.find(item => item.img_info?.tar_uri === uri) ?? {};
|
||||
}
|
||||
// 当前tab:只有在 仅gif在状态不为done时 在gif tab
|
||||
if (gifDotStatus !== DotStatus.None) {
|
||||
state.activeKey = GenerateType.Gif;
|
||||
}
|
||||
// 当前正在生成的taskId
|
||||
if (
|
||||
gifDotStatus === DotStatus.Generating ||
|
||||
imageDotStatus === DotStatus.Generating
|
||||
) {
|
||||
state.generatingTaskId =
|
||||
gifDotStatus === DotStatus.Generating
|
||||
? lastGifTask?.id
|
||||
: lastImageTask?.id;
|
||||
}
|
||||
};
|
||||
|
||||
export const getInitAvatarInfo = (
|
||||
data: GetPicTaskData,
|
||||
state: GenerateAvatarModal,
|
||||
) => {
|
||||
const { tasks = [] } = data || {};
|
||||
const lastImageTask = tasks.find(
|
||||
item => item.type === PicType.IconStatic,
|
||||
) || {
|
||||
id: '',
|
||||
img_info: {},
|
||||
};
|
||||
const lastGifTask = tasks.find(item => item.type === PicType.IconGif) || {
|
||||
id: '',
|
||||
img_info: {},
|
||||
};
|
||||
const gifDotStatus = getDotStatus(data, PicType.IconGif) as DotStatus;
|
||||
const imageDotStatus = getDotStatus(data, PicType.IconStatic) as DotStatus;
|
||||
if (
|
||||
gifDotStatus === DotStatus.Success ||
|
||||
imageDotStatus === DotStatus.Success
|
||||
) {
|
||||
state.selectedImage =
|
||||
gifDotStatus === DotStatus.Success ? lastGifTask : lastImageTask;
|
||||
}
|
||||
|
||||
if (
|
||||
gifDotStatus === DotStatus.Generating ||
|
||||
imageDotStatus === DotStatus.Generating
|
||||
) {
|
||||
state.generatingTaskId =
|
||||
gifDotStatus === DotStatus.Generating
|
||||
? lastGifTask?.id
|
||||
: lastImageTask?.id;
|
||||
}
|
||||
state.gif = {
|
||||
dotStatus: gifDotStatus,
|
||||
text: lastGifTask?.img_info?.prompt?.ori_prompt ?? '',
|
||||
loading: gifDotStatus === DotStatus.Generating,
|
||||
image: {
|
||||
id: lastGifTask.img_info?.ori_uri ?? '',
|
||||
img_info: {
|
||||
tar_uri: lastGifTask.img_info?.ori_uri ?? '',
|
||||
tar_url: lastGifTask.img_info?.ori_url ?? '',
|
||||
},
|
||||
},
|
||||
};
|
||||
state.image = {
|
||||
dotStatus: imageDotStatus,
|
||||
text: lastImageTask.img_info?.prompt?.ori_prompt ?? '',
|
||||
loading: imageDotStatus === DotStatus.Generating,
|
||||
textCustomizable: Boolean(lastImageTask.img_info?.prompt?.ori_prompt),
|
||||
};
|
||||
};
|
||||
@@ -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 {
|
||||
type PicType,
|
||||
type GetPicTaskData,
|
||||
} from '@coze-arch/idl/playground_api';
|
||||
|
||||
import { DotStatus } from '../types/generate-image';
|
||||
|
||||
function getDotStatus(data: GetPicTaskData, picType: PicType) {
|
||||
const { notices = [], tasks = [] } = data || {};
|
||||
const task = tasks.find(item => item.type === picType);
|
||||
return (task?.status as number) === DotStatus.Generating ||
|
||||
notices.some(item => item.type === picType && item.un_read)
|
||||
? task?.status ?? DotStatus.None
|
||||
: DotStatus.None;
|
||||
}
|
||||
|
||||
export default getDotStatus;
|
||||
@@ -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 { usePageRuntimeStore } from '../store/page-runtime';
|
||||
import { useCollaborationStore, EditLockStatus } from '../store/collaboration';
|
||||
|
||||
/**
|
||||
* 非响应式;参考 useBotDetailIsReadonly 方法
|
||||
*/
|
||||
export function getBotDetailIsReadonly() {
|
||||
const pageRuntime = usePageRuntimeStore.getState();
|
||||
const collaboration = useCollaborationStore.getState();
|
||||
return getBotDetailIsReadonlyByState({
|
||||
editable: pageRuntime.editable,
|
||||
isPreview: pageRuntime.isPreview,
|
||||
editLockStatus: collaboration.editLockStatus,
|
||||
});
|
||||
}
|
||||
|
||||
export const getBotDetailIsReadonlyByState = ({
|
||||
editable,
|
||||
isPreview,
|
||||
editLockStatus,
|
||||
}: {
|
||||
editable: boolean;
|
||||
isPreview: boolean;
|
||||
editLockStatus?: EditLockStatus;
|
||||
}) => !editable || isPreview || editLockStatus === EditLockStatus.Lose;
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 { Toast } from '@coze-arch/bot-semi';
|
||||
import { MultiAgentSessionType } from '@coze-arch/bot-api/playground_api';
|
||||
|
||||
import { useMultiAgentStore } from '../store/multi-agent';
|
||||
import { useManuallySwitchAgentStore } from '../store/manually-switch-agent-store';
|
||||
import { saveDeleteAgents } from '../save-manager/manual-save/multi-agent';
|
||||
import { findTargetAgentIndex } from './find-agent';
|
||||
|
||||
/**
|
||||
* FG全量后,默认用结构化的新接口
|
||||
*/
|
||||
export const deleteAgent = async (agentId?: string) => {
|
||||
if (!agentId) {
|
||||
return;
|
||||
}
|
||||
await saveDeleteAgents(agentId);
|
||||
useMultiAgentStore.getState().setMultiAgentByImmer(multiAgent => {
|
||||
const { agents } = multiAgent;
|
||||
// 找到要删除的位置
|
||||
const targetAgentIndex = findTargetAgentIndex(agents, agentId);
|
||||
if (targetAgentIndex < 0) {
|
||||
Toast.error(I18n.t('chatflow_error_delete_failed'));
|
||||
return;
|
||||
}
|
||||
// 删除当前的agent
|
||||
agents.splice(targetAgentIndex, 1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 用户手动切换 chatting 节点
|
||||
*
|
||||
* host 模式下会一并切换 host 节点
|
||||
*/
|
||||
export const manuallySwitchAgent = (agentID: string) => {
|
||||
const { setMultiAgentByImmer } = useMultiAgentStore.getState();
|
||||
useManuallySwitchAgentStore
|
||||
.getState()
|
||||
.recordAgentIdOnManuallySwitchAgent(agentID);
|
||||
setMultiAgentByImmer(multiAgent => {
|
||||
multiAgent.currentAgentID = agentID;
|
||||
if (multiAgent.chatModeConfig.type === MultiAgentSessionType.Host) {
|
||||
multiAgent.chatModeConfig.currentHostId = agentID;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -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 { type Branch, type Committer } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import { useCollaborationStore } from '../store/collaboration';
|
||||
|
||||
interface HeaderStatusType {
|
||||
branch?: Branch;
|
||||
same_with_online?: boolean;
|
||||
committer?: Committer;
|
||||
commit_version?: string;
|
||||
}
|
||||
|
||||
export function updateHeaderStatus(props: HeaderStatusType) {
|
||||
const { setCollaborationByImmer } = useCollaborationStore.getState();
|
||||
setCollaborationByImmer(store => {
|
||||
store.sameWithOnline = props.same_with_online ?? false;
|
||||
if (props.committer) {
|
||||
store.commit_time = props.committer.commit_time ?? '';
|
||||
store.committer_name = props.committer.name ?? '';
|
||||
}
|
||||
if (props.commit_version) {
|
||||
store.commit_version = props.commit_version;
|
||||
store.baseVersion = props.commit_version;
|
||||
}
|
||||
if (props.branch) {
|
||||
store.branch = props.branch;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -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 { omit } from 'lodash-es';
|
||||
import type { PluginApi } from '@coze-arch/bot-api/playground_api';
|
||||
|
||||
import { type EnabledPluginApi } from '../types/skill';
|
||||
|
||||
// 过滤 debug_example 字段 以免超出模型解析长度
|
||||
export const getPluginApisFilterExample = (
|
||||
pluginApis: PluginApi[],
|
||||
): EnabledPluginApi[] => pluginApis.map(item => omit(item, 'debug_example'));
|
||||
|
||||
export const getSinglePluginApiFilterExample = (
|
||||
tool: PluginApi,
|
||||
): EnabledPluginApi => omit(tool, 'debug_example');
|
||||
@@ -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 { PromptType } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
export function replacedBotPrompt(data) {
|
||||
return [
|
||||
{
|
||||
prompt_type: PromptType.SYSTEM,
|
||||
data: data.data,
|
||||
record_id: data.record_id,
|
||||
},
|
||||
{
|
||||
prompt_type: PromptType.USERPREFIX,
|
||||
data: '',
|
||||
},
|
||||
{
|
||||
prompt_type: PromptType.USERSUFFIX,
|
||||
data: '',
|
||||
},
|
||||
];
|
||||
}
|
||||
42
frontend/packages/studio/stores/bot-detail/src/utils/save.ts
Normal file
42
frontend/packages/studio/stores/bot-detail/src/utils/save.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 BotPrompt, PromptType } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
import { usePersonaStore } from '../store/persona';
|
||||
|
||||
export interface SaveBotPrompt extends BotPrompt {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export const getReplacedBotPrompt = () => {
|
||||
const { systemMessage } = usePersonaStore.getState();
|
||||
|
||||
return [
|
||||
{
|
||||
prompt_type: PromptType.SYSTEM,
|
||||
data: systemMessage.data,
|
||||
},
|
||||
{
|
||||
prompt_type: PromptType.USERPREFIX,
|
||||
data: '',
|
||||
},
|
||||
{
|
||||
prompt_type: PromptType.USERSUFFIX,
|
||||
data: '',
|
||||
},
|
||||
];
|
||||
};
|
||||
@@ -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 { type create } from 'zustand';
|
||||
|
||||
export interface SetterAction<T> {
|
||||
/**
|
||||
* 增量更新
|
||||
*
|
||||
* @example
|
||||
* // store.x: { a: 1, b: 2 }
|
||||
* setX({a: 2});
|
||||
* // store.x: { a: 2, b: 2 }
|
||||
*/
|
||||
(state: Partial<T>): void;
|
||||
/**
|
||||
* 全量更新
|
||||
*
|
||||
* @example
|
||||
* // store.x: { a: 1, b: 2 }
|
||||
* setX({a: 2}, { replace: true });
|
||||
* // store.x: { a: 2 }
|
||||
*/
|
||||
(state: T, config: { replace: true }): void;
|
||||
}
|
||||
|
||||
export function setterActionFactory<T>(
|
||||
set: Parameters<Parameters<typeof create<T, []>>[0]>[0],
|
||||
): SetterAction<T> {
|
||||
return (state: Partial<T>, config?: { replace: true }) => {
|
||||
if (config?.replace) {
|
||||
set(state);
|
||||
} else {
|
||||
set(prevState => ({ ...prevState, ...state }));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 { useCollaborationStore } from '../store/collaboration';
|
||||
|
||||
export function createStorage<T extends object>(
|
||||
s: Storage,
|
||||
target: T,
|
||||
prefix = 'common_storage',
|
||||
) {
|
||||
return new Proxy(target, {
|
||||
set: (_, prop: string, value) => {
|
||||
if (typeof value === 'string') {
|
||||
s.setItem(`${prefix}.${prop}`, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
get: (_, prop: string) => s.getItem(`${prefix}.${prop}`) ?? undefined,
|
||||
deleteProperty: (_, prop): boolean => {
|
||||
if (typeof prop === 'string') {
|
||||
s.removeItem(`${prefix}.${prop}`);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
});
|
||||
}
|
||||
export const storageLocal = createStorage<Record<string, string | undefined>>(
|
||||
localStorage,
|
||||
{},
|
||||
);
|
||||
|
||||
// NOTICE: 定制逻辑: baseVersion转从 bot_detail_store中获取
|
||||
export const storage = new Proxy(storageLocal, {
|
||||
get: (target, prop: string, receiver) => {
|
||||
if (prop === 'baseVersion') {
|
||||
return useCollaborationStore.getState().getBaseVersion();
|
||||
}
|
||||
return Reflect.get(target, prop, receiver);
|
||||
},
|
||||
set(target, prop, ...rest) {
|
||||
if (prop === 'baseVersion') {
|
||||
console.error(
|
||||
'you should use botDetailStore instead of storage to keep base_commit_version',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return Reflect.set(target, prop, ...rest);
|
||||
},
|
||||
});
|
||||
@@ -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 { I18n } from '@coze-arch/i18n';
|
||||
import { UIToast } from '@coze-arch/bot-semi';
|
||||
|
||||
export const hasBraces = (str: string) => {
|
||||
const pattern = /{{/g;
|
||||
return pattern.test(str);
|
||||
};
|
||||
// 判断是所有环境还是 只是release 环境限制{{}} 并弹出toast提示
|
||||
export const verifyBracesAndToast = (str: string, isAll = false) => {
|
||||
if (isAll && hasBraces(str)) {
|
||||
UIToast.warning({
|
||||
showClose: false,
|
||||
content: I18n.t('bot_prompt_bracket_error'),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -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 VariableItem, VariableKeyErrType } from '../types/skill';
|
||||
|
||||
export function uniqMemoryList(
|
||||
list: VariableItem[],
|
||||
sysVariables: VariableItem[] = [],
|
||||
) {
|
||||
return list.map(i => {
|
||||
const res = { ...i };
|
||||
if (
|
||||
list.filter(j => j.key === i.key).length === 1 &&
|
||||
sysVariables.filter(v => v.key === i.key)?.length === 0
|
||||
) {
|
||||
res.errType = VariableKeyErrType.KEY_CHECK_PASS;
|
||||
} else {
|
||||
res.errType = VariableKeyErrType.KEY_NAME_USED;
|
||||
}
|
||||
if (!i.key) {
|
||||
res.errType = VariableKeyErrType.KEY_IS_NULL;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user