feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
233
frontend/packages/studio/stores/bot-plugin/src/context.tsx
Normal file
233
frontend/packages/studio/stores/bot-plugin/src/context.tsx
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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 {
|
||||
createContext,
|
||||
type PropsWithChildren,
|
||||
type FC,
|
||||
useRef,
|
||||
useContext,
|
||||
} from 'react';
|
||||
|
||||
import { useStoreWithEqualityFn } from 'zustand/traditional';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useCreation } from 'ahooks';
|
||||
import { REPORT_EVENTS } from '@coze-arch/report-events';
|
||||
import { CustomError } from '@coze-arch/bot-error';
|
||||
|
||||
import { type BotPluginStateAction } from './types/store/plugin';
|
||||
import { type BotPluginStore } from './types/store';
|
||||
import {
|
||||
createPluginHistoryPanelUIStore,
|
||||
type PluginHistoryPanelUIStore,
|
||||
} from './store/plugin-history-panel-ui';
|
||||
import { createPluginStore } from './store/plugin';
|
||||
|
||||
interface StoreRef {
|
||||
plugin?: BotPluginStore;
|
||||
}
|
||||
|
||||
export interface PluginNavType {
|
||||
toResource?: (
|
||||
res: string,
|
||||
resID?: string,
|
||||
query?: Record<string, string>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
options?: Record<string, any>,
|
||||
) => void;
|
||||
// submodule
|
||||
tool?: (
|
||||
toolID: string,
|
||||
query?: Record<string, string>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
options?: Record<string, any>,
|
||||
) => void;
|
||||
mocksetList?: (
|
||||
toolID: string,
|
||||
query?: Record<string, string>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
options?: Record<string, any>,
|
||||
) => void;
|
||||
mocksetDetail?: (
|
||||
toolID: string,
|
||||
mocksetID: string,
|
||||
query?: Record<string, string>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
options?: Record<string, any>,
|
||||
) => void;
|
||||
cloudIDE?: (
|
||||
query?: Record<string, string>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
options?: Record<string, any>,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export interface CallbacksType {
|
||||
onUpdateDisplayName?: (displayName: string) => void;
|
||||
onStatusChange?: (status: WidgetUIState) => void;
|
||||
}
|
||||
|
||||
const BotPluginStoreContext = createContext<{
|
||||
storeRef: StoreRef;
|
||||
callbacks: CallbacksType;
|
||||
resourceNavigate: PluginNavType;
|
||||
memorizedStoreSet: null | {
|
||||
usePluginHistoryPanelUIStore: PluginHistoryPanelUIStore;
|
||||
};
|
||||
}>({
|
||||
storeRef: {
|
||||
plugin: undefined,
|
||||
},
|
||||
callbacks: {},
|
||||
resourceNavigate: {},
|
||||
memorizedStoreSet: null,
|
||||
});
|
||||
|
||||
interface PluginHistoryControllerType {
|
||||
reload: () => void;
|
||||
}
|
||||
|
||||
const BotPluginControllerContext = createContext<{
|
||||
pluginHistoryController: { current: PluginHistoryControllerType | null };
|
||||
registryPluginHistoryController: (
|
||||
controller: PluginHistoryControllerType,
|
||||
) => void;
|
||||
}>({
|
||||
pluginHistoryController: { current: null },
|
||||
registryPluginHistoryController: () => 0,
|
||||
});
|
||||
|
||||
export type WidgetUIState = 'loading' | 'saving' | 'error' | 'normal';
|
||||
|
||||
export const BotPluginStoreProvider: FC<
|
||||
PropsWithChildren<{
|
||||
pluginID: string;
|
||||
spaceID: string;
|
||||
projectID?: string;
|
||||
version?: string;
|
||||
|
||||
onUpdateDisplayName?: (displayName: string) => void;
|
||||
onStatusChange?: (status: WidgetUIState) => void;
|
||||
resourceNavigate: PluginNavType;
|
||||
}>
|
||||
> = ({
|
||||
pluginID,
|
||||
spaceID,
|
||||
projectID,
|
||||
version,
|
||||
children,
|
||||
onUpdateDisplayName,
|
||||
onStatusChange,
|
||||
resourceNavigate,
|
||||
}) => {
|
||||
const store = useRef<StoreRef>({});
|
||||
const usePluginHistoryPanelUIStore = useCreation(
|
||||
() => createPluginHistoryPanelUIStore(),
|
||||
[],
|
||||
);
|
||||
const pluginHistoryControllerRef = useRef<PluginHistoryControllerType | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
if (!store.current?.plugin) {
|
||||
store.current.plugin = createPluginStore({
|
||||
pluginID,
|
||||
spaceID,
|
||||
projectID,
|
||||
version,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<BotPluginStoreContext.Provider
|
||||
value={{
|
||||
storeRef: store.current,
|
||||
memorizedStoreSet: { usePluginHistoryPanelUIStore },
|
||||
callbacks: {
|
||||
onUpdateDisplayName,
|
||||
onStatusChange,
|
||||
},
|
||||
resourceNavigate,
|
||||
}}
|
||||
>
|
||||
<BotPluginControllerContext.Provider
|
||||
value={{
|
||||
pluginHistoryController: pluginHistoryControllerRef,
|
||||
registryPluginHistoryController: inputController => {
|
||||
pluginHistoryControllerRef.current = inputController;
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</BotPluginControllerContext.Provider>
|
||||
</BotPluginStoreContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const usePluginStore: <T>(
|
||||
selector: (store: BotPluginStateAction) => T,
|
||||
) => T = selector => {
|
||||
const ctx = useContext(BotPluginStoreContext);
|
||||
|
||||
if (!ctx.storeRef.plugin) {
|
||||
throw new CustomError(REPORT_EVENTS.normalError, 'plugin store context');
|
||||
}
|
||||
|
||||
return useStoreWithEqualityFn(ctx.storeRef.plugin, selector, shallow);
|
||||
};
|
||||
|
||||
export const usePluginStoreInstance = () => {
|
||||
const ctx = useContext(BotPluginStoreContext);
|
||||
|
||||
if (!ctx.storeRef.plugin) {
|
||||
throw new CustomError(REPORT_EVENTS.normalError, 'plugin store context');
|
||||
}
|
||||
return ctx.storeRef.plugin;
|
||||
};
|
||||
|
||||
export const usePluginCallbacks: () => CallbacksType = () => {
|
||||
const {
|
||||
callbacks: { onStatusChange, onUpdateDisplayName },
|
||||
} = useContext(BotPluginStoreContext);
|
||||
|
||||
return { onStatusChange, onUpdateDisplayName };
|
||||
};
|
||||
|
||||
export const usePluginNavigate: () => PluginNavType = () => {
|
||||
const { resourceNavigate } = useContext(BotPluginStoreContext);
|
||||
|
||||
return resourceNavigate;
|
||||
};
|
||||
|
||||
export const useMemorizedPluginStoreSet = () => {
|
||||
const { memorizedStoreSet } = useContext(BotPluginStoreContext);
|
||||
if (!memorizedStoreSet) {
|
||||
throw new Error('plugin memorized store set not provided');
|
||||
}
|
||||
return memorizedStoreSet;
|
||||
};
|
||||
|
||||
export const usePluginHistoryController = () => {
|
||||
const { pluginHistoryController } = useContext(BotPluginControllerContext);
|
||||
return pluginHistoryController;
|
||||
};
|
||||
|
||||
export const usePluginHistoryControllerRegistry = () => {
|
||||
const { registryPluginHistoryController } = useContext(
|
||||
BotPluginControllerContext,
|
||||
);
|
||||
return registryPluginHistoryController;
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { unlockByFetch } from '../utils/fetch';
|
||||
|
||||
export const useUnmountUnlock = (pluginId: string) => {
|
||||
useEffect(() => {
|
||||
const unlock = () => unlockByFetch(pluginId);
|
||||
|
||||
window.addEventListener('beforeunload', unlock);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('beforeunload', unlock);
|
||||
};
|
||||
}, []);
|
||||
};
|
||||
29
frontend/packages/studio/stores/bot-plugin/src/index.ts
Normal file
29
frontend/packages/studio/stores/bot-plugin/src/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {
|
||||
BotPluginStoreProvider,
|
||||
usePluginStore,
|
||||
usePluginCallbacks,
|
||||
usePluginNavigate,
|
||||
useMemorizedPluginStoreSet,
|
||||
usePluginStoreInstance,
|
||||
usePluginHistoryController,
|
||||
usePluginHistoryControllerRegistry,
|
||||
} from './context';
|
||||
export { ROLE_TAG_TEXT_MAP } from './types/auth';
|
||||
export { useUnmountUnlock } from './hook/unlock';
|
||||
export { checkOutPluginContext, unlockOutPluginContext } from './utils/api';
|
||||
@@ -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 { devtools } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
|
||||
export interface PluginHistoryPanelUIState {
|
||||
isVisible: boolean;
|
||||
}
|
||||
export interface PluginHistoryPanelUIAction {
|
||||
setVisible: (action: ((prevVisible: boolean) => boolean) | boolean) => void;
|
||||
}
|
||||
|
||||
export const createPluginHistoryPanelUIStore = () =>
|
||||
create<PluginHistoryPanelUIState & PluginHistoryPanelUIAction>()(
|
||||
devtools(
|
||||
(set, get) => ({
|
||||
isVisible: false,
|
||||
setVisible: action =>
|
||||
set(
|
||||
{
|
||||
isVisible:
|
||||
typeof action === 'boolean' ? action : action(get().isVisible),
|
||||
},
|
||||
false,
|
||||
'setVisible',
|
||||
),
|
||||
}),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.plugin-history-panel-ui',
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export type PluginHistoryPanelUIStore = ReturnType<
|
||||
typeof createPluginHistoryPanelUIStore
|
||||
>;
|
||||
264
frontend/packages/studio/stores/bot-plugin/src/store/plugin.ts
Normal file
264
frontend/packages/studio/stores/bot-plugin/src/store/plugin.ts
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @coze-arch/max-line-per-function -- store */
|
||||
/* eslint-disable max-lines-per-function -- store */
|
||||
import { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import { produce } from 'immer';
|
||||
import { REPORT_EVENTS } from '@coze-arch/report-events';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { UIModal } from '@coze-arch/bot-semi';
|
||||
import { CustomError } from '@coze-arch/bot-error';
|
||||
import { PluginDevelopApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { getPluginErrorMessage } from '../utils/error';
|
||||
import { type BotPluginStateAction } from '../types/store/plugin';
|
||||
import { CreationMethod, ROLE_TAG_TEXT_MAP } from '../types';
|
||||
|
||||
export const createPluginStore = (options: {
|
||||
pluginID: string;
|
||||
spaceID: string;
|
||||
projectID?: string;
|
||||
version?: string;
|
||||
}) => {
|
||||
const { pluginID, spaceID, projectID, version } = options;
|
||||
|
||||
return create<BotPluginStateAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
version,
|
||||
canEdit: !version,
|
||||
isUnlocking: false,
|
||||
pluginId: pluginID,
|
||||
spaceID,
|
||||
projectID,
|
||||
pluginInfo: {},
|
||||
initSuccessed: false,
|
||||
getIsIdePlugin: () => {
|
||||
const { pluginInfo } = get();
|
||||
|
||||
return pluginInfo?.creation_method === CreationMethod.IDE;
|
||||
},
|
||||
setInitSuccessed: (v: boolean) =>
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
s.initSuccessed = v;
|
||||
}),
|
||||
false,
|
||||
'setInitSuccessed',
|
||||
),
|
||||
setPluginInfo: info =>
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
s.pluginInfo = info;
|
||||
}),
|
||||
false,
|
||||
'setPluginInfo',
|
||||
),
|
||||
setUpdatedInfo: info =>
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
s.updatedInfo = info;
|
||||
}),
|
||||
false,
|
||||
'setUpdatedInfo',
|
||||
),
|
||||
initUserPluginAuth: async () => {
|
||||
const { setCanEdit } = get();
|
||||
const resp = await PluginDevelopApi.GetUserAuthority({
|
||||
project_id: projectID,
|
||||
plugin_id: pluginID,
|
||||
creation_method: CreationMethod.COZE,
|
||||
});
|
||||
|
||||
if (resp.code !== 0) {
|
||||
throw new CustomError(
|
||||
REPORT_EVENTS.normalError,
|
||||
getPluginErrorMessage('auth init'),
|
||||
);
|
||||
}
|
||||
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
s.auth = resp.data;
|
||||
}),
|
||||
false,
|
||||
'initUserPluginAuth',
|
||||
);
|
||||
|
||||
setCanEdit(!!resp.data?.can_edit && !version);
|
||||
},
|
||||
setCanEdit(can) {
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
s.canEdit = can;
|
||||
}),
|
||||
false,
|
||||
'setCanEdit',
|
||||
);
|
||||
},
|
||||
wrapWithCheckLock: fn => async () => {
|
||||
const { checkPluginIsLockedByOthers } = get();
|
||||
|
||||
const isLocked = await checkPluginIsLockedByOthers();
|
||||
|
||||
if (isLocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
fn();
|
||||
},
|
||||
initPlugin: async () => {
|
||||
const { pluginId, setPluginInfo } = get();
|
||||
|
||||
const res = await PluginDevelopApi.GetPluginInfo({
|
||||
plugin_id: pluginId || '',
|
||||
preview_version_ts: version,
|
||||
});
|
||||
|
||||
if (res?.code !== 0) {
|
||||
throw new CustomError(
|
||||
REPORT_EVENTS.normalError,
|
||||
getPluginErrorMessage('getPluginInfo error'),
|
||||
);
|
||||
}
|
||||
setPluginInfo({ ...res, plugin_id: pluginId || '' });
|
||||
},
|
||||
initTool: async () => {
|
||||
const { pluginId, setUpdatedInfo } = get();
|
||||
|
||||
const res = await PluginDevelopApi.GetUpdatedAPIs(
|
||||
{
|
||||
plugin_id: pluginId || '',
|
||||
},
|
||||
{ __disableErrorToast: true },
|
||||
);
|
||||
|
||||
if (res?.code !== 0) {
|
||||
throw new CustomError(
|
||||
REPORT_EVENTS.normalError,
|
||||
getPluginErrorMessage('getToolInfo error'),
|
||||
);
|
||||
}
|
||||
|
||||
setUpdatedInfo({
|
||||
updated_api_names: res?.updated_api_names || [],
|
||||
created_api_names: res?.created_api_names || [], //暂时只判断新增的tool的mockset权限
|
||||
});
|
||||
},
|
||||
init: async () => {
|
||||
const { initPlugin, initTool, initUserPluginAuth, setInitSuccessed } =
|
||||
get();
|
||||
await Promise.all([initPlugin(), initTool(), initUserPluginAuth()]);
|
||||
setInitSuccessed(true);
|
||||
},
|
||||
checkPluginIsLockedByOthers: async () => {
|
||||
const { pluginId, getIsIdePlugin } = get();
|
||||
|
||||
if (getIsIdePlugin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const resp = await PluginDevelopApi.CheckAndLockPluginEdit({
|
||||
plugin_id: pluginId,
|
||||
});
|
||||
|
||||
if (resp.code !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { data } = resp;
|
||||
const user = data?.user;
|
||||
|
||||
/**
|
||||
* 有人占用 & 不是自己
|
||||
*/
|
||||
if (data?.Occupied && user && !user.self) {
|
||||
UIModal.info({
|
||||
okText: I18n.t('guidance_got_it'),
|
||||
title: I18n.t('plugin_team_edit_tip_unable_to_edit'),
|
||||
content: `${user.name}(${
|
||||
// @ts-expect-error -- linter-disable-autofix
|
||||
ROLE_TAG_TEXT_MAP[user.space_roly_type]
|
||||
}) ${I18n.t('plugin_team_edit_tip_another_user_is_editing')}`,
|
||||
hasCancel: false,
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
unlockPlugin: async () => {
|
||||
const { pluginId, canEdit, isUnlocking, getIsIdePlugin } = get();
|
||||
if (getIsIdePlugin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!canEdit) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUnlocking) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
s.isUnlocking = true;
|
||||
}),
|
||||
false,
|
||||
'unlocking-true',
|
||||
);
|
||||
|
||||
const resp = await PluginDevelopApi.UnlockPluginEdit({
|
||||
plugin_id: pluginId,
|
||||
});
|
||||
|
||||
if (resp.code !== 0) {
|
||||
throw new CustomError(
|
||||
REPORT_EVENTS.normalError,
|
||||
getPluginErrorMessage('unlock'),
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
s.isUnlocking = false;
|
||||
}),
|
||||
false,
|
||||
'unlocking-false',
|
||||
);
|
||||
}
|
||||
},
|
||||
updatePluginInfoByImmer: updateFn =>
|
||||
set(
|
||||
produce<BotPluginStateAction>(s => {
|
||||
updateFn(s.pluginInfo);
|
||||
}),
|
||||
false,
|
||||
'updatePluginInfoByImmer',
|
||||
),
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.botPlugin',
|
||||
},
|
||||
),
|
||||
);
|
||||
};
|
||||
29
frontend/packages/studio/stores/bot-plugin/src/types/auth.ts
Normal file
29
frontend/packages/studio/stores/bot-plugin/src/types/auth.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SpaceRoleType } from '@coze-arch/bot-api/plugin_develop';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
export { type GetUserAuthorityData } from '@coze-arch/bot-api/plugin_develop';
|
||||
export { CreationMethod } from '@coze-arch/bot-api/plugin_develop';
|
||||
|
||||
export const ROLE_TAG_TEXT_MAP = {
|
||||
[SpaceRoleType.Owner]: I18n.t('team_management_role_owner', {}, 'Owner'),
|
||||
[SpaceRoleType.Admin]: I18n.t('team_management_role_admin', {}, 'Admin'),
|
||||
[SpaceRoleType.Member]: I18n.t('team_management_role_member', {}, 'Member'),
|
||||
[SpaceRoleType.Default]: '-',
|
||||
} as const;
|
||||
|
||||
export { SpaceRoleType };
|
||||
18
frontend/packages/studio/stores/bot-plugin/src/types/global.d.ts
vendored
Normal file
18
frontend/packages/studio/stores/bot-plugin/src/types/global.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/// <reference types='@coze-arch/bot-typings' />
|
||||
/// <reference types='@coze-arch/bot-env/typings' />
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @coze-arch/no-batch-import-or-export -- 内部均为具名export */
|
||||
export * from './auth';
|
||||
export * from './user';
|
||||
export * from './tool';
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type createPluginStore } from '@/store/plugin';
|
||||
|
||||
export type BotPluginStore = ReturnType<typeof createPluginStore>;
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 GetUserAuthorityData,
|
||||
type GetUpdatedAPIsResponse,
|
||||
type GetPluginInfoResponse,
|
||||
} from '@/types';
|
||||
|
||||
interface PluginState {
|
||||
readonly pluginId: string;
|
||||
readonly spaceID: string;
|
||||
projectID?: string;
|
||||
isUnlocking: boolean;
|
||||
auth?: GetUserAuthorityData;
|
||||
canEdit: boolean;
|
||||
updatedInfo?: GetUpdatedAPIsResponse;
|
||||
pluginInfo?: GetPluginInfoResponse & { plugin_id?: string };
|
||||
initSuccessed: boolean;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
interface PluginGetter {
|
||||
getIsIdePlugin: () => boolean;
|
||||
}
|
||||
|
||||
interface PluginAction {
|
||||
initUserPluginAuth: () => void;
|
||||
checkPluginIsLockedByOthers: () => Promise<boolean>;
|
||||
wrapWithCheckLock: (fn: () => void) => () => Promise<void>;
|
||||
unlockPlugin: () => Promise<void>;
|
||||
setPluginInfo: (info: PluginState['pluginInfo']) => void;
|
||||
setUpdatedInfo: (info: GetUpdatedAPIsResponse) => void;
|
||||
initPlugin: () => Promise<void>;
|
||||
initTool: () => Promise<void>;
|
||||
init: () => Promise<void>;
|
||||
setCanEdit: (can: boolean) => void;
|
||||
setInitSuccessed: (v: boolean) => void;
|
||||
updatePluginInfoByImmer: (
|
||||
updateFn: (pluginInfo: PluginState['pluginInfo']) => void,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export type BotPluginStateAction = PluginState & PluginGetter & PluginAction;
|
||||
20
frontend/packages/studio/stores/bot-plugin/src/types/tool.ts
Normal file
20
frontend/packages/studio/stores/bot-plugin/src/types/tool.ts
Normal file
@@ -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.
|
||||
*/
|
||||
|
||||
export {
|
||||
type GetUpdatedAPIsResponse,
|
||||
type GetPluginInfoResponse,
|
||||
} from '@coze-arch/bot-api/plugin_develop';
|
||||
17
frontend/packages/studio/stores/bot-plugin/src/types/user.ts
Normal file
17
frontend/packages/studio/stores/bot-plugin/src/types/user.ts
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.
|
||||
*/
|
||||
|
||||
export { type Creator } from '@coze-arch/bot-api/plugin_develop';
|
||||
69
frontend/packages/studio/stores/bot-plugin/src/utils/api.ts
Normal file
69
frontend/packages/studio/stores/bot-plugin/src/utils/api.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 } from '@coze-arch/report-events';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { UIModal } from '@coze-arch/bot-semi';
|
||||
import { CustomError } from '@coze-arch/bot-error';
|
||||
import { PluginDevelopApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { getPluginErrorMessage } from '../utils/error';
|
||||
import { ROLE_TAG_TEXT_MAP } from '../types';
|
||||
|
||||
export const checkOutPluginContext = async (pluginId: string) => {
|
||||
const resp = await PluginDevelopApi.CheckAndLockPluginEdit({
|
||||
plugin_id: pluginId,
|
||||
});
|
||||
|
||||
if (resp.code !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { data } = resp;
|
||||
const user = data?.user;
|
||||
|
||||
/**
|
||||
* 有人占用 & 不是自己
|
||||
*/
|
||||
if (data?.Occupied && user && !user.self) {
|
||||
UIModal.info({
|
||||
okText: I18n.t('guidance_got_it'),
|
||||
title: I18n.t('plugin_team_edit_tip_unable_to_edit'),
|
||||
content: `${user.name}(${
|
||||
// @ts-expect-error -- linter-disable-autofix
|
||||
ROLE_TAG_TEXT_MAP[user.space_roly_type]
|
||||
}) ${I18n.t('plugin_team_edit_tip_another_user_is_editing')}`,
|
||||
hasCancel: false,
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
export const unlockOutPluginContext = async (pluginId: string) => {
|
||||
const resp = await PluginDevelopApi.UnlockPluginEdit({
|
||||
plugin_id: pluginId,
|
||||
});
|
||||
|
||||
if (resp.code !== 0) {
|
||||
throw new CustomError(
|
||||
REPORT_EVENTS.normalError,
|
||||
getPluginErrorMessage('unlock out'),
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -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 const getPluginErrorMessage = (msg: string) =>
|
||||
`[PluginStore.Error]: ${msg}`;
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 const unlockByFetch = (pluginId: string) =>
|
||||
fetch('/api/plugin_api/unlock_plugin_edit', {
|
||||
keepalive: true,
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
plugin_id: pluginId,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user