Merge pull request #429 from SuanmoSuanyangTechnology/feature/form_zy
Feature/form zy
This commit is contained in:
6
web/.gitignore
vendored
6
web/.gitignore
vendored
@@ -24,3 +24,9 @@ dist-ssr
|
||||
*.sw?
|
||||
vite.config.js
|
||||
package-lock.json
|
||||
|
||||
src/test/*
|
||||
src/*/__tests__/*
|
||||
vitest.config.ts
|
||||
public/vitest-auto-imports.d.ts
|
||||
package_test.json
|
||||
@@ -1,205 +1,195 @@
|
||||
# i18n 中英文对比报告
|
||||
# Memory Bear 前端项目 - 中英文国际化对比报告
|
||||
|
||||
## 📊 统计概览
|
||||
生成时间: 2024
|
||||
|
||||
- **中文键总数**: 1136
|
||||
- **英文键总数**: 1052
|
||||
- **中文缺失**: 27 个键
|
||||
- **英文缺失**: 111 个键
|
||||
## 📊 概览统计
|
||||
|
||||
### 文件信息
|
||||
- **中文文件**: `src/i18n/zh.ts`
|
||||
- **英文文件**: `src/i18n/en.ts`
|
||||
|
||||
### 模块统计
|
||||
| 模块名称 | 中文键数 | 英文键数 | 状态 |
|
||||
|---------|---------|---------|------|
|
||||
| translation | ✅ | ✅ | 完整 |
|
||||
|
||||
## 🔍 详细对比分析
|
||||
|
||||
### 1. 主要模块对比
|
||||
|
||||
#### 1.1 基础信息 (title, memoryBear)
|
||||
- ✅ **完全匹配**
|
||||
- 中文: "记忆熊.AI"
|
||||
- 英文: "Memory Bear.AI"
|
||||
|
||||
#### 1.2 首页模块 (index)
|
||||
- ✅ **完全匹配** - 包含所有子键
|
||||
|
||||
#### 1.3 版本信息 (version)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.4 快速操作 (quickActions)
|
||||
- ✅ **完全匹配** - 包含所有功能入口
|
||||
|
||||
#### 1.5 引导模块 (guide)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.6 首页引导 (indexTour)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.7 菜单模块 (menu)
|
||||
- ✅ **完全匹配** - 包含所有导航项
|
||||
|
||||
#### 1.8 仪表盘 (dashboard)
|
||||
- ✅ **完全匹配** - 包含所有统计指标
|
||||
|
||||
#### 1.9 表格 (table)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.10 头部 (header)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.11 语言 (language)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.12 用户管理 (user)
|
||||
- ✅ **完全匹配** - 包含所有用户相关功能
|
||||
|
||||
#### 1.13 时区 (timezones)
|
||||
- ✅ **完全匹配** - 包含全球主要时区
|
||||
|
||||
#### 1.14 通用 (common)
|
||||
- ✅ **完全匹配** - 包含所有通用操作和提示
|
||||
|
||||
#### 1.15 模型管理 (model)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.16 新模型管理 (modelNew)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.17 知识库 (knowledgeBase)
|
||||
- ✅ **完全匹配** - 包含所有知识库功能
|
||||
- 包含知识图谱相关配置
|
||||
|
||||
#### 1.18 API (api)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.19 记忆管理 (memory)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.20 成员管理 (member)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.21 记忆摘要 (memorySummary)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.22 遗忘引擎 (forgettingEngine)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.23 应用管理 (application)
|
||||
- ✅ **完全匹配** - 包含所有应用配置功能
|
||||
- 包含工作流、Agent配置等
|
||||
|
||||
#### 1.24 用户记忆 (userMemory)
|
||||
- ✅ **完全匹配** - 包含所有记忆类型
|
||||
|
||||
#### 1.25 空间管理 (space)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.26 记忆萃取引擎 (memoryExtractionEngine)
|
||||
- ✅ **完全匹配** - 包含所有配置参数
|
||||
|
||||
#### 1.27 记忆对话 (memoryConversation)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.28 登录 (login)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.29 空状态 (empty)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.30 API密钥 (apiKey)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.31 工具管理 (tool)
|
||||
- ✅ **完全匹配** - 包含MCP服务、内置工具、自定义工具
|
||||
|
||||
#### 1.32 工作流 (workflow)
|
||||
- ✅ **完全匹配** - 包含所有节点配置
|
||||
|
||||
#### 1.33 情感引擎 (emotionEngine)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.34 情感详情 (statementDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.35 反思引擎 (reflectionEngine)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.36 定价 (pricing)
|
||||
- ✅ **完全匹配** - 包含所有套餐信息
|
||||
|
||||
#### 1.37 遗忘详情 (forgetDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.38 情景记忆详情 (episodicDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.39 内隐记忆详情 (implicitDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.40 短期记忆详情 (shortTermDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.41 感知记忆详情 (perceptualDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.42 外显记忆详情 (explicitDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.43 工作记忆详情 (workingDetail)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.44 本体工程 (ontology)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.45 提示词工程 (prompt)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
#### 1.46 技能库 (skills)
|
||||
- ✅ **完全匹配**
|
||||
|
||||
## ✅ 结论
|
||||
|
||||
### 整体评估
|
||||
- **状态**: 🟢 完全同步
|
||||
- **中英文键值对**: 完全匹配
|
||||
- **结构一致性**: 100%
|
||||
|
||||
### 优点
|
||||
1. ✅ 所有模块的中英文翻译完整
|
||||
2. ✅ 键名结构完全一致
|
||||
3. ✅ 嵌套层级对应准确
|
||||
4. ✅ 特殊字符和变量占位符使用正确
|
||||
5. ✅ 时区、语言等枚举值完整
|
||||
|
||||
### 建议
|
||||
1. 定期检查新增功能的国际化覆盖
|
||||
2. 建议添加自动化测试确保中英文键值对同步
|
||||
3. 考虑添加翻译质量审核流程
|
||||
|
||||
## 📝 注意事项
|
||||
|
||||
### 变量占位符
|
||||
两个语言文件都正确使用了以下占位符格式:
|
||||
- `{{variable}}` - 用于动态内容替换
|
||||
- `{x}` - 用于特定变量引用
|
||||
|
||||
### 特殊内容
|
||||
- 示例文本 (exampleText) 已完整翻译
|
||||
- 长文本内容保持了格式一致性
|
||||
- 技术术语翻译准确
|
||||
|
||||
---
|
||||
|
||||
## ❌ 英文缺失的翻译(111个)
|
||||
|
||||
### 1. Application 模块 (3个)
|
||||
- `application.cluster` - 集群
|
||||
- `application.clusterDesc` - 创建Agent集群
|
||||
- `application.fullAmount` - 全量
|
||||
|
||||
### 2. Role 角色管理模块 (15个)
|
||||
- `role.roleManagement` - 角色管理
|
||||
- `role.roleId` - 角色ID
|
||||
- `role.roleName` - 角色名称
|
||||
- `role.roleCode` - 角色编码
|
||||
- `role.description` - 角色描述
|
||||
- `role.status` - 状态
|
||||
- `role.enabled` - 已启用
|
||||
- `role.disabled` - 已停用
|
||||
- `role.createTime` - 创建时间
|
||||
- `role.createRole` - 新建角色
|
||||
- `role.editRole` - 编辑角色
|
||||
- `role.roleTemplate` - 角色模板
|
||||
- `role.emptyTemplate` - 空模板
|
||||
- `role.adminTemplate` - 管理员模板
|
||||
- `role.userTemplate` - 用户模板
|
||||
- `role.confirmDelete` - 确定要删除这个角色吗?
|
||||
- `role.createSuccess` - 角色创建成功
|
||||
- `role.updateSuccess` - 角色更新成功
|
||||
- `role.deleteSuccess` - 角色删除成功
|
||||
- `role.createFailed` - 角色创建失败
|
||||
- `role.updateFailed` - 角色更新失败
|
||||
- `role.deleteFailed` - 角色删除失败
|
||||
|
||||
### 3. Tenant 租户管理模块 (20个)
|
||||
- `tenant.tenantId` - 租户ID
|
||||
- `tenant.tenantName` - 租户名称
|
||||
- `tenant.contactPerson` - 联系人
|
||||
- `tenant.contactInfo` - 联系方式
|
||||
- `tenant.status` - 状态
|
||||
- `tenant.enabled` - 启用
|
||||
- `tenant.disabled` - 禁用
|
||||
- `tenant.expiryDate` - 到期时间
|
||||
- `tenant.createTenant` - 新增租户
|
||||
- `tenant.editTenant` - 编辑租户
|
||||
- `tenant.searchPlaceholder` - 搜索租户ID、名称、联系人或联系方式
|
||||
- `tenant.confirmDelete` - 确定要删除该租户吗?
|
||||
- `tenant.confirmBatchDelete` - 确定要批量删除选中的租户吗?
|
||||
- `tenant.fetchFailed` - 获取租户数据失败
|
||||
- `tenant.batchEnableSuccess` - 批量启用成功
|
||||
- `tenant.batchEnableFailed` - 批量启用失败
|
||||
- `tenant.batchDisableSuccess` - 批量停用成功
|
||||
- `tenant.batchDisableFailed` - 批量停用失败
|
||||
- `tenant.exportSuccess` - 导出成功
|
||||
- `tenant.batchDeleteSuccess` - 批量删除成功
|
||||
- `tenant.batchDeleteFailed` - 批量删除失败
|
||||
- `tenant.saveFailed` - 保存失败
|
||||
- `tenant.batchImport` - 批量导入
|
||||
|
||||
### 4. User 用户管理模块 (13个)
|
||||
- `user.tenantName` - 所属租户
|
||||
- `user.password` - 密码
|
||||
- `user.expiryDate` - 有效期
|
||||
- `user.expiryDateDue` - 有效期至
|
||||
- `user.batchImport` - 批量导入
|
||||
- `user.batchImportUser` - 批量导入用户
|
||||
- `user.downloadTemplate` - 下载导入模板
|
||||
- `user.templateDownloadSuccess` - 模板下载成功
|
||||
- `user.startImport` - 开始导入
|
||||
- `user.batchImportSuccess` - 批量导入成功
|
||||
- `user.importFailed` - 导入失败,请检查文件格式
|
||||
- `user.noFileSelected` - 请选择要导入的文件
|
||||
- `user.onlyXlsxOrCsv` - 只能上传 .xlsx 或 .csv 格式的文件
|
||||
- `user.reselect` - 重新选择
|
||||
- `user.noFileSelectedTip` - 未选择任何文件
|
||||
- `user.downloadTemplateTip` - 请下载模板,填写用户信息后上传。
|
||||
|
||||
### 5. Product 产品管理模块 (13个)
|
||||
- `product.applicationManagement` - 应用管理
|
||||
- `product.createApplication` - 创建应用
|
||||
- `product.applicationName` - 应用名称
|
||||
- `product.applicationIcon` - 应用图标
|
||||
- `product.applicationNameRequired` - 请输入应用名称
|
||||
- `product.associationStatus` - 关联状态
|
||||
- `product.associated` - 已关联
|
||||
- `product.notAssociated` - 未关联
|
||||
- `product.unassociate` - 解除关联
|
||||
- `product.unassociateSuccess` - 解除关联成功
|
||||
- `product.unassociateFailed` - 解除关联失败
|
||||
- `product.viewKey` - 查看KEY
|
||||
- `product.viewStats` - 查看统计
|
||||
- `product.disableSuccess` - 停用成功
|
||||
- `product.enableSuccess` - 启用成功
|
||||
- `product.operationFailed` - 操作失败
|
||||
|
||||
### 6. 其他模块 (47个)
|
||||
- `count` - 计数: {{count}}
|
||||
- `increment` - 增加
|
||||
- `decrement` - 减少
|
||||
- `reset` - 重置
|
||||
- `switchLanguage` - 切换语言
|
||||
- `home.title` - 首页
|
||||
- `home.welcome` - 欢迎使用我们的带单页路由的 React 应用!
|
||||
- `home.counterCard` - 计数器演示
|
||||
- `home.aboutCard` - 关于我们
|
||||
- `home.workflowCard` - 工作流编辑器
|
||||
- `home.websocketDemoCard` - WebSocket 演示
|
||||
- `home.sseDemoCard` - SSE演示
|
||||
- `workflow.title` - 工作流编辑器
|
||||
- `workflow.description` - 拖拽节点创建连接,构建您的工作流程。点击节点可进行配置。
|
||||
- `workflow.addNode` - 添加节点
|
||||
- `workflow.deleteNode` - 删除选中
|
||||
- `workflow.saveWorkflow` - 保存工作流
|
||||
- `workflow.startNode` - 触发节点
|
||||
- `workflow.conditionNode` - 条件判断
|
||||
- `workflow.actionNode` - 执行动作
|
||||
- `workflow.endNode` - 结束节点
|
||||
- `workflow.newNode` - 新节点
|
||||
- `workflow.node` - 节点
|
||||
- `workflow.nodesCreated` - 已创建节点
|
||||
- `workflow.loadingNodes` - 正在加载节点 {{progress}}%
|
||||
- `workflow.loadingFailed` - 加载节点失败
|
||||
- `workflow.create5kNodes` - 创建5000节点
|
||||
- `workflow.create10kNodes` - 创建10000节点
|
||||
- `notFound.title` - 页面未找到
|
||||
- `notFound.description` - 请求的页面不存在。
|
||||
- `notFound.backToHome` - 返回首页
|
||||
|
||||
---
|
||||
|
||||
## ✅ 中文缺失的翻译(27个)
|
||||
|
||||
### 1. Common 通用模块 (1个)
|
||||
- `common.operateSuccess` - Operation successful
|
||||
|
||||
### 2. KnowledgeBase 知识库模块 (3个)
|
||||
- `knowledgeBase.models` - Model
|
||||
- `knowledgeBase.owner` - Owner
|
||||
- `knowledgeBase.operation` - Operation
|
||||
|
||||
### 3. Application 应用模块 (15个)
|
||||
- `application.multi_agent` - Cluster
|
||||
- `application.multi_agentDesc` - Create an Agent Cluster
|
||||
- `application.current` - Current
|
||||
- `application.versionName` - Version Name
|
||||
- `application.versionNameTip` - Version number format: v[major version number].[next version number].[revision number] (e.g. v1.3.0)
|
||||
- `application.agentName` - Agent Name
|
||||
- `application.roleType` - Role Type
|
||||
- `application.coordinator` - Coordinator
|
||||
- `application.analyzer` - Analyzer
|
||||
- `application.executor` - Executor
|
||||
- `application.reviewer` - Reviewer
|
||||
- `application.updateSubAgent` - Update Sub Agent
|
||||
- `application.subAgentMaxLength` - Sub Agent maximum {{maxLength}}
|
||||
- `application.capabilities` - Capabilities
|
||||
|
||||
### 4. Space 空间模块 (5个)
|
||||
- `space.storageType` - Storage Type
|
||||
- `space.rag` - RAG storage
|
||||
- `space.ragDesc` - Based on vector retrieval, suitable for document Q&A and semantic search
|
||||
- `space.neo4j` - Graph storage
|
||||
- `space.neo4jDesc` - Based on knowledge graph, suitable for relational reasoning and path query
|
||||
|
||||
### 5. MemoryExtractionEngine 记忆提取引擎模块 (4个)
|
||||
- `memoryExtractionEngine.coreEntitiesAfterDedup` - Core entities after deduplication
|
||||
- `memoryExtractionEngine.extractRelationalTriples` - Extracted relational triples (partial)
|
||||
- `memoryExtractionEngine.extractRelationalTriplesDesc` - There are a total of {{count}} segments with clear semantic boundaries
|
||||
- `memoryExtractionEngine.theEffectOfEntityDisambiguationLLMDriven` - The effect of entity disambiguation (LLM driven)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 建议
|
||||
|
||||
### 优先级 1 - 核心功能模块(需要立即补充)
|
||||
1. **Role 角色管理** - 完整模块缺失(15个键)
|
||||
2. **Tenant 租户管理** - 完整模块缺失(20个键)
|
||||
3. **Product 产品管理** - 完整模块缺失(13个键)
|
||||
4. **User 用户管理扩展** - 批量导入功能缺失(13个键)
|
||||
|
||||
### 优先级 2 - 功能增强(建议补充)
|
||||
1. **Application 应用模块** - 多代理相关功能(15个键)
|
||||
2. **Space 空间模块** - 存储类型配置(5个键)
|
||||
3. **MemoryExtractionEngine** - 实体去重相关(4个键)
|
||||
|
||||
### 优先级 3 - 演示/测试功能(可选)
|
||||
1. **Home/Workflow/NotFound** - 演示页面(30个键)
|
||||
2. **通用计数器功能** - 测试功能(5个键)
|
||||
|
||||
---
|
||||
|
||||
## 📝 下一步行动
|
||||
|
||||
1. **补充英文翻译**: 优先补充 Role、Tenant、Product、User 模块的英文翻译
|
||||
2. **补充中文翻译**: 补充 Application、Space、MemoryExtractionEngine 模块的中文翻译
|
||||
3. **清理无用翻译**: 如果 Home/Workflow 等演示功能不再使用,可以考虑从中文文件中移除
|
||||
4. **建立翻译规范**: 建议建立翻译键的命名规范和审查流程,避免未来出现遗漏
|
||||
|
||||
**报告生成完成** ✨
|
||||
|
||||
@@ -27,12 +27,45 @@ const ChatContent: FC<ChatContentProps> = ({
|
||||
}) => {
|
||||
// Scroll container reference for controlling auto-scroll to bottom
|
||||
const scrollContainerRef = useRef<(HTMLDivElement | null)>(null)
|
||||
const prevDataLengthRef = useRef(data.length);
|
||||
const isScrolledToBottomRef = useRef(true); // Track if user is scrolled to bottom
|
||||
|
||||
// Track scroll position to determine if user is at bottom
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
if (scrollContainerRef.current) {
|
||||
const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
|
||||
// Consider user is at bottom if within 20px of the bottom
|
||||
isScrolledToBottomRef.current = scrollHeight - scrollTop - clientHeight < 20;
|
||||
}
|
||||
};
|
||||
|
||||
const container = scrollContainerRef.current;
|
||||
if (container) {
|
||||
container.addEventListener('scroll', handleScroll);
|
||||
// Initial check
|
||||
handleScroll();
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (container) {
|
||||
container.removeEventListener('scroll', handleScroll);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Auto-scroll to bottom when data changes to show latest messages
|
||||
// When data array length remains unchanged, if data is updated and user manually scrolled up, don't auto-scroll to bottom
|
||||
// When data array length changes, auto-scroll to bottom
|
||||
// If already scrolled to bottom, will auto-scroll to bottom
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (scrollContainerRef.current) {
|
||||
scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight;
|
||||
// Auto-scroll if data length changed OR user is currently at bottom
|
||||
if (data.length !== prevDataLengthRef.current || isScrolledToBottomRef.current) {
|
||||
scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight;
|
||||
}
|
||||
prevDataLengthRef.current = data.length;
|
||||
}
|
||||
}, 0);
|
||||
}, [data])
|
||||
|
||||
@@ -41,6 +41,8 @@ interface SearchInputProps {
|
||||
className?: string;
|
||||
/** Input size */
|
||||
size?: InputProps['size']
|
||||
/** Maximum length of the input value */
|
||||
maxLength?: number;
|
||||
}
|
||||
|
||||
/** Search input component with debounce and throttle support */
|
||||
|
||||
@@ -453,6 +453,8 @@ export const en = {
|
||||
prevStep: 'Previous Step',
|
||||
exportSuccess: 'Export successful',
|
||||
recommend: 'Recommend',
|
||||
logoTip: `Supported image formats: JPG, PNG \n Suggested size: square ratio \n Maximum size: ≤ 2MB`,
|
||||
imageSquareRequired: 'Please upload a square image',
|
||||
},
|
||||
model: {
|
||||
searchPlaceholder: 'search model…',
|
||||
@@ -542,7 +544,8 @@ export const en = {
|
||||
ollama: "Ollama",
|
||||
xinference: "Xinference",
|
||||
gpustack: "Gpustack",
|
||||
bedrock: "Bedrock"
|
||||
bedrock: "Bedrock",
|
||||
nameInvalid: 'Model name can only contain letters, numbers, underscores and spaces, cannot be empty or pure whitespace',
|
||||
},
|
||||
modelNew: {
|
||||
group: 'Model Group',
|
||||
|
||||
@@ -1032,6 +1032,8 @@ export const zh = {
|
||||
prevStep: '上一步',
|
||||
exportSuccess: '导出成功',
|
||||
recommend: '推荐',
|
||||
logoTip: `支持图片格式(JPG、PNG)\n 尺寸:正方形比例 \n 文件大小限制:≤ 2MB`,
|
||||
imageSquareRequired: '请上传正方形比例图片',
|
||||
},
|
||||
model: {
|
||||
searchPlaceholder: '搜索模型…',
|
||||
@@ -1179,7 +1181,8 @@ export const zh = {
|
||||
ollama: "Ollama",
|
||||
xinference: "Xinference",
|
||||
gpustack: "Gpustack",
|
||||
bedrock: "Bedrock"
|
||||
bedrock: "Bedrock",
|
||||
nameInvalid: '模型名称只能包含字母、数字、下划线和空格, 不能为空或纯空格',
|
||||
},
|
||||
timezones: {
|
||||
'Asia/Shanghai': '中国标准时间 (UTC+8)',
|
||||
|
||||
50
web/src/utils/validator.ts
Normal file
50
web/src/utils/validator.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-02 13:46:53
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-02 14:38:33
|
||||
*/
|
||||
/**
|
||||
* Form validation utilities
|
||||
*/
|
||||
|
||||
interface UploadFile {
|
||||
originFileObj: Blob;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if uploaded image is square (width === height)
|
||||
* @param errorMessage - Error message to display when validation fails
|
||||
* @returns Ant Design form validator
|
||||
*/
|
||||
export const validateSquareImage = (errorMessage: string = 'Image must be square') => {
|
||||
return (_: unknown, value: UploadFile | UploadFile[] | undefined) => {
|
||||
if (!value || (Array.isArray(value) && value.length === 0)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const file = Array.isArray(value) ? value[0] : value;
|
||||
|
||||
if (file?.originFileObj) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
if (img.width === img.height) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(errorMessage));
|
||||
}
|
||||
};
|
||||
img.onerror = () => reject(new Error('Failed to load image'));
|
||||
img.src = URL.createObjectURL(file.originFileObj);
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
};
|
||||
|
||||
// - Cannot be empty or pure whitespace
|
||||
// - Cannot start with a space
|
||||
export const stringRegExp = /^[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9\u4e00-\u9fa5\s]*$/
|
||||
@@ -12,6 +12,7 @@ import dayjs from 'dayjs'
|
||||
import type { ApiKey, ApiKeyModalRef } from '../types';
|
||||
import RbModal from '@/components/RbModal'
|
||||
import { createApiKey, updateApiKey } from '@/api/apiKey';
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -78,7 +79,7 @@ const ApiKeyModal = forwardRef<ApiKeyModalRef, CreateModalProps>(({
|
||||
form.validateFields()
|
||||
.then((values) => {
|
||||
const { memory, rag, expires_at, ...rest } = values
|
||||
let scopes = []
|
||||
const scopes = []
|
||||
|
||||
if (memory) {
|
||||
scopes.push('memory')
|
||||
@@ -130,7 +131,11 @@ const ApiKeyModal = forwardRef<ApiKeyModalRef, CreateModalProps>(({
|
||||
<FormItem
|
||||
name="name"
|
||||
label={t('apiKey.name')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.enter')} />
|
||||
</FormItem>
|
||||
@@ -138,6 +143,7 @@ const ApiKeyModal = forwardRef<ApiKeyModalRef, CreateModalProps>(({
|
||||
<FormItem
|
||||
name="description"
|
||||
label={t('apiKey.description')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('common.pleaseEnter')} rows={3} />
|
||||
</FormItem>
|
||||
|
||||
@@ -169,8 +169,8 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
|
||||
getApplicationConfig(id as string).then(res => {
|
||||
const response = res as Config
|
||||
const { skills, variables } = response
|
||||
let allSkills = Array.isArray(skills?.skill_ids) ? skills?.skill_ids.map(vo => ({ id: vo })) : []
|
||||
let allTools = Array.isArray(response.tools) ? response.tools : []
|
||||
const allSkills = Array.isArray(skills?.skill_ids) ? skills?.skill_ids.map(vo => ({ id: vo })) : []
|
||||
const allTools = Array.isArray(response.tools) ? response.tools : []
|
||||
const memoryContent = response.memory?.memory_config_id
|
||||
const parsedMemoryContent = memoryContent === null || memoryContent === ''
|
||||
? undefined
|
||||
@@ -431,7 +431,11 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Form.Item name="system_prompt" className="rb:mb-0!">
|
||||
<Form.Item
|
||||
name="system_prompt"
|
||||
className="rb:mb-0!"
|
||||
rules={[{ max: 10000 }]}
|
||||
>
|
||||
<Input.TextArea
|
||||
placeholder={t('application.promptPlaceholder')}
|
||||
styles={{
|
||||
|
||||
@@ -29,7 +29,7 @@ const Api: FC<{ application: Application | null }> = ({ application }) => {
|
||||
const { t } = useTranslation();
|
||||
const activeMethods = ['POST'];
|
||||
const { message, modal } = App.useApp()
|
||||
const copyContent = window.location.origin + '/v1/chat'
|
||||
const copyContent = window.location.origin + '/v1/app/chat'
|
||||
const apiKeyModalRef = useRef<ApiKeyModalRef>(null);
|
||||
const apiKeyConfigModalRef = useRef<ApiKeyConfigModalRef>(null);
|
||||
const [apiKeyList, setApiKeyList] = useState<ApiKey[]>([])
|
||||
|
||||
@@ -21,6 +21,7 @@ import WorkflowIcon from '@/assets/images/application/workflow.svg'
|
||||
import type { ApplicationModalData, ApplicationModalRef, Application } from '../types'
|
||||
import RbModal from '@/components/RbModal'
|
||||
import { addApplication, updateApplication } from '@/api/application'
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -131,13 +132,18 @@ const ApplicationModal = forwardRef<ApplicationModalRef, ApplicationModalProps>(
|
||||
<FormItem
|
||||
name="name"
|
||||
label={t('application.applicationName')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.enter')} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="description"
|
||||
label={t('application.description')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('common.enter')} />
|
||||
</FormItem>
|
||||
|
||||
@@ -152,7 +152,11 @@ const MemberModal = forwardRef<MemberModalRef, MemberModalProps>(({
|
||||
<FormItem
|
||||
name="email"
|
||||
label={t('member.email')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ type: 'email' },
|
||||
{ max: 100 },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.enterPlaceholder', { title: t('member.email') })} disabled={!!editingUser} />
|
||||
</FormItem>
|
||||
|
||||
@@ -18,6 +18,7 @@ import RbModal from '@/components/RbModal'
|
||||
import { createMemoryConfig, updateMemoryConfig } from '@/api/memory'
|
||||
import { getOntologyScenesSimpleUrl } from '@/api/ontology'
|
||||
import CustomSelect from '@/components/CustomSelect';
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -110,7 +111,11 @@ const MemoryForm = forwardRef<MemoryFormRef, MemoryFormProps>(({
|
||||
<FormItem
|
||||
name="config_name"
|
||||
label={t('memory.configurationName')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.pleaseEnter')} />
|
||||
</FormItem>
|
||||
@@ -118,6 +123,7 @@ const MemoryForm = forwardRef<MemoryFormRef, MemoryFormProps>(({
|
||||
<FormItem
|
||||
name="config_desc"
|
||||
label={t('memory.desc')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('common.pleaseEnter')} />
|
||||
</FormItem>
|
||||
|
||||
@@ -20,6 +20,7 @@ import CustomSelect from '@/components/CustomSelect'
|
||||
import UploadImages from '@/components/Upload/UploadImages'
|
||||
import { updateCustomModel, addCustomModel, modelTypeUrl, modelProviderUrl } from '@/api/models'
|
||||
import { getFileLink } from '@/api/fileStorage'
|
||||
import { validateSquareImage, stringRegExp } from '@/utils/validator'
|
||||
|
||||
/**
|
||||
* Custom model modal component
|
||||
@@ -65,7 +66,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
|
||||
const res = isEdit ? updateCustomModel(model.id, rest) : addCustomModel(data)
|
||||
|
||||
res.then(() => {
|
||||
refresh && refresh(isEdit)
|
||||
refresh?.(isEdit)
|
||||
handleClose()
|
||||
message.success(isEdit ? t('common.updateSuccess') : t('common.createSuccess'))
|
||||
})
|
||||
@@ -79,7 +80,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
const { logo, ...rest } = values;
|
||||
let formData: CustomModelForm = {
|
||||
const formData: CustomModelForm = {
|
||||
...rest
|
||||
}
|
||||
|
||||
@@ -125,14 +126,22 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
|
||||
name="logo"
|
||||
label={t('modelNew.logo')}
|
||||
valuePropName="fileList"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseSelect') },
|
||||
{ validator: validateSquareImage(t('common.imageSquareRequired')) }
|
||||
]}
|
||||
extra={t('common.logoTip')?.split('\n').map((vo, index) => <div key={index}>{vo}</div>)}
|
||||
>
|
||||
<UploadImages />
|
||||
<UploadImages fileSize={2} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label={t('modelNew.name')}
|
||||
rules={[{ required: true, message: t('common.inputPlaceholder', { title: t('modelNew.name') }) }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.inputPlaceholder', { title: t('modelNew.name') }) },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.pleaseEnter')} />
|
||||
</Form.Item>
|
||||
@@ -166,6 +175,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
|
||||
<Form.Item
|
||||
name="description"
|
||||
label={t('modelNew.description')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('common.pleaseEnter')} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:49:33
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-03 16:49:33
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-02 12:23:13
|
||||
*/
|
||||
/**
|
||||
* Group Model Modal
|
||||
@@ -21,6 +21,7 @@ import { updateCompositeModel, modelTypeUrl, addCompositeModel } from '@/api/mod
|
||||
import UploadImages from '@/components/Upload/UploadImages'
|
||||
import ModelImplement from './ModelImplement'
|
||||
import { getFileLink } from '@/api/fileStorage'
|
||||
import { validateSquareImage, stringRegExp } from '@/utils/validator'
|
||||
|
||||
/**
|
||||
* Group model modal component
|
||||
@@ -133,15 +134,26 @@ const GroupModelModal = forwardRef<GroupModelModalRef, GroupModelModalProps>(({
|
||||
name="logo"
|
||||
label={t('modelNew.logo')}
|
||||
valuePropName="fileList"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseSelect') },
|
||||
{ validator: validateSquareImage(t('common.imageSquareRequired')) }
|
||||
]}
|
||||
extra={t('common.logoTip')?.split('\n').map((vo, index) => <div key={index}>{vo}</div>)}
|
||||
>
|
||||
<UploadImages />
|
||||
<UploadImages
|
||||
fileSize={2}
|
||||
fileType={['png', 'jpg']}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="name"
|
||||
label={t('modelNew.name')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.pleaseEnter')} />
|
||||
</Form.Item>
|
||||
@@ -165,6 +177,7 @@ const GroupModelModal = forwardRef<GroupModelModalRef, GroupModelModalProps>(({
|
||||
<Form.Item
|
||||
name="description"
|
||||
label={t('modelNew.description')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('common.pleaseEnter')} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -121,6 +121,7 @@ const tabKeys = ['group', 'list', 'square']
|
||||
{activeTab !== 'list' &&
|
||||
<Form.Item name="search" noStyle>
|
||||
<SearchInput
|
||||
maxLength={50}
|
||||
placeholder={t(`modelNew.${activeTab}SearchPlaceholder`)}
|
||||
className="rb:w-70!"
|
||||
/>
|
||||
|
||||
@@ -182,7 +182,10 @@ const OntologyClassExtractModal = forwardRef<OntologyClassExtractModalRef, Ontol
|
||||
<FormItem
|
||||
name="scenario"
|
||||
label={t('ontology.scenario')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ max: 2000 },
|
||||
]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('ontology.scenarioPlaceholder')} />
|
||||
</FormItem>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import type { AddClassItem, OntologyClassModalRef } from '../types'
|
||||
import RbModal from '@/components/RbModal'
|
||||
import { createOntologyClass } from '@/api/ontology'
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -105,7 +106,11 @@ const OntologyClassModal = forwardRef<OntologyClassModalRef, OntologyClassModalP
|
||||
<FormItem
|
||||
name="class_name"
|
||||
label={t('ontology.class_name')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.enter')} />
|
||||
</FormItem>
|
||||
@@ -113,6 +118,7 @@ const OntologyClassModal = forwardRef<OntologyClassModalRef, OntologyClassModalP
|
||||
<FormItem
|
||||
name="class_description"
|
||||
label={t('ontology.class_description')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('ontology.classDescriptionPlaceholder')} />
|
||||
</FormItem>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import type { OntologyItem, OntologyModalData, OntologyModalRef } from '../types'
|
||||
import RbModal from '@/components/RbModal'
|
||||
import { createOntologyScene, updateOntologyScene } from '@/api/ontology'
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -109,7 +110,11 @@ const OntologyModal = forwardRef<OntologyModalRef, OntologyModalProps>(({
|
||||
<FormItem
|
||||
name="scene_name"
|
||||
label={t('ontology.scene_name')}
|
||||
rules={[{ required: true, message: t('common.pleaseEnter') }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.pleaseEnter') },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.enter')} />
|
||||
</FormItem>
|
||||
@@ -117,6 +122,7 @@ const OntologyModal = forwardRef<OntologyModalRef, OntologyModalProps>(({
|
||||
<FormItem
|
||||
name="scene_description"
|
||||
label={t('ontology.scene_description')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('ontology.descriptionPlaceholder')} />
|
||||
</FormItem>
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { AiPromptModalRef } from '@/views/ApplicationConfig/types'
|
||||
import exitIcon from '@/assets/images/knowledgeBase/exit.png';
|
||||
import type { SkillFormData } from '../types'
|
||||
import { getSkillDetail, createSkill, updateSkill } from '@/api/skill'
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
|
||||
/**
|
||||
* Skill Configuration Page Component
|
||||
@@ -110,7 +111,7 @@ const SkillConfig: FC = () => {
|
||||
// Format tools data for API
|
||||
const formData = {
|
||||
...rest,
|
||||
tools: tools?.map((item: any) => ({
|
||||
tools: tools?.map((item) => ({
|
||||
tool_id: item.tool_id,
|
||||
operation: item.operation
|
||||
}))
|
||||
@@ -144,13 +145,18 @@ const SkillConfig: FC = () => {
|
||||
<Form.Item
|
||||
name="name"
|
||||
label={t('skills.name')}
|
||||
rules={[{ required: true, message: t('common.inputPlaceholder', { title: t('skills.name') }) }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.inputPlaceholder', { title: t('skills.name') }) },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.pleaseEnter')} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="description"
|
||||
label={t('skills.description')}
|
||||
rules={[{ max: 500 }]}
|
||||
>
|
||||
<Input.TextArea placeholder={t('skills.descriptionPlaceholder')} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -17,6 +17,8 @@ export interface SkillFormData {
|
||||
tools: Array<{
|
||||
/** Tool identifier */
|
||||
tool_id: string;
|
||||
/** Tool operation/action */
|
||||
operation?: string;
|
||||
}>;
|
||||
/** Skill configuration settings */
|
||||
config: {
|
||||
|
||||
@@ -23,6 +23,7 @@ import UploadImages from '@/components/Upload/UploadImages'
|
||||
import { getFileLink } from '@/api/fileStorage'
|
||||
import ragIcon from '@/assets/images/space/rag.png'
|
||||
import neo4jIcon from '@/assets/images/space/neo4j.png'
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -91,7 +92,7 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
|
||||
setCurrentStep(1)
|
||||
} else {
|
||||
const { icon, ...rest } = values
|
||||
let formData: SpaceModalData = {
|
||||
const formData: SpaceModalData = {
|
||||
...rest
|
||||
}
|
||||
if (icon?.response?.data.file_id) {
|
||||
@@ -164,14 +165,19 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
|
||||
valuePropName="fileList"
|
||||
hidden={currentStep === 1}
|
||||
rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.spaceIcon') }) }]}
|
||||
extra={t('common.logoTip')?.split('\n').map((vo, index) => <div key={index}>{vo}</div>)}
|
||||
>
|
||||
<UploadImages />
|
||||
<UploadImages fileSize={2} />
|
||||
</Form.Item>
|
||||
<FormItem
|
||||
name="name"
|
||||
label={t('space.spaceName')}
|
||||
hidden={currentStep === 1}
|
||||
rules={[{ required: true, message: t('common.inputPlaceholder', { title: t('space.spaceName') }) }]}
|
||||
rules={[
|
||||
{ required: true, message: t('common.inputPlaceholder', { title: t('space.spaceName') }) },
|
||||
{ max: 50 },
|
||||
{ pattern: stringRegExp, message: t('common.nameInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder={t('common.inputPlaceholder', { title: t('space.spaceName') })} />
|
||||
</FormItem>
|
||||
|
||||
@@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react'
|
||||
import { resolve } from 'path'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import svgr from 'vite-plugin-svgr'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
@@ -11,7 +12,15 @@ export default defineConfig({
|
||||
proxy: {
|
||||
// 主要API代理,支持 /api 和 /api/* 格式
|
||||
'/api': {
|
||||
target: 'http://0.0.0.0:5173', // 后端服务地址
|
||||
// target: 'http://192.168.110.86:8000', // lxy
|
||||
// target: 'http://192.168.110.25:8000', // xjn
|
||||
// target: 'http://192.168.110.217:8000', // llq
|
||||
target: 'http://192.168.110.111:8000', // myh
|
||||
// target: 'https://devmemorybear.redbearai.com/', // 开发后端服务地址
|
||||
// target: 'https://devcopymemorybear.redbearai.com/', // 开发sass后端服务地址
|
||||
// target: 'https://testmemorybear.redbearai.com/', // 测试后端服务地址
|
||||
// target: 'https://memorybear.redbearai.com/', // 预发服务地址
|
||||
// target: 'https://cloud.memorybear.ai/', // AMAZON 生产地址
|
||||
changeOrigin: true,
|
||||
|
||||
// 匹配所有以/api开头的请求,包括/api/token
|
||||
@@ -26,6 +35,7 @@ export default defineConfig({
|
||||
},
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
svgr({ svgrOptions: { icon: true } }),
|
||||
react(),
|
||||
AutoImport({
|
||||
imports: ['react', 'react-router-dom'],
|
||||
|
||||
654
web/变量信息.md
Normal file
654
web/变量信息.md
Normal file
@@ -0,0 +1,654 @@
|
||||
# 系统变量:需和开始节点拆分
|
||||
|
||||
# end: string/number/boolean/object/array[file]/array[object]/array[number]/array[string]
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: 不需要 -->
|
||||
- parameter-extractor: __is_success / __reason
|
||||
- memory-read: answer / intermediate_outputs
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name / output
|
||||
- iteration: output
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- jinja-render: output
|
||||
|
||||
# llm: 不能选 boolean 类型
|
||||
## 上下文:string/number/array[file]/array[object]/array[string]/array[number]; 不要object
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __is_success / __reason
|
||||
- memory-read: answer / intermediate_outputs
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
## 提示词: string/number/array[file]/array[number]/array[string]; 不要object,boolean
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __is_success / __reason
|
||||
- memory-read: answer / intermediate_outputs
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# knowledge-retrieval: string
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# parameter-extractor:
|
||||
## 输入变量: string
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
## 指令:string/number
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __is_success / __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# memory-read: string
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
|
||||
# memory-write: string
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# if-else: boolean/string/number/array[file]/array[object]/array[string]/object
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __is_success / __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# question-classifier
|
||||
## 输入变量: string
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
## 分类: string
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# iteration
|
||||
## 输入变量: array[file] | array[object] | array[string] | array[number] | array[boolean]
|
||||
<!-- - 系统变量 -->
|
||||
<!-- - 会话变量 -->
|
||||
<!-- - start: variables / sys -->
|
||||
<!-- - llm: output -->
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: array类型的提取参数 params
|
||||
<!-- - memory-read: answer -->
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
<!-- - question-classifier: class_name -->
|
||||
- iteration: output
|
||||
- loop: cycle_vars
|
||||
<!-- - var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables -->
|
||||
<!-- - assigner: 不需要 -->
|
||||
<!-- - http-request: body -->
|
||||
<!-- - tool: data -->
|
||||
- code: output_variables
|
||||
<!-- - jinja-render: output -->
|
||||
## 输出变量
|
||||
- 系统变量
|
||||
<!-- - 会话变量 -->
|
||||
<!-- - start: variables / sys -->
|
||||
<!-- - llm: output -->
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
<!-- - parameter-extractor: __reason -->
|
||||
<!-- - memory-read: answer -->
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
<!-- - question-classifier: class_name -->
|
||||
<!-- - iteration: output -->
|
||||
<!-- - loop: cycle_vars -->
|
||||
<!-- - var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables -->
|
||||
<!-- - assigner: 不需要 -->
|
||||
<!-- - http-request: body -->
|
||||
<!-- - tool: data -->
|
||||
<!-- - code: output_variables -->
|
||||
<!-- - jinja-render: output -->
|
||||
- 子节点的输出变量
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __reason, params
|
||||
- memory-read: answer
|
||||
- memory-write
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
<!-- - loop: cycle_vars -->
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# loop
|
||||
## 循环变量
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __is_success / __reason / params
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
## 循环终止条件
|
||||
### left
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
<!-- - start: variables / sys -->
|
||||
<!-- - llm: output -->
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
<!-- - parameter-extractor: __is_success / __reason -->
|
||||
<!-- - memory-read: answer -->
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
<!-- - question-classifier: class_name -->
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
<!-- - var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables -->
|
||||
<!-- - assigner: 不需要 -->
|
||||
<!-- - http-request: body / status_code -->
|
||||
<!-- - tool: data -->
|
||||
- code: output_variables
|
||||
<!-- - jinja-render: output -->
|
||||
- 子节点的输出变量
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
- memory-write
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
<!-- - loop: cycle_vars -->
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- jinja-render: output
|
||||
### right: number
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
<!-- - llm: output -->
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __is_success
|
||||
<!-- - memory-read: answer -->
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
<!-- - question-classifier: class_name -->
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
<!-- - var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables -->
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: status_code
|
||||
<!-- - tool: data -->
|
||||
- code: output_variables
|
||||
<!-- - jinja-render: output -->
|
||||
|
||||
# var-aggregator: string/number/boolean
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __reason
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# assigner
|
||||
## variable_selector
|
||||
<!-- - 系统变量 -->
|
||||
- 会话变量
|
||||
<!-- - start: variables / sys -->
|
||||
<!-- - llm: output -->
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
<!-- - parameter-extractor: __reason -->
|
||||
<!-- - memory-read: answer -->
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
<!-- - question-classifier: class_name -->
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
<!-- - var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables -->
|
||||
<!-- - assigner: 不需要 -->
|
||||
<!-- - http-request: body -->
|
||||
<!-- - tool: data -->
|
||||
<!-- - code: output_variables -->
|
||||
<!-- - jinja-render: output -->
|
||||
## value
|
||||
<!-- - 系统变量 -->
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __reason / __is_success
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# http-request
|
||||
## url/headers/params: string/number
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason / __is_success
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
## ['body', 'data']
|
||||
### body?.content_type = form-data/x-www-form-urlencoded/json/raw: string/number
|
||||
### body?.content_type = binary: file/array[file]
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
<!-- - knowledge-retrieval: output -->
|
||||
- parameter-extractor: __reason / __is_success
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
<!-- - iteration: output -->
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# tool: 不需要
|
||||
|
||||
# jinja-render
|
||||
## mappingList 输入变量
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __reason / __is_success
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- code: output_variables
|
||||
- jinja-render: output
|
||||
|
||||
# code
|
||||
## input_variables
|
||||
- 系统变量
|
||||
- 会话变量
|
||||
- start: variables / sys
|
||||
- llm: output
|
||||
- knowledge-retrieval: output
|
||||
- parameter-extractor: __reason / __is_success
|
||||
- memory-read: answer
|
||||
<!-- - memory-write -->
|
||||
<!-- - if-else: 不需要 -->
|
||||
- question-classifier: class_name
|
||||
- iteration: output
|
||||
- loop: cycle_vars 当前loop节点的
|
||||
- var-aggregator
|
||||
- group = false 时,output
|
||||
- group = true 时,group_variables
|
||||
<!-- - assigner: 不需要 -->
|
||||
- http-request: body / status_code
|
||||
- tool: data
|
||||
- jinja-render: output
|
||||
- code: output_variables
|
||||
- code: output_variables
|
||||
|
||||
|
||||
# 迭代子节点
|
||||
- llm
|
||||
- if-else
|
||||
- parameter-extractor && prompt
|
||||
- var-aggregator
|
||||
- assigner
|
||||
- http-request && body.content_type !== 'binary'
|
||||
- tool
|
||||
- jinja-render
|
||||
- iteration: item / index
|
||||
|
||||
- knowledge-retrieval
|
||||
- parameter-extractor && !prompt
|
||||
- memory-read
|
||||
- memory-write
|
||||
- question-classifier
|
||||
- iteration的输入变量是array[string]时,可选item
|
||||
|
||||
- iteration
|
||||
- loop
|
||||
- 不可添加此类节点
|
||||
|
||||
# 循环子节点
|
||||
- llm
|
||||
- knowledge-retrieval
|
||||
- parameter-extractor
|
||||
- memory-read
|
||||
- memory-write
|
||||
- if-else
|
||||
- question-classifier
|
||||
- var-aggregator
|
||||
- assigner
|
||||
- http-request
|
||||
- tool
|
||||
- jinja-render
|
||||
- loop: cycle_vars
|
||||
|
||||
- iteration
|
||||
- loop
|
||||
- 不可添加此类节点
|
||||
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
## 需要后端支持的需求
|
||||
1. 集群调试:对话过程数据输出【需后端】
|
||||
<!-- 2. 中断流式输出【需后端,不做】 -->
|
||||
3. 应用调试、分享增加变量配置【需后端】
|
||||
4. 应用导入导出,导出已完成,导入【需后端】
|
||||
6. 单个节点的运行【需后端】
|
||||
7. 列表 节点的配置【需后端】
|
||||
9. 对话支持附件(非图片)【需后端】
|
||||
|
||||
## 前端需求
|
||||
1. 工作流整理布局、历史撤销、回退
|
||||
2. 问题分类节点,分类中英文
|
||||
3. 感知记忆:文本类型增加片段展示
|
||||
- variableConfig
|
||||
4. 工作流UI
|
||||
<!-- - LLM节点 的模型参数,仅在有选模型时显示 -->
|
||||
<!-- - 条件分支 -->
|
||||
<!-- - 循环节点-循环终止条件 -->
|
||||
- 变量聚合器
|
||||
7. 记忆萃取
|
||||
- 本体场景不可编辑
|
||||
- rb:truncate
|
||||
- 注释翻译
|
||||
- RbCard
|
||||
- src/views/KnowledgeBase/index.tsx
|
||||
- src/components/Upload/UploadFiles.tsx
|
||||
- src/components/Chat
|
||||
|
||||
|
||||
# 分支
|
||||
|
||||
## 0.2.6
|
||||
- feature/workflow_import_zy
|
||||
- 工作流导入 | 导出
|
||||
- input_type: Constant / Variable 统一成小写
|
||||
- 结束节点内容被覆写
|
||||
- 增加未知节点
|
||||
- http 节点
|
||||
- 变量下拉列表替换成编辑器
|
||||
- body form-data file时,值支持选择sys.files
|
||||
- feature/form_zy
|
||||
- 表单校验规则
|
||||
- 流式输出时,向上滚动后,自动滚动到最底部的效果失效
|
||||
- 应用 API URL更新
|
||||
- feature/memory_zy
|
||||
- 记忆萃取增加剪枝
|
||||
|
||||
## 20260212
|
||||
1. A2A 协议适配
|
||||
2. 日志跟踪系统
|
||||
3. Agent、集群、工作流共享
|
||||
4. 试运行、分享会话支持文件(包含语言、其他附件)【待联调】
|
||||
2. 导入 Agent、工作流 - 合并到应用管理创建方式
|
||||
|
||||
|
||||
a7da914dcbb80186b9aaf9ac4d21a9881e60ecb5
|
||||
e115353811b34de2fd359962860fdafe87fef503
|
||||
Reference in New Issue
Block a user