chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { ContentType, useSendTextMessage } from '@coze-common/chat-area';
|
||||
import { sendTeaEvent, EVENT_NAMES } from '@coze-arch/bot-tea';
|
||||
import { type ShortCutCommand } from '@coze-agent-ide/tool-config';
|
||||
@@ -188,7 +188,7 @@ describe('useSendUseToolMessage', () => {
|
||||
work_flow_id: '',
|
||||
};
|
||||
const componentsFormValues = { news: '查询北京news' };
|
||||
// @ts-expect-error --单测忽略
|
||||
// @ts-expect-error -- single test ignored
|
||||
sendUseToolMessage({ shortcut, componentsFormValues });
|
||||
expect(sendMultimodalMessage).toHaveBeenCalled();
|
||||
expect(sendTeaEvent).toHaveBeenCalledWith(EVENT_NAMES.shortcut_use, {
|
||||
@@ -237,7 +237,7 @@ describe('getTemplateQuery', () => {
|
||||
work_flow_id: '',
|
||||
};
|
||||
const componentsFormValues = { news: '北京新闻' };
|
||||
// @ts-expect-error --单测忽略
|
||||
// @ts-expect-error -- single test ignored
|
||||
const result = getTemplateQuery(shortcut, componentsFormValues);
|
||||
expect(result).toBe('查询北京新闻');
|
||||
});
|
||||
@@ -278,7 +278,7 @@ describe('getTemplateQuery', () => {
|
||||
work_flow_id: '',
|
||||
};
|
||||
const componentsFormValues = { news: '北京新闻' };
|
||||
// @ts-expect-error --单测忽略
|
||||
// @ts-expect-error -- single test ignored
|
||||
expect(() => getTemplateQuery(shortcut, componentsFormValues)).toThrowError(
|
||||
'template_query is not defined',
|
||||
);
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('initToolInfoByToolApi', () => {
|
||||
|
||||
const result = initToolInfoByToolApi(plugin);
|
||||
expect(result?.tool_params_list.length).toBe(MAX_TOOL_PARAMS_COUNT + 2);
|
||||
// 前10个是required=true的参数
|
||||
// The first 10 parameters are required = true
|
||||
expect(
|
||||
result?.tool_params_list
|
||||
.slice(0, MAX_TOOL_PARAMS_COUNT)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import {
|
||||
InputType,
|
||||
// eslint-disable-next-line camelcase
|
||||
@@ -136,7 +136,7 @@ describe('getSubmitFieldFromComponentTypeForm', () => {
|
||||
});
|
||||
|
||||
it('returns TextInput type for unrecognized type', () => {
|
||||
// @ts-expect-error -- 无视
|
||||
// @ts-expect-error -- ignore
|
||||
const values: ComponentTypeItem = { type: 'unknown' };
|
||||
const result = getSubmitFieldFromComponentTypeForm(values);
|
||||
expect(result).toEqual({ input_type: InputType.TextInput });
|
||||
|
||||
@@ -138,7 +138,7 @@ export const LoadMoreList = <TData extends object>(
|
||||
onSelect?.(item);
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
// 鼠标位于滚动条中,会触发该事件,设置仅在移动鼠标过程中进行更新
|
||||
// The mouse is in the scroll bar, which triggers the event, and the settings are only updated during mouse movement
|
||||
if (mouseMovingRef.current) {
|
||||
focusTo(item);
|
||||
listRef.current?.focus();
|
||||
|
||||
@@ -30,7 +30,7 @@ export const DSLForm: DSLComponent = ({
|
||||
const formRef = useRef<FormApi>();
|
||||
|
||||
/**
|
||||
* text类型组件交互 支持 placeholder 表示默认值
|
||||
* Text type component interaction, support placeholder to represent default value
|
||||
* @param formValues
|
||||
*/
|
||||
const onSubmitWrap = (formValues: FormValue) => {
|
||||
|
||||
@@ -24,7 +24,7 @@ import { DSLPlaceholer } from './placeholder';
|
||||
import { DSLColumnLayout } from './layout';
|
||||
import { DSLForm } from './form';
|
||||
|
||||
// 组件参数是在运行时决定,无法具体做类型约束
|
||||
// Component parameters are determined at run time and cannot be subject to specific type constraints
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const DSLWidgetsMap: Record<string, DSLComponent<any>> = {
|
||||
'@flowpd/cici-components/Input': DSLFormInput,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import type { FC, PropsWithChildren } from 'react';
|
||||
|
||||
// 本期不需要不支持复布局解析
|
||||
// This issue does not need to support multiple layout analysis
|
||||
export const DSLColumnLayout: FC<PropsWithChildren> = ({ children }) => (
|
||||
<div className="flex items-center justify-between w-full mb-3 gap-2">
|
||||
{children}
|
||||
|
||||
@@ -25,7 +25,7 @@ const parseRules = (rules: RuleItem[]): RuleItem[] =>
|
||||
if (rule.required) {
|
||||
return {
|
||||
...rule,
|
||||
// required 情况下,禁止输入空格
|
||||
// Do not enter spaces if required
|
||||
validator: (r, v) => !!v?.trim(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ export type TCustomUpload = (uploadParams: {
|
||||
export interface DSLContext {
|
||||
dsl: DSL;
|
||||
uploadFile?: TCustomUpload;
|
||||
onChange?: (value: Record<string, TValue>) => void; // 需要兼容 file
|
||||
onChange?: (value: Record<string, TValue>) => void; // Compatible files required
|
||||
onSubmit?: (value: Record<string, TValue>) => void;
|
||||
readonly?: boolean; // 支持搭建时的预览模式
|
||||
readonly?: boolean; // Support preview mode during build
|
||||
}
|
||||
|
||||
export interface DSLFormFieldCommonProps {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { type FC, useState, useRef, useEffect } from 'react';
|
||||
|
||||
import classnames from 'classnames';
|
||||
@@ -72,7 +72,7 @@ const UploadContent: FC<{
|
||||
},
|
||||
)}
|
||||
style={{
|
||||
// @ts-expect-error ts 无法识别自定义变量
|
||||
// @ts-expect-error ts cannot recognize custom variable
|
||||
'--var-percent': `${file.percent}%`,
|
||||
}}
|
||||
>
|
||||
@@ -152,7 +152,7 @@ const FileUpload: FC<
|
||||
percent: 0,
|
||||
status: 'uploading',
|
||||
});
|
||||
// 立即清理错误状态
|
||||
// Immediately clean up the error state
|
||||
fieldApi.setError(true);
|
||||
uidRef.current = newFile?.uid;
|
||||
uploadFile?.({
|
||||
@@ -188,7 +188,7 @@ const FileUpload: FC<
|
||||
if (uidRef.current !== newFile.uid) {
|
||||
return;
|
||||
}
|
||||
// 上传失败,触发错误状态
|
||||
// Upload failed, error status triggered
|
||||
fieldApi.setError(false);
|
||||
setFile({
|
||||
...newFile,
|
||||
@@ -221,13 +221,13 @@ const FileUpload: FC<
|
||||
}
|
||||
}}
|
||||
customRequest={({ onSuccess }) => {
|
||||
// 即使 action="" ,在不传 customRequest 仍然会触发一次向当前 URL 上传文件的请求
|
||||
// 这里传一个 mock customRequest 来阻止 semi 默认的上传行为
|
||||
// Even if action = ", a request to upload a file to the current URL will still be triggered without customRequest
|
||||
// Here is a mock customRequest to prevent semi default upload behavior
|
||||
onSuccess('');
|
||||
}}
|
||||
showUploadList={false}
|
||||
onChange={({ currentFile }) => {
|
||||
// semi 同一个文件会触发多次 onChange,这里只响应首个
|
||||
// Semi The same file will trigger multiple onChanges, only the first one is responded here
|
||||
if (
|
||||
uidRef.current !== currentFile.uid &&
|
||||
(!props.maxSize ||
|
||||
@@ -247,7 +247,7 @@ const FileUpload: FC<
|
||||
setFile(undefined);
|
||||
onChange?.('');
|
||||
setTimeout(() => {
|
||||
// 删除文件,清理错误状态避免立刻飘红
|
||||
// Delete files, clean up error states to avoid immediate redness
|
||||
fieldApi.setError(true);
|
||||
});
|
||||
}}
|
||||
@@ -295,17 +295,17 @@ const FileInput: FC<
|
||||
</>
|
||||
);
|
||||
|
||||
// 为了方便控制向外传递的 value
|
||||
// To facilitate control of the value passed outward
|
||||
const UploadInner = withField((props: UploadProps) => {
|
||||
const [showInput, setShowInput] = useState(false);
|
||||
const hasError = props.validateStatus === 'error';
|
||||
const fieldApi = useFieldApi(props.name);
|
||||
|
||||
// 避免清空输入导致的飘红
|
||||
// Avoid flushing red caused by empty input
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
props.onChange?.('');
|
||||
// 避免 onchange 触发校验导致立刻飘红
|
||||
// Avoid onchange triggering verification and causing immediate redness
|
||||
setTimeout(() => {
|
||||
fieldApi.setError(true);
|
||||
});
|
||||
|
||||
@@ -126,7 +126,7 @@ export const useSendUseToolMessage = () => {
|
||||
shortcut,
|
||||
componentsFormValues,
|
||||
/**
|
||||
* 无参数调用 store 场景下没有 componentList
|
||||
* Calling store without parameters does not have a pixentList
|
||||
*/
|
||||
withoutComponentsList,
|
||||
);
|
||||
@@ -145,9 +145,9 @@ export const useSendUseToolMessage = () => {
|
||||
mixList: [
|
||||
{
|
||||
type: ContentType.Text,
|
||||
// TODO 需要看下是否能够优化
|
||||
// TODO needs to see if it can be optimized.
|
||||
/**
|
||||
* 防止发送空消息(没有对话的气泡框) => 使用空格占位
|
||||
* Prevent sending empty messages (no dialog bubble box) = > Use spaces to occupy space
|
||||
*/
|
||||
text: sendQuery || ' ',
|
||||
},
|
||||
@@ -219,7 +219,7 @@ const getPluginParams = (
|
||||
}),
|
||||
);
|
||||
|
||||
// key: components_list中的parameter属性 value:values中对应的值 | default_value
|
||||
// The parameter attribute value in key: components_list: the corresponding value in values | default_value
|
||||
const runPluginVariables = (tool_params_list ?? []).reduce<
|
||||
Record<string, ToolParamValue>
|
||||
>((acc, cur) => {
|
||||
@@ -271,7 +271,7 @@ const getPluginDefaultParams = (shortcut: ShortCutCommand) => {
|
||||
tool_info: { tool_params_list } = {},
|
||||
} = shortcut;
|
||||
|
||||
// key: components_list中的parameter属性 value:values中对应的值 | default_value
|
||||
// The parameter attribute value in key: components_list: the corresponding value in values | default_value
|
||||
const runPluginVariables = (tool_params_list ?? []).reduce<
|
||||
Record<string, ToolParamValue>
|
||||
>((acc, cur) => {
|
||||
@@ -309,7 +309,7 @@ export const getTemplateQuery = (
|
||||
if (!template_query) {
|
||||
throw new Error('template_query is not defined');
|
||||
}
|
||||
// 处理图片文件
|
||||
// Processing image files
|
||||
const componentListValue = getComponentListValue(
|
||||
components_list,
|
||||
componentsFormValues,
|
||||
@@ -330,12 +330,12 @@ const filterComponentFormValues = (
|
||||
Object.keys(componentsFormValues).reduce<Record<string, unknown>>(
|
||||
(acc, cur) => {
|
||||
const value = componentsFormValues[cur];
|
||||
// 文件类型
|
||||
// file type
|
||||
if (typeof value === 'object' && value.fileInstance) {
|
||||
acc[cur] = setImageAndFileValue(value);
|
||||
return acc;
|
||||
}
|
||||
// 普通文本类型
|
||||
// plain text type
|
||||
acc[cur] = setTextValue(value as string);
|
||||
return acc;
|
||||
},
|
||||
@@ -388,7 +388,7 @@ const isComponentImage = (
|
||||
getFileInfo(value.fileInstance)?.fileType === 'image',
|
||||
);
|
||||
|
||||
// 获取component_list的value, 带上默认值
|
||||
// Get component_list value with default value
|
||||
export const getComponentListValue = (
|
||||
componentsList: ShortCutCommand['components_list'],
|
||||
componentsFormValues: Record<string, TValue>,
|
||||
@@ -399,7 +399,7 @@ export const getComponentListValue = (
|
||||
value => value,
|
||||
);
|
||||
|
||||
// key: components_list中的parameter属性 value:values中对应的值 | default_value
|
||||
// The parameter attribute value in key: components_list: the corresponding value in values | default_value
|
||||
return (componentsList ?? []).reduce<Record<string, string>>((acc, cur) => {
|
||||
const { default_value, name, hide } = cur;
|
||||
if (!name) {
|
||||
|
||||
@@ -32,7 +32,7 @@ export const useImperativeLayoutEffect = <Params extends unknown[]>(
|
||||
if (!effectValue) {
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- 体操不动, 凑活用吧
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- gymnastics don't move, let's make a living
|
||||
// @ts-expect-error
|
||||
const params = paramRef.current || ([] as Params);
|
||||
return effectRef.current(...params);
|
||||
|
||||
@@ -20,15 +20,15 @@ import {
|
||||
} from '@coze-common/chat-core';
|
||||
import { useGetRegisteredPlugin } from '@coze-common/chat-area';
|
||||
|
||||
// 延迟1.5s后开始模拟上传进度
|
||||
// Start simulating upload progress after 1.5s delay
|
||||
const FAKE_PROGRESS_START_DELAY = 1500;
|
||||
// fake progress 初始进度
|
||||
// Fake progress initial progress
|
||||
const FAKE_PROGRESS_START = 50;
|
||||
// 最大进度
|
||||
// maximum progress
|
||||
const FAKE_PROGRESS_MAX = 85;
|
||||
// 每次步进值
|
||||
// value per step
|
||||
const FAKE_PROGRESS_STEP = 5;
|
||||
// 循环间隔
|
||||
// Cycle interval
|
||||
const FAKE_PROGRESS_INTERVAL = 100;
|
||||
|
||||
export const useGetUploadPluginInstance = () => {
|
||||
@@ -55,7 +55,7 @@ export const useGetUploadPluginInstance = () => {
|
||||
file,
|
||||
type: getFileInfo(file)?.fileType === 'image' ? 'image' : 'object',
|
||||
});
|
||||
// 如果1s内上传进度没有变化,主动触发fake progress, 500ms内从50%上升到80%,忽略后续的真实进度
|
||||
// If the upload progress does not change within 1s, actively trigger fake progress, increase from 50% to 80% within 500ms, ignoring the subsequent real progress
|
||||
let isStartFakeProgress = false;
|
||||
let fakeProgressTimer: number | undefined;
|
||||
let fakeProgress = FAKE_PROGRESS_START;
|
||||
@@ -82,7 +82,7 @@ export const useGetUploadPluginInstance = () => {
|
||||
isStartFakeProgress = false;
|
||||
}
|
||||
uploader.on('progress', ({ percent }) => {
|
||||
// 有假进度,忽略后续的真实进度
|
||||
// There is a fake progress, ignore the subsequent real progress.
|
||||
if (isStartFakeProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// !Notice 禁止直接导出 shortcut-tool,会导致下游依赖不需要的 knowledge-upload
|
||||
// ! Notice prohibits direct export of shortcut-tool, causing downstream dependencies on unwanted knowledge-uploads
|
||||
// export { ShortcutToolConfig } from './shortcut-tool';
|
||||
export { ShortcutBar } from './shortcut-bar';
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// 快捷指令操作bar
|
||||
|
||||
// Quick command bar
|
||||
import { type CSSProperties, type FC, useRef, useState } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
@@ -48,7 +48,7 @@ interface ChatShortCutBarProps {
|
||||
) => void;
|
||||
className?: string;
|
||||
wrapperClassName?: string;
|
||||
uiMode?: UIMode; // 默认为白色,有背景的时候为模糊
|
||||
uiMode?: UIMode; // The default is white, and it is blurred when there is a background.
|
||||
defaultId?: string;
|
||||
wrapperStyle?: CSSProperties;
|
||||
toolTipFooterSlot?: React.ReactNode;
|
||||
@@ -100,8 +100,8 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
|
||||
|
||||
const shortcutClick = (shortcut: ShortCutCommand) => {
|
||||
/**
|
||||
* send_type=SendTypePanel 且 components_list hide均为true
|
||||
* 直接发送
|
||||
* send_type = SendTypePanel and components_list hide is true
|
||||
* send directly
|
||||
*/
|
||||
const hideTemplate = enableSendTypePanelHideTemplate(shortcut);
|
||||
|
||||
@@ -174,7 +174,7 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
|
||||
};
|
||||
|
||||
/**
|
||||
* sendType=panel 支持不展示组件直接发送
|
||||
* sendType = panel supports sending directly without displaying components
|
||||
*/
|
||||
const onShortcutTemplateNoParamsSubmit = (
|
||||
componentsFormValues: Record<string, TValue>,
|
||||
@@ -186,7 +186,7 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
|
||||
|
||||
const { agent_id, object_id, components_list, tool_info } = shortcut;
|
||||
/**
|
||||
* sendType=panel,useTool=true 无参数直接发送
|
||||
* sendType = panel, useTool = true Send directly without parameters
|
||||
*/
|
||||
const withoutComponentsList =
|
||||
!!tool_info?.tool_name && !components_list?.length;
|
||||
@@ -270,7 +270,7 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
|
||||
}}
|
||||
minVisibleItems={1}
|
||||
items={shortcuts}
|
||||
// @ts-expect-error visibleItemRenderer 有问题
|
||||
// @ts-expect-error visibleItemRenderer has a problem
|
||||
visibleItemRenderer={renderShortcut}
|
||||
overflowRenderer={overflowItems => {
|
||||
if (!overflowItems.length) {
|
||||
|
||||
@@ -22,11 +22,11 @@ import {
|
||||
} from '@coze-common/chat-core';
|
||||
|
||||
export interface ChatShortCutBarProps {
|
||||
shortcuts: ShortCutCommand[]; // 目前支持两种快捷键
|
||||
shortcuts: ShortCutCommand[]; // Currently supports two shortcuts
|
||||
onClickShortCut: (shortcutInfo: ShortCutCommand) => void;
|
||||
}
|
||||
// 更新后 home 为 white 调试区、商店为 grey
|
||||
export type UIMode = 'grey' | 'white' | 'blur'; // 默认为白色,有背景的时候为模糊
|
||||
// After the update, the home is white debugging area and the store is grey.
|
||||
export type UIMode = 'grey' | 'white' | 'blur'; // The default is white, and it is blurred when there is a background.
|
||||
|
||||
export interface OnBeforeSendTemplateShortcutParams {
|
||||
message: TextAndFileMixMessageProps;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// 快捷指令换起的模板组件
|
||||
// Template component for shortcut command replacement
|
||||
import { type FC, useMemo, useRef } from 'react';
|
||||
|
||||
import { type ShortCutCommand } from '@coze-agent-ide/tool-config';
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// 快捷指令在IDE中的配置tool
|
||||
// Quick instructions in the IDE configuration tool
|
||||
export { ShortcutToolConfig } from './shortcut-config';
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// 快捷指令在IDE中的配置tool
|
||||
// Quick instructions in the IDE configuration tool
|
||||
import React, { type FC, useState } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
@@ -85,7 +85,7 @@ export const ShortcutToolConfig: FC<ShortcutToolConfigProps> = props => {
|
||||
const getSpaceId = useSpaceStore(state => state.getSpaceId);
|
||||
const setHasValidData = useToolValidData();
|
||||
|
||||
// single不展示指定agent的快捷指令
|
||||
// Single command that does not show the specified agent
|
||||
const singleShortcuts = initShortcuts?.filter(shortcut => !shortcut.agent_id);
|
||||
const shortcuts =
|
||||
botMode === BotMode.SingleMode ? singleShortcuts : initShortcuts;
|
||||
@@ -174,7 +174,7 @@ export const ShortcutToolConfig: FC<ShortcutToolConfigProps> = props => {
|
||||
},
|
||||
{ __disableErrorToast: true },
|
||||
);
|
||||
// TODO: hzf 得加上
|
||||
// TODO: hzf has to be added
|
||||
// if (res && res.data?.check_not_pass) {
|
||||
// Toast.error(I18n.t('shortcut_modal_illegal_keyword_detected_error'));
|
||||
// onFail();
|
||||
@@ -214,7 +214,7 @@ export const ShortcutToolConfig: FC<ShortcutToolConfigProps> = props => {
|
||||
{ __disableErrorToast: true },
|
||||
);
|
||||
const strictShortcuts = newShortcut && getStrictShortcuts([newShortcut]);
|
||||
// 一次只能添加一个快捷指令
|
||||
// Only one shortcut can be added at a time
|
||||
const strictShortcut = strictShortcuts?.[0];
|
||||
if (!strictShortcut) {
|
||||
Toast.error('Please fill in the required fields');
|
||||
|
||||
@@ -54,7 +54,7 @@ export const ShortcutItem: FC<ShortcutItemProps> = ({
|
||||
useEffect(() => {
|
||||
connect(dropRef, dragRef);
|
||||
}, [dragRef, dropRef]);
|
||||
// 点击删除,弹出二次确认弹窗
|
||||
// Click Delete to pop up the secondary confirmation pop-up window.
|
||||
const openConfirmRemoveModal = () => {
|
||||
UIModal.info({
|
||||
title: I18n.t('bot_ide_shortcut_removal_confirm'),
|
||||
|
||||
@@ -113,10 +113,10 @@ export const ActionSwitchArea = forwardRef<
|
||||
tool_params_list = [],
|
||||
} = toolInfo || {};
|
||||
const newComponents = initComponentsByToolParams(tool_params_list);
|
||||
// TODO: hzf, 有点复杂,看看可以initValue么
|
||||
// TODO: hzf, it's a bit complicated, let's see if it can initValue
|
||||
formRef.current?.formApi.setValue('components_list', newComponents);
|
||||
setComponents(newComponents);
|
||||
// 只有这种情况需要手动更新数据
|
||||
// Only in this case do you need to manually update the data
|
||||
componentsRef.current?.formApi?.setValues(newComponents);
|
||||
|
||||
formRef.current?.formApi.setValue('tool_type', tool_type);
|
||||
|
||||
@@ -39,7 +39,7 @@ export const initComponentsByToolParams = (
|
||||
};
|
||||
});
|
||||
|
||||
// 获取没有被使用的组件
|
||||
// Get unused components
|
||||
export const getUnusedComponents = (
|
||||
shortcut: ShortcutEditFormValues,
|
||||
): shortcut_command.Components[] => {
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// format选择的插件参数列表
|
||||
// Format selected plugin parameter list
|
||||
import { type WorkFlowItemType } from '@coze-studio/bot-detail-store';
|
||||
import { type PluginApi, ToolType } from '@coze-arch/bot-api/playground_api';
|
||||
|
||||
import { type ToolInfo } from '../../../types';
|
||||
|
||||
// 最多勾选10个,如果入参数量超过10个,仅勾选其中10个,优先勾选required参数;勾满10个时,其他checkbox置灰不可继续勾选。
|
||||
// Check up to 10 parameters. If the number of input parameters exceeds 10, only 10 of them will be checked, and the required parameters will be selected first; when 10 parameters are checked, other checkboxes out grey cannot be checked.
|
||||
export const MAX_TOOL_PARAMS_COUNT = 10;
|
||||
|
||||
// 初始化工具列表参数
|
||||
// Initialization tool list parameters
|
||||
export const initToolInfoByToolApi = (
|
||||
toolApi?: WorkFlowItemType | PluginApi,
|
||||
): ToolInfo | null => {
|
||||
@@ -38,7 +38,7 @@ export const initToolInfoByToolApi = (
|
||||
|
||||
const { tool_params_list } = workflowPluginProcessedToolInfo;
|
||||
|
||||
// 对params进行排序,将required=true的字段排在前面
|
||||
// Sort params to rank fields with required = true first
|
||||
const sortedParams = tool_params_list?.sort(
|
||||
(a, b) => (b.required ? 1 : -1) - (a.required ? 1 : -1),
|
||||
);
|
||||
@@ -60,7 +60,7 @@ export const initToolInfoByToolApi = (
|
||||
};
|
||||
};
|
||||
|
||||
// workflow参数转化为toolParams
|
||||
// Convert workflow parameters to toolParams
|
||||
export const initToolInfoByWorkFlow = (
|
||||
workFlow: WorkFlowItemType,
|
||||
): ToolInfo => {
|
||||
@@ -86,7 +86,7 @@ export const initToolInfoByPlugin = (plugin: PluginApi): ToolInfo => {
|
||||
};
|
||||
};
|
||||
|
||||
// 获取skillModal开启的tab
|
||||
// Get tabs opened by skillModal
|
||||
export const getSkillModalTab = (): (
|
||||
| 'plugin'
|
||||
| 'workflow'
|
||||
|
||||
@@ -53,7 +53,7 @@ export const ButtonName: FC<ButtonNameProps> = props => {
|
||||
noLabel
|
||||
fieldClassName="!pb-0"
|
||||
onLoadList={list => {
|
||||
// 如果是编辑状态,不设置默认icon, 新增下默认选中列表第一个icon
|
||||
// If it is an editing state, do not set the default icon, and add the first icon in the default selected list.
|
||||
const isEdit = !!editedShortcut.command_id;
|
||||
if (isEdit) {
|
||||
return;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { type FC, useState } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
@@ -107,7 +107,7 @@ export const IconListField = () => (
|
||||
<div className="flex justify-center items-center flex-col w-[420px] h-[148px]">
|
||||
<IconCozWarningCircle className="mb-4 w-8 h-8 coz-fg-hglt-red" />
|
||||
<div className="coz-fg-secondary text-xs">
|
||||
{/*@ts-expect-error --替换*/}
|
||||
{/* @ts-expect-error -- replace*/}
|
||||
{I18n.t('Connection failed')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -86,7 +86,7 @@ export const ComponentDefaultValue: FC<ComponentDefaultValueProps> = props => {
|
||||
);
|
||||
}
|
||||
if (type === 'upload') {
|
||||
// 先置灰,后续放开上传默认值
|
||||
// Grey out first, then release the upload default value.
|
||||
return <UploadField />;
|
||||
// return (
|
||||
// <UploadDefaultValue
|
||||
|
||||
@@ -67,13 +67,13 @@ export const getInputTypeFromFile = (file: File): UploadItemType | '' => {
|
||||
return getInputTypeFromFileType(fileType);
|
||||
};
|
||||
|
||||
// 判断文件是否超过最大限制
|
||||
// Determine whether the file exceeds the maximum limit
|
||||
export const isOverMaxSizeByUploadItemConfig = (
|
||||
file: File | undefined,
|
||||
config: UploadItemConfig | undefined,
|
||||
): {
|
||||
isOverSize: boolean;
|
||||
// 单位 MB
|
||||
// Unit MB
|
||||
maxSize?: number;
|
||||
} => {
|
||||
if (!file) {
|
||||
@@ -104,7 +104,7 @@ export const isOverMaxSizeByUploadItemConfig = (
|
||||
};
|
||||
};
|
||||
|
||||
// 根据acceptUploadItemTypes获取accept
|
||||
// Accept based on acceptUploadItemTypes
|
||||
export const getAcceptByUploadItemTypes = (
|
||||
acceptUploadItemTypes: UploadItemType[],
|
||||
) => {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
||||
|
||||
import { DndProvider } from '@coze-studio/components/dnd-provider';
|
||||
@@ -45,7 +45,7 @@ import { tableEmpty } from './empty';
|
||||
import styles from './index.module.less';
|
||||
|
||||
export interface ComponentsTableProps {
|
||||
components: shortcut_command.Components[]; // 变量列表
|
||||
components: shortcut_command.Components[]; // Variable list
|
||||
onChange?: (components: shortcut_command.Components[]) => void;
|
||||
toolType?: shortcut_command.ToolType;
|
||||
toolInfo: ToolInfo;
|
||||
@@ -59,7 +59,7 @@ export interface ComponentsTableActions {
|
||||
|
||||
const MAX_COMPONENTS = 10;
|
||||
|
||||
// 半受控组件,使用初始值 + 暴露 API 的方式,方便内部维护本地 id 用于拖拽排序标识数据
|
||||
// Semi-controlled component, using initial value + exposed API to facilitate internal maintenance of local ID for dragging and dropping sorting identification data
|
||||
export const ComponentsTable = forwardRef<
|
||||
{ formApi?: ComponentsTableActions },
|
||||
ComponentsTableProps
|
||||
@@ -80,7 +80,7 @@ export const ComponentsTable = forwardRef<
|
||||
formApi: formRef.current
|
||||
? {
|
||||
validate: async (...props) => {
|
||||
// 在这里统一处理,避免多个相同字段触发多次 toast
|
||||
// It is handled uniformly here to avoid multiple identical fields triggering multiple toasts.
|
||||
if (
|
||||
values.some(
|
||||
component =>
|
||||
@@ -128,10 +128,10 @@ export const ComponentsTable = forwardRef<
|
||||
(isBefore ? 0 : 1);
|
||||
sourceItem && newValues.splice(targetIndex, 0, sourceItem);
|
||||
errors.splice(targetIndex, 0, sourceError);
|
||||
// 前后 index 相同的情况不触发 onChange 避免频繁 rerender
|
||||
// Do not trigger onChange if the index is the same before and after to avoid frequent rerender
|
||||
if (sourceIndex !== targetIndex) {
|
||||
onChangeInner(newValues);
|
||||
// 只在拖拽排序后,需要手动更新 form value
|
||||
// Only after dragging sort, you need to manually update the form value
|
||||
formRef.current?.setValues(
|
||||
{
|
||||
values: newValues,
|
||||
@@ -190,7 +190,7 @@ export const ComponentsTable = forwardRef<
|
||||
<DndProvider>
|
||||
<Form<{ values: ComponentsWithId[] }>
|
||||
initValues={{ values }}
|
||||
// 手动触发校验,避免受增删和拖拽排序影响
|
||||
// Manually trigger validation to avoid being affected by addition, deletion and drag-and-drop sorting
|
||||
trigger="custom"
|
||||
autoComplete="off"
|
||||
disabled={disabled}
|
||||
@@ -199,16 +199,16 @@ export const ComponentsTable = forwardRef<
|
||||
const changedKeys = Object.keys(changedValues);
|
||||
if (
|
||||
changedKeys.length === 1 &&
|
||||
// 只在表单修改场景下触发 onChange 避免无限循环
|
||||
// Trigger onChange only in form modification scenarios to avoid infinite loops
|
||||
changedKeys[0]?.startsWith('values.[')
|
||||
) {
|
||||
onChangeInner([...newValues.values]);
|
||||
// 只在编辑表单场景下对具体字段触发校验,其它场景(整行的增删排序)不触发校验
|
||||
// Validation is only triggered for specific fields in the edit form scenario, and verification is not triggered in other scenarios (addition and deletion sorting of entire lines)
|
||||
setTimeout(() => {
|
||||
if (formRef.current) {
|
||||
checkDuplicateName(newValues.values, formRef.current);
|
||||
}
|
||||
// @ts-expect-error semi 的类型定义无法支持多段 path
|
||||
// @ts-expect-error -- The type definition of semi cannot support multi-segment paths
|
||||
formRef.current?.validate([changedKeys[0]]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export const checkDuplicateName = (
|
||||
}
|
||||
});
|
||||
setTimeout(() => {
|
||||
// 避免修改后立刻被 field 自己的校验状态覆盖
|
||||
// Avoid being overwritten by the field's own check state immediately after modification
|
||||
Object.entries(fieldMap).forEach(([name, indexArray]) => {
|
||||
const isDuplicated = indexArray.length > 1;
|
||||
indexArray.forEach(index => {
|
||||
@@ -81,7 +81,7 @@ export const getComponentTypeSelectFormInitValues = (): ComponentTypeItem => ({
|
||||
type: 'text',
|
||||
});
|
||||
|
||||
// 定义一个映射对象,将ComponentTypeItem的type映射到对应的input_type和其他字段
|
||||
// Define a mapping object that maps the ComponentTypeItem type to the corresponding input_type and other fields
|
||||
const componentTypeHandlers = {
|
||||
text: () => ({ input_type: InputType.TextInput }),
|
||||
select: (value: ComponentTypeItem) => {
|
||||
@@ -126,11 +126,11 @@ export const getSubmitFieldFromComponentTypeForm = (
|
||||
return result;
|
||||
}
|
||||
|
||||
// 如果没有找到处理函数,就返回默认值
|
||||
// If no handler is found, the default value is returned
|
||||
return { input_type: InputType.TextInput };
|
||||
};
|
||||
|
||||
// 是否是上传类型
|
||||
// Is it the upload type?
|
||||
export const isUploadType = (
|
||||
type: InputType,
|
||||
): type is
|
||||
@@ -157,7 +157,7 @@ export const isUploadType = (
|
||||
InputType.MixUpload,
|
||||
].includes(type);
|
||||
|
||||
// 将input_type映射到对应的处理函数
|
||||
// Map input_type to the corresponding handler
|
||||
const inputTypeHandlers = {
|
||||
[InputType.TextInput]: () => ({ type: 'text' }),
|
||||
[InputType.Select]: (options: string[] = []) => ({
|
||||
@@ -194,7 +194,7 @@ export const getComponentTypeFormBySubmitField = (
|
||||
};
|
||||
|
||||
/**
|
||||
* 1. 修改components列表中对应组件的hide:true
|
||||
* 1. Modify the hide of the corresponding component in the components list: true
|
||||
*/
|
||||
export const modifyComponentWhenSwitchChange = ({
|
||||
components,
|
||||
@@ -215,7 +215,7 @@ export const modifyComponentWhenSwitchChange = ({
|
||||
return item;
|
||||
});
|
||||
|
||||
// components switch是否disable
|
||||
// Components switching disabled
|
||||
export const isSwitchDisabled = ({
|
||||
components,
|
||||
record,
|
||||
@@ -233,17 +233,17 @@ export const isSwitchDisabled = ({
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用工具&为必填参数
|
||||
* Use tools & required parameters
|
||||
*/
|
||||
return !!toolInfo?.tool_params_list?.find(t => t.name === record.parameter)
|
||||
?.required;
|
||||
})();
|
||||
|
||||
// 组件超过最大数量, 不允许开启
|
||||
// Components exceed the maximum number and are not allowed to be opened
|
||||
const isMaxCount =
|
||||
record.hide && components.filter(com => !com.hide).length >= MAX_COMPONENTS;
|
||||
|
||||
/** 必填且没有默认值不允许关闭 */
|
||||
/** Required and no default value Closure is not allowed */
|
||||
const isFinalRequired = isRequired && !isWithDefaultValue;
|
||||
|
||||
return isFinalRequired || isMaxCount;
|
||||
|
||||
@@ -308,7 +308,7 @@ const DraggableBodyRow: FC<
|
||||
onMove: OnMove<string>;
|
||||
}>
|
||||
> = ({ id, onMove, children, sortable }) => {
|
||||
// 因为 name 可能为空,这里拿 shortid 做一个兜底
|
||||
// Because the name may be empty, take shortid as a bottom line here.
|
||||
const dropRef = useRef<HTMLElement>(null);
|
||||
const { connect } = useDnDSortableItem<string>({
|
||||
type,
|
||||
@@ -317,7 +317,7 @@ const DraggableBodyRow: FC<
|
||||
enabled: sortable,
|
||||
});
|
||||
useEffect(() => {
|
||||
// 为了避免复杂的跨组件传值,这里稍微直接操作一下 DOM ,非常抱歉
|
||||
// In order to avoid complicated cross-component value transfer, here is a little direct manipulation of the DOM, I'm very sorry.
|
||||
const handleRef = {
|
||||
current: (dropRef.current?.querySelector(`#${handleId}`) ??
|
||||
null) as HTMLElement | null,
|
||||
@@ -329,7 +329,7 @@ const DraggableBodyRow: FC<
|
||||
|
||||
export const tableComponents = {
|
||||
body: {
|
||||
// semi-ui 导出的类型定义非常不负责任
|
||||
// The type definition exported by semi-ui is very irresponsible
|
||||
row: DraggableBodyRow,
|
||||
},
|
||||
} as unknown as TableComponents;
|
||||
|
||||
@@ -20,11 +20,11 @@ import { Form } from '@coze-arch/bot-semi';
|
||||
|
||||
import style from './index.module.less';
|
||||
|
||||
// TODO: hzf, 取名component有点奇怪
|
||||
// TODO: hzf, the named component is a bit strange
|
||||
export type FormInputWithMaxCountProps = {
|
||||
maxCount: number;
|
||||
} & React.ComponentProps<typeof Form.Input>;
|
||||
// input后带上suffix,表示能够输入的最大字数
|
||||
// After input, put a suffix to indicate the maximum number of words that can be entered
|
||||
export const FormInputWithMaxCount = (props: FormInputWithMaxCountProps) => {
|
||||
const [count, setCount] = React.useState(0);
|
||||
const handleChange = (v: string) => {
|
||||
|
||||
@@ -32,7 +32,7 @@ export const getSubmitValue = (
|
||||
const newValues = { ...values };
|
||||
|
||||
/**
|
||||
* 最先执行 根据是否包含 components_list 设置 send_type
|
||||
* Execute first, depending on whether components_list is included send_type
|
||||
*/
|
||||
mutableSendType(newValues);
|
||||
|
||||
@@ -50,7 +50,7 @@ export const getSubmitValue = (
|
||||
if (!use_tool) {
|
||||
mutableInitNotUseToolFormValues(newValues);
|
||||
}
|
||||
// TODO: hzf干掉不合理
|
||||
// TODO: hzf killing is unreasonable
|
||||
return newValues as ShortCutCommand;
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ const mutableSendType = (value: ShortcutEditFormValues) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 为了兼容,需要在修改components_list的default_value,hide的时候同步修改toolParams
|
||||
* For compatibility, you need to modify the toolParams synchronously when modifying the default_value and hide of the components_list
|
||||
* 1.components_list.hide => !toolParams.refer_component
|
||||
* 2.components_list.default_value => refer_component:false && toolParams.default_value
|
||||
*/
|
||||
@@ -90,7 +90,7 @@ export const findToolParamsByComponent = (
|
||||
component: Components,
|
||||
) => params?.find(param => param.name === component.parameter);
|
||||
|
||||
// 初始化query类型的表单参数
|
||||
// Initialize form parameters for query types
|
||||
const mutableInitQueryFormValues = (values: ShortcutEditFormValues): void => {
|
||||
values.tool_type = undefined;
|
||||
values.plugin_id = '';
|
||||
@@ -104,7 +104,7 @@ const mutableInitQueryFormValues = (values: ShortcutEditFormValues): void => {
|
||||
values.card_schema = '';
|
||||
};
|
||||
|
||||
// 初始化使用插件组件的时候表单参数
|
||||
// Initialize form parameters when using plug-in components
|
||||
const mutableInitNotUseToolFormValues = (
|
||||
values: ShortcutEditFormValues,
|
||||
): void => {
|
||||
@@ -137,10 +137,10 @@ const mutableFormatCommandName = (values: ShortcutEditFormValues): void => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 筛选toolParams存在,components中不存在的变量
|
||||
* 并且refer_component=false,
|
||||
* 转化为components_list
|
||||
* 用于向前兼容,旧指令中tool的默认参数放在toolParams中
|
||||
* Filter toolParams exists, variables that do not exist in components
|
||||
* And refer_component = false,
|
||||
* Converted to components_list
|
||||
* For forward compatibility, the default parameters of tool in the old directive are placed in toolParams
|
||||
*/
|
||||
export const initComponentsListFromToolParams = (
|
||||
components: Components[],
|
||||
@@ -167,10 +167,10 @@ export const initComponentsListFromToolParams = (
|
||||
};
|
||||
|
||||
/**
|
||||
* 兼容旧指令
|
||||
* 如果InputType为 UploadImage, UploadDoc, UploadTable, UploadAudio,
|
||||
* 判断upload_options是否为空
|
||||
* 为空,加上对应的upload_options
|
||||
* Compatible with outdated instructions
|
||||
* If the InputType is UploadImage, UploadDoc, UploadTable, UploadAudio,
|
||||
* Determine if upload_options is empty
|
||||
* Is empty, plus the corresponding upload_options
|
||||
*/
|
||||
export const initComponentsUploadOptions = (
|
||||
components: Components[],
|
||||
@@ -198,14 +198,14 @@ export const initComponentsUploadOptions = (
|
||||
export const getInitialValues = (
|
||||
initShortcut?: ShortCutCommand,
|
||||
): ShortcutEditFormValues => {
|
||||
// 初始化
|
||||
// initialization
|
||||
if (!initShortcut) {
|
||||
return {
|
||||
send_type: SendType.SendTypeQuery,
|
||||
use_tool: false,
|
||||
};
|
||||
}
|
||||
// 回显
|
||||
// echo
|
||||
const {
|
||||
shortcut_command,
|
||||
tool_type,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import React, {
|
||||
type Dispatch,
|
||||
type FC,
|
||||
@@ -106,7 +106,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
|
||||
getInitialValues(shortcut),
|
||||
);
|
||||
|
||||
// 使用技能 & 未选择工具 => 禁止提交
|
||||
// Use Skills & Unselected Tools = > Forbid Submissions
|
||||
const disableSubmit =
|
||||
editedShortcut?.use_tool && !editedShortcut?.tool_info?.tool_name;
|
||||
|
||||
@@ -127,7 +127,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
|
||||
console.log('onConfirm', formattedValues);
|
||||
|
||||
if (mode === 'create') {
|
||||
// TODO: hzf add的类型应该没有command_id
|
||||
// TODO: hzf add type should have no command_id
|
||||
onAdd?.(formattedValues, () => {
|
||||
setConfirmLoading(false);
|
||||
});
|
||||
@@ -146,7 +146,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
|
||||
await formRef.current?.formApi.validate();
|
||||
|
||||
return actionSwitchAreaRef.current?.validate();
|
||||
// eslint-disable-next-line @coze-arch/use-error-in-catch -- 正常表单校验不需要处理e
|
||||
// eslint-disable-next-line @coze-arch/use-error-in-catch -- normal form validation does not require processing e
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
|
||||
|
||||
const { data: pluginData } = useRequest(
|
||||
async () => {
|
||||
// 方便类型推断
|
||||
// convenient type inference
|
||||
if (shortcut?.plugin_id && spaceId) {
|
||||
const res = await PluginDevelopApi.GetPlaygroundPluginList({
|
||||
page: 1,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import React, { type RefObject, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
@@ -61,7 +61,7 @@ export const SwitchAgent = (props: SwitchAgentProps) => {
|
||||
if (!editedShortcut.agent_id) {
|
||||
return {
|
||||
defaultAgentId: '',
|
||||
// @ts-expect-error --后面替换
|
||||
// @ts-expect-error -- replace later
|
||||
defaultName: I18n.t('Do not specify'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,10 +78,10 @@ const ExpressionEditorContainer = forwardRef<
|
||||
useEffect(() => model.setVariableTree(variableTree), [variableTree]);
|
||||
useEffect(() => model.setFocus(focus), [focus]);
|
||||
|
||||
// 同步表单值变化
|
||||
// Synchronize form value changes
|
||||
useEffect(() => {
|
||||
if (model.value === formValue) {
|
||||
// 无需同步
|
||||
// No synchronization required
|
||||
return;
|
||||
}
|
||||
model.setValue(formValue);
|
||||
|
||||
@@ -70,7 +70,7 @@ const VarQueryTextarea: FC<UsageWithVarTextAreaProps> = props => {
|
||||
|
||||
useEffect(() => editorRef.current?.model.setFocus(focus), [focus]);
|
||||
|
||||
// 设置防抖防止 onFocus / onBlur 在点击时出现抖动
|
||||
// Set anti-shake to prevent onFocus/onBlur from shaking when clicked
|
||||
const setFocus = useCallback(
|
||||
debounce((newFocusValue: boolean) => {
|
||||
_setFocus(newFocusValue);
|
||||
|
||||
@@ -55,7 +55,7 @@ interface ExpressionEditorSuggestionProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动提示
|
||||
* autoprompt
|
||||
*/
|
||||
export const VarExpressionEditorSuggestion: FC<
|
||||
ExpressionEditorSuggestionProps
|
||||
|
||||
@@ -23,7 +23,7 @@ import type { ShortCutCommand } from '@coze-agent-ide/tool-config';
|
||||
export enum OpenModeType {
|
||||
OnlyOnceAdd = 'only_once_add',
|
||||
}
|
||||
// TODO: hzf 两份定义?
|
||||
// TODO: hzf two definitions?
|
||||
export interface SkillsModalProps {
|
||||
tabsConfig?: {
|
||||
plugin?: {
|
||||
@@ -44,9 +44,9 @@ export interface SkillsModalProps {
|
||||
};
|
||||
};
|
||||
tabs: ('plugin' | 'workflow' | 'datasets' | 'imageFlow')[];
|
||||
/** 打开弹窗模式:
|
||||
* 默认不传
|
||||
* only_once_add:仅可添加一次后关闭,并返回callback函数
|
||||
/** Open pop-up mode:
|
||||
* Do not pass by default
|
||||
* only_once_add: close after adding only once and return the callback function
|
||||
*/
|
||||
openMode?: OpenModeType;
|
||||
openModeCallback?: (val?: PluginApi | WorkFlowItemType) => void;
|
||||
|
||||
@@ -83,7 +83,7 @@ export const QueryShortcut: FC<QueryShortcutProps> = props => {
|
||||
|
||||
return (
|
||||
<div className={typeSafeShortcutCommandVariants({ color: props.uiMode })}>
|
||||
{/*指令名称不超长,展示描述*/}
|
||||
{/*Instruction name is not too long, display description*/}
|
||||
<TooltipWithContent
|
||||
shortcut={shortcut}
|
||||
toolTipFooterSlot={toolTipFooterSlot}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { type shortcut_command } from '@coze-arch/bot-api/playground_api';
|
||||
|
||||
import { type DSL } from '../../types';
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
getLayoutDSL,
|
||||
} from './templates';
|
||||
|
||||
// 通过 Components 生成完整的 DSL
|
||||
// Generating a complete DSL with Components
|
||||
export const getDSLFromComponents = (
|
||||
params: shortcut_command.Components[],
|
||||
): DSL => {
|
||||
@@ -36,7 +36,7 @@ export const getDSLFromComponents = (
|
||||
[...formItemsDSL, ...layoutDSL].forEach(
|
||||
item => (template.elements[item.id] = item),
|
||||
);
|
||||
// @ts-expect-error 支持直接传递 props
|
||||
// @ts-expect-error supports direct delivery of props
|
||||
template.elements.submitButton.props.formFields = formItemsDSL.map(
|
||||
item => item.id,
|
||||
);
|
||||
@@ -45,7 +45,7 @@ export const getDSLFromComponents = (
|
||||
|
||||
type DSLElement = DSL['elements'][string];
|
||||
|
||||
// 通过 Components 创建 DSL 中对应的表单元素 Element
|
||||
// Create the corresponding form element Element in the DSL through Components
|
||||
export const getFormElementFromComponent = (
|
||||
param: shortcut_command.Components,
|
||||
): DSLElement => {
|
||||
@@ -55,12 +55,12 @@ export const getFormElementFromComponent = (
|
||||
return getFormItemPlaceholderDSL();
|
||||
};
|
||||
|
||||
// 用于生成 DSL 语法中双列布局的容器元素
|
||||
// Container elements for generating two-column layouts in DSL syntax
|
||||
const ITEMS_PER_LINE = 2;
|
||||
export const getElementsLayout = (elements: DSLElement[]): DSLElement[] => {
|
||||
const res: DSLElement[] = [];
|
||||
const elementsCopy = [...elements];
|
||||
// 如出现奇数个,最后一行占满
|
||||
// If an odd number appears, the last line is full
|
||||
while (elementsCopy.length) {
|
||||
res.push(getLayoutDSL(elementsCopy.splice(0, ITEMS_PER_LINE)));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import { shortid } from '../uuid';
|
||||
import { getAcceptByUploadItemTypes } from '../file-const';
|
||||
import { type DSL, ElementDirectiveType, ElementPropsType } from '../../types';
|
||||
|
||||
// @fixme DSL 类型定义需要更新
|
||||
// @Fixme DSL type definition needs to be updated
|
||||
export const getDSLTemplate = (): DSL => ({
|
||||
elements: {
|
||||
root: {
|
||||
@@ -32,7 +32,7 @@ export const getDSLTemplate = (): DSL => ({
|
||||
},
|
||||
form: {
|
||||
id: 'form',
|
||||
name: 'FlowpdCiciComponentsForm', // TODO 组件名 & type 最好也能事先就约定好
|
||||
name: 'FlowpdCiciComponentsForm', // TODO component name & type can preferably be agreed in advance
|
||||
type: '@flowpd/cici-components/Form',
|
||||
props: {
|
||||
value: {
|
||||
@@ -47,15 +47,15 @@ export const getDSLTemplate = (): DSL => ({
|
||||
// some rules value
|
||||
},
|
||||
},
|
||||
children: ['submitButton'], // 根据 variables + layout 生成
|
||||
children: ['submitButton'], // Generated from variables + layout
|
||||
},
|
||||
// 通过 getFormElementsFromcomponent 生成表单元素
|
||||
// Generate form elements from getFormElementsFromcomponent
|
||||
// ...inputElements,
|
||||
// 通过 getElementsLayout 生成表单元素 layout
|
||||
// Generate form element layout with getElementsLayout
|
||||
// ...inputLayoutElements,
|
||||
submitButton: {
|
||||
id: 'submitButton',
|
||||
name: 'FlowpdCiciComponentsButton', // TODO 组件名 & type 最好也能事先就约定好
|
||||
name: 'FlowpdCiciComponentsButton', // TODO component name & type can preferably be agreed in advance
|
||||
type: '@flowpd/cici-components/Button',
|
||||
props: {
|
||||
onClick: {
|
||||
@@ -69,7 +69,7 @@ export const getDSLTemplate = (): DSL => ({
|
||||
variables: {
|
||||
formValue: {
|
||||
id: 'formValue',
|
||||
defaultValue: {}, // 不需要缺省值
|
||||
defaultValue: {}, // No default is required
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
@@ -96,7 +96,7 @@ export type GetFormItemTemplate = (
|
||||
|
||||
export const getInputElementDSL: GetFormItemTemplate = component => ({
|
||||
id: component.name ?? shortid(),
|
||||
name: 'FlowpdCiciComponentsInput', // TODO 组件名最好也能事先就约定好
|
||||
name: 'FlowpdCiciComponentsInput', // The TODO component name should preferably be agreed in advance
|
||||
type: '@flowpd/cici-components/Input',
|
||||
props: {
|
||||
name: component.name,
|
||||
@@ -104,13 +104,13 @@ export const getInputElementDSL: GetFormItemTemplate = component => ({
|
||||
defaultValue: component.default_value,
|
||||
rules: [],
|
||||
noErrorMessage: true,
|
||||
// @FIXME DSL 解析逻辑实际支持传入任意值作为 props,但是类型定义里没有兼容这种语法
|
||||
// The @FIXME DSL parsing logic actually supports passing arbitrary values as props, but there is no compatible syntax in the type definition
|
||||
} as unknown as DSLElement['props'],
|
||||
});
|
||||
|
||||
export const getSelectElementDSL: GetFormItemTemplate = component => ({
|
||||
id: component.name ?? shortid(),
|
||||
name: 'FlowpdCiciComponentsSelect', // TODO 组件名最好也能事先就约定好
|
||||
name: 'FlowpdCiciComponentsSelect', // The TODO component name should preferably be agreed in advance
|
||||
type: '@flowpd/cici-components/Select',
|
||||
props: {
|
||||
name: component.name,
|
||||
@@ -126,11 +126,11 @@ export const getSelectElementDSL: GetFormItemTemplate = component => ({
|
||||
},
|
||||
],
|
||||
noErrorMessage: true,
|
||||
// @FIXME DSL 解析逻辑实际支持传入任意值作为 props,但是类型定义里没有兼容这种语法
|
||||
// The @FIXME DSL parsing logic actually supports passing arbitrary values as props, but there is no compatible syntax in the type definition
|
||||
} as unknown as DSLElement['props'],
|
||||
});
|
||||
|
||||
// 单位 kb
|
||||
// Unit kb
|
||||
export const IMAGE_MAX_SIZE = 500 * 1024; // 500 mb
|
||||
export const FILE_MAX_SIZE = 500 * 1024; // 500 mb
|
||||
|
||||
@@ -147,7 +147,7 @@ const getAcceptByComponent = (component: shortcut_command.Components) => {
|
||||
|
||||
export const getUploadElementDSL: GetFormItemTemplate = component => ({
|
||||
id: component.name ?? shortid(),
|
||||
name: 'FlowpdCiciComponentsUpload', // TODO 组件名最好也能事先就约定好
|
||||
name: 'FlowpdCiciComponentsUpload', // The TODO component name should preferably be agreed in advance
|
||||
type: '@flowpd/cici-components/Upload',
|
||||
props: {
|
||||
name: component.name,
|
||||
@@ -164,11 +164,11 @@ export const getUploadElementDSL: GetFormItemTemplate = component => ({
|
||||
},
|
||||
],
|
||||
noErrorMessage: true,
|
||||
// @FIXME DSL 解析逻辑实际支持传入任意值作为 props,但是类型定义里没有兼容这种语法
|
||||
// The @FIXME DSL parsing logic actually supports passing arbitrary values as props, but there is no compatible syntax in the type definition
|
||||
} as unknown as DSLElement['props'],
|
||||
});
|
||||
|
||||
// 配置 & 预览模式占位符
|
||||
// Configuration & Preview Mode Placeholders
|
||||
export const getFormItemPlaceholderDSL = () => ({
|
||||
id: shortid(),
|
||||
name: 'FlowpdCiciComponentsFormItemPlaceholder',
|
||||
@@ -180,7 +180,7 @@ export const getLayoutDSL = (items: DSLElement[]): DSLElement => ({
|
||||
name: 'FlowpdCiciComponentsColumnLayout',
|
||||
type: '@flowpd/cici-components/ColumnLayout',
|
||||
props: {
|
||||
// 如出现奇数个,最后一行占满
|
||||
// If an odd number appears, the last line is full
|
||||
Columns: items.map(item => ({
|
||||
children: [item.id],
|
||||
config: { vertical: 'top', weight: 1, width: 'weighted' },
|
||||
@@ -189,7 +189,7 @@ export const getLayoutDSL = (items: DSLElement[]): DSLElement => ({
|
||||
action: 'enableUrl',
|
||||
backgroundColor: 'transparent',
|
||||
enableClickEvent: false,
|
||||
// @FIXME card-buidler Layout 现有的数据结构,但是实际上类型非法
|
||||
// @FIXME card-buidler Layout an existing data structure, but the type is actually illegal
|
||||
} as unknown as DSLElement['props'],
|
||||
});
|
||||
export const getFormItemDSLMap: Record<
|
||||
|
||||
@@ -95,7 +95,7 @@ export const ACCEPT_UPLOAD_TYPES: {
|
||||
},
|
||||
];
|
||||
|
||||
// 和chat支持的文件格式做映射
|
||||
// Map with file formats supported by chat
|
||||
export const fileTypeToInputTypeMap = {
|
||||
[FileTypeEnum.IMAGE]: shortcut_command.InputType.UploadImage,
|
||||
[FileTypeEnum.AUDIO]: shortcut_command.InputType.UploadAudio,
|
||||
@@ -126,7 +126,7 @@ export const acceptMap = FILE_TYPE_CONFIG.reduce<{
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// 根据acceptUploadItemTypes获取accept
|
||||
// Accept based on acceptUploadItemTypes
|
||||
export const getAcceptByUploadItemTypes = (
|
||||
acceptUploadItemTypes: shortcut_command.InputType[],
|
||||
) => {
|
||||
@@ -144,7 +144,7 @@ export const getAcceptByUploadItemTypes = (
|
||||
return accept.join(',');
|
||||
};
|
||||
|
||||
// 根据fileType获取对应的fileInfo
|
||||
// Get the corresponding fileInfo according to fileType
|
||||
export const getFileInfoByFileType = (fileType: FileTypeEnum) => {
|
||||
const inputType = fileTypeToInputTypeMap[fileType];
|
||||
if (!inputType) {
|
||||
@@ -153,7 +153,7 @@ export const getFileInfoByFileType = (fileType: FileTypeEnum) => {
|
||||
return ACCEPT_UPLOAD_TYPES.find(item => item.type === inputType);
|
||||
};
|
||||
|
||||
// ACCEPT_UPLOAD_TYPES转化为map
|
||||
// ACCEPT_UPLOAD_TYPES converted to map
|
||||
export const getAcceptUploadItemTypesMap = () =>
|
||||
ACCEPT_UPLOAD_TYPES.reduce<{
|
||||
[key in shortcut_command.InputType]?: string;
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// 根据template_query和components拼接query
|
||||
// Stitching queries based on template_query and components
|
||||
export const getQueryFromTemplate = (
|
||||
templateQuery: string,
|
||||
values: Record<string, unknown>,
|
||||
) => {
|
||||
let query = templateQuery;
|
||||
// 替换模板中的{{key}}为values中key对应的值
|
||||
// Replace the {{key}} in the template with the value corresponding to the key in values
|
||||
Object.keys(values).forEach(key => {
|
||||
query = query.replace(
|
||||
new RegExp(`\\{\\{${key}\\}\\}`, 'g'),
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
|
||||
import { type ToolInfo } from '../shortcut-tool/types';
|
||||
|
||||
// 根据shortcut获取toolInfo
|
||||
// Get toolInfo by shortcut
|
||||
export const getToolInfoByShortcut = (
|
||||
shortcut: shortcut_command.ShortcutCommand | undefined,
|
||||
): ToolInfo => {
|
||||
@@ -51,11 +51,11 @@ export const getToolInfoByShortcut = (
|
||||
};
|
||||
};
|
||||
|
||||
// 校验string:数字 + 英文 + _ & 不能是纯数字
|
||||
// Check string: number + English + _ & cannot be pure numbers
|
||||
export const validateCmdString = (value: string) =>
|
||||
/^[a-zA-Z0-9_]+$/.test(value) && !/^[0-9]+$/.test(value);
|
||||
|
||||
// 根据tool_type判断是否开启了tool
|
||||
// According to tool_type determine whether the tool is turned on.
|
||||
export const initToolEnabledByToolTYpe = (
|
||||
toolType: shortcut_command.ToolType | undefined,
|
||||
) =>
|
||||
@@ -65,7 +65,7 @@ export const initToolEnabledByToolTYpe = (
|
||||
shortcut_command.ToolType.ToolTypePlugin,
|
||||
].includes(toolType);
|
||||
|
||||
// 校验plugin和workflow参数是否为string|integer类型,不支持复杂的对象类型
|
||||
// Verify that the plugin and workflow parameters are of type string | integer, and do not support complex object types
|
||||
export const validatePluginAndWorkflowParams = (
|
||||
params: ToolParams[],
|
||||
enableEmpty = false,
|
||||
@@ -89,7 +89,7 @@ export const validatePluginAndWorkflowParams = (
|
||||
};
|
||||
};
|
||||
|
||||
// 校验shortcut_command是否重复
|
||||
// Check if shortcut_command duplicate
|
||||
export const validateCommandNameRepeat = (
|
||||
checkShortcut: shortcut_command.ShortcutCommand,
|
||||
shortcuts: shortcut_command.ShortcutCommand[],
|
||||
@@ -101,7 +101,7 @@ export const validateCommandNameRepeat = (
|
||||
shortcut.shortcut_command === shortcutCommand,
|
||||
);
|
||||
};
|
||||
// 校验按钮名称command_name是否重复
|
||||
// Check button name command_name duplicate
|
||||
export const validateButtonNameRepeat = (
|
||||
checkShortcut: shortcut_command.ShortcutCommand,
|
||||
shortcuts: shortcut_command.ShortcutCommand[],
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// 对齐 card-builder 生成 ID 的逻辑,暂时拷贝一份,未来计划直接使用 card-buidler 的底层能力
|
||||
// Align the logic of card-builder generating ID, make a copy temporarily, and plan to use the underlying capabilities of card-buidler directly in the future
|
||||
import { nanoid, customAlphabet } from 'nanoid';
|
||||
|
||||
/**
|
||||
* @param prefix - id前缀
|
||||
* @param options - alphabet: 字母表; length: 长度,默认10;
|
||||
* @param prefix - id prefix
|
||||
* @Param options - alphabet; length: length, default 10;
|
||||
*/
|
||||
export const shortid = (
|
||||
prefix = '',
|
||||
|
||||
Reference in New Issue
Block a user