* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* Fix/interface home (#182)
* [fix]Fix the interface for statistics of recent activities and applications
* [changes]Modify the code based on the AI review
1.Use the boolean auxiliary methods provided by SQLAlchemy instead of using == True in the is_active filter.
2.The calculation of the "PROJECT_ROOT" has now been hardcoded with five levels of nested os.path.dirname calls.
* [fix]Fix the interface for statistics of recent activities and applications
* [changes]Modify the code based on the AI review
1.Use the boolean auxiliary methods provided by SQLAlchemy instead of using == True in the is_active filter.
2.The calculation of the "PROJECT_ROOT" has now been hardcoded with five levels of nested os.path.dirname calls.
* Fix/optimize inerface (#183)
* [changes]Optimize the time consumption of the "/end_users" interface
* [fix]Optimize the time consumption of the "/hot_memory_tags" interface
* [changes]Optimize the time consumption of the "/end_users" interface
* [fix]Optimize the time consumption of the "/hot_memory_tags" interface
* [changes]Improve the code based on AI review
* Fix/memory mcp2 1 (#184)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* Fix/memory mcp2 1 (#185)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* Fix/memory mcp2 1 (#188)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* 解决冲突
* 解决冲突
* feat(home page): version description update
* Fix/memory mcp2 1 (#190)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* 深度检索优化,搜索不到数据/提问的概念过于蘑菇,以引导的方式继续提问
* 深度检索优化,搜索不到数据/提问的概念过于蘑菇,以引导的方式继续提问
* 深度检索优化,搜索不到数据/提问的概念过于蘑菇,以引导的方式继续提问
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* feat(web): memory related interface parameter transfer adjustment
* 感知meta_data字段BUG修复
* Fix/memory bug fix (#171)
* feat(sandbox): add Python 3 code execution sandbox support
* feat(workflow): emit SSE events for node exception output
* perf(sandbox): optimize code encryption handling
* perf(workflow): update standard node output structure
* [add] migration script
* [modify] migration script
* feat(web): add workflow runtime info
* fix(web): handleSSE bugfix
* fix(sandbox): prevent imports from being blocked when network is disabled
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* Fix/memory bug fix (#199)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* user_id->显示为config_id_old传输
* feat(web): update read_all_config select valueKey
* user_id->显示为config_id_old传输
* feat(workflow): Add a new node for executing code
* fix(web): KnowledgeConfigModal bugfix
* fix(web): iteration's variable add parameter-extractor node
* fix(sandbox): treat non-zero exit codes as errors instead of relying only on stderr
* Fix/memory bug fix (#200)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* Refactor/benchmark test (#196)
* [changes]refactor locomo_test
* [fix]Fix the circular import of ModelParameters
* [changes]The benchmark test can run stably.
* [fix]Complete end-to-end LoCoMo repair
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [changes]refactor locomo_test
* [fix]Fix the circular import of ModelParameters
* [changes]The benchmark test can run stably.
* [fix]Complete end-to-end LoCoMo repair
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [changes]Benchmark test adaptation for end_user_id
* [changes]refactor locomo_test
* [fix]Fix the circular import of ModelParameters
* [changes]The benchmark test can run stably.
* [fix]Complete end-to-end LoCoMo repair
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [changes]Benchmark test adaptation for end_user_id
* [modify] migration script
* delete benchmark-test (#204)
* Refactor: Move evaluation folder to redbear-mem-benchmark submodule
* [changes]Restore .gitmodules
* feat(web): workflow add code node
* 检查需要更改的格式问题
* Fix/redbear benchmark (#205)
* Refactor: Move evaluation folder to redbear-mem-benchmark submodule
* [changes]Update submodule reference
* Refactor: Move evaluation folder to redbear-mem-benchmark submodule
* [changes]Update submodule reference
* Remove duplicate evaluation submodule, use redbear-mem-benchmark instead
* Fix/memory bug fix (#207)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* fix(web): remove URI decode and encode
* [add] plugin system and base sso module
* 修复宿主列表获取memory_config_idBUG
* Fix/memory bug fix (#209)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* [modify] file local server url
* [add] migration script
* fix(workflow): fix activation and branch control issues in streaming output
* fix(workflow): fix function cache not taking effect and potential list index overflow
* style(workflow): enforce PEP8 style and remove redundant imports
* fix(workflow): fix streaming output error when variable is not a string
* [fix]remove aspose-slides
* perf(workflow): enhance streaming output node activation performance
* feat(workflow): store token usage in message table
* feat(web): add PageEmpty component
* feat(web): add PageTabs component
* perf(workflow): make memory configuration backward compatible
* feat(web): update model management
* config_id做映射
* config_id做映射
* Fix/memory bug fix (#211)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(web): getModelListUrl add is_active param
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
* feat(web): remove file url replace
* Fix/memory bug fix (#212)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(model and app statistic): 1. Optimize the model list; 2. Increase the model combination; 3. Add a model square; 4. Add application management statistics
* feat(web): model logo update
* 应用层memory_content->memory_config
* fix(web): correct spelling
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* Fix/memory bug fix (#215)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(model and app statistic): 1. Optimize the model list; 2. Increase the model combination; 3. Add a model square; 4. Add application management statistics
* fix(web): model loading update
* 统一字段为config_id_old
* 统一字段为config_id_old
* feat(model and app statistic): 1. Optimize the model list; 2. Increase the model combination; 3. Add a model square; 4. Add application management statistics
* 统一字段为config_id_old
* 统一字段为config_id_old
* memory_content暂时不修改
* memory_content暂时不修改
* Fix/memory bug fix (#217)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* 统一字段为config_id_old
* 统一字段为config_id_old
* 统一字段为config_id_old
* 统一字段为config_id_old
* memory_content暂时不修改
* memory_content暂时不修改
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(web): add app statistics
* fix(workflow): fix streaming output issues with multi-output End nodes
End nodes with multiple output segments could cause cursor errors or leave some
segments inactive, resulting in incorrect final outputs.
Unified _emit_active_chunks and _update_scope_activate to ensure all segments
are activated in order and streamed correctly.
* feat(web): add apps statistics api
* fix(web): agent's knowledge_bases bugfix
* Revert "feat(web): update read_all_config select valueKey"
This reverts commit 46f0f3cee9.
* [add] migrations script
* perf(workflow): make memory write node backward-compatible and defer config validation
* 旧数据兼容
* 旧数据兼容
* 旧数据兼容
* 旧数据兼容
* fix(web): model bugfix
* fix(web): model bugfix
* 提交遗漏 (#228)
* [fix] chat api for workflow
* [fix] web search set for v1 api
* fix(web): model bugfix
* fix(web): model list remove is_active
* fix(model): bug fix
* [add]migration script
* [fix] api
* [fix] api
* fix(web): model bugfix
* fix(model): the model type does not allow modification, delete tts and speech2text type
* fix(model): bug fix
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* Add/develop memory (#239)
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* feat(web): model ui update
* feat(web): model ui update
* Add/develop memory (#243)
* 遗漏的历史映射
* 遗漏的历史映射
* fix(model): bug fix
* feat(web): model ui update
* Add/develop memory (#247)
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* [modify] migration script
* [add] migration script
* fix(web): change form message
* fix(web): the memoryContent field is compatible with numbers and strings
* feat(web): code node hidden
* fix(model):
1. create a basic model to check if the name and provider are duplicated.
2. The result shows error models because the provider created API Keys for all matching models.
---------
Co-authored-by: lixinyue <2569494688@qq.com>
Co-authored-by: lanceyq <1982376970@qq.com>
Co-authored-by: yujiangping <yujiangping@taofen8.com>
Co-authored-by: 乐力齐 <162269739+lanceyq@users.noreply.github.com>
Co-authored-by: lixinyue11 <94037597+lixinyue11@users.noreply.github.com>
Co-authored-by: yingzhao <zhaoyingyz@126.com>
Co-authored-by: Timebomb2018 <18868801967@163.com>
Co-authored-by: Mark <zhuwenhui5566@163.com>
Co-authored-by: zhaoying <yzhao96@best-inc.com>
Co-authored-by: Eternity <1533512157@qq.com>
Co-authored-by: lixiangcheng1 <lixiangcheng1@wanda.cn>
611 lines
21 KiB
Python
611 lines
21 KiB
Python
"""
|
||
工作流 API 控制器
|
||
"""
|
||
|
||
import logging
|
||
import uuid
|
||
from typing import Annotated
|
||
|
||
from fastapi import APIRouter, Depends, Path, Query
|
||
from sqlalchemy.orm import Session
|
||
|
||
from app.db import get_db
|
||
from app.dependencies import get_current_user, cur_workspace_access_guard
|
||
|
||
from app.models.user_model import User
|
||
from app.models.app_model import App
|
||
from app.services.workflow_service import WorkflowService, get_workflow_service
|
||
from app.schemas.workflow_schema import (
|
||
WorkflowConfigCreate,
|
||
WorkflowConfigUpdate,
|
||
WorkflowConfig,
|
||
WorkflowValidationResponse,
|
||
WorkflowExecution,
|
||
WorkflowNodeExecution,
|
||
WorkflowExecutionRequest,
|
||
WorkflowExecutionResponse
|
||
)
|
||
from app.core.response_utils import success, fail
|
||
from app.core.exceptions import BusinessException
|
||
from app.core.error_codes import BizCode
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
router = APIRouter(prefix="/apps", tags=["workflow"])
|
||
|
||
|
||
# ==================== 工作流配置管理 ====================
|
||
|
||
@router.post("/{app_id}/workflow")
|
||
@cur_workspace_access_guard()
|
||
async def create_workflow_config(
|
||
app_id: Annotated[uuid.UUID, Path(description="应用 ID")],
|
||
config: WorkflowConfigCreate,
|
||
db: Annotated[Session, Depends(get_db)],
|
||
current_user: Annotated[User, Depends(get_current_user)],
|
||
service: Annotated[WorkflowService, Depends(get_workflow_service)]
|
||
):
|
||
"""创建工作流配置
|
||
|
||
创建或更新应用的工作流配置。配置会进行基础验证,但允许保存不完整的配置(草稿)。
|
||
"""
|
||
try:
|
||
# 验证应用是否存在且属于当前工作空间
|
||
app = db.query(App).filter(
|
||
App.id == app_id,
|
||
App.workspace_id == current_user.current_workspace_id,
|
||
App.is_active.is_(True)
|
||
).first()
|
||
|
||
if not app:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="应用不存在或无权访问"
|
||
)
|
||
|
||
# 验证应用类型
|
||
if app.type != "workflow":
|
||
return fail(
|
||
code=BizCode.INVALID_PARAMETER,
|
||
msg=f"应用类型必须为 workflow,当前为 {app.type}"
|
||
)
|
||
|
||
# 创建工作流配置
|
||
workflow_config = service.create_workflow_config(
|
||
app_id=app_id,
|
||
nodes=[node.model_dump() for node in config.nodes],
|
||
edges=[edge.model_dump() for edge in config.edges],
|
||
variables=[var.model_dump() for var in config.variables],
|
||
execution_config=config.execution_config.model_dump(),
|
||
triggers=[trigger.model_dump() for trigger in config.triggers],
|
||
validate=True # 进行基础验证
|
||
)
|
||
|
||
return success(
|
||
data=WorkflowConfig.model_validate(workflow_config),
|
||
msg="工作流配置创建成功"
|
||
)
|
||
|
||
except BusinessException as e:
|
||
logger.warning(f"创建工作流配置失败: {e.message}")
|
||
return fail(code=e.error_code, msg=e.message)
|
||
except Exception as e:
|
||
logger.error(f"创建工作流配置异常: {e}", exc_info=True)
|
||
return fail(
|
||
code=BizCode.INTERNAL_ERROR,
|
||
msg=f"创建工作流配置失败: {str(e)}"
|
||
)
|
||
|
||
|
||
#
|
||
# @router.get("/{app_id}/workflow")
|
||
# async def get_workflow_config(
|
||
# app_id: Annotated[uuid.UUID, Path(description="应用 ID")],
|
||
# db: Annotated[Session, Depends(get_db)],
|
||
# current_user: Annotated[User, Depends(get_current_user)]
|
||
#
|
||
# ):
|
||
# """获取工作流配置
|
||
#
|
||
# 获取应用的工作流配置详情。
|
||
# """
|
||
# try:
|
||
# # 验证应用是否存在且属于当前工作空间
|
||
# app = db.query(App).filter(
|
||
# App.id == app_id,
|
||
# App.workspace_id == current_user.current_workspace_id,
|
||
# App.is_active == True
|
||
# ).first()
|
||
#
|
||
# if not app:
|
||
# return fail(
|
||
# code=BizCode.NOT_FOUND,
|
||
# msg="应用不存在或无权访问"
|
||
# )
|
||
#
|
||
# # 获取工作流配置
|
||
# service = WorkflowService(db)
|
||
# workflow_config = service.get_workflow_config(app_id)
|
||
#
|
||
# if not workflow_config:
|
||
# return fail(
|
||
# code=BizCode.NOT_FOUND,
|
||
# msg="工作流配置不存在"
|
||
# )
|
||
#
|
||
# return success(
|
||
# data=WorkflowConfig.model_validate(workflow_config)
|
||
# )
|
||
#
|
||
# except Exception as e:
|
||
# logger.error(f"获取工作流配置异常: {e}", exc_info=True)
|
||
# return fail(
|
||
# code=BizCode.INTERNAL_ERROR,
|
||
# msg=f"获取工作流配置失败: {str(e)}"
|
||
# )
|
||
|
||
|
||
# @router.put("/{app_id}/workflow")
|
||
# async def update_workflow_config(
|
||
# app_id: Annotated[uuid.UUID, Path(description="应用 ID")],
|
||
# config: WorkflowConfigUpdate,
|
||
# db: Annotated[Session, Depends(get_db)],
|
||
# current_user: Annotated[User, Depends(get_current_user)],
|
||
# service: Annotated[WorkflowService, Depends(get_workflow_service)]
|
||
# ):
|
||
# """更新工作流配置
|
||
|
||
# 更新应用的工作流配置。可以部分更新,未提供的字段保持不变。
|
||
# """
|
||
# try:
|
||
# # 验证应用是否存在且属于当前工作空间
|
||
# app = db.query(App).filter(
|
||
# App.id == app_id,
|
||
# App.workspace_id == current_user.current_workspace_id,
|
||
# App.is_active == True
|
||
# ).first()
|
||
|
||
# if not app:
|
||
# return fail(
|
||
# code=BizCode.NOT_FOUND,
|
||
# msg="应用不存在或无权访问"
|
||
# )
|
||
|
||
# # 更新工作流配置
|
||
# workflow_config = service.update_workflow_config(
|
||
# app_id=app_id,
|
||
# nodes=[node.model_dump() for node in config.nodes] if config.nodes else None,
|
||
# edges=[edge.model_dump() for edge in config.edges] if config.edges else None,
|
||
# variables=[var.model_dump() for var in config.variables] if config.variables else None,
|
||
# execution_config=config.execution_config.model_dump() if config.execution_config else None,
|
||
# triggers=[trigger.model_dump() for trigger in config.triggers] if config.triggers else None,
|
||
# validate=True
|
||
# )
|
||
|
||
# return success(
|
||
# data=WorkflowConfig.model_validate(workflow_config),
|
||
# msg="工作流配置更新成功"
|
||
# )
|
||
|
||
# except BusinessException as e:
|
||
# logger.warning(f"更新工作流配置失败: {e.message}")
|
||
# return fail(code=e.error_code, msg=e.message)
|
||
# except Exception as e:
|
||
# logger.error(f"更新工作流配置异常: {e}", exc_info=True)
|
||
# return fail(
|
||
# code=BizCode.INTERNAL_ERROR,
|
||
# msg=f"更新工作流配置失败: {str(e)}"
|
||
# )
|
||
|
||
|
||
@router.delete("/{app_id}/workflow")
|
||
async def delete_workflow_config(
|
||
app_id: Annotated[uuid.UUID, Path(description="应用 ID")],
|
||
db: Annotated[Session, Depends(get_db)],
|
||
current_user: Annotated[User, Depends(get_current_user)],
|
||
service: Annotated[WorkflowService, Depends(get_workflow_service)]
|
||
):
|
||
"""删除工作流配置
|
||
|
||
删除应用的工作流配置。
|
||
"""
|
||
try:
|
||
# 验证应用是否存在且属于当前工作空间
|
||
app = db.query(App).filter(
|
||
App.id == app_id,
|
||
App.workspace_id == current_user.current_workspace_id,
|
||
App.is_active.is_(True)
|
||
).first()
|
||
|
||
if not app:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="应用不存在或无权访问"
|
||
)
|
||
|
||
# 删除工作流配置
|
||
deleted = service.delete_workflow_config(app_id)
|
||
|
||
if not deleted:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="工作流配置不存在"
|
||
)
|
||
|
||
return success(msg="工作流配置删除成功")
|
||
|
||
except Exception as e:
|
||
logger.error(f"删除工作流配置异常: {e}", exc_info=True)
|
||
return fail(
|
||
code=BizCode.INTERNAL_ERROR,
|
||
msg=f"删除工作流配置失败: {str(e)}"
|
||
)
|
||
|
||
|
||
@router.post("/{app_id}/workflow/validate")
|
||
async def validate_workflow_config(
|
||
app_id: Annotated[uuid.UUID, Path(description="应用 ID")],
|
||
db: Annotated[Session, Depends(get_db)],
|
||
current_user: Annotated[User, Depends(get_current_user)],
|
||
service: Annotated[WorkflowService, Depends(get_workflow_service)],
|
||
for_publish: Annotated[bool, Query(description="是否为发布验证")] = False
|
||
):
|
||
"""验证工作流配置
|
||
|
||
验证工作流配置是否有效。可以选择是否进行发布级别的严格验证。
|
||
"""
|
||
try:
|
||
# 验证应用是否存在且属于当前工作空间
|
||
app = db.query(App).filter(
|
||
App.id == app_id,
|
||
App.workspace_id == current_user.current_workspace_id,
|
||
App.is_active.is_(True)
|
||
).first()
|
||
|
||
if not app:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="应用不存在或无权访问"
|
||
)
|
||
|
||
# 验证工作流配置
|
||
|
||
if for_publish:
|
||
is_valid, errors = service.validate_workflow_config_for_publish(app_id)
|
||
else:
|
||
workflow_config = service.get_workflow_config(app_id)
|
||
if not workflow_config:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="工作流配置不存在"
|
||
)
|
||
|
||
from app.core.workflow.validator import validate_workflow_config as validate_config
|
||
config_dict = {
|
||
"nodes": workflow_config.nodes,
|
||
"edges": workflow_config.edges,
|
||
"variables": workflow_config.variables,
|
||
"execution_config": workflow_config.execution_config,
|
||
"triggers": workflow_config.triggers
|
||
}
|
||
is_valid, errors = validate_config(config_dict, for_publish=False)
|
||
|
||
return success(
|
||
data=WorkflowValidationResponse(
|
||
is_valid=is_valid,
|
||
errors=errors,
|
||
warnings=[]
|
||
)
|
||
)
|
||
|
||
except BusinessException as e:
|
||
logger.warning(f"验证工作流配置失败: {e.message}")
|
||
return fail(code=e.error_code, msg=e.message)
|
||
except Exception as e:
|
||
logger.error(f"验证工作流配置异常: {e}", exc_info=True)
|
||
return fail(
|
||
code=BizCode.INTERNAL_ERROR,
|
||
msg=f"验证工作流配置失败: {str(e)}"
|
||
)
|
||
|
||
|
||
# ==================== 工作流执行管理 ====================
|
||
|
||
@router.get("/{app_id}/workflow/executions")
|
||
async def get_workflow_executions(
|
||
app_id: Annotated[uuid.UUID, Path(description="应用 ID")],
|
||
db: Annotated[Session, Depends(get_db)],
|
||
current_user: Annotated[User, Depends(get_current_user)],
|
||
service: Annotated[WorkflowService, Depends(get_workflow_service)],
|
||
limit: Annotated[int, Query(ge=1, le=100)] = 50,
|
||
offset: Annotated[int, Query(ge=0)] = 0
|
||
):
|
||
"""获取工作流执行记录列表
|
||
|
||
获取应用的工作流执行历史记录。
|
||
"""
|
||
try:
|
||
# 验证应用是否存在且属于当前工作空间
|
||
app = db.query(App).filter(
|
||
App.id == app_id,
|
||
App.workspace_id == current_user.current_workspace_id,
|
||
App.is_active.is_(True)
|
||
).first()
|
||
|
||
if not app:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="应用不存在或无权访问"
|
||
)
|
||
|
||
# 获取执行记录
|
||
executions = service.get_executions_by_app(app_id, limit, offset)
|
||
|
||
# 获取统计信息
|
||
statistics = service.get_execution_statistics(app_id)
|
||
|
||
return success(
|
||
data={
|
||
"executions": [WorkflowExecution.model_validate(e) for e in executions],
|
||
"statistics": statistics,
|
||
"pagination": {
|
||
"limit": limit,
|
||
"offset": offset,
|
||
"total": statistics["total"]
|
||
}
|
||
}
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取工作流执行记录异常: {e}", exc_info=True)
|
||
return fail(
|
||
code=BizCode.INTERNAL_ERROR,
|
||
msg=f"获取工作流执行记录失败: {str(e)}"
|
||
)
|
||
|
||
|
||
@router.get("/workflow/executions/{execution_id}")
|
||
async def get_workflow_execution(
|
||
execution_id: Annotated[str, Path(description="执行 ID")],
|
||
db: Annotated[Session, Depends(get_db)],
|
||
current_user: Annotated[User, Depends(get_current_user)],
|
||
service: Annotated[WorkflowService, Depends(get_workflow_service)]
|
||
):
|
||
"""获取工作流执行详情
|
||
|
||
获取单个工作流执行的详细信息,包括所有节点的执行记录。
|
||
"""
|
||
try:
|
||
# 获取执行记录
|
||
execution = service.get_execution(execution_id)
|
||
|
||
if not execution:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="执行记录不存在"
|
||
)
|
||
|
||
# 验证应用是否属于当前工作空间
|
||
app = db.query(App).filter(
|
||
App.id == execution.app_id,
|
||
App.workspace_id == current_user.current_workspace_id,
|
||
App.is_active.is_(True)
|
||
).first()
|
||
|
||
if not app:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="无权访问该执行记录"
|
||
)
|
||
|
||
# 获取节点执行记录
|
||
node_executions = service.node_execution_repo.get_by_execution_id(execution.id)
|
||
|
||
return success(
|
||
data={
|
||
"execution": WorkflowExecution.model_validate(execution),
|
||
"node_executions": [
|
||
WorkflowNodeExecution.model_validate(ne) for ne in node_executions
|
||
]
|
||
}
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取工作流执行详情异常: {e}", exc_info=True)
|
||
return fail(
|
||
code=BizCode.INTERNAL_ERROR,
|
||
msg=f"获取工作流执行详情失败: {str(e)}"
|
||
)
|
||
|
||
|
||
# ==================== 工作流执行 ====================
|
||
@router.post("/{app_id}/workflow/run")
|
||
async def run_workflow(
|
||
app_id: Annotated[uuid.UUID, Path(description="应用 ID")],
|
||
request: WorkflowExecutionRequest,
|
||
db: Annotated[Session, Depends(get_db)],
|
||
current_user: Annotated[User, Depends(get_current_user)],
|
||
service: Annotated[WorkflowService, Depends(get_workflow_service)]
|
||
):
|
||
"""执行工作流
|
||
|
||
执行工作流并返回结果。支持流式和非流式两种模式。
|
||
|
||
**非流式模式**:等待工作流执行完成后返回完整结果。
|
||
|
||
**流式模式**:实时返回执行过程中的事件(节点开始、节点完成、工作流完成等)。
|
||
"""
|
||
try:
|
||
# 验证应用是否存在且属于当前工作空间
|
||
app = db.query(App).filter(
|
||
App.id == app_id,
|
||
App.workspace_id == current_user.current_workspace_id,
|
||
App.is_active.is_(True)
|
||
).first()
|
||
|
||
if not app:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="应用不存在或无权访问"
|
||
)
|
||
|
||
# 验证应用类型
|
||
if app.type != "workflow":
|
||
return fail(
|
||
code=BizCode.INVALID_PARAMETER,
|
||
msg=f"应用类型必须为 workflow,当前为 {app.type}"
|
||
)
|
||
|
||
# 准备输入数据
|
||
input_data = {
|
||
"message": request.message or "",
|
||
"variables": request.variables
|
||
}
|
||
|
||
# 执行工作流
|
||
|
||
if request.stream:
|
||
# 流式执行
|
||
from fastapi.responses import StreamingResponse
|
||
import json
|
||
|
||
async def event_generator():
|
||
"""生成 SSE 事件
|
||
|
||
SSE 格式:
|
||
event: <event_type>
|
||
data: <json_data>
|
||
|
||
支持的事件类型:
|
||
- workflow_start: 工作流开始
|
||
- workflow_end: 工作流结束
|
||
- node_start: 节点开始执行
|
||
- node_end: 节点执行完成
|
||
- node_chunk: 中间节点的流式输出
|
||
- message: 最终消息的流式输出(End 节点及其相邻节点)
|
||
"""
|
||
try:
|
||
async for event in await service.run_workflow(
|
||
app_id=app_id,
|
||
input_data=input_data,
|
||
triggered_by=current_user.id,
|
||
conversation_id=uuid.UUID(request.conversation_id) if request.conversation_id else None,
|
||
stream=True
|
||
):
|
||
# 提取事件类型和数据
|
||
event_type = event.get("event", "message")
|
||
event_data = event.get("data", {})
|
||
|
||
# 转换为标准 SSE 格式(字符串)
|
||
# event: <type>
|
||
# data: <json>
|
||
sse_message = f"event: {event_type}\ndata: {json.dumps(event_data)}\n\n"
|
||
yield sse_message
|
||
|
||
except Exception as e:
|
||
logger.error(f"流式执行异常: {e}", exc_info=True)
|
||
# 发送错误事件
|
||
sse_error = f"event: error\ndata: {json.dumps({'error': str(e)})}\n\n"
|
||
yield sse_error
|
||
|
||
return StreamingResponse(
|
||
event_generator(),
|
||
media_type="text/event-stream",
|
||
headers={
|
||
"Cache-Control": "no-cache",
|
||
"Connection": "keep-alive",
|
||
"X-Accel-Buffering": "no" # 禁用 nginx 缓冲
|
||
}
|
||
)
|
||
else:
|
||
# 非流式执行
|
||
result = await service.run_workflow(
|
||
app_id=app_id,
|
||
input_data=input_data,
|
||
triggered_by=current_user.id,
|
||
conversation_id=uuid.UUID(request.conversation_id) if request.conversation_id else None,
|
||
stream=False
|
||
)
|
||
|
||
return success(
|
||
data=WorkflowExecutionResponse(
|
||
execution_id=result["execution_id"],
|
||
status=result["status"],
|
||
output=result.get("output"),
|
||
output_data=result.get("output_data"),
|
||
error_message=result.get("error_message"),
|
||
elapsed_time=result.get("elapsed_time"),
|
||
token_usage=result.get("token_usage")
|
||
),
|
||
msg="工作流执行完成"
|
||
)
|
||
|
||
except BusinessException as e:
|
||
logger.warning(f"执行工作流失败: {e.message}")
|
||
return fail(code=e.error_code, msg=e.message)
|
||
except Exception as e:
|
||
logger.error(f"执行工作流异常: {e}", exc_info=True)
|
||
return fail(
|
||
code=BizCode.INTERNAL_ERROR,
|
||
msg=f"执行工作流失败: {str(e)}"
|
||
)
|
||
|
||
|
||
@router.post("/workflow/executions/{execution_id}/cancel")
|
||
async def cancel_workflow_execution(
|
||
execution_id: Annotated[str, Path(description="执行 ID")],
|
||
db: Annotated[Session, Depends(get_db)],
|
||
current_user: Annotated[User, Depends(get_current_user)],
|
||
service: Annotated[WorkflowService, Depends(get_workflow_service)]
|
||
):
|
||
"""取消工作流执行
|
||
|
||
取消正在运行的工作流执行。
|
||
|
||
**注意**:当前版本仅更新状态为 cancelled,实际的执行取消功能待实现。
|
||
"""
|
||
try:
|
||
# 获取执行记录
|
||
execution = service.get_execution(execution_id)
|
||
|
||
if not execution:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="执行记录不存在"
|
||
)
|
||
|
||
# 验证应用是否属于当前工作空间
|
||
app = db.query(App).filter(
|
||
App.id == execution.app_id,
|
||
App.workspace_id == current_user.current_workspace_id,
|
||
App.is_active.is_(True)
|
||
).first()
|
||
|
||
if not app:
|
||
return fail(
|
||
code=BizCode.NOT_FOUND,
|
||
msg="无权访问该执行记录"
|
||
)
|
||
|
||
# 检查执行状态
|
||
if execution.status not in ["pending", "running"]:
|
||
return fail(
|
||
code=BizCode.INVALID_PARAMETER,
|
||
msg=f"无法取消状态为 {execution.status} 的执行"
|
||
)
|
||
|
||
# 更新状态为 cancelled
|
||
service.update_execution_status(execution_id, "cancelled")
|
||
|
||
return success(msg="工作流执行已取消")
|
||
|
||
except BusinessException as e:
|
||
logger.warning(f"取消工作流执行失败: {e.message}")
|
||
return fail(code=e.code, msg=e.message)
|
||
except Exception as e:
|
||
logger.error(f"取消工作流执行异常: {e}", exc_info=True)
|
||
return fail(
|
||
code=BizCode.INTERNAL_ERROR,
|
||
msg=f"取消工作流执行失败: {str(e)}"
|
||
)
|