Compare commits
56 Commits
v0.2.0
...
feat/chatf
| Author | SHA1 | Date | |
|---|---|---|---|
| ab465ff3eb | |||
| 0d5c330b51 | |||
| e678c24b0c | |||
| 13d30605f1 | |||
| 03b8d8e17a | |||
| e3930873c6 | |||
| 2ed2a60479 | |||
| f589bb94bb | |||
| 02b4171576 | |||
| 0d83a5e7bc | |||
| 14ca189316 | |||
| 4310dee4c2 | |||
| 4ca3e597ff | |||
| 53345f58c2 | |||
| 8137b0aee5 | |||
| b48c4c2792 | |||
| f8840810ce | |||
| 9b68bd5387 | |||
| a6f97f61f8 | |||
| 0965d69acc | |||
| 183d0324bb | |||
| 04f0491454 | |||
| 9ed2f8be67 | |||
| 403128b5d3 | |||
| db7c95885d | |||
| 2ee3fa68ab | |||
| a0d3bcf998 | |||
| cc593fc270 | |||
| 6e961bb60d | |||
| f93b60512f | |||
| 9dcdb70508 | |||
| 4a44c0ddbd | |||
| b299adacf3 | |||
| 0ce6a4da4c | |||
| be5178d57b | |||
| 2d925ca241 | |||
| 60a9c7a281 | |||
| 376e563e4f | |||
| f0c339d231 | |||
| 81b5867a62 | |||
| 5ac7b8d26e | |||
| 48b52c3592 | |||
| 033df3f8ee | |||
| f294e19af5 | |||
| 23a1f1cab0 | |||
| c3d8def0e6 | |||
| 32d9bf9a39 | |||
| be4aa3f2ca | |||
| bc68869493 | |||
| ccee6dcde8 | |||
| d9ec4f60e0 | |||
| 9ca1ae506f | |||
| d045dea008 | |||
| 8e62e61c77 | |||
| ae6f57eade | |||
| 35d2f38110 |
@ -1,73 +0,0 @@
|
||||
name: "ci@backend pipeline"
|
||||
|
||||
trigger:
|
||||
change:
|
||||
paths:
|
||||
- "backend/**"
|
||||
|
||||
jobs:
|
||||
unit_test:
|
||||
image: hub.byted.org/codebase/ci_go_1_24:latest
|
||||
name: Unit Test
|
||||
steps:
|
||||
- id: mysql_scripts
|
||||
name: mysql scripts
|
||||
uses: actions/mysql-scripts@v1
|
||||
inputs:
|
||||
db_name: opencoze
|
||||
host: mysql
|
||||
path: "docker/atlas/migrations/*.sql"
|
||||
user: root
|
||||
password: root
|
||||
- name: Go Test
|
||||
uses: actions/codecov
|
||||
inputs:
|
||||
driver: go
|
||||
commands:
|
||||
- modules=`find . -name "go.mod" -exec dirname {} \;`
|
||||
- echo $modules
|
||||
- list=""
|
||||
- coverpkg=""
|
||||
- if [[ ! -f "go.work" ]];then go work init;fi
|
||||
- for module in $modules; do go work use $module; list=$module"/... "$list; coverpkg=$module"/...,"$coverpkg; done
|
||||
- go work sync
|
||||
- go test -coverprofile=coverage.out -gcflags="all=-l -N" -coverpkg=$coverpkg $list
|
||||
config:
|
||||
status:
|
||||
project:
|
||||
opencoze:
|
||||
minimum_coverage: 0%
|
||||
paths:
|
||||
- "!tests"
|
||||
- "!examples/**"
|
||||
- "!*/examples/**"
|
||||
- "!*/mock/**"
|
||||
- "!*/model/**"
|
||||
diff:
|
||||
eino:
|
||||
line_limit: 10 # 增量行数少于多少行时,默认置成功
|
||||
minimum_coverage: 0%
|
||||
paths:
|
||||
- "!tests"
|
||||
- "!examples/**"
|
||||
- "!*/examples/**"
|
||||
- "!*/mock/**"
|
||||
- "!*/model/**"
|
||||
- name: Sonar
|
||||
uses: actions/sonar@v1
|
||||
inputs:
|
||||
coverage_path: /tmp/coverage.out
|
||||
coverage_type: go
|
||||
disable_quality_gates: true
|
||||
exclusions_list:
|
||||
- "!tests"
|
||||
- "examples/**"
|
||||
- "*/mock/**"
|
||||
- "*/model/**"
|
||||
language: go
|
||||
services:
|
||||
- id: mysql
|
||||
image: hub.byted.org/ee/mysql:8.0
|
||||
envs:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: opencoze
|
||||
@ -1,180 +0,0 @@
|
||||
name: CI@fe-master
|
||||
trigger:
|
||||
cron:
|
||||
push:
|
||||
branches: []
|
||||
paths:
|
||||
- "frontend/**"
|
||||
types: [branch]
|
||||
notification:
|
||||
when: failure
|
||||
# 搜索群名:Bot Studio Monorepo CI 报警群
|
||||
to: ['7350862409475031044']
|
||||
manual:
|
||||
notification:
|
||||
when: failure
|
||||
|
||||
jobs:
|
||||
lint: &base_job
|
||||
runs-on:
|
||||
env: online
|
||||
name: Lint
|
||||
image: hub.byted.org/base/bot_monorepo_ci_env:ae543e9bbc6d8155cffbd8f5ed27fb73
|
||||
# 从最近的 CI 执行记录看,install 步骤有概率会等待超时
|
||||
# 目前已 oncall,这里先设置一个超时时间,避免阻塞
|
||||
timeout: 30
|
||||
envs:
|
||||
RUSH_BUILD_CACHE_WRITE_ALLOWED: ${{RUSH_BUILD_CACHE_WRITE_ALLOWED}}
|
||||
RUSH_BUILD_CACHE_ENABLED: ${{RUSH_BUILD_CACHE_ENABLED}}
|
||||
RUSH_BUILD_CACHE_CREDENTIAL: ${{RUSH_BUILD_CACHE_CREDENTIAL}}
|
||||
ACCESS_TOKEN: ${{CI_BOT_ACCESS_TOKEN}}
|
||||
CI: 'true'
|
||||
RUN_BYTEST_COV: 'false' # disable Jupiter default behavior of invoke bytestcov
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 'true'
|
||||
CYPRESS_INSTALL_BINARY: '0'
|
||||
TAIKO_SKIP_CHROMIUM_DOWNLOAD: '0'
|
||||
RE2_DOWNLOAD_SKIP_PATH: '1'
|
||||
RE2_DOWNLOAD_MIRROR: https://bnpm.bytedance.net/mirrors
|
||||
# https://typescript-eslint.io/packages/parser/#allowautomaticsingleruninference
|
||||
TSESTREE_SINGLE_RUN: 'true'
|
||||
# 使用云盘缓存:https://bytedance.larkoffice.com/wiki/A60lwgolSinteMkOz71cFPvFneg
|
||||
# TODO:不同job的缓存key暂时使用同一个,后续可以考虑区分
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-master-v2-lint
|
||||
size: 256
|
||||
steps:
|
||||
- &checkout_step
|
||||
id: Checkout
|
||||
uses: actions/checkout
|
||||
inputs:
|
||||
depth: 1
|
||||
- &proxy_step
|
||||
name: SetupProxy
|
||||
commands:
|
||||
- bash .codebase/scripts/env.sh
|
||||
- &init_env_step
|
||||
name: Initialization
|
||||
commands:
|
||||
- printenv
|
||||
- git config user.name ci_flow
|
||||
- git config user.email ci_flow@bytedance.com
|
||||
- &install_deps_step
|
||||
name: Install dependencies
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js install
|
||||
# 暂时不启用,因为eslintignore文件移除会导致解析报错,后期接入可考虑动态读取eslint ignore配置
|
||||
# - name: PreLint
|
||||
# parallel-with-next-step: true
|
||||
# commands:
|
||||
# - npx oxlint@latest -A all .
|
||||
- name: Lint
|
||||
commands:
|
||||
- NODE_OPTIONS="--max-old-space-size=4096" node common/scripts/install-run-rush.js lint
|
||||
|
||||
ts_check:
|
||||
<<: *base_job
|
||||
name: Check TS Type
|
||||
timeout: 30
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-master-v2-ts-check
|
||||
size: 256
|
||||
steps:
|
||||
- *checkout_step
|
||||
- *proxy_step
|
||||
- *init_env_step
|
||||
- *install_deps_step
|
||||
- name: Check TS Type
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js ts-check -v
|
||||
|
||||
build:
|
||||
<<: *base_job
|
||||
name: Build
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-master-v2-build
|
||||
size: 256
|
||||
steps:
|
||||
- *checkout_step
|
||||
- *proxy_step
|
||||
- *init_env_step
|
||||
- *install_deps_step
|
||||
- name: Build
|
||||
commands:
|
||||
- CUSTOM_VERSION=release REGION=sg BUILD_BRANCH=test node common/scripts/install-run-rush.js build -v
|
||||
|
||||
test:
|
||||
<<: *base_job
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-master-v2-test
|
||||
size: 256
|
||||
name: Test
|
||||
services:
|
||||
# 下面启动一个mysql和mongo服务,主要用于coze.hub.core相关服务的集成测试
|
||||
# id需要保持跟代码中连接的host一致
|
||||
- id: hub_mysql
|
||||
image: hub.byted.org/ee/mysql:5.7
|
||||
envs:
|
||||
MYSQL_ROOT_PASSWORD: test
|
||||
MYSQL_DATABASE: coze_hub
|
||||
MYSQL_USER: test
|
||||
MYSQL_PASSWORD: test
|
||||
MYSQL_TCP_PORT: 3306
|
||||
- id: hub_mongo
|
||||
image: hub.byted.org/ee/mongo:4.0.24
|
||||
commands:
|
||||
- mongod --replSet rs0
|
||||
- id: mongo-init
|
||||
image: hub.byted.org/ee/mongo:4.0.24
|
||||
commands:
|
||||
- sleep 10s
|
||||
- mongo mongodb://127.0.0.1:27017 --eval 'rs.initiate()'
|
||||
steps:
|
||||
- *checkout_step
|
||||
- *proxy_step
|
||||
- *init_env_step
|
||||
- *install_deps_step
|
||||
- name: wait mongo ready
|
||||
uses: actions/mongodb-scripts
|
||||
inputs:
|
||||
host: 127.0.0.1
|
||||
port: 27017
|
||||
- name: wait mysql ready
|
||||
uses: actions/mysql-scripts
|
||||
inputs:
|
||||
host: hub_mysql
|
||||
user: test
|
||||
password: test
|
||||
commands:
|
||||
- mysql -u test -ptest -h hub_mysql -P 3306 -e 'show databases;'
|
||||
# 服务发现
|
||||
- id: consul
|
||||
uses: actions/setup-consul
|
||||
- name: Test Coverage
|
||||
id: test
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js test:cov -v
|
||||
# https://bytedance.feishu.cn/wiki/wikcn9Z4azEdfJalVPKcOs9vxsR
|
||||
|
||||
security_scan:
|
||||
<<: *base_job
|
||||
name: Security Scan
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-master-v2-scan
|
||||
size: 256
|
||||
steps:
|
||||
- *checkout_step
|
||||
- *proxy_step
|
||||
- *init_env_step
|
||||
- *install_deps_step
|
||||
- name: build
|
||||
commands:
|
||||
- CUSTOM_VERSION=release REGION=sg node common/scripts/install-run-rush.js build -o app-botstudio-main -v
|
||||
- id: Argus
|
||||
commands:
|
||||
- npm i @ies/argus-scan@0.30.37 -g
|
||||
- bash .codebase/scripts/argus-scan.sh
|
||||
@ -1,89 +0,0 @@
|
||||
name: CI@fe-tsc
|
||||
trigger:
|
||||
manual:
|
||||
change:
|
||||
# 临时支持 project-ide 项目需求,临时修改为如下格式
|
||||
# 后续需调整回 integration/**
|
||||
types: [create, push, restore]
|
||||
paths:
|
||||
- "frontend/**"
|
||||
notification:
|
||||
when: failure
|
||||
|
||||
jobs:
|
||||
ts_check: &base_job
|
||||
runs-on:
|
||||
env: online
|
||||
image: hub.byted.org/base/bot_monorepo_ci_env:ae543e9bbc6d8155cffbd8f5ed27fb73
|
||||
# 从最近的 CI 执行记录看,install 步骤有概率会等待超时
|
||||
# 目前已 oncall,这里先设置一个超时时间,避免阻塞
|
||||
timeout: 30
|
||||
if: ${{ !Event.Change.IsPreSubmit }}
|
||||
envs:
|
||||
targetBranch: ${{Event.Change.Target.Branch}}
|
||||
RUSH_BUILD_CACHE_WRITE_ALLOWED: ${{RUSH_BUILD_CACHE_WRITE_ALLOWED}}
|
||||
RUSH_BUILD_CACHE_ENABLED: ${{RUSH_BUILD_CACHE_ENABLED}}
|
||||
RUSH_BUILD_CACHE_CREDENTIAL: ${{RUSH_BUILD_CACHE_CREDENTIAL}}
|
||||
ACCESS_TOKEN: ${{CI_BOT_ACCESS_TOKEN}}
|
||||
CI: 'true'
|
||||
RUN_BYTEST_COV: 'false'
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 'true'
|
||||
CYPRESS_INSTALL_BINARY: '0'
|
||||
TAIKO_SKIP_CHROMIUM_DOWNLOAD: '0'
|
||||
RE2_DOWNLOAD_SKIP_PATH: '1'
|
||||
RE2_DOWNLOAD_MIRROR: https://bnpm.bytedance.net/mirrors
|
||||
MERGE_REQUEST_TITLE: ${{Event.Change.Title}}
|
||||
TSESTREE_SINGLE_RUN: 'true'
|
||||
steps:
|
||||
- &checkout_step
|
||||
name: Checkout
|
||||
uses: actions/checkout
|
||||
inputs:
|
||||
submodules: true
|
||||
depth: 1
|
||||
|
||||
- &proxy_step
|
||||
name: SetupProxy
|
||||
commands:
|
||||
- bash .codebase/scripts/env.sh
|
||||
|
||||
- &remote_info_step
|
||||
id: RemoteInfo
|
||||
uses: 'actions/mr-remote-info'
|
||||
inputs:
|
||||
info_list: ['behind_commits', 'changed_files', 'changed_files_path']
|
||||
|
||||
- &cache_step
|
||||
id: Cache
|
||||
uses: actions/cache
|
||||
inputs:
|
||||
key: flow-monorepo-${{Event.Change.Source.Branch}}
|
||||
paths:
|
||||
- common/temp/pnpm-store
|
||||
restore_keys:
|
||||
- flow-monorepo-${{Event.Change.Source.Branch}}
|
||||
- flow-monorepo-store-master
|
||||
|
||||
- &init_env_step
|
||||
id: InitEnv
|
||||
name: Initialization
|
||||
commands:
|
||||
- printenv
|
||||
- git config user.name ci_flow
|
||||
- git config user.email ci_flow@bytedance.com
|
||||
- npm config set registry=https://registry.npmjs.org
|
||||
- pnpm config set network-concurrency 32
|
||||
- echo "$(<${{Steps.RemoteInfo.Outputs.changed_files_path}})"
|
||||
- echo "::set-output name=ShouldRunBuild::${{ Event.Change.IsPreSubmit || int(Steps.RemoteInfo.Outputs.behind_commits) <= 6 }}"
|
||||
|
||||
- &install_deps_step
|
||||
name: Install dependencies
|
||||
commands:
|
||||
- npx why-is-node-running@v2.x common/scripts/install-run-rush.js increment --action install -p ${{Steps.RemoteInfo.Outputs.changed_files_path}}
|
||||
|
||||
- name: Prepare basic packages
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js pre-build -v
|
||||
- name: Check TS Type
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js increment --action ts-check -p ${{Steps.RemoteInfo.Outputs.changed_files_path}}
|
||||
@ -1,184 +0,0 @@
|
||||
name: CI@fe
|
||||
trigger:
|
||||
manual:
|
||||
change:
|
||||
source-branches: ['!release/**', '!task/**']
|
||||
types: [create, push, restore]
|
||||
paths:
|
||||
- "frontend/**"
|
||||
notification:
|
||||
when: failure
|
||||
|
||||
jobs:
|
||||
lint: &base_job
|
||||
runs-on:
|
||||
env: online
|
||||
image: hub.byted.org/base/bot_monorepo_ci_env:ae543e9bbc6d8155cffbd8f5ed27fb73
|
||||
# 从最近的 CI 执行记录看,install 步骤有概率会等待超时
|
||||
# 目前已 oncall,这里先设置一个超时时间,避免阻塞
|
||||
timeout: 30
|
||||
if: ${{ !Event.Change.IsPreSubmit }}
|
||||
envs:
|
||||
targetBranch: ${{Event.Change.Target.Branch}}
|
||||
RUSH_BUILD_CACHE_WRITE_ALLOWED: ${{RUSH_BUILD_CACHE_WRITE_ALLOWED}}
|
||||
RUSH_BUILD_CACHE_ENABLED: ${{RUSH_BUILD_CACHE_ENABLED}}
|
||||
RUSH_BUILD_CACHE_CREDENTIAL: ${{RUSH_BUILD_CACHE_CREDENTIAL}}
|
||||
ACCESS_TOKEN: ${{CI_BOT_ACCESS_TOKEN}}
|
||||
CI: 'true'
|
||||
RUN_BYTEST_COV: 'false'
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 'true'
|
||||
CYPRESS_INSTALL_BINARY: '0'
|
||||
TAIKO_SKIP_CHROMIUM_DOWNLOAD: '0'
|
||||
BUILD_BRANCH: ${{Event.Change.Source.Branch}}
|
||||
RE2_DOWNLOAD_SKIP_PATH: '1'
|
||||
MERGE_REQUEST_TITLE: ${{Event.Change.Title}}
|
||||
TSESTREE_SINGLE_RUN: 'true'
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-ci-v2-lint
|
||||
size: 256
|
||||
steps:
|
||||
- &checkout_step
|
||||
name: Checkout
|
||||
uses: actions/checkout
|
||||
inputs:
|
||||
submodules: true
|
||||
depth: 1
|
||||
|
||||
- &proxy_step
|
||||
name: SetupProxy
|
||||
commands:
|
||||
- bash .codebase/scripts/env.sh
|
||||
|
||||
- &remote_info_step
|
||||
id: RemoteInfo
|
||||
uses: 'actions/mr-remote-info'
|
||||
inputs:
|
||||
info_list: ['behind_commits', 'changed_files', 'changed_files_path']
|
||||
|
||||
- &cache_step
|
||||
id: Cache
|
||||
uses: actions/cache
|
||||
inputs:
|
||||
key: flow-monorepo-${{Event.Change.Source.Branch}}
|
||||
paths:
|
||||
- common/temp/pnpm-store
|
||||
- packages/arch/idl/src/auto-generated
|
||||
restore_keys:
|
||||
- flow-monorepo-${{Event.Change.Source.Branch}}
|
||||
- flow-monorepo-store-master
|
||||
|
||||
- &init_env_step
|
||||
id: InitEnv
|
||||
name: Initialization
|
||||
commands:
|
||||
- printenv
|
||||
- git config user.name ci_flow
|
||||
- git config user.email ci_flow@bytedance.com
|
||||
- npm config set registry=https://registry.npmjs.org
|
||||
- pnpm config set network-concurrency 32
|
||||
- echo "$(<${{Steps.RemoteInfo.Outputs.changed_files_path}})"
|
||||
- echo "::set-output name=ShouldRunBuild::${{ Event.Change.IsPreSubmit || int(Steps.RemoteInfo.Outputs.behind_commits) <= 6 }}"
|
||||
|
||||
- &install_deps_step
|
||||
name: Install dependencies
|
||||
commands:
|
||||
- npx why-is-node-running@v2.x common/scripts/install-run-rush.js increment --action install -p ${{Steps.RemoteInfo.Outputs.changed_files_path}}
|
||||
|
||||
- name: Check Lint
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js increment --action lint -p ${{Steps.RemoteInfo.Outputs.changed_files_path}}
|
||||
|
||||
style_check:
|
||||
<<: *base_job
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-ci-v2-style-check
|
||||
size: 256
|
||||
name: Check Stylelint
|
||||
steps:
|
||||
- *checkout_step
|
||||
- *proxy_step
|
||||
- *remote_info_step
|
||||
- *cache_step
|
||||
- *init_env_step
|
||||
- *install_deps_step
|
||||
- name: Check Stylelint
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js increment --action style -p ${{Steps.RemoteInfo.Outputs.changed_files_path}}
|
||||
|
||||
build:
|
||||
<<: *base_job
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-ci-v2-build
|
||||
size: 256
|
||||
name: Build
|
||||
timeout: 20
|
||||
steps:
|
||||
- *checkout_step
|
||||
- *proxy_step
|
||||
- *remote_info_step
|
||||
- *cache_step
|
||||
- *init_env_step
|
||||
- *install_deps_step
|
||||
- name: Build
|
||||
id: build
|
||||
if: ${{ Steps.InitEnv.Outputs.ShouldRunBuild }}
|
||||
commands:
|
||||
- node common/scripts/install-run-rush.js increment --action build -p ${{Steps.RemoteInfo.Outputs.changed_files_path}}
|
||||
|
||||
test:
|
||||
<<: *base_job
|
||||
caches:
|
||||
- backend: ebs
|
||||
key: bot-studio-monorepo-ci-v2-test
|
||||
size: 256
|
||||
name: Test Coverage
|
||||
services:
|
||||
# 下面启动一个mysql和mongo服务,主要用于coze.hub.core相关服务的集成测试
|
||||
# id需要保持跟代码中连接的host一致
|
||||
- id: hub_mysql
|
||||
image: hub.byted.org/ee/mysql:5.7
|
||||
envs:
|
||||
MYSQL_ROOT_PASSWORD: test
|
||||
MYSQL_DATABASE: coze_hub
|
||||
MYSQL_USER: test
|
||||
MYSQL_PASSWORD: test
|
||||
MYSQL_TCP_PORT: 3306
|
||||
- id: hub_mongo
|
||||
image: hub.byted.org/ee/mongo:4.0.24
|
||||
commands:
|
||||
- mongod --replSet rs0
|
||||
- id: mongo-init
|
||||
image: hub.byted.org/ee/mongo:4.0.24
|
||||
commands:
|
||||
- sleep 10s
|
||||
- mongo mongodb://127.0.0.1:27017 --eval 'rs.initiate()'
|
||||
steps:
|
||||
- *checkout_step
|
||||
- *proxy_step
|
||||
- *remote_info_step
|
||||
- *cache_step
|
||||
- *init_env_step
|
||||
- *install_deps_step
|
||||
- name: wait mongo ready
|
||||
uses: actions/mongodb-scripts
|
||||
inputs:
|
||||
host: 127.0.0.1
|
||||
port: 27017
|
||||
- name: wait mysql ready
|
||||
uses: actions/mysql-scripts
|
||||
inputs:
|
||||
host: hub_mysql
|
||||
user: test
|
||||
password: test
|
||||
commands:
|
||||
- mysql -u test -ptest -h hub_mysql -P 3306 -e 'show databases;'
|
||||
# 服务发现
|
||||
- id: consul
|
||||
uses: actions/setup-consul
|
||||
- name: Test Coverage
|
||||
commands:
|
||||
- git fetch --filter=blob:none --unshallow -q
|
||||
- node common/scripts/install-run-rush.js increment --action test:cov -p ${{Steps.RemoteInfo.Outputs.changed_files_path}}
|
||||
@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# 暂时只扫描 app-botstudio-main 项目的产物
|
||||
result=$(argus scm -c apps/bot/dist_sg/static -n obric/cloud/bot_studio_oversea -l)
|
||||
|
||||
if echo "$result" | grep -q '::add-message level=error:::'; then
|
||||
if [ "$CI" ]; then
|
||||
echo '::add-message level=info::本地验证命令:`npm install -g @ies/argus-scan@0.30.37 && REGION=sg CUSTOM_VERSION=release rush build -o app-botstudio-main && argus scm -c apps/bot/dist_sg/static -n obric/cloud/bot_studio_oversea -l`'
|
||||
fi
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
SOURCE_BRANCH=${SOURCE_BRANCH}
|
||||
TARGET_BRANCH=${targetBranch}
|
||||
|
||||
if [[ $TARGET_BRANCH == "master" && !($SOURCE_BRANCH =~ ^release/ || $SOURCE_BRANCH =~ ^hotfix/ || $SOURCE_BRANCH =~ ^task/ || $SOURCE_BRANCH =~ ^fix/) ]]; then
|
||||
# 检查$SOURCE_BRANCH是否以'release/'或'hotfix/'或'task/'或'fix/'开头
|
||||
LATEST_BRANCH="release/$(date -d '+8 hour' +%Y%m%d)"
|
||||
CONCLUSION="{\"name\": \"Target Branch\", \"conclusion\": \"failed\", \"output\":{\"summary\":\"Error: Please don't merge to master directly, use [$LATEST_BRANCH](https://code.byted.org/obric/bot-studio-monorepo/commits/$LATEST_BRANCH) instead.\n You can contact [@fanwenjie.fe](https://code.byted.org/fanwenjie.fe) to skip this error.\" }}"
|
||||
else
|
||||
CONCLUSION="{\"name\": \"Target Branch\", \"conclusion\": \"success\", \"output\":{\"summary\":\"Good Pratice\" }}"
|
||||
fi
|
||||
|
||||
echo $CONCLUSION >>check-merge-target.log
|
||||
echo "::update-check-run::check-merge-target.log"
|
||||
@ -1,55 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# Your target branch
|
||||
TARGET_BRANCH=$targetBranch
|
||||
|
||||
if [[ ${SOURCE_BRANCH} =~ ^integration/ || ${SOURCE_BRANCH} =~ ^release/ ]]; then
|
||||
# integration -> xxx or release/xxx -> master SKIP check-mr-size.
|
||||
echo "::add-message level=info::SKIP check-mr-size"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Specify the pattern you want to exclude, using *space* as the separator
|
||||
EXCLUDE_PATTERNS=(
|
||||
'**/pnpm-lock.yaml'
|
||||
'packages/arch/bot-api/src/auto-generate/**'
|
||||
'apps/bot-op/src/services/bam-auto-generate/**'
|
||||
'apps/prompt-platform/src/services/auto-generate/**'
|
||||
"**/lib/**"
|
||||
"**/.*/**"
|
||||
'**/__tests__/**'
|
||||
'**/__test__/**'
|
||||
"**/__mocks__/**"
|
||||
"**/__mock__/**"
|
||||
"**/*.test.*/**"
|
||||
"**/*.spec.*/**"
|
||||
"**/__snapshots__/**"
|
||||
"**/*.snap"
|
||||
'**/*.svg'
|
||||
'ee/e2e/bot-studio/**'
|
||||
'common/changes/**'
|
||||
'apps/fornax/**'
|
||||
"apps/api-builder/**"
|
||||
"packages/api-builder/**"
|
||||
)
|
||||
|
||||
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
|
||||
EXCLUDE_STRING+=":(exclude)$pattern "
|
||||
done
|
||||
|
||||
# Count the number of files changed but exclude certain files and folders
|
||||
file_changes=$(git diff --name-only "origin/$TARGET_BRANCH..." $EXCLUDE_STRING | wc -l)
|
||||
|
||||
# Count the number of line changes but exclude certain files and folders
|
||||
line_changes=$(git diff --shortstat "origin/$TARGET_BRANCH..." $EXCLUDE_STRING | awk '{print ($4>$6)?$4:$6}')
|
||||
|
||||
# Check if number of changed files is greater than 100 or if number of line changes is greater than 2000
|
||||
if [ "$file_changes" -gt 100 ] || [ "$line_changes" -gt 2000 ]; then
|
||||
CONCLUSION="{\"name\": \"MR Size\", \"conclusion\": \"failed\", \"output\":{\"summary\":\"Error: Too many changes. Number of changed files is **""$file_changes""**, number of changed lines is **""$line_changes""**.\n You can contact [@fanwenjie.fe](https://code.byted.org/fanwenjie.fe) to skip this error.\" }}"
|
||||
else
|
||||
CONCLUSION="{\"name\": \"MR Size\", \"conclusion\": \"success\", \"output\":{\"summary\":\"Good\" }}"
|
||||
fi
|
||||
|
||||
echo $CONCLUSION >>check-mr-size.log
|
||||
echo "::update-check-run::check-mr-size.log"
|
||||
@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
PRE_COMMITS=$1
|
||||
|
||||
# 按 codebase 给出的口径,pre commits 超过 5 时容易导致 rebase 失败,因此主动给出警告,避免进入 CQ 后被弹出
|
||||
if [ $PRE_COMMITS -gt 5 ]; then
|
||||
CONCLUSION="{\"name\": \"Pre Commits Check\", \"conclusion\": \"failed\", \"output\":{\"summary\":\"分支已落后目标分支较多,非常容易导致进入 CQ 后被弹出,请执行 rebase/merge 同步代码后重试。\" }}"
|
||||
else
|
||||
CONCLUSION="{\"name\": \"Pre Commits Check\", \"conclusion\": \"success\", \"output\":{\"summary\":\"good\" }}"
|
||||
fi
|
||||
|
||||
echo $CONCLUSION >> check-pre-commits.log
|
||||
echo "::update-check-run::check-pre-commits.log"
|
||||
@ -1,54 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
basename=$(basename "$CHANGE_URL")
|
||||
lastParam=$(echo "$basename" | cut -d'/' -f1)
|
||||
|
||||
targetBranch="${targetBranch}"
|
||||
sourceBranch="${SOURCE_BRANCH}"
|
||||
mrTitle="${MR_TITLE}"
|
||||
mrDescription="${MR_DESCRIPTION}"
|
||||
|
||||
echo "::set-output name=mrId::$lastParam" # 输出 lastParam 的值
|
||||
|
||||
result=$(curl --location "https://code.byted.org/api/v4/projects/548801/merge_requests/$lastParam" \
|
||||
--header "Private-Token: $GITLAB_TOKEN")
|
||||
|
||||
commits=$(curl --location "https://code.byted.org/api/v4/projects/548801/merge_requests/$lastParam/commits" \
|
||||
--header "Private-Token: $GITLAB_TOKEN")
|
||||
|
||||
isSquash=$(echo "$result" | jq -r '.squash') # 使用jq提取isSquash的值
|
||||
|
||||
commitsCount=$(echo "$commits" | jq length)
|
||||
|
||||
echo "::set-output name=squash::$isSquash" # 输出 isSquash 的值
|
||||
echo "::set-output name=commitsCount::$commitsCount" # 输出 commitsCount 的值
|
||||
|
||||
if [[ $isSquash == true ]]; then
|
||||
# 勾选squash
|
||||
|
||||
if [[ $sourceBranch == release/* && $targetBranch == master ]]; then
|
||||
echo "::add-message level=error::**release 分支合入 master 时,不可开启 squash **"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $mrDescription == \[no-squash\]* ]]; then
|
||||
echo "::add-message level=error::**当前 MR 勾选了 Squash 选项,但是描述中包含[no-squash]**"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
# 没有勾选squash
|
||||
|
||||
if [[ $mrDescription == \[no-squash\]* ||
|
||||
$commitsCount -le 1 ||
|
||||
$mrTitle == WIP:* ||
|
||||
$mrTitle == wip:* ||
|
||||
$sourceBranch == release/* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::add-message level=error::**当前 MR 应该勾选 Squash 选项**"
|
||||
exit 1
|
||||
|
||||
fi
|
||||
@ -1,53 +0,0 @@
|
||||
const fs = require('fs/promises');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
// node scripts/checksum-by-change.js /usr/changed-path.json
|
||||
// change-path 文件来自 ci
|
||||
const changedPath = process.argv[2];
|
||||
const readJson = async jsonFile => {
|
||||
const content = await fs.readFile(jsonFile, 'utf-8');
|
||||
let _val = null;
|
||||
try {
|
||||
eval(`_val = ${content}`);
|
||||
return _val;
|
||||
} catch (e) {
|
||||
console.error(`json parse failure: `, e);
|
||||
}
|
||||
};
|
||||
|
||||
const readChangedPackages = async changedPath => {
|
||||
const [changedFiles, { projects }] = await Promise.all([
|
||||
readJson(changedPath),
|
||||
readJson(path.resolve(__dirname, '../../rush.json')),
|
||||
]);
|
||||
const changedProjects = projects
|
||||
.filter(project => {
|
||||
const { projectFolder } = project;
|
||||
const endsWithSlash = projectFolder.endsWith('/');
|
||||
const compareFolder = `${projectFolder}${endsWithSlash ? '' : '/'}`;
|
||||
if (!changedFiles) {
|
||||
// changed-path.json 内容可能为null
|
||||
return true;
|
||||
}
|
||||
const matched = changedFiles.find(file => file.startsWith(compareFolder));
|
||||
return !!matched;
|
||||
})
|
||||
.map(({ packageName }) => packageName)
|
||||
.sort((r1, r2) => r1.localeCompare(r2));
|
||||
return changedProjects;
|
||||
};
|
||||
|
||||
async function main() {
|
||||
if (!changedPath || changedPath.length <= 0) {
|
||||
throw new Error(`Please pass the correct "changedPath" path`);
|
||||
}
|
||||
const changedPackages = await readChangedPackages(changedPath);
|
||||
|
||||
const hash = crypto.createHash('md5');
|
||||
changedPackages.forEach(r => hash.update(r));
|
||||
const hashValue = hash.digest('hex');
|
||||
console.log(`::set-output name=hash::${hashValue}`);
|
||||
}
|
||||
|
||||
main();
|
||||
@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo ::set-env name=no_proxy::cn.goofy.app,.cn.goofy.app,goofy.app,.goofy.app,localhost,.byted.org,byted.org,.bytedance.net,bytedance.net,127.0.0.1,127.0.0.0/8,169.254.0.0/16,100.64.0.0/10,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,::1,fe80::/10,fd00::/8
|
||||
echo ::set-env name=all_proxy::http://sys-proxy-rd-relay.byted.org:3128
|
||||
echo ::set-env name=http_proxy::http://sys-proxy-rd-relay.byted.org:3128
|
||||
echo ::set-env name=https_proxy::http://sys-proxy-rd-relay.byted.org:3128
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Setup common env for CI & SCM
|
||||
# 1. 忽略不影响构建的 install
|
||||
export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=true
|
||||
export CYPRESS_INSTALL_BINARY=0
|
||||
export TAIKO_SKIP_CHROMIUM_DOWNLOAD=0
|
||||
export CUSTOM_VERSION="inhouse"
|
||||
export RE2_DOWNLOAD_SKIP_PATH=1
|
||||
export RE2_DOWNLOAD_MIRROR="https://bnpm.bytedance.net/mirrors"
|
||||
export PUPPETEER_SKIP_DOWNLOAD=true
|
||||
|
||||
# 2. 在 CI 环境生效:
|
||||
echo ::set-env name=PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD::$PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD
|
||||
echo ::set-env name=CYPRESS_INSTALL_BINARY::$CYPRESS_INSTALL_BINARY
|
||||
echo ::set-env name=TAIKO_SKIP_CHROMIUM_DOWNLOAD::$TAIKO_SKIP_CHROMIUM_DOWNLOAD
|
||||
echo ::set-env name=RE2_DOWNLOAD_SKIP_PATH::$RE2_DOWNLOAD_SKIP_PATH
|
||||
echo ::set-env name=RE2_DOWNLOAD_MIRROR::$RE2_DOWNLOAD_MIRROR
|
||||
echo ::set-env name=PUPPETEER_SKIP_DOWNLOAD::$PUPPETEER_SKIP_DOWNLOAD
|
||||
5
.github/.licenserc.yaml
vendored
5
.github/.licenserc.yaml
vendored
@ -21,5 +21,10 @@ header:
|
||||
- '**/gorm_gen/**'
|
||||
- '**/kitex_gen/**'
|
||||
- '**/*.gen.go'
|
||||
- '**/gen.go'
|
||||
- 'backend/api/**'
|
||||
- '**/*_mock.go'
|
||||
- 'backend/internal/mock/**'
|
||||
- '**/mock/**'
|
||||
files:
|
||||
- ../backend/go.mod
|
||||
540
.github/CODEOWNERS
vendored
540
.github/CODEOWNERS
vendored
@ -1,268 +1,274 @@
|
||||
* Tecvan-fe
|
||||
* @Tecvan-fe @hi-pender @fanlv
|
||||
|
||||
/apps/coze-studio/ @Tecvan-fe @evan-crash @duwenhan2byte
|
||||
/packages/agent-ide/agent-publish/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei @catee
|
||||
/packages/agent-ide/commons/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/arch/bot-api/ @Tecvan-fe
|
||||
/packages/arch/bot-http/ @Tecvan-fe
|
||||
/packages/arch/logger/ @Tecvan-fe
|
||||
/packages/arch/slardar-interface/ @Tecvan-fe @evan-crash
|
||||
/config/eslint-config/ @Tecvan-fe @leeight @soonco
|
||||
/infra/eslint-plugin/ @Tecvan-fe
|
||||
/config/ts-config/ @leeight @Tecvan-fe
|
||||
/config/vitest-config/ @Tecvan-fe
|
||||
/packages/arch/bot-env/ @Tecvan-fe @leeight
|
||||
/packages/arch/bot-env-adapter/ @dragooncjw @Tecvan-fe @leeight
|
||||
/packages/arch/bot-typings/ @Tecvan-fe
|
||||
/packages/arch/web-context/ @Tecvan-fe
|
||||
/packages/components/bot-semi/ @Tecvan-fe
|
||||
/packages/components/bot-icons/ @DingGao-Devin
|
||||
/packages/arch/i18n/ @Tecvan-fe @leeight
|
||||
/packages/arch/resources/studio-i18n-resource/ @dragooncjw @Tecvan-fe
|
||||
/config/stylelint-config/ @Tecvan-fe
|
||||
/packages/arch/idl/ @Tecvan-fe
|
||||
/infra/utils/fs-enhance/ @Tecvan-fe
|
||||
/packages/arch/bot-store/ @Tecvan-fe @catee @duwenhan2byte
|
||||
/packages/arch/bot-error/ @haozhenfei @duwenhan2byte
|
||||
/packages/foundation/space-store/ @evan-crash @duwenhan2byte
|
||||
/packages/arch/bot-flags/ @Tecvan-fe
|
||||
/packages/arch/report-events/ @Tecvan-fe
|
||||
/packages/foundation/enterprise-store-adapter/ @evan-crash @duwenhan2byte
|
||||
/packages/foundation/local-storage/ @duwenhan2byte @evan-crash
|
||||
/packages/foundation/space-store-adapter/ @evan-crash @duwenhan2byte
|
||||
/packages/arch/bot-tea/ @Tecvan-fe @catee @soonco
|
||||
/packages/arch/tea/ @Tecvan-fe @evan-crash @soonco
|
||||
/packages/arch/tea-adapter/ @dragooncjw @Tecvan-fe
|
||||
/packages/arch/tea-interface/ @dragooncjw @Tecvan-fe
|
||||
/packages/studio/stores/bot-detail/ @Hezi-crypto @catee @DingGao-Devin @duwenhan2byte @evan-crash
|
||||
/packages/agent-ide/bot-input-length-limit/ @Hezi-crypto @catee @duwenhan2byte
|
||||
/packages/agent-ide/tool-config/ @haozhenfei @catee
|
||||
/packages/arch/bot-space-api/ @Tecvan-fe @duwenhan2byte
|
||||
/packages/arch/bot-utils/ @Tecvan-fe
|
||||
/packages/common/uploader-adapter/ @dragooncjw @Tecvan-fe
|
||||
/packages/common/uploader-interface/ @dragooncjw @Tecvan-fe
|
||||
/packages/studio/user-store/ @duwenhan2byte @catee @lihuiwen
|
||||
/packages/arch/foundation-sdk/ @evan-crash @duwenhan2byte
|
||||
/packages/common/chat-area/chat-core/ @haozhenfei @Hezi-crypto @evan-crash
|
||||
/packages/common/chat-area/utils/ @Hezi-crypto @haozhenfei
|
||||
/packages/arch/bot-md-box-adapter/ @Hezi-crypto @iu1340 @dragooncjw @Tecvan-fe
|
||||
/packages/studio/common/file-kit/ @haozhenfei @evan-crash
|
||||
/packages/arch/slardar-adapter/ @Tecvan-fe @dragooncjw
|
||||
/packages/arch/default-slardar/ @Tecvan-fe @evan-crash
|
||||
/packages/arch/fetch-stream/ @Hezi-crypto @haozhenfei
|
||||
/packages/common/websocket-manager-adapter/ @haozhenfei @Hezi-crypto @catee
|
||||
/packages/studio/autosave/ @catee
|
||||
/packages/studio/bot-utils/ @catee @soonco @Hezi-crypto
|
||||
/packages/common/flowgram-adapter/common/ @zxhfighter @xiamidaxia @dragooncjw
|
||||
/packages/common/flowgram-adapter/free-layout-editor/ @zxhfighter @xiamidaxia @dragooncjw
|
||||
/packages/agent-ide/space-bot/ @soonco @evan-crash @duwenhan2byte @catee @DingGao-Devin
|
||||
/packages/agent-ide/space-bot/src/store/bot-list-filter/ @duwenhan2byte @lihuiwen
|
||||
/packages/agent-ide/space-bot/src/store/bot-page/ @DingGao-Devin
|
||||
/packages/agent-ide/space-bot/src/store/explore/ @Tecvan-fe
|
||||
/packages/agent-ide/space-bot/src/store/risk-warning/ @lihuiwen @catee
|
||||
/packages/agent-ide/context/ @evan-crash
|
||||
/packages/agent-ide/bot-editor-context-store/ @Hezi-crypto @duwenhan2byte @catee
|
||||
/packages/agent-ide/chat-background/ @catee
|
||||
/packages/agent-ide/chat-background-config-content-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/chat-background-config-content/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/chat-background-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/common/chat-area/chat-uikit/ @catee @Hezi-crypto @evan-crash @haozhenfei
|
||||
/packages/common/chat-area/hooks/ @Hezi-crypto @evan-crash
|
||||
/packages/common/chat-area/chat-uikit-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/bot-audit-adapter/ @evan-crash @duwenhan2byte @Hezi-crypto @haozhenfei
|
||||
/packages/agent-ide/bot-audit-base/ @evan-crash @duwenhan2byte @Hezi-crypto @haozhenfei
|
||||
/packages/studio/components/ @soonco @evan-crash @duwenhan2byte @catee
|
||||
/packages/arch/bot-hooks/ @catee @Tecvan-fe @soonco
|
||||
/packages/arch/bot-hooks/src/page-jump/ @evan-crash @catee
|
||||
/packages/arch/bot-hooks-adapter/ @catee @Tecvan-fe @soonco
|
||||
/packages/arch/bot-hooks-base/ @catee @Tecvan-fe @soonco
|
||||
/packages/arch/responsive-kit/ @Tecvan-fe @DingGao-Devin
|
||||
/packages/common/chat-area/chat-area/ @Hezi-crypto @haozhenfei @evan-crash @haozhenfei
|
||||
/packages/data/memory/llm-plugins/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/common/reporter/ @soonco @catee @evan-crash
|
||||
/packages/components/json-viewer/ @duwenhan2byte
|
||||
/packages/components/scroll-view/ @evan-crash
|
||||
/packages/common/assets/ @Tecvan-fe @catee
|
||||
/packages/common/biz-components/ @duwenhan2byte
|
||||
/packages/data/common/e2e/ @soonco @catee @evan-crash @haozhenfei @duwenhan2byte
|
||||
/packages/agent-ide/debug-tool-list/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/model-manager/ @Hezi-crypto @catee
|
||||
/packages/agent-ide/model-manager/src/components/multi-agent/ @catee
|
||||
/packages/agent-ide/tool/ @catee
|
||||
/packages/data/knowledge/knowledge-modal-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/components/biz-tooltip-ui/ @Hezi-crypto @catee @evan-crash
|
||||
/packages/components/table-view/ @lihuiwen
|
||||
/packages/components/virtual-list/ @Tecvan-fe
|
||||
/packages/data/common/utils/ @soonco @catee @evan-crash
|
||||
/packages/data/knowledge/knowledge-resource-processor-core/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/arch/pdfjs-shadow/ @Tecvan-fe
|
||||
/packages/data/knowledge/common/stores/ @soonco @catee @evan-crash
|
||||
/packages/foundation/global-store/ @duwenhan2byte @evan-crash
|
||||
/config/postcss-config/ @Tecvan-fe
|
||||
/config/tailwind-config/ @Tecvan-fe
|
||||
/infra/utils/monorepo-kits/ @Tecvan-fe @evan-crash
|
||||
/packages/studio/premium/premium-components-adapter/ @evan-crash
|
||||
/packages/studio/premium/premium-store-adapter/ @evan-crash
|
||||
/packages/agent-ide/onboarding/ @Hezi-crypto @catee
|
||||
/packages/agent-ide/publish-to-base/ @catee
|
||||
/packages/arch/report-tti/ @duwenhan2byte
|
||||
/packages/data/memory/database-creator/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/arch/hooks/ @Tecvan-fe @evan-crash
|
||||
/packages/common/coze-mitt/ @evan-crash @duwenhan2byte
|
||||
/packages/common/editor-plugins/ @haozhenfei @stream-pipe @Hezi-crypto
|
||||
/packages/common/md-editor-adapter/ @haozhenfei @Hezi-crypto @catee
|
||||
/packages/common/prompt-kit/main/ @haozhenfei @Hezi-crypto @catee
|
||||
/packages/common/chat-area/chat-answer-action/ @Hezi-crypto @haozhenfei @lihuiwen
|
||||
/packages/common/chat-area/plugin-message-grab/ @Hezi-crypto @haozhenfei
|
||||
/packages/common/chat-area/text-grab/ @Hezi-crypto @haozhenfei
|
||||
/packages/common/prompt-kit/adapter/ @haozhenfei @Hezi-crypto @catee
|
||||
/packages/common/prompt-kit/base/ @haozhenfei @Hezi-crypto @catee
|
||||
/packages/data/memory/database/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/knowledge/knowledge-resource-processor-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/arch/utils/ @Tecvan-fe @evan-crash
|
||||
/packages/data/knowledge/common/components/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/common/feature-register/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/knowledge/common/hooks/ @Hezi-crypto @catee @evan-crash
|
||||
/packages/data/knowledge/common/services/ @Hezi-crypto @catee @evan-crash
|
||||
/packages/data/memory/database-v2-main/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/memory/database-v2-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/memory/database-v2-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/knowledge/knowledge-data-set-for-agent/ @Hezi-crypto @catee @evan-crash
|
||||
/packages/data/knowledge/knowledge-ide-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/arch/bot-monaco-editor/ @Tecvan-fe
|
||||
/packages/data/knowledge/knowledge-modal-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/knowledge/knowledge-resource-processor-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/devops/debug/debug-panel/ @soonco @evan-crash @catee
|
||||
/packages/devops/json-link-preview/ @Maidang1 @Zhangchi123456
|
||||
/packages/devops/common-modules/ @duwenhan2byte @evan-crash @catee
|
||||
/packages/foundation/account-adapter/ @duwenhan2byte @evan-crash
|
||||
/packages/foundation/account-base/ @evan-crash @duwenhan2byte
|
||||
/packages/arch/api-schema/ @Tecvan-fe @evan-crash
|
||||
/infra/idl/idl2ts-runtime/ @Tecvan-fe @evan-crash
|
||||
/infra/idl/idl2ts-cli/ @Tecvan-fe @evan-crash
|
||||
/infra/idl/idl2ts-generator/ @Tecvan-fe @evan-crash
|
||||
/infra/idl/idl-parser/ @Tecvan-fe @evan-crash
|
||||
/infra/utils/rush-logger/ @catee @Tecvan-fe
|
||||
/infra/idl/idl2ts-helper/ @Tecvan-fe @evan-crash
|
||||
/infra/idl/idl2ts-plugin/ @Tecvan-fe @evan-crash
|
||||
/packages/studio/open-platform/open-env-adapter/ @soonco @Hezi-crypto @DingGao-Devin
|
||||
/infra/plugins/pkg-root-webpack-plugin/ @Tecvan-fe
|
||||
/packages/studio/publish-manage-hooks/ @duwenhan2byte @evan-crash
|
||||
/packages/foundation/layout/ @evan-crash @duwenhan2byte
|
||||
/packages/studio/open-platform/open-auth/ @evan-crash @DingGao-Devin
|
||||
/packages/agent-ide/entry-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/entry/ @soonco @duwenhan2byte @catee @evan-crash
|
||||
/packages/agent-ide/bot-config-area-adapter/ @haozhenfei @Hezi-crypto @duwenhan2byte @catee @evan-crash
|
||||
/packages/agent-ide/bot-config-area/ @haozhenfei @Hezi-crypto @duwenhan2byte @catee @evan-crash
|
||||
/packages/agent-ide/bot-plugin/entry/ @evan-crash @lihuiwen @catee
|
||||
/packages/agent-ide/bot-plugin/export/ @lihuiwen @catee
|
||||
/packages/agent-ide/bot-plugin/mock-set/ @lihuiwen @catee @duwenhan2byte
|
||||
/packages/studio/mockset-edit-modal-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/studio/mockset-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/studio/mockset-editor/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/studio/mockset-editor-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/bot-plugin/tools/ @lihuiwen @catee
|
||||
/packages/studio/stores/bot-plugin/ @lihuiwen @Hezi-crypto @catee
|
||||
/packages/studio/plugin-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/plugin-modal-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/plugin-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/community/component/ @DingGao-Devin @Hezi-crypto @evan-crash @duwenhan2byte
|
||||
/packages/studio/plugin-form-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/workflow/base/ @xiamidaxia @zxhfighter
|
||||
/packages/agent-ide/plugin-content-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/plugin-content/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/plugin-setting-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/plugin-setting/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/bot-plugin/plugin-risk-warning/ @catee @evan-crash
|
||||
/packages/studio/plugin-publish-ui-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/studio/plugin-tool-columns-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/studio/plugin-tool-columns/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/chat-debug-area/ @soonco @duwenhan2byte @catee @Hezi-crypto @haozhenfei @evan-crash
|
||||
/packages/agent-ide/chat-answer-action-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/chat-area-plugin-debug-common/ @Hezi-crypto @haozhenfei
|
||||
/packages/agent-ide/chat-components-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/common/chat-area/plugin-chat-background/ @Tecvan-fe
|
||||
/packages/common/chat-area/chat-area-plugin-reasoning/ @catee @Hezi-crypto
|
||||
/packages/common/chat-area/plugin-resume/ @Tecvan-fe
|
||||
/packages/common/chat-area/plugin-chat-shortcuts/ @haozhenfei @duwenhan2byte @Hezi-crypto
|
||||
/packages/workflow/sdk/ @zxhfighter @xiamidaxia
|
||||
/packages/workflow/components/ @LLLLeeJ @zxhfighter
|
||||
/packages/components/loading-button/ @catee
|
||||
/packages/components/mouse-pad-selector/ @zxhfighter
|
||||
/packages/workflow/adapter/resources/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/packages/common/chat-area/chat-workflow-render/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/onboarding-message-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/plugin-area-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/prompt-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/prompt/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/workflow/ @soonco @duwenhan2byte @catee
|
||||
/packages/agent-ide/navigate/ @soonco @duwenhan2byte @catee
|
||||
/packages/agent-ide/workflow-as-agent-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/workflow-item/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/workflow-card-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/workflow-modal/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/memory-tool-pane-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/skills-pane-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/layout-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/layout/ @soonco @duwenhan2byte @catee
|
||||
/packages/agent-ide/chat-area-provider-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/agent-ide/chat-area-provider/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/studio/entity-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/foundation/account-ui-adapter/ @duwenhan2byte @evan-crash
|
||||
/packages/foundation/account-ui-base/ @evan-crash @duwenhan2byte
|
||||
/packages/foundation/foundation-sdk/ @evan-crash @duwenhan2byte
|
||||
/packages/foundation/global/ @evan-crash @duwenhan2byte
|
||||
/packages/studio/workspace/project-entity-adapter/ @Hezi-crypto @catee @duwenhan2byte
|
||||
/packages/studio/workspace/project-entity-base/ @Hezi-crypto @catee @duwenhan2byte
|
||||
/packages/foundation/global-adapter/ @evan-crash @duwenhan2byte
|
||||
/packages/foundation/browser-upgrade-banner/ @evan-crash @duwenhan2byte
|
||||
/packages/foundation/space-ui-adapter/ @evan-crash @duwenhan2byte
|
||||
/packages/foundation/space-ui-base/ @evan-crash @duwenhan2byte
|
||||
/packages/common/auth/ @evan-crash @duwenhan2byte
|
||||
/packages/common/auth-adapter/ @evan-crash @duwenhan2byte
|
||||
/packages/project-ide/main/ @dragooncjw @JxJuly @xiamidaxia @catee @lihuiwen
|
||||
/packages/components/resource-tree/ @dragooncjw @xiamidaxia @JxJuly
|
||||
/packages/common/flowgram-adapter/fixed-layout-editor/ @zxhfighter @xiamidaxia @dragooncjw
|
||||
/packages/project-ide/biz-components/ @zxhfighter @xiamidaxia
|
||||
/packages/project-ide/framework/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/packages/project-ide/base-adapter/ @dragooncjw @xiamidaxia
|
||||
/packages/project-ide/base-interface/ @dragooncjw @xiamidaxia
|
||||
/packages/project-ide/client/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/packages/project-ide/core/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/packages/project-ide/view/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/packages/project-ide/biz-data/ @haozhenfei @lihuiwen @catee @soonco
|
||||
/packages/data/knowledge/knowledge-ide-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/data/memory/variables/ @haozhenfei @catee @Hezi-crypto
|
||||
/packages/project-ide/biz-plugin/ @xiamidaxia @lihuiwen @catee
|
||||
/packages/project-ide/biz-plugin-registry-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/packages/project-ide/biz-workflow/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/packages/studio/open-platform/open-chat/ @soonco @Hezi-crypto @DingGao-Devin
|
||||
/packages/workflow/playground/ @LLLLeeJ @xiamidaxia @luics @zxhfighter
|
||||
/packages/arch/load-remote-worker/ @Tecvan-fe
|
||||
/packages/devops/mockset-manage/ @soonco @evan-crash @catee
|
||||
/packages/devops/testset-manage/ @mocayo @JxJuly
|
||||
/packages/workflow/adapter/base/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/packages/workflow/adapter/code-editor/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/packages/workflow/fabric-canvas/ @xiamidaxia @zxhfighter
|
||||
/packages/workflow/feature-encapsulate/ @zxhfighter
|
||||
/packages/workflow/nodes/ @xiamidaxia @zxhfighter
|
||||
/packages/workflow/setters/ @Tecvan-fe
|
||||
/packages/workflow/variable/ @zxhfighter @LLLLeeJ @xiamidaxia
|
||||
/packages/workflow/render/ @dragooncjw @xiamidaxia
|
||||
/packages/workflow/history/ @xiamidaxia @zxhfighter
|
||||
/packages/workflow/adapter/nodes/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/packages/workflow/test-run/ @JxJuly @xiamidaxia @luics @zxhfighter @dragooncjw
|
||||
/packages/workflow/test-run-next/main/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/packages/workflow/test-run-next/form/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/packages/workflow/test-run-next/shared/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/packages/workflow/test-run-next/trace/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/packages/project-ide/ui-adapter/ @dragooncjw @xiamidaxia
|
||||
/packages/studio/workspace/project-publish/ @catee @lihuiwen
|
||||
/packages/studio/workspace/entry-adapter/ @duwenhan2byte @evan-crash
|
||||
/packages/studio/workspace/entry-base/ @duwenhan2byte @catee @evan-crash
|
||||
/packages/workflow/adapter/playground/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/infra/plugins/import-watch-loader/ @Tecvan-fe
|
||||
/config/rsbuild-config/ @Tecvan-fe
|
||||
/packages/community/explore/ @evan-crash @duwenhan2byte
|
||||
/common/_templates/node-core/ @Tecvan-fe
|
||||
/common/_templates/rspack-web/ @Tecvan-fe
|
||||
/frontend/apps/coze-studio/ @Tecvan-fe @evan-crash @duwenhan2byte
|
||||
/frontend/packages/agent-ide/agent-publish/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei @catee
|
||||
/frontend/packages/agent-ide/commons/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/arch/bot-api/ @Tecvan-fe
|
||||
/frontend/packages/arch/bot-http/ @Tecvan-fe
|
||||
/frontend/packages/arch/logger/ @Tecvan-fe
|
||||
/frontend/packages/arch/slardar-interface/ @Tecvan-fe @evan-crash
|
||||
/frontend/config/eslint-config/ @Tecvan-fe @leeight @soonco
|
||||
/frontend/infra/eslint-plugin/ @Tecvan-fe
|
||||
/frontend/config/ts-config/ @leeight @Tecvan-fe
|
||||
/frontend/config/vitest-config/ @Tecvan-fe
|
||||
/frontend/packages/arch/bot-env/ @Tecvan-fe @leeight
|
||||
/frontend/packages/arch/bot-env-adapter/ @dragooncjw @Tecvan-fe @leeight
|
||||
/frontend/packages/arch/bot-typings/ @Tecvan-fe
|
||||
/frontend/packages/arch/web-context/ @Tecvan-fe
|
||||
/frontend/packages/components/bot-semi/ @Tecvan-fe
|
||||
/frontend/packages/components/bot-icons/ @DingGao-Devin
|
||||
/frontend/packages/arch/i18n/ @Tecvan-fe @leeight
|
||||
/frontend/packages/arch/resources/studio-i18n-resource/ @dragooncjw @Tecvan-fe
|
||||
/frontend/config/stylelint-config/ @Tecvan-fe
|
||||
/frontend/packages/arch/idl/ @Tecvan-fe
|
||||
/frontend/infra/utils/fs-enhance/ @Tecvan-fe
|
||||
/frontend/packages/arch/bot-store/ @Tecvan-fe @catee @duwenhan2byte
|
||||
/frontend/packages/arch/bot-error/ @haozhenfei @duwenhan2byte
|
||||
/frontend/packages/foundation/space-store/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/arch/bot-flags/ @Tecvan-fe
|
||||
/frontend/packages/arch/report-events/ @Tecvan-fe
|
||||
/frontend/packages/foundation/enterprise-store-adapter/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/foundation/local-storage/ @duwenhan2byte @evan-crash
|
||||
/frontend/packages/foundation/space-store-adapter/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/arch/bot-tea/ @Tecvan-fe @catee @soonco
|
||||
/frontend/packages/arch/tea/ @Tecvan-fe @evan-crash @soonco
|
||||
/frontend/packages/arch/tea-adapter/ @dragooncjw @Tecvan-fe
|
||||
/frontend/packages/arch/tea-interface/ @dragooncjw @Tecvan-fe
|
||||
/frontend/packages/studio/stores/bot-detail/ @Hezi-crypto @catee @DingGao-Devin @duwenhan2byte @evan-crash
|
||||
/frontend/packages/agent-ide/bot-input-length-limit/ @Hezi-crypto @catee @duwenhan2byte
|
||||
/frontend/packages/agent-ide/tool-config/ @haozhenfei @catee
|
||||
/frontend/packages/arch/bot-space-api/ @Tecvan-fe @duwenhan2byte
|
||||
/frontend/packages/arch/bot-utils/ @Tecvan-fe
|
||||
/frontend/packages/common/uploader-adapter/ @dragooncjw @Tecvan-fe
|
||||
/frontend/packages/common/uploader-interface/ @dragooncjw @Tecvan-fe
|
||||
/frontend/packages/studio/user-store/ @duwenhan2byte @catee @lihuiwen
|
||||
/frontend/packages/arch/foundation-sdk/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/common/chat-area/chat-core/ @haozhenfei @Hezi-crypto @evan-crash
|
||||
/frontend/packages/common/chat-area/utils/ @Hezi-crypto @haozhenfei
|
||||
/frontend/packages/arch/bot-md-box-adapter/ @Hezi-crypto @iu1340 @dragooncjw @Tecvan-fe
|
||||
/frontend/packages/studio/common/file-kit/ @haozhenfei @evan-crash
|
||||
/frontend/packages/arch/slardar-adapter/ @Tecvan-fe @dragooncjw
|
||||
/frontend/packages/arch/default-slardar/ @Tecvan-fe @evan-crash
|
||||
/frontend/packages/arch/fetch-stream/ @Hezi-crypto @haozhenfei
|
||||
/frontend/packages/common/websocket-manager-adapter/ @haozhenfei @Hezi-crypto @catee
|
||||
/frontend/packages/studio/autosave/ @catee
|
||||
/frontend/packages/studio/bot-utils/ @catee @soonco @Hezi-crypto
|
||||
/frontend/packages/common/flowgram-adapter/common/ @zxhfighter @xiamidaxia @dragooncjw
|
||||
/frontend/packages/common/flowgram-adapter/free-layout-editor/ @zxhfighter @xiamidaxia @dragooncjw
|
||||
/frontend/packages/agent-ide/space-bot/ @soonco @evan-crash @duwenhan2byte @catee @DingGao-Devin
|
||||
/frontend/packages/agent-ide/space-bot/src/store/bot-list-filter/ @duwenhan2byte @lihuiwen
|
||||
/frontend/packages/agent-ide/space-bot/src/store/bot-page/ @DingGao-Devin
|
||||
/frontend/packages/agent-ide/space-bot/src/store/explore/ @Tecvan-fe
|
||||
/frontend/packages/agent-ide/space-bot/src/store/risk-warning/ @lihuiwen @catee
|
||||
/frontend/packages/agent-ide/context/ @evan-crash
|
||||
/frontend/packages/agent-ide/bot-editor-context-store/ @Hezi-crypto @duwenhan2byte @catee
|
||||
/frontend/packages/agent-ide/chat-background/ @catee
|
||||
/frontend/packages/agent-ide/chat-background-config-content-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/chat-background-config-content/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/chat-background-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/common/chat-area/chat-uikit/ @catee @Hezi-crypto @evan-crash @haozhenfei
|
||||
/frontend/packages/common/chat-area/hooks/ @Hezi-crypto @evan-crash
|
||||
/frontend/packages/common/chat-area/chat-uikit-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/bot-audit-adapter/ @evan-crash @duwenhan2byte @Hezi-crypto @haozhenfei
|
||||
/frontend/packages/agent-ide/bot-audit-base/ @evan-crash @duwenhan2byte @Hezi-crypto @haozhenfei
|
||||
/frontend/packages/studio/components/ @soonco @evan-crash @duwenhan2byte @catee
|
||||
/frontend/packages/arch/bot-hooks/ @catee @Tecvan-fe @soonco
|
||||
/frontend/packages/arch/bot-hooks/src/page-jump/ @evan-crash @catee
|
||||
/frontend/packages/arch/bot-hooks-adapter/ @catee @Tecvan-fe @soonco
|
||||
/frontend/packages/arch/bot-hooks-base/ @catee @Tecvan-fe @soonco
|
||||
/frontend/packages/arch/responsive-kit/ @Tecvan-fe @DingGao-Devin
|
||||
/frontend/packages/common/chat-area/chat-area/ @Hezi-crypto @haozhenfei @evan-crash @haozhenfei
|
||||
/frontend/packages/data/memory/llm-plugins/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/common/reporter/ @soonco @catee @evan-crash
|
||||
/frontend/packages/components/json-viewer/ @duwenhan2byte
|
||||
/frontend/packages/components/scroll-view/ @evan-crash
|
||||
/frontend/packages/common/assets/ @Tecvan-fe @catee
|
||||
/frontend/packages/common/biz-components/ @duwenhan2byte
|
||||
/frontend/packages/data/common/e2e/ @soonco @catee @evan-crash @haozhenfei @duwenhan2byte
|
||||
/frontend/packages/agent-ide/debug-tool-list/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/model-manager/ @Hezi-crypto @catee
|
||||
/frontend/packages/agent-ide/model-manager/src/components/multi-agent/ @catee
|
||||
/frontend/packages/agent-ide/tool/ @catee
|
||||
/frontend/packages/data/knowledge/knowledge-modal-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/components/biz-tooltip-ui/ @Hezi-crypto @catee @evan-crash
|
||||
/frontend/packages/components/table-view/ @lihuiwen
|
||||
/frontend/packages/components/virtual-list/ @Tecvan-fe
|
||||
/frontend/packages/data/common/utils/ @soonco @catee @evan-crash
|
||||
/frontend/packages/data/knowledge/knowledge-resource-processor-core/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/arch/pdfjs-shadow/ @Tecvan-fe
|
||||
/frontend/packages/data/knowledge/common/stores/ @soonco @catee @evan-crash
|
||||
/frontend/packages/foundation/global-store/ @duwenhan2byte @evan-crash
|
||||
/frontend/config/postcss-config/ @Tecvan-fe
|
||||
/frontend/config/tailwind-config/ @Tecvan-fe
|
||||
/frontend/infra/utils/monorepo-kits/ @Tecvan-fe @evan-crash
|
||||
/frontend/packages/studio/premium/premium-components-adapter/ @evan-crash
|
||||
/frontend/packages/studio/premium/premium-store-adapter/ @evan-crash
|
||||
/frontend/packages/agent-ide/onboarding/ @Hezi-crypto @catee
|
||||
/frontend/packages/agent-ide/publish-to-base/ @catee
|
||||
/frontend/packages/arch/report-tti/ @duwenhan2byte
|
||||
/frontend/packages/data/memory/database-creator/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/arch/hooks/ @Tecvan-fe @evan-crash
|
||||
/frontend/packages/common/coze-mitt/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/common/editor-plugins/ @haozhenfei @stream-pipe @Hezi-crypto
|
||||
/frontend/packages/common/md-editor-adapter/ @haozhenfei @Hezi-crypto @catee
|
||||
/frontend/packages/common/prompt-kit/main/ @haozhenfei @Hezi-crypto @catee
|
||||
/frontend/packages/common/chat-area/chat-answer-action/ @Hezi-crypto @haozhenfei @lihuiwen
|
||||
/frontend/packages/common/chat-area/plugin-message-grab/ @Hezi-crypto @haozhenfei
|
||||
/frontend/packages/common/chat-area/text-grab/ @Hezi-crypto @haozhenfei
|
||||
/frontend/packages/common/prompt-kit/adapter/ @haozhenfei @Hezi-crypto @catee
|
||||
/frontend/packages/common/prompt-kit/base/ @haozhenfei @Hezi-crypto @catee
|
||||
/frontend/packages/data/memory/database/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/knowledge/knowledge-resource-processor-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/arch/utils/ @Tecvan-fe @evan-crash
|
||||
/frontend/packages/data/knowledge/common/components/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/common/feature-register/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/knowledge/common/hooks/ @Hezi-crypto @catee @evan-crash
|
||||
/frontend/packages/data/knowledge/common/services/ @Hezi-crypto @catee @evan-crash
|
||||
/frontend/packages/data/memory/database-v2-main/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/memory/database-v2-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/memory/database-v2-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/knowledge/knowledge-data-set-for-agent/ @Hezi-crypto @catee @evan-crash
|
||||
/frontend/packages/data/knowledge/knowledge-ide-base/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/arch/bot-monaco-editor/ @Tecvan-fe
|
||||
/frontend/packages/data/knowledge/knowledge-modal-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/knowledge/knowledge-resource-processor-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/devops/debug/debug-panel/ @soonco @evan-crash @catee
|
||||
/frontend/packages/devops/json-link-preview/ @Maidang1 @Zhangchi123456
|
||||
/frontend/packages/devops/common-modules/ @duwenhan2byte @evan-crash @catee
|
||||
/frontend/packages/foundation/account-adapter/ @duwenhan2byte @evan-crash
|
||||
/frontend/packages/foundation/account-base/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/arch/api-schema/ @Tecvan-fe @evan-crash
|
||||
/frontend/infra/idl/idl2ts-runtime/ @Tecvan-fe @evan-crash
|
||||
/frontend/infra/idl/idl2ts-cli/ @Tecvan-fe @evan-crash
|
||||
/frontend/infra/idl/idl2ts-generator/ @Tecvan-fe @evan-crash
|
||||
/frontend/infra/idl/idl-parser/ @Tecvan-fe @evan-crash
|
||||
/frontend/infra/utils/rush-logger/ @catee @Tecvan-fe
|
||||
/frontend/infra/idl/idl2ts-helper/ @Tecvan-fe @evan-crash
|
||||
/frontend/infra/idl/idl2ts-plugin/ @Tecvan-fe @evan-crash
|
||||
/frontend/packages/studio/open-platform/open-env-adapter/ @soonco @Hezi-crypto @DingGao-Devin
|
||||
/frontend/infra/plugins/pkg-root-webpack-plugin/ @Tecvan-fe
|
||||
/frontend/packages/studio/publish-manage-hooks/ @duwenhan2byte @evan-crash
|
||||
/frontend/packages/foundation/layout/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/studio/open-platform/open-auth/ @evan-crash @DingGao-Devin
|
||||
/frontend/packages/studio/open-platform/open-chat/ @tomasyu985 @DingGao-Devin
|
||||
/frontend/packages/agent-ide/entry-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/entry/ @soonco @duwenhan2byte @catee @evan-crash
|
||||
/frontend/packages/agent-ide/bot-config-area-adapter/ @haozhenfei @Hezi-crypto @duwenhan2byte @catee @evan-crash
|
||||
/frontend/packages/agent-ide/bot-config-area/ @haozhenfei @Hezi-crypto @duwenhan2byte @catee @evan-crash
|
||||
/frontend/packages/agent-ide/bot-plugin/entry/ @evan-crash @lihuiwen @catee
|
||||
/frontend/packages/agent-ide/bot-plugin/export/ @lihuiwen @catee
|
||||
/frontend/packages/agent-ide/bot-plugin/mock-set/ @lihuiwen @catee @duwenhan2byte
|
||||
/frontend/packages/studio/mockset-edit-modal-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/studio/mockset-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/studio/mockset-editor/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/studio/mockset-editor-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/bot-plugin/tools/ @lihuiwen @catee
|
||||
/frontend/packages/studio/stores/bot-plugin/ @lihuiwen @Hezi-crypto @catee
|
||||
/frontend/packages/studio/plugin-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/plugin-modal-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/plugin-shared/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/community/component/ @DingGao-Devin @Hezi-crypto @evan-crash @duwenhan2byte
|
||||
/frontend/packages/studio/plugin-form-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/workflow/base/ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/agent-ide/plugin-content-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/plugin-content/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/plugin-setting-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/plugin-setting/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/bot-plugin/plugin-risk-warning/ @catee @evan-crash
|
||||
/frontend/packages/studio/plugin-publish-ui-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/studio/plugin-tool-columns-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/studio/plugin-tool-columns/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/chat-debug-area/ @soonco @duwenhan2byte @catee @Hezi-crypto @haozhenfei @evan-crash
|
||||
/frontend/packages/agent-ide/chat-answer-action-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/chat-area-plugin-debug-common/ @Hezi-crypto @haozhenfei
|
||||
/frontend/packages/agent-ide/chat-components-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/common/chat-area/plugin-chat-background/ @Tecvan-fe
|
||||
/frontend/packages/common/chat-area/chat-area-plugin-reasoning/ @catee @Hezi-crypto
|
||||
/frontend/packages/common/chat-area/plugin-resume/ @Tecvan-fe
|
||||
/frontend/packages/common/chat-area/plugin-chat-shortcuts/ @haozhenfei @duwenhan2byte @Hezi-crypto
|
||||
/frontend/packages/workflow/sdk/ @zxhfighter @xiamidaxia
|
||||
/frontend/packages/workflow/components/ @LLLLeeJ @zxhfighter
|
||||
/frontend/packages/components/loading-button/ @catee
|
||||
/frontend/packages/components/mouse-pad-selector/ @zxhfighter
|
||||
/frontend/packages/workflow/adapter/resources/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/frontend/packages/common/chat-area/chat-workflow-render/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/onboarding-message-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/plugin-area-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/prompt-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/prompt/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/workflow/ @soonco @duwenhan2byte @catee
|
||||
/frontend/packages/agent-ide/navigate/ @soonco @duwenhan2byte @catee
|
||||
/frontend/packages/agent-ide/workflow-as-agent-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/workflow-item/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/workflow-card-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/workflow-modal/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/memory-tool-pane-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/skills-pane-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/layout-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/layout/ @soonco @duwenhan2byte @catee
|
||||
/frontend/packages/agent-ide/chat-area-provider-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/agent-ide/chat-area-provider/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/studio/entity-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/foundation/account-ui-adapter/ @duwenhan2byte @evan-crash
|
||||
/frontend/packages/foundation/account-ui-base/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/foundation/foundation-sdk/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/foundation/global/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/studio/workspace/project-entity-adapter/ @Hezi-crypto @catee @duwenhan2byte
|
||||
/frontend/packages/studio/workspace/project-entity-base/ @Hezi-crypto @catee @duwenhan2byte
|
||||
/frontend/packages/foundation/global-adapter/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/foundation/browser-upgrade-banner/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/foundation/space-ui-adapter/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/foundation/space-ui-base/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/common/auth/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/common/auth-adapter/ @evan-crash @duwenhan2byte
|
||||
/frontend/packages/project-ide/main/ @dragooncjw @JxJuly @xiamidaxia @catee @lihuiwen
|
||||
/frontend/packages/components/resource-tree/ @dragooncjw @xiamidaxia @JxJuly
|
||||
/frontend/packages/common/flowgram-adapter/fixed-layout-editor/ @zxhfighter @xiamidaxia @dragooncjw
|
||||
/frontend/packages/project-ide/biz-components/ @zxhfighter @xiamidaxia
|
||||
/frontend/packages/project-ide/framework/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/frontend/packages/project-ide/base-adapter/ @dragooncjw @xiamidaxia
|
||||
/frontend/packages/project-ide/base-interface/ @dragooncjw @xiamidaxia
|
||||
/frontend/packages/project-ide/client/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/frontend/packages/project-ide/core/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/frontend/packages/project-ide/view/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/frontend/packages/project-ide/biz-data/ @haozhenfei @lihuiwen @catee @soonco
|
||||
/frontend/packages/data/knowledge/knowledge-ide-adapter/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/data/memory/variables/ @haozhenfei @catee @Hezi-crypto
|
||||
/frontend/packages/project-ide/biz-plugin/ @xiamidaxia @lihuiwen @catee
|
||||
/frontend/packages/project-ide/biz-plugin-registry-adapter/ @Hezi-crypto @duwenhan2byte @catee @evan-crash @haozhenfei
|
||||
/frontend/packages/project-ide/biz-workflow/ @dragooncjw @JxJuly @xiamidaxia
|
||||
/frontend/packages/studio/open-platform/open-chat/ @soonco @Hezi-crypto @DingGao-Devin
|
||||
/frontend/packages/workflow/playground/ @LLLLeeJ @xiamidaxia @luics @zxhfighter
|
||||
/frontend/packages/arch/load-remote-worker/ @Tecvan-fe
|
||||
/frontend/packages/devops/mockset-manage/ @soonco @evan-crash @catee
|
||||
/frontend/packages/devops/testset-manage/ @mocayo @JxJuly
|
||||
/frontend/packages/workflow/adapter/base/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/frontend/packages/workflow/adapter/code-editor/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/frontend/packages/workflow/fabric-canvas/ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/workflow/feature-encapsulate/ @zxhfighter
|
||||
/frontend/packages/workflow/nodes/ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/workflow/setters/ @Tecvan-fe
|
||||
/frontend/packages/workflow/variable/ @zxhfighter @LLLLeeJ @xiamidaxia
|
||||
/frontend/packages/workflow/render/ @dragooncjw @xiamidaxia
|
||||
/frontend/packages/workflow/history/ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/workflow/adapter/nodes/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/frontend/packages/workflow/test-run/ @JxJuly @xiamidaxia @luics @zxhfighter @dragooncjw
|
||||
/frontend/packages/workflow/test-run-next/main/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/workflow/test-run-next/form/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/workflow/test-run-next/shared/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/workflow/test-run-next/trace/ @JxJuly @LLLLeeJ @xiamidaxia @zxhfighter
|
||||
/frontend/packages/project-ide/ui-adapter/ @dragooncjw @xiamidaxia
|
||||
/frontend/packages/studio/workspace/project-publish/ @catee @lihuiwen
|
||||
/frontend/packages/studio/workspace/entry-adapter/ @duwenhan2byte @evan-crash
|
||||
/frontend/packages/studio/workspace/entry-base/ @duwenhan2byte @catee @evan-crash
|
||||
/frontend/packages/workflow/adapter/playground/ @LLLLeeJ @JxJuly @xiamidaxia @luics @zxhfighter @stream-pipe
|
||||
/frontend/infra/plugins/import-watch-loader/ @Tecvan-fe
|
||||
/frontend/config/rsbuild-config/ @Tecvan-fe
|
||||
/frontend/packages/community/explore/ @evan-crash @duwenhan2byte
|
||||
/frontend/common/_templates/node-core/ @Tecvan-fe
|
||||
/frontend/common/_templates/rspack-web/ @Tecvan-fe
|
||||
|
||||
|
||||
/backend/ @fanlv @junwen-lee @liuyunchao-1998 @lvxinyu-1117 @hi-pender @luohq-bytedance @shentongmartin @mrh997 @meguminnnnnnnnn @N3kox @zhuangjie1125
|
||||
/docker/ @fanlv @junwen-lee @liuyunchao-1998 @lvxinyu-1117 @hi-pender @luohq-bytedance @shentongmartin @mrh997 @meguminnnnnnnnn @N3kox @zhuangjie1125
|
||||
/helm/ @fanlv @junwen-lee @liuyunchao-1998 @lvxinyu-1117 @hi-pender @luohq-bytedance @shentongmartin @mrh997 @meguminnnnnnnnn @N3kox @zhuangjie1125
|
||||
@ -10,7 +10,6 @@ EXCLUDE_PATTERNS=(
|
||||
'packages/arch/bot-api/src/auto-generate/**'
|
||||
'apps/bot-op/src/services/bam-auto-generate/**'
|
||||
'apps/prompt-platform/src/services/auto-generate/**'
|
||||
".cursor/api/**"
|
||||
"**/lib/**"
|
||||
"**/.*/**"
|
||||
'**/__tests__/**'
|
||||
@ -24,9 +23,7 @@ EXCLUDE_PATTERNS=(
|
||||
'**/e2e/**'
|
||||
'common/changes/**'
|
||||
'apps/fornax/**',
|
||||
"packages/arch/semi-theme-hand01",
|
||||
"packages/arch/arco-icon",
|
||||
"packages/arch/resources/**"
|
||||
"packages/arch/semi-theme-hand01"
|
||||
)
|
||||
|
||||
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
|
||||
294
.github/workflows/ci.yml
vendored
Normal file
294
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,294 @@
|
||||
name: CI
|
||||
on:
|
||||
pull_request:
|
||||
branches: ['main']
|
||||
paths:
|
||||
- 'github/**'
|
||||
- 'idl/**'
|
||||
- 'frontend/**'
|
||||
- 'common/**'
|
||||
- 'rush.json'
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- NodeVersion: 22.16.0
|
||||
NodeVersionDisplayName: 22
|
||||
OS: ubuntu-latest
|
||||
name: Setup and Install Dependencies
|
||||
runs-on: ${{ matrix.OS }}
|
||||
outputs:
|
||||
cache_file: ${{ steps.process-files.outputs.cache_file }}
|
||||
matrix_node_version: ${{ matrix.NodeVersion }}
|
||||
matrix_os: ${{ matrix.OS }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v45
|
||||
|
||||
- name: Process changed files
|
||||
id: process-files
|
||||
run: |
|
||||
# 获取所有变更文件
|
||||
all_files="${{ steps.changed-files.outputs.all_changed_files }}"
|
||||
|
||||
# 过滤掉 common/changes 目录下的文件
|
||||
filtered_files=""
|
||||
for file in $all_files; do
|
||||
if [[ ! "$file" =~ ^common/changes/.* ]]; then
|
||||
if [ -z "$filtered_files" ]; then
|
||||
filtered_files="$file"
|
||||
else
|
||||
filtered_files="$filtered_files $file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 创建 JSON 格式的缓存文件
|
||||
echo "[$( echo "$filtered_files" | sed 's/ /", "/g' | sed 's/^/"/' | sed 's/$/"/' )]" > changed-files-cache.json
|
||||
|
||||
# 输出缓存文件路径供后续步骤使用
|
||||
echo "cache_file=changed-files-cache.json" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "过滤前文件数量: $(echo $all_files | wc -w)"
|
||||
echo "过滤后文件数量: $(echo $filtered_files | wc -w)"
|
||||
echo "已生成缓存文件: changed-files-cache.json"
|
||||
|
||||
- name: Config Git User
|
||||
# should be turn to ci user
|
||||
run: |
|
||||
git config --local user.name "flow_bot"
|
||||
git config --local user.email "flow_bot@bytedance.com"
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.NodeVersion }}
|
||||
|
||||
- name: Upload changed files cache
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: changed-files-cache
|
||||
path: changed-files-cache.json
|
||||
retention-days: 1
|
||||
|
||||
build:
|
||||
needs: setup
|
||||
runs-on: ${{ needs.setup.outputs.matrix_os }}
|
||||
name: Increment Build
|
||||
env:
|
||||
BUILD_BRANCH: ${{ github.head_ref || github.ref_name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ needs.setup.outputs.matrix_node_version }}
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
common/temp/pnpm-local
|
||||
common/temp/pnpm-store
|
||||
common/temp/install-run
|
||||
key: ${{ runner.os }}-rush-store-${{ hashFiles('common/config/subspaces/**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-rush-store-main
|
||||
${{ runner.os }}-rush-store
|
||||
|
||||
- name: Download changed files cache
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: changed-files-cache
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libasound2-dev
|
||||
node common/scripts/install-run-rush.js install --to tag:core
|
||||
node common/scripts/install-run-rush.js update-autoinstaller --name plugins
|
||||
node common/scripts/install-run-rush.js increment --action install -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
- name: Increment Build
|
||||
run: node common/scripts/install-run-rush.js increment --action build -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
test:
|
||||
needs: setup
|
||||
runs-on: ${{ needs.setup.outputs.matrix_os }}
|
||||
name: Increment Test Coverage
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ needs.setup.outputs.matrix_node_version }}
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
common/temp/pnpm-local
|
||||
common/temp/pnpm-store
|
||||
common/temp/install-run
|
||||
key: ${{ runner.os }}-rush-store-${{ hashFiles('common/config/subspaces/**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-rush-store-main
|
||||
${{ runner.os }}-rush-store
|
||||
|
||||
- name: Download changed files cache
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: changed-files-cache
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libasound2-dev
|
||||
node common/scripts/install-run-rush.js install --to tag:core
|
||||
node common/scripts/install-run-rush.js update-autoinstaller --name plugins
|
||||
node common/scripts/install-run-rush.js increment --action install -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
- name: Increment Test:cov
|
||||
run: node common/scripts/install-run-rush.js increment --action test:cov -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
- name: Upload coverage reports
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
|
||||
lint:
|
||||
needs: setup
|
||||
runs-on: ${{ needs.setup.outputs.matrix_os }}
|
||||
name: Increment Lint
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ needs.setup.outputs.matrix_node_version }}
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
common/temp/pnpm-local
|
||||
common/temp/pnpm-store
|
||||
common/temp/install-run
|
||||
key: ${{ runner.os }}-rush-store-${{ hashFiles('common/config/subspaces/**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-rush-store-main
|
||||
${{ runner.os }}-rush-store
|
||||
|
||||
- name: Download changed files cache
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: changed-files-cache
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libasound2-dev
|
||||
node common/scripts/install-run-rush.js install --to tag:core
|
||||
node common/scripts/install-run-rush.js update-autoinstaller --name plugins
|
||||
node common/scripts/install-run-rush.js increment --action install -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
- name: Increment Lint
|
||||
run: node common/scripts/install-run-rush.js increment --action lint -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
ts-check:
|
||||
needs: setup
|
||||
runs-on: ${{ needs.setup.outputs.matrix_os }}
|
||||
name: Increment TS Check
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ needs.setup.outputs.matrix_node_version }}
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
common/temp/pnpm-local
|
||||
common/temp/pnpm-store
|
||||
common/temp/install-run
|
||||
key: ${{ runner.os }}-rush-store-${{ hashFiles('common/config/subspaces/**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-rush-store-main
|
||||
${{ runner.os }}-rush-store
|
||||
|
||||
- name: Download changed files cache
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: changed-files-cache
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libasound2-dev
|
||||
node common/scripts/install-run-rush.js install --to tag:core
|
||||
node common/scripts/install-run-rush.js update-autoinstaller --name plugins
|
||||
node common/scripts/install-run-rush.js increment --action install -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
- name: Increment TS Check
|
||||
run: node common/scripts/install-run-rush.js increment --action ts-check -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
package-audit:
|
||||
needs: setup
|
||||
runs-on: ${{ needs.setup.outputs.matrix_os }}
|
||||
name: Increment Package Audit
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ needs.setup.outputs.matrix_node_version }}
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
common/temp/pnpm-local
|
||||
common/temp/pnpm-store
|
||||
common/temp/install-run
|
||||
key: ${{ runner.os }}-rush-store-${{ hashFiles('common/config/subspaces/**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-rush-store-main
|
||||
${{ runner.os }}-rush-store
|
||||
|
||||
- name: Download changed files cache
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: changed-files-cache
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libasound2-dev
|
||||
node common/scripts/install-run-rush.js install --to tag:core
|
||||
node common/scripts/install-run-rush.js update-autoinstaller --name plugins
|
||||
node common/scripts/install-run-rush.js increment --action install -p "${{ needs.setup.outputs.cache_file }}"
|
||||
|
||||
- name: Increment Package Audit
|
||||
run: node common/scripts/install-run-rush.js increment --action package-audit -p "${{ needs.setup.outputs.cache_file }}"
|
||||
72
.github/workflows/ci@main.yml
vendored
Normal file
72
.github/workflows/ci@main.yml
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
# should be optimize as increment build & test
|
||||
name: CI@main
|
||||
on:
|
||||
push:
|
||||
# test only
|
||||
branches: ['main',"chore/setup-ci"]
|
||||
paths:
|
||||
- 'github/**'
|
||||
- 'idl/**'
|
||||
- 'frontend/**'
|
||||
- 'common/**'
|
||||
- 'rush.json'
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- NodeVersion: 22.16.0
|
||||
NodeVersionDisplayName: 22
|
||||
OS: ubuntu-latest
|
||||
name: Node.js v${{ matrix.NodeVersionDisplayName }} (${{ matrix.OS }})
|
||||
runs-on: ${{ matrix.OS }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Config Git User
|
||||
# should be turn to ci user
|
||||
run: |
|
||||
git config --local user.name "flow_bot"
|
||||
git config --local user.email "flow_bot@bytedance.com"
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.NodeVersion }}
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
common/temp/pnpm-local
|
||||
common/temp/pnpm-store
|
||||
common/temp/install-run
|
||||
key: ${{ runner.os }}-rush-store-main
|
||||
restore-keys: |
|
||||
${{ runner.os }}-rush-store-main
|
||||
${{ runner.os }}-rush-store
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libasound2-dev
|
||||
node common/scripts/install-run-rush.js install
|
||||
|
||||
- name: Build all
|
||||
run: node common/scripts/install-run-rush.js build --verbose
|
||||
|
||||
- name: Test:cov all
|
||||
run: node common/scripts/install-run-rush.js test:cov --verbose
|
||||
|
||||
- name: Upload coverage reports
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
|
||||
- name: Lint all
|
||||
run: node common/scripts/install-run-rush.js lint --verbose
|
||||
45
.github/workflows/common-pr-checks.yml
vendored
Normal file
45
.github/workflows/common-pr-checks.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
name: PR Common Checks
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'github/**'
|
||||
- 'idl/**'
|
||||
- 'frontend/**'
|
||||
- 'common/**'
|
||||
- 'rush.json'
|
||||
types: [opened, edited, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
common-checks:
|
||||
name: PR Common Checks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Config Git User
|
||||
run: |
|
||||
git config --local user.name "flow_bot"
|
||||
git config --local user.email "flow_bot@bytedance.com"
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.16.0
|
||||
|
||||
- name: Install Dependencies
|
||||
run: node common/scripts/install-run-rush.js install
|
||||
|
||||
# PR Title Format Check
|
||||
- name: Check PR Title Format
|
||||
if: ${{ !contains(github.event.pull_request.title, 'WIP') && !contains(github.event.pull_request.title, 'wip') }}
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
run: |
|
||||
node common/scripts/install-run-rush.js update-autoinstaller --name rush-commitlint && \
|
||||
pushd common/autoinstallers/rush-commitlint && \
|
||||
echo "$PR_TITLE" | npx commitlint --config commitlint.config.js && \
|
||||
popd
|
||||
|
||||
# Add more common checks here
|
||||
# For example: file size checks, specific file format validations, etc.
|
||||
4
.github/workflows/semantic-pull-request.yaml
vendored
4
.github/workflows/semantic-pull-request.yaml
vendored
@ -57,6 +57,8 @@ jobs:
|
||||
model
|
||||
database
|
||||
foundation
|
||||
comment
|
||||
ci
|
||||
|
||||
# The pull request's title should be fulfilled the following pattern:
|
||||
#
|
||||
@ -65,5 +67,5 @@ jobs:
|
||||
# ... where valid types and scopes can be found above; for example:
|
||||
#
|
||||
# [fix][test] flaky test V1_ProxyAuthenticationTest.anonymousSocketTest
|
||||
headerPattern: '^\[(\w*?)\](?:\[(.*?)\])?(?:\s*)(.*)$'
|
||||
# headerPattern: '^\[(\w*?)\](?:\[(.*?)\])?(?:\s*)(.*)$'
|
||||
headerPatternCorrespondence: type, scope, subject
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -49,3 +49,6 @@ node_modules
|
||||
common/temp
|
||||
.rush
|
||||
.eslintcache
|
||||
|
||||
|
||||
backend/conf/model/*.yaml
|
||||
|
||||
2
AUTHORS
2
AUTHORS
@ -44,3 +44,5 @@ lingyibin.jason <lingyibin.jason@bytedance.com>
|
||||
chenchen.dabaishu <chenchen.dabaishu@bytedance.com>
|
||||
jiangxujin <jiangxujin@bytedance.com>
|
||||
huyongbiao <huyongbiao@bytedance.com>
|
||||
wenming.2020 <wenming.2020@bytedance.com>
|
||||
tanjizhen <tanjizhen@bytedance.com>
|
||||
|
||||
@ -28,7 +28,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
3. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) the coze-dev {project_name} repo.
|
||||
4. In your forked repository, make your changes in a new git branch:
|
||||
```
|
||||
git checkout -b my-fix-branch develop
|
||||
git checkout -b my-fix-branch main
|
||||
```
|
||||
5. Create your patch, including appropriate test cases.
|
||||
6. Follow our [Style Guides](#code-style-guides).
|
||||
@ -38,7 +38,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
```
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
9. In GitHub, send a pull request to `{project_name}:develop`
|
||||
9. In GitHub, send a pull request to `{project_name}:main`
|
||||
|
||||
## Contribution Prerequisites
|
||||
- Our development environment keeps up with [Go Official](https://golang.org/project/).
|
||||
|
||||
10
Makefile
10
Makefile
@ -13,6 +13,8 @@ MYSQL_SCHEMA := ./docker/volumes/mysql/schema.sql
|
||||
MYSQL_INIT_SQL := ./docker/volumes/mysql/sql_init.sql
|
||||
ENV_FILE := ./docker/.env
|
||||
STATIC_DIR := ./bin/resources/static
|
||||
ES_INDEX_SCHEMA := ./docker/volumes/elasticsearch/es_index_schema
|
||||
ES_SETUP_SCRIPT := ./docker/volumes/elasticsearch/setup_es.sh
|
||||
|
||||
debug: env middleware python server
|
||||
|
||||
@ -26,7 +28,7 @@ fe:
|
||||
@echo "Building frontend..."
|
||||
@bash $(BUILD_FE_SCRIPT)
|
||||
|
||||
server: env
|
||||
server: env setup_es_index
|
||||
@if [ ! -d "$(STATIC_DIR)" ]; then \
|
||||
echo "Static directory '$(STATIC_DIR)' not found, building frontend..."; \
|
||||
$(MAKE) fe; \
|
||||
@ -84,6 +86,11 @@ atlas-hash:
|
||||
@echo "Rehash atlas migration files..."
|
||||
@(cd ./docker/atlas && atlas migrate hash)
|
||||
|
||||
setup_es_index:
|
||||
@echo "Setting up Elasticsearch index..."
|
||||
@. $(ENV_FILE); \
|
||||
bash $(ES_SETUP_SCRIPT) --index-dir $(ES_INDEX_SCHEMA) --docker-host false --es-address "$$ES_ADDR"
|
||||
|
||||
help:
|
||||
@echo "Usage: make [target]"
|
||||
@echo ""
|
||||
@ -103,4 +110,5 @@ help:
|
||||
@echo " clean - Stop the docker containers and clean volumes."
|
||||
@echo " python - Setup python environment."
|
||||
@echo " atlas-hash - Rehash atlas migration files."
|
||||
@echo " setup_es_index - Setup elasticsearch index."
|
||||
@echo " help - Show this help message."
|
||||
|
||||
37
README.md
37
README.md
@ -17,12 +17,12 @@ English | [中文](README.zh_CN.md)
|
||||
|
||||
## What is Coze Studio?
|
||||
|
||||
[Coze Studio](https://www.coze.cn/home) is an all-in-one AI agent development tool. Providing the latest large models and tools, various development modes and frameworks, Coze Studio offers the most convenient AI agent development environment, from development to deployment. Tens of thousands of enterprises and millions of developers are using Coze Studio.
|
||||
[Coze Studio](https://www.coze.cn/home) is an all-in-one AI agent development tool. Providing the latest large models and tools, various development modes and frameworks, Coze Studio offers the most convenient AI agent development environment, from development to deployment.
|
||||
|
||||
* **Provides all core technologies needed for AI agent development**: prompt, RAG, plugin, workflow, enabling developers to focus on creating the core value of AI.
|
||||
* **Ready to use for professional AI agent development at the lowest cost**: Coze Studio provides developers with complete app templates and build frameworks, allowing you to quickly construct various AI agents and turn creative ideas into reality.
|
||||
|
||||
Coze Studio is the open-source version of ByteDance's new AI agent development platform **Coze**. Through Coze Studio's visual design and build tools, developers can quickly create and debug agents, apps, and workflows using no-code or low-code approaches, enabling powerful AI app development and more customized business logic. It's an ideal choice for building low-code AI products tailored . Coze Studio aims to lower the threshold for AI agent development and application, encouraging community co-construction and sharing for deeper exploration and practice in the AI field.
|
||||
Coze Studio, derived from the "Coze Development Platform" which has served tens of thousands of enterprises and millions of developers, we have made its core engine completely open. It is a one-stop visual development tool for AI Agents that makes creating, debugging, and deploying AI Agents unprecedentedly simple. Through Coze Studio's visual design and build tools, developers can quickly create and debug agents, apps, and workflows using no-code or low-code approaches, enabling powerful AI app development and more customized business logic. It's an ideal choice for building low-code AI products tailored . Coze Studio aims to lower the threshold for AI agent development and application, encouraging community co-construction and sharing for deeper exploration and practice in the AI field.
|
||||
|
||||
The backend of Coze Studio is developed using Golang, the frontend uses React + TypeScript, and the overall architecture is based on microservices and built following domain-driven design (DDD) principles. Provide developers with a high-performance, highly scalable, and easy-to-customize underlying framework to help them address complex business needs.
|
||||
## Feature list
|
||||
@ -72,8 +72,10 @@ Deployment steps:
|
||||
# Start the service
|
||||
cd docker
|
||||
cp .env.example .env
|
||||
docker compose --profile '*' up -d
|
||||
docker compose --profile "*" up -d
|
||||
```
|
||||
After the service starts, it is normal for the `coze-minio-setup` , `coze-mysql-setup-init-sql` , and `coze-mysql-setup-schema` containers to be in an exited state (exit 0). For common startup failure issues, **please refer to the [FAQ](https://github.com/coze-dev/coze-studio/wiki/9.-FAQ)**.
|
||||
4. After starting the service, you can open Coze Studio by accessing `http://localhost:8888/` through your browser.
|
||||
|
||||
|
||||
## Developer Guide
|
||||
@ -82,7 +84,7 @@ Deployment steps:
|
||||
* [Model Configuration](https://github.com/coze-dev/coze-studio/wiki/3.-Model-configuration): Before deploying the open-source version of Coze Studio, you must configure the model service. Otherwise, you cannot select models when building agents, workflows, and apps.
|
||||
* [Plugin Configuration](https://github.com/coze-dev/coze-studio/wiki/4.-Plugin-Configuration): To use official plugins from the plugin store, you must first configure the plugins and add the authentication keys for third-party services.
|
||||
* [Basic Component Configuration](https://github.com/coze-dev/coze-studio/wiki/5.-Basic-component-configuration): Learn how to configure components such as image uploaders to use functions like image uploading in Coze Studio .
|
||||
* [API Reference](https://github.com/coze-dev/coze-studio/wiki/6.-API-Reference): Unlike the commercial edition, the open-source version of Coze Studio only supports personal access token (PAT) authentication and supports APIs related to chat and workflows.
|
||||
* [API Reference](https://github.com/coze-dev/coze-studio/wiki/6.-API-Reference): The Coze Studio Community Edition API and Chat SDK are authenticated using Personal Access Token, providing APIs for conversations and workflows.
|
||||
* [Development Guidelines](https://github.com/coze-dev/coze-studio/wiki/7.-Development-Standards):
|
||||
* [Project Architecture](https://github.com/coze-dev/coze-studio/wiki/7.-Development-Standards#project-architecture): Learn about the technical architecture and core components of the open-source version of Coze Studio.
|
||||
* [Code Development and Testing](https://github.com/coze-dev/coze-studio/wiki/7.-Development-Standards#code-development-and-testing): Learn how to perform secondary development and testing based on the open-source version of Coze Studio.
|
||||
@ -106,14 +108,33 @@ We welcome community contributions. For contribution guidelines, please refer to
|
||||
## Security and privacy
|
||||
If you discover potential security issues in the project, or believe you may have found a security issue, please notify the ByteDance security team through our [security center](https://security.bytedance.com/src) or [vulnerability reporting mailbox](https://code.byted.org/flowdevops/cozeloop/blob/feat/release/sec@bytedance.com).
|
||||
Please **do not** create public GitHub Issues.
|
||||
## Join the community
|
||||
Scan the QR code below using the Lark mobile app to join the Coze Studio technical exchange group.
|
||||
## Join Community
|
||||
|
||||
We are committed to building an open and friendly developer community. All developers interested in AI Agent development are welcome to join us!
|
||||
|
||||
### 🐛 Issue Reports & Feature Requests
|
||||
To efficiently track and resolve issues while ensuring transparency and collaboration, we recommend participating through:
|
||||
- **GitHub Issues**: [Submit bug reports or feature requests](https://github.com/coze-dev/coze-studio/issues)
|
||||
- **Pull Requests**: [Contribute code or documentation improvements](https://github.com/coze-dev/coze-studio/pulls)
|
||||
|
||||
### 💬 Technical Discussion & Communication
|
||||
Join our technical discussion groups to share experiences with other developers and stay updated with the latest project developments:
|
||||
|
||||
**Feishu Group Chat**
|
||||
Scan the QR code below with Feishu mobile app to join:
|
||||
|
||||

|
||||
|
||||
**Discord Server**
|
||||
Click to join: [Coze Community](https://discord.gg/sTVN9EVS4B)
|
||||
|
||||
**Telegram Group**
|
||||
Click to join: Telegram Group [Coze](https://t.me/+pP9CkPnomDA0Mjgx)
|
||||
|
||||
## Acknowledgments
|
||||
Thank you to all the developers and community members who have contributed to the Coze Studio project. Special thanks:
|
||||
|
||||
* LLM integration support provided by the Eino framework team
|
||||
* High-performance framework developed by the Cloudwego team
|
||||
* The [Eino](https://github.com/cloudwego/eino) framework team - providing powerful support for Coze Studio's agent and workflow runtime engines, model abstractions and implementations, and knowledge base indexing and retrieval
|
||||
* The [FlowGram](https://github.com/bytedance/flowgram.ai) team - providing a high-quality workflow building engine for Coze Studio's frontend workflow canvas editor
|
||||
* The [Hertz](https://github.com/cloudwego/hertz) team - Go HTTP framework with high-performance and strong-extensibility for building micro-services
|
||||
* All users who participated in testing and feedback
|
||||
@ -17,14 +17,15 @@
|
||||
|
||||
## 什么是 Coze Studio
|
||||
|
||||
[Coze Studio](https://www.coze.cn/home) 是一站式 AI Agent 开发工具。提供各类最新大模型和工具、多种开发模式和框架,从开发到部署,为你提供最便捷的 AI Agent 开发环境。上万家企业、数百万开发者正在使 Coze Studio。
|
||||
[Coze Studio](https://www.coze.cn/home) 是一站式 AI Agent 开发工具。提供各类最新大模型和工具、多种开发模式和框架,从开发到部署,为你提供最便捷的 AI Agent 开发环境。
|
||||
|
||||
* **提供 AI Agent 开发所需的全部核心技术**:Prompt、RAG、Plugin、Workflow,使得开发者可以聚焦创造 AI 核心价值。
|
||||
* **开箱即用,用最低的成本开发最专业的 AI Agent**:Coze Studio 为开发者提供了健全的应用模板和编排框架,你可以基于它们快速构建各种 AI Agent ,将创意变为现实。
|
||||
|
||||
Coze Studio 是字节跳动新一代 AI Agent 开发平台**扣子(Coze)**的**开源版本**。通过 Coze Studio 提供的可视化设计与编排工具,开发者可以通过零代码或低代码的方式,快速打造和调试智能体、应用和工作流,实现强大的 AI 应用开发和更多定制化业务逻辑,是构建低代码 AI 产品的理想选择。Coze Studio 致力于降低 AI Agent 开发与应用门槛,鼓励社区共建和分享交流,助你在 AI 领域进行更深层次的探索与实践。
|
||||
Coze Studio,源自服务了上万家企业、数百万开发者的「扣子开发平台」,我们将它的核心引擎完全开放。它是一个一站式的 AI Agent 可视化开发工具,让 AI Agent 的创建、调试和部署变得前所未有的简单。通过 Coze Studio 提供的可视化设计与编排工具,开发者可以通过零代码或低代码的方式,快速打造和调试智能体、应用和工作流,实现强大的 AI 应用开发和更多定制化业务逻辑,是构建低代码 AI 产品的理想选择。Coze Studio 致力于降低 AI Agent 开发与应用门槛,鼓励社区共建和分享交流,助你在 AI 领域进行更深层次的探索与实践。
|
||||
|
||||
Coze Studio 的后端采用 Golang 开发,前端使用 React + TypeScript,整体基于微服务架构并遵循领域驱动设计(DDD)原则构建。为开发者提供一个高性能、高扩展性、易于二次开发的底层框架,助力开发者应对复杂的业务需求。
|
||||
|
||||
## 功能清单
|
||||
| **功能模块** | **功能点** |
|
||||
| --- | --- |
|
||||
@ -71,9 +72,11 @@ Coze Studio 的后端采用 Golang 开发,前端使用 React + TypeScript,
|
||||
# 启动服务
|
||||
cd docker
|
||||
cp .env.example .env
|
||||
docker compose --profile '*' up -d
|
||||
docker compose --profile "*" up -d
|
||||
```
|
||||
服务启动之后`coze-minio-setup`、`coze-mysql-setup-init-sql`、`coze-mysql-setup-schema` 这几个容器处于退出状态(exit 0),是正常现象。**启动失败常见问题可参考[常见问题](https://github.com/coze-dev/coze-studio/wiki/9.-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)**。
|
||||
|
||||
4. 启动服务后,通过浏览器访问 `http://localhost:8888/` 即可打开 Coze Studio。
|
||||
|
||||
## 开发指南
|
||||
|
||||
@ -81,7 +84,7 @@ Coze Studio 的后端采用 Golang 开发,前端使用 React + TypeScript,
|
||||
* [模型配置](https://github.com/coze-dev/coze-studio/wiki/3.-模型配置):部署 Coze Studio 开源版之前,必须配置模型服务,否则无法在搭建智能体、工作流和应用时选择模型。
|
||||
* [插件配置](https://github.com/coze-dev/coze-studio/wiki/4.-插件配置):如需使用插件商店中的官方插件,必须先配置插件,添加第三方服务的鉴权秘钥。
|
||||
* [基础组件配置](https://github.com/coze-dev/coze-studio/wiki/5.-基础组件配置):了解如何配置图片上传等组件,以便在 Coze Studio 中使用上传图片等功能。
|
||||
* [API 参考](https://github.com/coze-dev/coze-studio/wiki/6.-API-参考):和商业版不同,Coze Studio 开源版仅支持个人访问秘钥(PAT)鉴权,并支持对话和工作流相关 API。
|
||||
* [API 参考](https://github.com/coze-dev/coze-studio/wiki/6.-API-参考):Coze Studio 社区版 API 和 Chat SDK 通过个人访问令牌鉴权,提供对话和工作流相关 API。
|
||||
* [开发规范](https://github.com/coze-dev/coze-studio/wiki/7.-开发规范):
|
||||
* [项目架构](https://github.com/coze-dev/coze-studio/wiki/7.-%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83#%E9%A1%B9%E7%9B%AE%E6%9E%B6%E6%9E%84):了解 Coze Studio 开源版的技术架构与核心组件。
|
||||
* [代码开发与测试](https://github.com/coze-dev/coze-studio/wiki/7.-%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83#%E4%BB%A3%E7%A0%81%E5%BC%80%E5%8F%91%E4%B8%8E%E6%B5%8B%E8%AF%95):了解如何基于 Coze Studio 开源版进行二次开发与测试。
|
||||
@ -106,13 +109,32 @@ Coze Studio 的后端采用 Golang 开发,前端使用 React + TypeScript,
|
||||
如果你在该项目中发现潜在的安全问题,或你认为可能发现了安全问题,请通过我们的[安全中心](https://security.bytedance.com/src) 或[漏洞报告邮箱](https://code.byted.org/flowdevops/cozeloop/blob/feat/release/sec@bytedance.com)通知字节跳动安全团队。
|
||||
请**不要**创建公开的 GitHub Issue。
|
||||
## 加入社区
|
||||
飞书移动端扫描以下二维码,加入 Coze Studio 技术交流群。
|
||||
|
||||
我们致力于构建一个开放、友好的开发者社区,欢迎所有对 AI Agent 开发感兴趣的开发者加入我们!
|
||||
|
||||
### 🐛 问题反馈与功能建议
|
||||
为了更高效地跟踪和解决问题,保证信息透明和便于协同,我们推荐通过以下方式参与:
|
||||
- **GitHub Issues**:[提交 Bug 报告或功能请求](https://github.com/coze-dev/coze-studio/issues)
|
||||
- **Pull Requests**:[贡献代码或文档改进](https://github.com/coze-dev/coze-studio/pulls)
|
||||
|
||||
### 💬 技术交流与讨论
|
||||
加入我们的技术交流群,与其他开发者分享经验、获取项目最新动态:
|
||||
|
||||
**飞书群聊**
|
||||
使用飞书移动端扫描下方二维码加入:
|
||||
|
||||

|
||||
|
||||
**Discord 服务器**
|
||||
点击加入:[Coze Community](https://discord.gg/sTVN9EVS4B)
|
||||
|
||||
**Telegram 群组**
|
||||
点击加入:Telegram Group [Coze](https://t.me/+pP9CkPnomDA0Mjgx)
|
||||
|
||||
## 致谢
|
||||
感谢所有为 Coze Studio 项目做出贡献的开发者和社区成员。特别感谢:
|
||||
|
||||
* Eino 框架团队提供的 LLM 集成支持
|
||||
* Cloudwego 团队开发的高性能框架
|
||||
* [Eino](https://github.com/cloudwego/eino) 框架团队 - 为 Coze Studio 的智能体和工作流运行时、模型抽象封装、知识库索引构建和检索提供了强大的支持
|
||||
* [FlowGram](https://github.com/bytedance/flowgram.ai) 团队 - 为 Coze Studio 的工作流画布编辑页提供了高质量的流程搭建引擎
|
||||
* [Hertz](https://github.com/cloudwego/hertz) 团队 - 高性能、强扩展性的 Go HTTP 框架,用于构建微服务
|
||||
* 所有参与测试和反馈的用户
|
||||
@ -31,7 +31,7 @@ WORKDIR /app
|
||||
# Install runtime dependencies for Go app and base for Python
|
||||
# pax-utils for scanelf, python3 for running Python, python3-dev for headers/shared libs
|
||||
# bind-tools for nslookup etc., file for debugging file types
|
||||
RUN apk add --no-cache pax-utils python3 python3-dev bind-tools file deno
|
||||
RUN apk add --no-cache pax-utils python3 python3-dev bind-tools file deno curl
|
||||
|
||||
# Install Python build dependencies, create venv, install packages, then remove build deps
|
||||
RUN apk add --no-cache --virtual .python-build-deps build-base py3-pip git && \
|
||||
@ -81,6 +81,9 @@ EXPOSE 8888
|
||||
|
||||
# Use a script to start both applications
|
||||
COPY backend/script/bootstrap.sh /app/bootstrap.sh
|
||||
RUN chmod +x /app/bootstrap.sh
|
||||
COPY docker/volumes/elasticsearch/setup_es.sh /app/setup_es.sh
|
||||
COPY docker/volumes/elasticsearch/es_index_schema /app/es_index_schemas
|
||||
|
||||
RUN chmod +x /app/bootstrap.sh /app/setup_es.sh
|
||||
|
||||
CMD ["/app/bootstrap.sh"]
|
||||
|
||||
@ -555,7 +555,11 @@ func CreateProjectConversationDef(ctx context.Context, c *app.RequestContext) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(workflow.CreateProjectConversationDefResponse)
|
||||
resp, err := appworkflow.SVC.CreateApplicationConversationDef(ctx, &req)
|
||||
if err != nil {
|
||||
internalServerErrorResponse(ctx, c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
@ -570,8 +574,11 @@ func UpdateProjectConversationDef(ctx context.Context, c *app.RequestContext) {
|
||||
invalidParamRequestResponse(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(workflow.UpdateProjectConversationDefResponse)
|
||||
resp, err := appworkflow.SVC.UpdateApplicationConversationDef(ctx, &req)
|
||||
if err != nil {
|
||||
internalServerErrorResponse(ctx, c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
@ -587,7 +594,11 @@ func DeleteProjectConversationDef(ctx context.Context, c *app.RequestContext) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(workflow.DeleteProjectConversationDefResponse)
|
||||
resp, err := appworkflow.SVC.DeleteApplicationConversationDef(ctx, &req)
|
||||
if err != nil {
|
||||
internalServerErrorResponse(ctx, c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
@ -603,7 +614,11 @@ func ListProjectConversationDef(ctx context.Context, c *app.RequestContext) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(workflow.ListProjectConversationResponse)
|
||||
resp, err := appworkflow.SVC.ListApplicationConversationDef(ctx, &req)
|
||||
if err != nil {
|
||||
internalServerErrorResponse(ctx, c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
@ -723,7 +738,11 @@ func GetChatFlowRole(ctx context.Context, c *app.RequestContext) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(workflow.GetChatFlowRoleResponse)
|
||||
resp, err := appworkflow.SVC.GetChatFlowRole(ctx, &req)
|
||||
if err != nil {
|
||||
internalServerErrorResponse(ctx, c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
@ -738,8 +757,11 @@ func CreateChatFlowRole(ctx context.Context, c *app.RequestContext) {
|
||||
invalidParamRequestResponse(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(workflow.CreateChatFlowRoleResponse)
|
||||
resp, err := appworkflow.SVC.CreateChatFlowRole(ctx, &req)
|
||||
if err != nil {
|
||||
internalServerErrorResponse(ctx, c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
@ -755,7 +777,11 @@ func DeleteChatFlowRole(ctx context.Context, c *app.RequestContext) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(workflow.DeleteChatFlowRoleResponse)
|
||||
resp, err := appworkflow.SVC.DeleteChatFlowRole(ctx, &req)
|
||||
if err != nil {
|
||||
internalServerErrorResponse(ctx, c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import (
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/bytedance/mockey"
|
||||
"github.com/cloudwego/eino/callbacks"
|
||||
model2 "github.com/cloudwego/eino/components/model"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
"github.com/cloudwego/hertz/pkg/app"
|
||||
@ -102,6 +103,11 @@ import (
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
callbacks.AppendGlobalHandlers(service.GetTokenCallbackHandler())
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
type wfTestRunner struct {
|
||||
t *testing.T
|
||||
h *server.Hertz
|
||||
|
||||
@ -26,6 +26,8 @@ const (
|
||||
Scene_GenerateAgentInfo Scene = 8
|
||||
//openapi
|
||||
Scene_SceneOpenApi Scene = 9
|
||||
// 工作流
|
||||
Scene_SceneWorkflow Scene = 50
|
||||
)
|
||||
|
||||
func (p Scene) String() string {
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package agentrun
|
||||
|
||||
type Tool struct {
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package connector
|
||||
|
||||
import "github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/developer_api"
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package conversation
|
||||
|
||||
import "github.com/coze-dev/coze-studio/backend/api/model/conversation/common"
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package database
|
||||
|
||||
type OperateType int64
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package knowledge
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package message
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import "github.com/getkin/kin-openapi/openapi3"
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
type ExecuteToolOption struct {
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
@ -247,6 +263,7 @@ func toAPIParameter(paramMeta paramMetaInfo, sc *openapi3.Schema) (*common.APIPa
|
||||
}
|
||||
|
||||
if sc.Default != nil {
|
||||
apiParam.GlobalDefault = ptr.Of(fmt.Sprintf("%v", sc.Default))
|
||||
apiParam.LocalDefault = ptr.Of(fmt.Sprintf("%v", sc.Default))
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package search
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package search
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package singleagent
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package variables
|
||||
|
||||
import (
|
||||
|
||||
@ -473,7 +473,10 @@ const (
|
||||
NodeType_Input NodeType = 30
|
||||
NodeType_Batch NodeType = 28
|
||||
NodeType_Continue NodeType = 29
|
||||
NodeType_MessageList NodeType = 37
|
||||
NodeType_AssignVariable NodeType = 40
|
||||
NodeType_ConversationList NodeType = 53
|
||||
NodeType_CreateMessage NodeType = 55
|
||||
NodeType_JsonSerialization NodeType = 58
|
||||
NodeType_JsonDeserialization NodeType = 59
|
||||
NodeType_DatasetDelete NodeType = 60
|
||||
@ -533,8 +536,14 @@ func (p NodeType) String() string {
|
||||
return "Batch"
|
||||
case NodeType_Continue:
|
||||
return "Continue"
|
||||
case NodeType_MessageList:
|
||||
return "MessageList"
|
||||
case NodeType_AssignVariable:
|
||||
return "AssignVariable"
|
||||
case NodeType_ConversationList:
|
||||
return "ConversationList"
|
||||
case NodeType_CreateMessage:
|
||||
return "CreateMessage"
|
||||
case NodeType_JsonSerialization:
|
||||
return "JsonSerialization"
|
||||
case NodeType_JsonDeserialization:
|
||||
@ -599,8 +608,14 @@ func NodeTypeFromString(s string) (NodeType, error) {
|
||||
return NodeType_Batch, nil
|
||||
case "Continue":
|
||||
return NodeType_Continue, nil
|
||||
case "MessageList":
|
||||
return NodeType_MessageList, nil
|
||||
case "AssignVariable":
|
||||
return NodeType_AssignVariable, nil
|
||||
case "ConversationList":
|
||||
return NodeType_ConversationList, nil
|
||||
case "CreateMessage":
|
||||
return NodeType_CreateMessage, nil
|
||||
case "JsonSerialization":
|
||||
return NodeType_JsonSerialization, nil
|
||||
case "JsonDeserialization":
|
||||
@ -657,11 +672,14 @@ const (
|
||||
NodeTemplateType_Input NodeTemplateType = 30
|
||||
NodeTemplateType_Batch NodeTemplateType = 28
|
||||
NodeTemplateType_Continue NodeTemplateType = 29
|
||||
NodeTemplateType_MessageList NodeTemplateType = 37
|
||||
NodeTemplateType_AssignVariable NodeTemplateType = 40
|
||||
NodeTemplateType_DatabaseInsert NodeTemplateType = 41
|
||||
NodeTemplateType_DatabaseUpdate NodeTemplateType = 42
|
||||
NodeTemplateType_DatabasesELECT NodeTemplateType = 43
|
||||
NodeTemplateType_DatabaseDelete NodeTemplateType = 44
|
||||
NodeTemplateType_ConversationList NodeTemplateType = 53
|
||||
NodeTemplateType_CreateMessage NodeTemplateType = 55
|
||||
NodeTemplateType_JsonSerialization NodeTemplateType = 58
|
||||
NodeTemplateType_JsonDeserialization NodeTemplateType = 59
|
||||
NodeTemplateType_DatasetDelete NodeTemplateType = 60
|
||||
@ -723,6 +741,8 @@ func (p NodeTemplateType) String() string {
|
||||
return "Batch"
|
||||
case NodeTemplateType_Continue:
|
||||
return "Continue"
|
||||
case NodeTemplateType_MessageList:
|
||||
return "MessageList"
|
||||
case NodeTemplateType_AssignVariable:
|
||||
return "AssignVariable"
|
||||
case NodeTemplateType_DatabaseInsert:
|
||||
@ -733,6 +753,10 @@ func (p NodeTemplateType) String() string {
|
||||
return "DatabasesELECT"
|
||||
case NodeTemplateType_DatabaseDelete:
|
||||
return "DatabaseDelete"
|
||||
case NodeTemplateType_ConversationList:
|
||||
return "ConversationList"
|
||||
case NodeTemplateType_CreateMessage:
|
||||
return "CreateMessage"
|
||||
case NodeTemplateType_JsonSerialization:
|
||||
return "JsonSerialization"
|
||||
case NodeTemplateType_JsonDeserialization:
|
||||
@ -799,6 +823,8 @@ func NodeTemplateTypeFromString(s string) (NodeTemplateType, error) {
|
||||
return NodeTemplateType_Batch, nil
|
||||
case "Continue":
|
||||
return NodeTemplateType_Continue, nil
|
||||
case "MessageList":
|
||||
return NodeTemplateType_MessageList, nil
|
||||
case "AssignVariable":
|
||||
return NodeTemplateType_AssignVariable, nil
|
||||
case "DatabaseInsert":
|
||||
@ -809,6 +835,10 @@ func NodeTemplateTypeFromString(s string) (NodeTemplateType, error) {
|
||||
return NodeTemplateType_DatabasesELECT, nil
|
||||
case "DatabaseDelete":
|
||||
return NodeTemplateType_DatabaseDelete, nil
|
||||
case "ConversationList":
|
||||
return NodeTemplateType_ConversationList, nil
|
||||
case "CreateMessage":
|
||||
return NodeTemplateType_CreateMessage, nil
|
||||
case "JsonSerialization":
|
||||
return NodeTemplateType_JsonSerialization, nil
|
||||
case "JsonDeserialization":
|
||||
@ -64103,7 +64133,7 @@ func (p *ChatFlowRole) String() string {
|
||||
}
|
||||
|
||||
type CreateChatFlowRoleRequest struct {
|
||||
ChatFlowRole *ChatFlowRole `thrift:"ChatFlowRole,1" json:"chat_flow_role" form:"ChatFlowRole" query:"ChatFlowRole"`
|
||||
ChatFlowRole *ChatFlowRole `thrift:"ChatFlowRole,1" json:"chat_flow_role" query:"chat_flow_role" `
|
||||
Base *base.Base `thrift:"Base,255,optional" form:"Base" json:"Base,omitempty" query:"Base"`
|
||||
}
|
||||
|
||||
@ -64302,7 +64332,9 @@ func (p *CreateChatFlowRoleRequest) String() string {
|
||||
|
||||
type CreateChatFlowRoleResponse struct {
|
||||
// 数据库中ID
|
||||
ID string `thrift:"ID,1" form:"ID" json:"ID" query:"ID"`
|
||||
ID string `thrift:"ID,1" json:"id" query:"id" `
|
||||
Code int64 `thrift:"code,253,required" form:"code,required" json:"code,required" query:"code,required"`
|
||||
Msg string `thrift:"msg,254,required" form:"msg,required" json:"msg,required" query:"msg,required"`
|
||||
BaseResp *base.BaseResp `thrift:"BaseResp,255,required" form:"BaseResp,required" json:"BaseResp,required" query:"BaseResp,required"`
|
||||
}
|
||||
|
||||
@ -64317,6 +64349,14 @@ func (p *CreateChatFlowRoleResponse) GetID() (v string) {
|
||||
return p.ID
|
||||
}
|
||||
|
||||
func (p *CreateChatFlowRoleResponse) GetCode() (v int64) {
|
||||
return p.Code
|
||||
}
|
||||
|
||||
func (p *CreateChatFlowRoleResponse) GetMsg() (v string) {
|
||||
return p.Msg
|
||||
}
|
||||
|
||||
var CreateChatFlowRoleResponse_BaseResp_DEFAULT *base.BaseResp
|
||||
|
||||
func (p *CreateChatFlowRoleResponse) GetBaseResp() (v *base.BaseResp) {
|
||||
@ -64328,6 +64368,8 @@ func (p *CreateChatFlowRoleResponse) GetBaseResp() (v *base.BaseResp) {
|
||||
|
||||
var fieldIDToName_CreateChatFlowRoleResponse = map[int16]string{
|
||||
1: "ID",
|
||||
253: "code",
|
||||
254: "msg",
|
||||
255: "BaseResp",
|
||||
}
|
||||
|
||||
@ -64338,6 +64380,8 @@ func (p *CreateChatFlowRoleResponse) IsSetBaseResp() bool {
|
||||
func (p *CreateChatFlowRoleResponse) Read(iprot thrift.TProtocol) (err error) {
|
||||
var fieldTypeId thrift.TType
|
||||
var fieldId int16
|
||||
var issetCode bool = false
|
||||
var issetMsg bool = false
|
||||
var issetBaseResp bool = false
|
||||
|
||||
if _, err = iprot.ReadStructBegin(); err != nil {
|
||||
@ -64362,6 +64406,24 @@ func (p *CreateChatFlowRoleResponse) Read(iprot thrift.TProtocol) (err error) {
|
||||
} else if err = iprot.Skip(fieldTypeId); err != nil {
|
||||
goto SkipFieldError
|
||||
}
|
||||
case 253:
|
||||
if fieldTypeId == thrift.I64 {
|
||||
if err = p.ReadField253(iprot); err != nil {
|
||||
goto ReadFieldError
|
||||
}
|
||||
issetCode = true
|
||||
} else if err = iprot.Skip(fieldTypeId); err != nil {
|
||||
goto SkipFieldError
|
||||
}
|
||||
case 254:
|
||||
if fieldTypeId == thrift.STRING {
|
||||
if err = p.ReadField254(iprot); err != nil {
|
||||
goto ReadFieldError
|
||||
}
|
||||
issetMsg = true
|
||||
} else if err = iprot.Skip(fieldTypeId); err != nil {
|
||||
goto SkipFieldError
|
||||
}
|
||||
case 255:
|
||||
if fieldTypeId == thrift.STRUCT {
|
||||
if err = p.ReadField255(iprot); err != nil {
|
||||
@ -64384,6 +64446,16 @@ func (p *CreateChatFlowRoleResponse) Read(iprot thrift.TProtocol) (err error) {
|
||||
goto ReadStructEndError
|
||||
}
|
||||
|
||||
if !issetCode {
|
||||
fieldId = 253
|
||||
goto RequiredFieldNotSetError
|
||||
}
|
||||
|
||||
if !issetMsg {
|
||||
fieldId = 254
|
||||
goto RequiredFieldNotSetError
|
||||
}
|
||||
|
||||
if !issetBaseResp {
|
||||
fieldId = 255
|
||||
goto RequiredFieldNotSetError
|
||||
@ -64417,6 +64489,28 @@ func (p *CreateChatFlowRoleResponse) ReadField1(iprot thrift.TProtocol) error {
|
||||
p.ID = _field
|
||||
return nil
|
||||
}
|
||||
func (p *CreateChatFlowRoleResponse) ReadField253(iprot thrift.TProtocol) error {
|
||||
|
||||
var _field int64
|
||||
if v, err := iprot.ReadI64(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_field = v
|
||||
}
|
||||
p.Code = _field
|
||||
return nil
|
||||
}
|
||||
func (p *CreateChatFlowRoleResponse) ReadField254(iprot thrift.TProtocol) error {
|
||||
|
||||
var _field string
|
||||
if v, err := iprot.ReadString(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_field = v
|
||||
}
|
||||
p.Msg = _field
|
||||
return nil
|
||||
}
|
||||
func (p *CreateChatFlowRoleResponse) ReadField255(iprot thrift.TProtocol) error {
|
||||
_field := base.NewBaseResp()
|
||||
if err := _field.Read(iprot); err != nil {
|
||||
@ -64436,6 +64530,14 @@ func (p *CreateChatFlowRoleResponse) Write(oprot thrift.TProtocol) (err error) {
|
||||
fieldId = 1
|
||||
goto WriteFieldError
|
||||
}
|
||||
if err = p.writeField253(oprot); err != nil {
|
||||
fieldId = 253
|
||||
goto WriteFieldError
|
||||
}
|
||||
if err = p.writeField254(oprot); err != nil {
|
||||
fieldId = 254
|
||||
goto WriteFieldError
|
||||
}
|
||||
if err = p.writeField255(oprot); err != nil {
|
||||
fieldId = 255
|
||||
goto WriteFieldError
|
||||
@ -64474,6 +64576,38 @@ WriteFieldBeginError:
|
||||
WriteFieldEndError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
|
||||
}
|
||||
func (p *CreateChatFlowRoleResponse) writeField253(oprot thrift.TProtocol) (err error) {
|
||||
if err = oprot.WriteFieldBegin("code", thrift.I64, 253); err != nil {
|
||||
goto WriteFieldBeginError
|
||||
}
|
||||
if err := oprot.WriteI64(p.Code); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = oprot.WriteFieldEnd(); err != nil {
|
||||
goto WriteFieldEndError
|
||||
}
|
||||
return nil
|
||||
WriteFieldBeginError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 253 begin error: ", p), err)
|
||||
WriteFieldEndError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 253 end error: ", p), err)
|
||||
}
|
||||
func (p *CreateChatFlowRoleResponse) writeField254(oprot thrift.TProtocol) (err error) {
|
||||
if err = oprot.WriteFieldBegin("msg", thrift.STRING, 254); err != nil {
|
||||
goto WriteFieldBeginError
|
||||
}
|
||||
if err := oprot.WriteString(p.Msg); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = oprot.WriteFieldEnd(); err != nil {
|
||||
goto WriteFieldEndError
|
||||
}
|
||||
return nil
|
||||
WriteFieldBeginError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 254 begin error: ", p), err)
|
||||
WriteFieldEndError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 254 end error: ", p), err)
|
||||
}
|
||||
func (p *CreateChatFlowRoleResponse) writeField255(oprot thrift.TProtocol) (err error) {
|
||||
if err = oprot.WriteFieldBegin("BaseResp", thrift.STRUCT, 255); err != nil {
|
||||
goto WriteFieldBeginError
|
||||
@ -64500,10 +64634,10 @@ func (p *CreateChatFlowRoleResponse) String() string {
|
||||
}
|
||||
|
||||
type DeleteChatFlowRoleRequest struct {
|
||||
WorkflowID string `thrift:"WorkflowID,1" form:"WorkflowID" json:"WorkflowID" query:"WorkflowID"`
|
||||
ConnectorID string `thrift:"ConnectorID,2" form:"ConnectorID" json:"ConnectorID" query:"ConnectorID"`
|
||||
WorkflowID string `thrift:"WorkflowID,1" json:"workflow_id" query:"workflow_id" `
|
||||
ConnectorID string `thrift:"ConnectorID,2" json:"connector_id" query:"connector_id" `
|
||||
// 数据库中ID
|
||||
ID string `thrift:"ID,4" form:"ID" json:"ID" query:"ID"`
|
||||
ID string `thrift:"ID,4" json:"id" query:"id" `
|
||||
Base *base.Base `thrift:"Base,255,optional" form:"Base" json:"Base,omitempty" query:"Base"`
|
||||
}
|
||||
|
||||
@ -64936,12 +65070,12 @@ func (p *DeleteChatFlowRoleResponse) String() string {
|
||||
}
|
||||
|
||||
type GetChatFlowRoleRequest struct {
|
||||
WorkflowID string `thrift:"WorkflowID,1" form:"WorkflowID" json:"WorkflowID" query:"WorkflowID"`
|
||||
ConnectorID string `thrift:"ConnectorID,2" form:"ConnectorID" json:"ConnectorID" query:"ConnectorID"`
|
||||
IsDebug bool `thrift:"IsDebug,3" form:"IsDebug" json:"IsDebug" query:"IsDebug"`
|
||||
WorkflowID string `thrift:"WorkflowID,1" json:"workflow_id" query:"workflow_id" `
|
||||
ConnectorID string `thrift:"ConnectorID,2" json:"connector_id" query:"connector_id" `
|
||||
IsDebug bool `thrift:"IsDebug,3" json:"is_debug" query:"is_debug" `
|
||||
// 4: optional string AppID (api.query = "app_id")
|
||||
Ext map[string]string `thrift:"Ext,5,optional" json:"Ext,omitempty" query:"ext"`
|
||||
Base *base.Base `thrift:"Base,255,optional" form:"Base" json:"Base,omitempty" query:"Base"`
|
||||
Base *base.Base `thrift:"Base,255,optional" json:"base" query:"base" `
|
||||
}
|
||||
|
||||
func NewGetChatFlowRoleRequest() *GetChatFlowRoleRequest {
|
||||
@ -65304,8 +65438,10 @@ func (p *GetChatFlowRoleRequest) String() string {
|
||||
}
|
||||
|
||||
type GetChatFlowRoleResponse struct {
|
||||
Role *ChatFlowRole `thrift:"Role,1,optional" form:"Role" json:"Role,omitempty" query:"Role"`
|
||||
BaseResp *base.BaseResp `thrift:"BaseResp,255,required" form:"BaseResp,required" json:"BaseResp,required" query:"BaseResp,required"`
|
||||
Code int64 `thrift:"code,1,required" form:"code,required" json:"code,required" query:"code,required"`
|
||||
Msg string `thrift:"msg,2,required" form:"msg,required" json:"msg,required" query:"msg,required"`
|
||||
Role *ChatFlowRole `thrift:"Role,3,optional" json:"role" query:"role" `
|
||||
BaseResp *base.BaseResp `thrift:"BaseResp,255,required" json:"base_resp" query:"base_resp,required" `
|
||||
}
|
||||
|
||||
func NewGetChatFlowRoleResponse() *GetChatFlowRoleResponse {
|
||||
@ -65315,6 +65451,14 @@ func NewGetChatFlowRoleResponse() *GetChatFlowRoleResponse {
|
||||
func (p *GetChatFlowRoleResponse) InitDefault() {
|
||||
}
|
||||
|
||||
func (p *GetChatFlowRoleResponse) GetCode() (v int64) {
|
||||
return p.Code
|
||||
}
|
||||
|
||||
func (p *GetChatFlowRoleResponse) GetMsg() (v string) {
|
||||
return p.Msg
|
||||
}
|
||||
|
||||
var GetChatFlowRoleResponse_Role_DEFAULT *ChatFlowRole
|
||||
|
||||
func (p *GetChatFlowRoleResponse) GetRole() (v *ChatFlowRole) {
|
||||
@ -65334,7 +65478,9 @@ func (p *GetChatFlowRoleResponse) GetBaseResp() (v *base.BaseResp) {
|
||||
}
|
||||
|
||||
var fieldIDToName_GetChatFlowRoleResponse = map[int16]string{
|
||||
1: "Role",
|
||||
1: "code",
|
||||
2: "msg",
|
||||
3: "Role",
|
||||
255: "BaseResp",
|
||||
}
|
||||
|
||||
@ -65349,6 +65495,8 @@ func (p *GetChatFlowRoleResponse) IsSetBaseResp() bool {
|
||||
func (p *GetChatFlowRoleResponse) Read(iprot thrift.TProtocol) (err error) {
|
||||
var fieldTypeId thrift.TType
|
||||
var fieldId int16
|
||||
var issetCode bool = false
|
||||
var issetMsg bool = false
|
||||
var issetBaseResp bool = false
|
||||
|
||||
if _, err = iprot.ReadStructBegin(); err != nil {
|
||||
@ -65366,10 +65514,28 @@ func (p *GetChatFlowRoleResponse) Read(iprot thrift.TProtocol) (err error) {
|
||||
|
||||
switch fieldId {
|
||||
case 1:
|
||||
if fieldTypeId == thrift.STRUCT {
|
||||
if fieldTypeId == thrift.I64 {
|
||||
if err = p.ReadField1(iprot); err != nil {
|
||||
goto ReadFieldError
|
||||
}
|
||||
issetCode = true
|
||||
} else if err = iprot.Skip(fieldTypeId); err != nil {
|
||||
goto SkipFieldError
|
||||
}
|
||||
case 2:
|
||||
if fieldTypeId == thrift.STRING {
|
||||
if err = p.ReadField2(iprot); err != nil {
|
||||
goto ReadFieldError
|
||||
}
|
||||
issetMsg = true
|
||||
} else if err = iprot.Skip(fieldTypeId); err != nil {
|
||||
goto SkipFieldError
|
||||
}
|
||||
case 3:
|
||||
if fieldTypeId == thrift.STRUCT {
|
||||
if err = p.ReadField3(iprot); err != nil {
|
||||
goto ReadFieldError
|
||||
}
|
||||
} else if err = iprot.Skip(fieldTypeId); err != nil {
|
||||
goto SkipFieldError
|
||||
}
|
||||
@ -65395,6 +65561,16 @@ func (p *GetChatFlowRoleResponse) Read(iprot thrift.TProtocol) (err error) {
|
||||
goto ReadStructEndError
|
||||
}
|
||||
|
||||
if !issetCode {
|
||||
fieldId = 1
|
||||
goto RequiredFieldNotSetError
|
||||
}
|
||||
|
||||
if !issetMsg {
|
||||
fieldId = 2
|
||||
goto RequiredFieldNotSetError
|
||||
}
|
||||
|
||||
if !issetBaseResp {
|
||||
fieldId = 255
|
||||
goto RequiredFieldNotSetError
|
||||
@ -65418,6 +65594,28 @@ RequiredFieldNotSetError:
|
||||
}
|
||||
|
||||
func (p *GetChatFlowRoleResponse) ReadField1(iprot thrift.TProtocol) error {
|
||||
|
||||
var _field int64
|
||||
if v, err := iprot.ReadI64(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_field = v
|
||||
}
|
||||
p.Code = _field
|
||||
return nil
|
||||
}
|
||||
func (p *GetChatFlowRoleResponse) ReadField2(iprot thrift.TProtocol) error {
|
||||
|
||||
var _field string
|
||||
if v, err := iprot.ReadString(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_field = v
|
||||
}
|
||||
p.Msg = _field
|
||||
return nil
|
||||
}
|
||||
func (p *GetChatFlowRoleResponse) ReadField3(iprot thrift.TProtocol) error {
|
||||
_field := NewChatFlowRole()
|
||||
if err := _field.Read(iprot); err != nil {
|
||||
return err
|
||||
@ -65444,6 +65642,14 @@ func (p *GetChatFlowRoleResponse) Write(oprot thrift.TProtocol) (err error) {
|
||||
fieldId = 1
|
||||
goto WriteFieldError
|
||||
}
|
||||
if err = p.writeField2(oprot); err != nil {
|
||||
fieldId = 2
|
||||
goto WriteFieldError
|
||||
}
|
||||
if err = p.writeField3(oprot); err != nil {
|
||||
fieldId = 3
|
||||
goto WriteFieldError
|
||||
}
|
||||
if err = p.writeField255(oprot); err != nil {
|
||||
fieldId = 255
|
||||
goto WriteFieldError
|
||||
@ -65467,8 +65673,40 @@ WriteStructEndError:
|
||||
}
|
||||
|
||||
func (p *GetChatFlowRoleResponse) writeField1(oprot thrift.TProtocol) (err error) {
|
||||
if err = oprot.WriteFieldBegin("code", thrift.I64, 1); err != nil {
|
||||
goto WriteFieldBeginError
|
||||
}
|
||||
if err := oprot.WriteI64(p.Code); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = oprot.WriteFieldEnd(); err != nil {
|
||||
goto WriteFieldEndError
|
||||
}
|
||||
return nil
|
||||
WriteFieldBeginError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
|
||||
WriteFieldEndError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
|
||||
}
|
||||
func (p *GetChatFlowRoleResponse) writeField2(oprot thrift.TProtocol) (err error) {
|
||||
if err = oprot.WriteFieldBegin("msg", thrift.STRING, 2); err != nil {
|
||||
goto WriteFieldBeginError
|
||||
}
|
||||
if err := oprot.WriteString(p.Msg); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = oprot.WriteFieldEnd(); err != nil {
|
||||
goto WriteFieldEndError
|
||||
}
|
||||
return nil
|
||||
WriteFieldBeginError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 2 begin error: ", p), err)
|
||||
WriteFieldEndError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
|
||||
}
|
||||
func (p *GetChatFlowRoleResponse) writeField3(oprot thrift.TProtocol) (err error) {
|
||||
if p.IsSetRole() {
|
||||
if err = oprot.WriteFieldBegin("Role", thrift.STRUCT, 1); err != nil {
|
||||
if err = oprot.WriteFieldBegin("Role", thrift.STRUCT, 3); err != nil {
|
||||
goto WriteFieldBeginError
|
||||
}
|
||||
if err := p.Role.Write(oprot); err != nil {
|
||||
@ -65480,9 +65718,9 @@ func (p *GetChatFlowRoleResponse) writeField1(oprot thrift.TProtocol) (err error
|
||||
}
|
||||
return nil
|
||||
WriteFieldBeginError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 3 begin error: ", p), err)
|
||||
WriteFieldEndError:
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field 3 end error: ", p), err)
|
||||
}
|
||||
func (p *GetChatFlowRoleResponse) writeField255(oprot thrift.TProtocol) (err error) {
|
||||
if err = oprot.WriteFieldBegin("BaseResp", thrift.STRUCT, 255); err != nil {
|
||||
|
||||
@ -60,6 +60,7 @@ import (
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/conv"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/logs"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/safego"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/taskgroup"
|
||||
"github.com/coze-dev/coze-studio/backend/types/consts"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
@ -183,18 +184,19 @@ func (a *APPApplicationService) DraftProjectDelete(ctx context.Context, req *pro
|
||||
logs.CtxErrorf(ctx, "publish project '%d' failed, err=%v", req.ProjectID, err)
|
||||
}
|
||||
|
||||
err = a.deleteAPPResources(ctx, req.ProjectID)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "delete app '%d' resources failed, err=%v", req.ProjectID, err)
|
||||
}
|
||||
safego.Go(ctx, func() {
|
||||
// When an app is deleted, resource deletion is currently handled as a weak dependency, meaning some resources might not be deleted, but they will be inaccessible to the user.
|
||||
// TODO:: Application resources need to check the deletion status of the application
|
||||
a.deleteAPPResources(ctx, req.ProjectID)
|
||||
})
|
||||
|
||||
resp = &projectAPI.DraftProjectDeleteResponse{}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (a *APPApplicationService) deleteAPPResources(ctx context.Context, appID int64) (err error) {
|
||||
err = plugin.PluginApplicationSVC.DeleteAPPAllPlugins(ctx, appID)
|
||||
func (a *APPApplicationService) deleteAPPResources(ctx context.Context, appID int64) {
|
||||
err := plugin.PluginApplicationSVC.DeleteAPPAllPlugins(ctx, appID)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "delete app '%d' plugins failed, err=%v", appID, err)
|
||||
}
|
||||
@ -218,8 +220,6 @@ func (a *APPApplicationService) deleteAPPResources(ctx context.Context, appID in
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "delete app '%d' workflow failed, err=%v", appID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *APPApplicationService) DraftProjectUpdate(ctx context.Context, req *projectAPI.DraftProjectUpdateRequest) (resp *projectAPI.DraftProjectUpdateResponse, err error) {
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package appinfra
|
||||
|
||||
import (
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package appinfra
|
||||
|
||||
import (
|
||||
|
||||
@ -20,9 +20,8 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
|
||||
common "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop_common"
|
||||
@ -33,14 +32,6 @@ import (
|
||||
func APIParamsToOpenapiOperation(reqParams, respParams []*common.APIParameter) (*openapi3.Operation, error) {
|
||||
op := &openapi3.Operation{}
|
||||
|
||||
if reqParams != nil && len(reqParams) == 0 {
|
||||
op.Parameters = []*openapi3.ParameterRef{}
|
||||
op.RequestBody = entity.DefaultOpenapi3RequestBody()
|
||||
}
|
||||
if respParams != nil && len(respParams) == 0 {
|
||||
op.Responses = entity.DefaultOpenapi3Responses()
|
||||
}
|
||||
|
||||
hasSetReqBody := false
|
||||
hasSetParams := false
|
||||
|
||||
@ -136,6 +127,16 @@ func APIParamsToOpenapiOperation(reqParams, respParams []*common.APIParameter) (
|
||||
}
|
||||
}
|
||||
|
||||
if op.Parameters == nil {
|
||||
op.Parameters = []*openapi3.ParameterRef{}
|
||||
}
|
||||
if op.RequestBody == nil {
|
||||
op.RequestBody = entity.DefaultOpenapi3RequestBody()
|
||||
}
|
||||
if op.Responses == nil {
|
||||
op.Responses = entity.DefaultOpenapi3Responses()
|
||||
}
|
||||
|
||||
return op, nil
|
||||
}
|
||||
|
||||
|
||||
@ -140,7 +140,7 @@ func (c *ConversationApplicationService) CreateConversation(ctx context.Context,
|
||||
Id: conversationData.ID,
|
||||
LastSectionID: &conversationData.SectionID,
|
||||
ConnectorID: &conversationData.ConnectorID,
|
||||
CreatedAt: conversationData.CreatedAt,
|
||||
CreatedAt: conversationData.CreatedAt / 1000,
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@ -176,7 +176,7 @@ func (c *ConversationApplicationService) ListConversation(ctx context.Context, r
|
||||
Id: conv.ID,
|
||||
LastSectionID: &conv.SectionID,
|
||||
ConnectorID: &conv.ConnectorID,
|
||||
CreatedAt: conv.CreatedAt,
|
||||
CreatedAt: conv.CreatedAt / 1000,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -299,6 +299,7 @@ func buildARSM2ApiMessage(chunk *entity.AgentRunResponse) []byte {
|
||||
MetaData: chunkMessageItem.Ext,
|
||||
ChatID: strconv.FormatInt(chunkMessageItem.RunID, 10),
|
||||
ReasoningContent: chunkMessageItem.ReasoningContent,
|
||||
CreatedAt: ptr.Of(chunkMessageItem.CreatedAt / 1000),
|
||||
}
|
||||
|
||||
mCM, _ := json.Marshal(chunkMessage)
|
||||
|
||||
@ -110,8 +110,8 @@ func (m *OpenapiMessageApplication) buildMessageListResponse(ctx context.Context
|
||||
Content: content,
|
||||
ContentType: string(dm.ContentType),
|
||||
SectionID: strconv.FormatInt(dm.SectionID, 10),
|
||||
CreatedAt: dm.CreatedAt,
|
||||
UpdatedAt: dm.UpdatedAt,
|
||||
CreatedAt: dm.CreatedAt / 1000,
|
||||
UpdatedAt: dm.UpdatedAt / 1000,
|
||||
ChatID: dm.RunID,
|
||||
MetaData: dm.Ext,
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/cloudwego/eino-ext/components/embedding/ark"
|
||||
ollamaEmb "github.com/cloudwego/eino-ext/components/embedding/ollama"
|
||||
"github.com/cloudwego/eino-ext/components/embedding/openai"
|
||||
ao "github.com/cloudwego/eino-ext/components/model/ark"
|
||||
"github.com/cloudwego/eino-ext/components/model/deepseek"
|
||||
@ -35,6 +36,7 @@ import (
|
||||
"github.com/cloudwego/eino-ext/components/model/qwen"
|
||||
"github.com/cloudwego/eino/components/prompt"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/impl/embedding/http"
|
||||
"github.com/milvus-io/milvus/client/v2/milvusclient"
|
||||
"github.com/volcengine/volc-sdk-golang/service/vikingdb"
|
||||
"github.com/volcengine/volc-sdk-golang/service/visual"
|
||||
@ -111,6 +113,9 @@ func InitService(c *ServiceComponents) (*KnowledgeApplicationService, error) {
|
||||
case "ve":
|
||||
ocrAK := os.Getenv("VE_OCR_AK")
|
||||
ocrSK := os.Getenv("VE_OCR_SK")
|
||||
if ocrAK == "" || ocrSK == "" {
|
||||
logs.Warnf("[ve_ocr] ak / sk not configured, ocr might not work well")
|
||||
}
|
||||
inst := visual.NewInstance()
|
||||
inst.Client.SetAccessKey(ocrAK)
|
||||
inst.Client.SetSecretKey(ocrSK)
|
||||
@ -346,6 +351,42 @@ func getEmbedding(ctx context.Context) (embedding.Embedder, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init ark embedding client failed, err=%w", err)
|
||||
}
|
||||
|
||||
case "ollama":
|
||||
var (
|
||||
ollamaEmbeddingBaseURL = os.Getenv("OLLAMA_EMBEDDING_BASE_URL")
|
||||
ollamaEmbeddingModel = os.Getenv("OLLAMA_EMBEDDING_MODEL")
|
||||
ollamaEmbeddingDims = os.Getenv("OLLAMA_EMBEDDING_DIMS")
|
||||
)
|
||||
|
||||
dims, err := strconv.ParseInt(ollamaEmbeddingDims, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init ollama embedding dims failed, err=%w", err)
|
||||
}
|
||||
|
||||
emb, err = wrap.NewOllamaEmbedder(ctx, &ollamaEmb.EmbeddingConfig{
|
||||
BaseURL: ollamaEmbeddingBaseURL,
|
||||
Model: ollamaEmbeddingModel,
|
||||
}, dims)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init ollama embedding failed, err=%w", err)
|
||||
}
|
||||
|
||||
|
||||
case "http":
|
||||
var (
|
||||
httpEmbeddingBaseURL = os.Getenv("HTTP_EMBEDDING_ADDR")
|
||||
httpEmbeddingDims = os.Getenv("HTTP_EMBEDDING_DIMS")
|
||||
)
|
||||
dims, err := strconv.ParseInt(httpEmbeddingDims, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init http embedding dims failed, err=%w", err)
|
||||
}
|
||||
emb, err = http.NewEmbedding(httpEmbeddingBaseURL, dims)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init http embedding failed, err=%w", err)
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("init knowledge embedding failed, type not configured")
|
||||
}
|
||||
|
||||
@ -438,7 +438,7 @@ func (k *KnowledgeApplicationService) GetDocumentProgress(ctx context.Context, r
|
||||
DocumentID: domainResp.ProgressList[i].ID,
|
||||
Progress: int32(domainResp.ProgressList[i].Progress),
|
||||
Status: convertDocumentStatus2Model(domainResp.ProgressList[i].Status),
|
||||
StatusDescript: ptr.Of(convertDocumentStatus2Model(domainResp.ProgressList[i].Status).String()),
|
||||
StatusDescript: &domainResp.ProgressList[i].StatusMsg,
|
||||
DocumentName: domainResp.ProgressList[i].Name,
|
||||
RemainingTime: &domainResp.ProgressList[i].RemainingSec,
|
||||
Size: &domainResp.ProgressList[i].Size,
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package modelmgr
|
||||
|
||||
import (
|
||||
|
||||
@ -18,9 +18,12 @@ package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/conf"
|
||||
pluginConf "github.com/coze-dev/coze-studio/backend/domain/plugin/conf"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/repository"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/service"
|
||||
@ -28,6 +31,9 @@ import (
|
||||
user "github.com/coze-dev/coze-studio/backend/domain/user/service"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/idgen"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
type ServiceComponents struct {
|
||||
@ -68,6 +74,11 @@ func InitService(ctx context.Context, components *ServiceComponents) (*PluginApp
|
||||
OAuthRepo: oauthRepo,
|
||||
})
|
||||
|
||||
err = checkIDExist(ctx, pluginSVC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
PluginApplicationSVC.DomainSVC = pluginSVC
|
||||
PluginApplicationSVC.eventbus = components.EventBus
|
||||
PluginApplicationSVC.oss = components.OSS
|
||||
@ -77,3 +88,51 @@ func InitService(ctx context.Context, components *ServiceComponents) (*PluginApp
|
||||
|
||||
return PluginApplicationSVC, nil
|
||||
}
|
||||
|
||||
func checkIDExist(ctx context.Context, pluginService service.PluginService) error {
|
||||
pluginProducts := conf.GetAllPluginProducts()
|
||||
|
||||
pluginIDs := make([]int64, 0, len(pluginProducts))
|
||||
var toolIDs []int64
|
||||
for _, p := range pluginProducts {
|
||||
pluginIDs = append(pluginIDs, p.Info.ID)
|
||||
toolIDs = append(toolIDs, p.ToolIDs...)
|
||||
}
|
||||
|
||||
pluginInfos, err := pluginService.MGetDraftPlugins(ctx, pluginIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(pluginInfos) > 0 {
|
||||
conflictsIDs := make([]int64, 0, len(pluginInfos))
|
||||
for _, p := range pluginInfos {
|
||||
conflictsIDs = append(conflictsIDs, p.ID)
|
||||
}
|
||||
|
||||
return errorx.New(errno.ErrPluginIDExist,
|
||||
errorx.KV("plugin_id", strings.Join(slices.Transform(conflictsIDs, func(id int64) string {
|
||||
return strconv.FormatInt(id, 10)
|
||||
}), ",")),
|
||||
)
|
||||
}
|
||||
|
||||
tools, err := pluginService.MGetDraftTools(ctx, toolIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(tools) > 0 {
|
||||
conflictsIDs := make([]int64, 0, len(tools))
|
||||
for _, t := range tools {
|
||||
conflictsIDs = append(conflictsIDs, t.ID)
|
||||
}
|
||||
|
||||
return errorx.New(errno.ErrToolIDExist,
|
||||
errorx.KV("tool_id", strings.Join(slices.Transform(conflictsIDs, func(id int64) string {
|
||||
return strconv.FormatInt(id, 10)
|
||||
}), ",")),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ func (p *PluginApplicationService) RegisterPluginMeta(ctx context.Context, req *
|
||||
if req.GetLocation() == common.AuthorizationServiceLocation_Query {
|
||||
loc = model.ParamInQuery
|
||||
} else if req.GetLocation() == common.AuthorizationServiceLocation_Header {
|
||||
loc = model.ParamInPath
|
||||
loc = model.ParamInHeader
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid location '%s'", req.GetLocation())
|
||||
}
|
||||
|
||||
@ -76,28 +76,38 @@ func (s *SearchApplicationService) GetDraftIntelligenceList(ctx context.Context,
|
||||
intelligenceDataList := make([]*intelligence.IntelligenceData, len(searchResp.Data))
|
||||
|
||||
logs.CtxDebugf(ctx, "[GetDraftIntelligenceList] searchResp.Data: %v", conv.DebugJsonToStr(searchResp.Data))
|
||||
if len(searchResp.Data) > 1 {
|
||||
for idx := range searchResp.Data[1:] {
|
||||
index := idx + 1
|
||||
data := searchResp.Data[index]
|
||||
tasks.Go(func() error {
|
||||
info, err := s.packIntelligenceData(ctx, data)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "[packIntelligenceData] failed id %v, type %d , name %s, err: %v", data.ID, data.Type, data.GetName(), err)
|
||||
return err
|
||||
}
|
||||
|
||||
for idx := range searchResp.Data {
|
||||
data := searchResp.Data[idx]
|
||||
index := idx
|
||||
tasks.Go(func() error {
|
||||
info, err := s.packIntelligenceData(ctx, data)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "[packIntelligenceData] failed id %v, type %d , name %s, err: %v", data.ID, data.Type, data.GetName(), err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
intelligenceDataList[index] = info
|
||||
return nil
|
||||
})
|
||||
|
||||
s.packIntelligenceData(ctx, data)
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
intelligenceDataList[index] = info
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(searchResp.Data) != 0 {
|
||||
info, err := s.packIntelligenceData(ctx, searchResp.Data[0])
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "[packIntelligenceData] failed id %v, type %d , name %s, err: %v", searchResp.Data[0].ID, searchResp.Data[0].Type, searchResp.Data[0].GetName(), err)
|
||||
return nil, err
|
||||
}
|
||||
lock.Lock()
|
||||
intelligenceDataList[0] = info
|
||||
lock.Unlock()
|
||||
}
|
||||
err = tasks.Wait()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_ = tasks.Wait()
|
||||
filterDataList := make([]*intelligence.IntelligenceData, 0)
|
||||
for _, data := range intelligenceDataList {
|
||||
if data != nil {
|
||||
|
||||
@ -86,25 +86,39 @@ func (s *SearchApplicationService) LibraryResourceList(ctx context.Context, req
|
||||
lock := sync.Mutex{}
|
||||
tasks := taskgroup.NewUninterruptibleTaskGroup(ctx, 10)
|
||||
resources := make([]*common.ResourceInfo, len(searchResp.Data))
|
||||
for idx := range searchResp.Data {
|
||||
v := searchResp.Data[idx]
|
||||
index := idx
|
||||
tasks.Go(func() error {
|
||||
ri, err := s.packResource(ctx, v)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "[LibraryResourceList] packResource failed, will ignore resID: %d, Name : %s, resType: %d, err: %v",
|
||||
v.ResID, v.GetName(), v.ResType, err)
|
||||
return err
|
||||
}
|
||||
if len(searchResp.Data) > 1 {
|
||||
for idx := range searchResp.Data[1:] {
|
||||
index := idx + 1
|
||||
v := searchResp.Data[index]
|
||||
tasks.Go(func() error {
|
||||
ri, err := s.packResource(ctx, v)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "[LibraryResourceList] packResource failed, will ignore resID: %d, Name : %s, resType: %d, err: %v",
|
||||
v.ResID, v.GetName(), v.ResType, err)
|
||||
return err
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
resources[index] = ri
|
||||
return nil
|
||||
})
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
resources[index] = ri
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(searchResp.Data) != 0 {
|
||||
ri, err := s.packResource(ctx, searchResp.Data[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lock.Lock()
|
||||
resources[0] = ri
|
||||
lock.Unlock()
|
||||
}
|
||||
err = tasks.Wait()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_ = tasks.Wait()
|
||||
filterResource := make([]*common.ResourceInfo, 0)
|
||||
for _, res := range resources {
|
||||
if res == nil {
|
||||
|
||||
@ -19,7 +19,10 @@ package user
|
||||
import (
|
||||
"context"
|
||||
"net/mail"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/developer_api"
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/playground"
|
||||
@ -30,7 +33,8 @@ import (
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
|
||||
langSlices "github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
|
||||
"github.com/coze-dev/coze-studio/backend/types/consts"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
@ -56,6 +60,11 @@ func (u *UserApplicationService) PassportWebEmailRegisterV2(ctx context.Context,
|
||||
return nil, "", errorx.New(errno.ErrUserInvalidParamCode, errorx.KV("msg", "Invalid email"))
|
||||
}
|
||||
|
||||
// Allow Register Checker
|
||||
if !u.allowRegisterChecker(req.GetEmail()) {
|
||||
return nil, "", errorx.New(errno.ErrNotAllowedRegisterCode)
|
||||
}
|
||||
|
||||
userInfo, err := u.DomainSVC.Create(ctx, &user.CreateUserRequest{
|
||||
Email: req.GetEmail(),
|
||||
Password: req.GetPassword(),
|
||||
@ -77,6 +86,20 @@ func (u *UserApplicationService) PassportWebEmailRegisterV2(ctx context.Context,
|
||||
}, userInfo.SessionKey, nil
|
||||
}
|
||||
|
||||
func (u *UserApplicationService) allowRegisterChecker(email string) bool {
|
||||
disableUserRegistration := os.Getenv(consts.DisableUserRegistration)
|
||||
if strings.ToLower(disableUserRegistration) != "true" {
|
||||
return true
|
||||
}
|
||||
|
||||
allowedEmails := os.Getenv(consts.AllowRegistrationEmail)
|
||||
if allowedEmails == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return slices.Contains(strings.Split(allowedEmails, ","), strings.ToLower(email))
|
||||
}
|
||||
|
||||
// PassportWebLogoutGet 处理用户登出请求
|
||||
func (u *UserApplicationService) PassportWebLogoutGet(ctx context.Context, req *passport.PassportWebLogoutGetRequest) (
|
||||
resp *passport.PassportWebLogoutGetResponse, err error,
|
||||
@ -204,7 +227,7 @@ func (u *UserApplicationService) GetSpaceListV2(ctx context.Context, req *playgr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
botSpaces := slices.Transform(spaces, func(space *entity.Space) *playground.BotSpaceV2 {
|
||||
botSpaces := langSlices.Transform(spaces, func(space *entity.Space) *playground.BotSpaceV2 {
|
||||
return &playground.BotSpaceV2{
|
||||
ID: space.ID,
|
||||
Name: space.Name,
|
||||
@ -230,7 +253,7 @@ func (u *UserApplicationService) GetSpaceListV2(ctx context.Context, req *playgr
|
||||
func (u *UserApplicationService) MGetUserBasicInfo(ctx context.Context, req *playground.MGetUserBasicInfoRequest) (
|
||||
resp *playground.MGetUserBasicInfoResponse, err error,
|
||||
) {
|
||||
userIDs, err := slices.TransformWithErrorCheck(req.GetUserIds(), func(s string) (int64, error) {
|
||||
userIDs, err := langSlices.TransformWithErrorCheck(req.GetUserIds(), func(s string) (int64, error) {
|
||||
return strconv.ParseInt(s, 10, 64)
|
||||
})
|
||||
if err != nil {
|
||||
@ -243,7 +266,7 @@ func (u *UserApplicationService) MGetUserBasicInfo(ctx context.Context, req *pla
|
||||
}
|
||||
|
||||
return &playground.MGetUserBasicInfoResponse{
|
||||
UserBasicInfoMap: slices.ToMap(userInfos, func(userInfo *entity.User) (string, *playground.UserBasicInfo) {
|
||||
UserBasicInfoMap: langSlices.ToMap(userInfos, func(userInfo *entity.User) (string, *playground.UserBasicInfo) {
|
||||
return strconv.FormatInt(userInfo.UserID, 10), userDo2PlaygroundTo(userInfo)
|
||||
}),
|
||||
Code: 0,
|
||||
|
||||
264
backend/application/workflow/chatflow.go
Normal file
264
backend/application/workflow/chatflow.go
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package workflow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/coze-dev/coze-studio/backend/types/consts"
|
||||
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/workflow"
|
||||
"github.com/coze-dev/coze-studio/backend/application/base/ctxutil"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/maps"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ternary"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/safego"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
func (w *ApplicationService) CreateApplicationConversationDef(ctx context.Context, req *workflow.CreateProjectConversationDefRequest) (resp *workflow.CreateProjectConversationDefResponse, err error) {
|
||||
defer func() {
|
||||
if panicErr := recover(); panicErr != nil {
|
||||
err = safego.NewPanicErr(panicErr, debug.Stack())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = vo.WrapIfNeeded(errno.ErrConversationOfAppOperationFail, err, errorx.KV("cause", vo.UnwrapRootErr(err).Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
var (
|
||||
spaceID = mustParseInt64(req.GetSpaceID())
|
||||
appID = mustParseInt64(req.GetProjectID())
|
||||
userID = ctxutil.MustGetUIDFromCtx(ctx)
|
||||
)
|
||||
|
||||
if err := checkUserSpace(ctx, userID, spaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uniqueID, err := GetWorkflowDomainSVC().CreateDraftConversationTemplate(ctx, &vo.CreateConversationTemplateMeta{
|
||||
AppID: appID,
|
||||
SpaceID: spaceID,
|
||||
Name: req.GetConversationName(),
|
||||
UserID: userID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &workflow.CreateProjectConversationDefResponse{
|
||||
UniqueID: strconv.FormatInt(uniqueID, 10),
|
||||
SpaceID: req.GetSpaceID(),
|
||||
}, err
|
||||
}
|
||||
|
||||
func (w *ApplicationService) UpdateApplicationConversationDef(ctx context.Context, req *workflow.UpdateProjectConversationDefRequest) (resp *workflow.UpdateProjectConversationDefResponse, err error) {
|
||||
defer func() {
|
||||
if panicErr := recover(); panicErr != nil {
|
||||
err = safego.NewPanicErr(panicErr, debug.Stack())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = vo.WrapIfNeeded(errno.ErrConversationOfAppOperationFail, err, errorx.KV("cause", vo.UnwrapRootErr(err).Error()))
|
||||
}
|
||||
}()
|
||||
var (
|
||||
spaceID = mustParseInt64(req.GetSpaceID())
|
||||
templateID = mustParseInt64(req.GetUniqueID())
|
||||
appID = mustParseInt64(req.GetProjectID())
|
||||
userID = ctxutil.MustGetUIDFromCtx(ctx)
|
||||
)
|
||||
|
||||
if err := checkUserSpace(ctx, userID, spaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = GetWorkflowDomainSVC().UpdateDraftConversationTemplateName(ctx, appID, userID, templateID, req.GetConversationName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &workflow.UpdateProjectConversationDefResponse{}, err
|
||||
}
|
||||
|
||||
func (w *ApplicationService) DeleteApplicationConversationDef(ctx context.Context, req *workflow.DeleteProjectConversationDefRequest) (resp *workflow.DeleteProjectConversationDefResponse, err error) {
|
||||
defer func() {
|
||||
if panicErr := recover(); panicErr != nil {
|
||||
err = safego.NewPanicErr(panicErr, debug.Stack())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = vo.WrapIfNeeded(errno.ErrConversationOfAppOperationFail, err, errorx.KV("cause", vo.UnwrapRootErr(err).Error()))
|
||||
}
|
||||
}()
|
||||
var (
|
||||
appID = mustParseInt64(req.GetProjectID())
|
||||
templateID = mustParseInt64(req.GetUniqueID())
|
||||
)
|
||||
if err := checkUserSpace(ctx, ctxutil.MustGetUIDFromCtx(ctx), mustParseInt64(req.GetSpaceID())); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req.GetCheckOnly() {
|
||||
wfs, err := GetWorkflowDomainSVC().CheckWorkflowsToReplace(ctx, appID, templateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp = &workflow.DeleteProjectConversationDefResponse{NeedReplace: make([]*workflow.Workflow, 0)}
|
||||
for _, wf := range wfs {
|
||||
resp.NeedReplace = append(resp.NeedReplace, &workflow.Workflow{
|
||||
Name: wf.Name,
|
||||
URL: wf.IconURL,
|
||||
WorkflowID: strconv.FormatInt(wf.ID, 10),
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
wfID2ConversationName, err := maps.TransformKeyWithErrorCheck(req.GetReplace(), func(k1 string) (int64, error) {
|
||||
return strconv.ParseInt(k1, 10, 64)
|
||||
})
|
||||
|
||||
rowsAffected, err := GetWorkflowDomainSVC().DeleteDraftConversationTemplate(ctx, templateID, wfID2ConversationName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rowsAffected > 0 {
|
||||
return &workflow.DeleteProjectConversationDefResponse{
|
||||
Success: true,
|
||||
}, err
|
||||
}
|
||||
|
||||
rowsAffected, err = GetWorkflowDomainSVC().DeleteDynamicConversation(ctx, vo.Draft, templateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, fmt.Errorf("delete conversation failed")
|
||||
}
|
||||
|
||||
return &workflow.DeleteProjectConversationDefResponse{
|
||||
Success: true,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (w *ApplicationService) ListApplicationConversationDef(ctx context.Context, req *workflow.ListProjectConversationRequest) (resp *workflow.ListProjectConversationResponse, err error) {
|
||||
defer func() {
|
||||
if panicErr := recover(); panicErr != nil {
|
||||
err = safego.NewPanicErr(panicErr, debug.Stack())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = vo.WrapIfNeeded(errno.ErrConversationOfAppOperationFail, err, errorx.KV("cause", vo.UnwrapRootErr(err).Error()))
|
||||
}
|
||||
}()
|
||||
var connectorID int64
|
||||
if len(req.GetConnectorID()) != 0 {
|
||||
connectorID = mustParseInt64(req.GetConnectorID())
|
||||
} else {
|
||||
connectorID = consts.CozeConnectorID
|
||||
}
|
||||
var (
|
||||
page = mustParseInt64(ternary.IFElse(req.GetCursor() == "", "0", req.GetCursor()))
|
||||
size = req.GetLimit()
|
||||
userID = ctxutil.MustGetUIDFromCtx(ctx)
|
||||
spaceID = mustParseInt64(req.GetSpaceID())
|
||||
appID = mustParseInt64(req.GetProjectID())
|
||||
version = req.ProjectVersion
|
||||
listConversationMeta = vo.ListConversationMeta{
|
||||
APPID: appID,
|
||||
UserID: userID,
|
||||
ConnectorID: connectorID,
|
||||
}
|
||||
)
|
||||
|
||||
if err := checkUserSpace(ctx, userID, spaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
env := ternary.IFElse(req.GetCreateEnv() == workflow.CreateEnv_Draft, vo.Draft, vo.Online)
|
||||
if req.GetCreateMethod() == workflow.CreateMethod_ManualCreate {
|
||||
templates, err := GetWorkflowDomainSVC().ListConversationTemplate(ctx, env, &vo.ListConversationTemplatePolicy{
|
||||
AppID: appID,
|
||||
Page: &vo.Page{
|
||||
Page: int32(page),
|
||||
Size: int32(size),
|
||||
},
|
||||
NameLike: ternary.IFElse(len(req.GetNameLike()) == 0, nil, ptr.Of(req.GetNameLike())),
|
||||
Version: version,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stsConversations, err := GetWorkflowDomainSVC().MGetStaticConversation(ctx, env, userID, connectorID, slices.Transform(templates, func(a *entity.ConversationTemplate) int64 {
|
||||
return a.TemplateID
|
||||
}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stsConversationMap := slices.ToMap(stsConversations, func(e *entity.StaticConversation) (int64, *entity.StaticConversation) {
|
||||
return e.TemplateID, e
|
||||
})
|
||||
|
||||
resp = &workflow.ListProjectConversationResponse{Data: make([]*workflow.ProjectConversation, 0)}
|
||||
for _, tmpl := range templates {
|
||||
conversationID := ""
|
||||
if c, ok := stsConversationMap[tmpl.TemplateID]; ok {
|
||||
conversationID = strconv.FormatInt(c.ConversationID, 10)
|
||||
}
|
||||
resp.Data = append(resp.Data, &workflow.ProjectConversation{
|
||||
UniqueID: strconv.FormatInt(tmpl.TemplateID, 10),
|
||||
ConversationName: tmpl.Name,
|
||||
ConversationID: conversationID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if req.GetCreateMethod() == workflow.CreateMethod_NodeCreate {
|
||||
dyConversations, err := GetWorkflowDomainSVC().ListDynamicConversation(ctx, env, &vo.ListConversationPolicy{
|
||||
ListConversationMeta: listConversationMeta,
|
||||
Page: &vo.Page{
|
||||
Page: int32(page),
|
||||
Size: int32(size),
|
||||
},
|
||||
NameLike: ternary.IFElse(len(req.GetNameLike()) == 0, nil, ptr.Of(req.GetNameLike())),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp = &workflow.ListProjectConversationResponse{Data: make([]*workflow.ProjectConversation, 0, len(dyConversations))}
|
||||
resp.Data = append(resp.Data, slices.Transform(dyConversations, func(a *entity.DynamicConversation) *workflow.ProjectConversation {
|
||||
return &workflow.ProjectConversation{
|
||||
UniqueID: strconv.FormatInt(a.ID, 10),
|
||||
ConversationName: a.Name,
|
||||
ConversationID: strconv.FormatInt(a.ConversationID, 10),
|
||||
}
|
||||
})...)
|
||||
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@ -17,10 +17,12 @@
|
||||
package workflow
|
||||
|
||||
import (
|
||||
"github.com/cloudwego/eino/callbacks"
|
||||
"github.com/cloudwego/eino/compose"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
|
||||
wfconversation "github.com/coze-dev/coze-studio/backend/crossdomain/workflow/conversation"
|
||||
wfdatabase "github.com/coze-dev/coze-studio/backend/crossdomain/workflow/database"
|
||||
wfknowledge "github.com/coze-dev/coze-studio/backend/crossdomain/workflow/knowledge"
|
||||
wfmodel "github.com/coze-dev/coze-studio/backend/crossdomain/workflow/model"
|
||||
@ -34,6 +36,7 @@ import (
|
||||
search "github.com/coze-dev/coze-studio/backend/domain/search/service"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow"
|
||||
crosscode "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/code"
|
||||
crossconversation "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/conversation"
|
||||
crossdatabase "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/database"
|
||||
crossknowledge "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/knowledge"
|
||||
crossmodel "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/model"
|
||||
@ -41,6 +44,7 @@ import (
|
||||
crosssearch "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/search"
|
||||
crossvariable "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/variable"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/service"
|
||||
workflowservice "github.com/coze-dev/coze-studio/backend/domain/workflow/service"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/coderunner"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/idgen"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/imagex"
|
||||
@ -78,6 +82,8 @@ func InitService(components *ServiceComponents) *ApplicationService {
|
||||
crossmodel.SetManager(wfmodel.NewModelManager(components.ModelManager, nil))
|
||||
crosscode.SetCodeRunner(components.CodeRunner)
|
||||
crosssearch.SetNotifier(wfsearch.NewNotify(components.DomainNotifier))
|
||||
crossconversation.SetConversationManager(wfconversation.NewConversationRepository())
|
||||
callbacks.AppendGlobalHandlers(workflowservice.GetTokenCallbackHandler())
|
||||
|
||||
SVC.DomainSVC = workflowDomainSVC
|
||||
SVC.ImageX = components.ImageX
|
||||
|
||||
@ -93,7 +93,7 @@ func (w *ApplicationService) GetNodeTemplateList(ctx context.Context, req *workf
|
||||
|
||||
toQueryTypes := make(map[entity.NodeType]bool)
|
||||
for _, t := range req.NodeTypes {
|
||||
entityType, err := nodeType2EntityNodeType(t)
|
||||
entityType, err := entity.BlockType2EntityNodeType(t)
|
||||
if err != nil {
|
||||
logs.Warnf("get node type %v failed, err:=%v", t, err)
|
||||
continue
|
||||
@ -116,7 +116,7 @@ func (w *ApplicationService) GetNodeTemplateList(ctx context.Context, req *workf
|
||||
Name: category,
|
||||
}
|
||||
for _, nodeMeta := range nodeMetaList {
|
||||
tplType, err := entityNodeTypeToAPINodeTemplateType(nodeMeta.Type)
|
||||
tplType, err := entity.NodeTypeToAPINodeTemplateType(nodeMeta.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -169,6 +169,21 @@ func (w *ApplicationService) CreateWorkflow(ctx context.Context, req *workflow.C
|
||||
if err := checkUserSpace(ctx, uID, spaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var createConversation bool
|
||||
if req.ProjectID != nil && req.IsSetFlowMode() && req.GetFlowMode() == workflow.WorkflowMode_ChatFlow && req.IsSetCreateConversation() && req.GetCreateConversation() {
|
||||
createConversation = true
|
||||
_, err := GetWorkflowDomainSVC().CreateDraftConversationTemplate(ctx, &vo.CreateConversationTemplateMeta{
|
||||
AppID: mustParseInt64(req.GetProjectID()),
|
||||
UserID: uID,
|
||||
SpaceID: spaceID,
|
||||
Name: req.Name,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
wf := &vo.MetaCreate{
|
||||
CreatorID: uID,
|
||||
SpaceID: spaceID,
|
||||
@ -180,6 +195,13 @@ func (w *ApplicationService) CreateWorkflow(ctx context.Context, req *workflow.C
|
||||
Mode: ternary.IFElse(req.IsSetFlowMode(), req.GetFlowMode(), workflow.WorkflowMode_Workflow),
|
||||
InitCanvasSchema: entity.GetDefaultInitCanvasJsonSchema(i18n.GetLocale(ctx)),
|
||||
}
|
||||
if req.IsSetFlowMode() && req.GetFlowMode() == workflow.WorkflowMode_ChatFlow {
|
||||
conversationName := req.Name
|
||||
if !req.IsSetProjectID() || mustParseInt64(req.GetProjectID()) == 0 || !createConversation {
|
||||
conversationName = "Default"
|
||||
}
|
||||
wf.InitCanvasSchema = entity.GetDefaultInitCanvasJsonSchemaChat(i18n.GetLocale(ctx), conversationName)
|
||||
}
|
||||
|
||||
id, err := GetWorkflowDomainSVC().Create(ctx, wf)
|
||||
if err != nil {
|
||||
@ -1034,6 +1056,18 @@ func (w *ApplicationService) CopyWorkflowFromLibraryToApp(ctx context.Context, w
|
||||
wf, err := GetWorkflowDomainSVC().CopyWorkflow(ctx, workflowID, vo.CopyWorkflowPolicy{
|
||||
TargetAppID: &appID,
|
||||
})
|
||||
|
||||
if wf.Mode == workflow.WorkflowMode_ChatFlow {
|
||||
err = GetWorkflowDomainSVC().CopyChatFlowRole(ctx, &vo.CopyRolePolicy{
|
||||
SourceID: workflowID,
|
||||
TargetID: wf.ID,
|
||||
CreatorID: wf.CreatorID,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -1127,7 +1161,7 @@ func (w *ApplicationService) MoveWorkflowFromAppToLibrary(ctx context.Context, w
|
||||
}
|
||||
|
||||
func convertNodeExecution(nodeExe *entity.NodeExecution) (*workflow.NodeResult, error) {
|
||||
nType, err := entityNodeTypeToAPINodeTemplateType(nodeExe.NodeType)
|
||||
nType, err := entity.NodeTypeToAPINodeTemplateType(nodeExe.NodeType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1317,7 +1351,7 @@ func convertStreamRunEvent(workflowID int64) func(msg *entity.Message) (res *wor
|
||||
}
|
||||
|
||||
var nodeType workflow.NodeTemplateType
|
||||
nodeType, err = entityNodeTypeToAPINodeTemplateType(msg.NodeType)
|
||||
nodeType, err = entity.NodeTypeToAPINodeTemplateType(msg.NodeType)
|
||||
if err != nil {
|
||||
logs.Errorf("convert node type %v failed, err:=%v", msg.NodeType, err)
|
||||
nodeType = workflow.NodeTemplateType(0)
|
||||
@ -2087,6 +2121,11 @@ func (w *ApplicationService) ListWorkflow(ctx context.Context, req *workflow.Get
|
||||
},
|
||||
}
|
||||
|
||||
ww.CheckResult, err = GetWorkflowDomainSVC().WorkflowSchemaCheck(ctx, w, req.Checker)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if qType == vo.FromDraft {
|
||||
ww.UpdateTime = w.DraftMeta.Timestamp.Unix()
|
||||
} else if qType == vo.FromLatestVersion || qType == vo.FromSpecificVersion {
|
||||
@ -3338,178 +3377,6 @@ func toWorkflowParameter(nType *vo.NamedTypeInfo) (*workflow.Parameter, error) {
|
||||
return wp, nil
|
||||
}
|
||||
|
||||
func nodeType2EntityNodeType(t string) (entity.NodeType, error) {
|
||||
i, err := strconv.Atoi(t)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid node type string '%s': %w", t, err)
|
||||
}
|
||||
|
||||
switch i {
|
||||
case 1:
|
||||
return entity.NodeTypeEntry, nil
|
||||
case 2:
|
||||
return entity.NodeTypeExit, nil
|
||||
case 3:
|
||||
return entity.NodeTypeLLM, nil
|
||||
case 4:
|
||||
return entity.NodeTypePlugin, nil
|
||||
case 5:
|
||||
return entity.NodeTypeCodeRunner, nil
|
||||
case 6:
|
||||
return entity.NodeTypeKnowledgeRetriever, nil
|
||||
case 8:
|
||||
return entity.NodeTypeSelector, nil
|
||||
case 9:
|
||||
return entity.NodeTypeSubWorkflow, nil
|
||||
case 12:
|
||||
return entity.NodeTypeDatabaseCustomSQL, nil
|
||||
case 13:
|
||||
return entity.NodeTypeOutputEmitter, nil
|
||||
case 15:
|
||||
return entity.NodeTypeTextProcessor, nil
|
||||
case 18:
|
||||
return entity.NodeTypeQuestionAnswer, nil
|
||||
case 19:
|
||||
return entity.NodeTypeBreak, nil
|
||||
case 20:
|
||||
return entity.NodeTypeVariableAssignerWithinLoop, nil
|
||||
case 21:
|
||||
return entity.NodeTypeLoop, nil
|
||||
case 22:
|
||||
return entity.NodeTypeIntentDetector, nil
|
||||
case 27:
|
||||
return entity.NodeTypeKnowledgeIndexer, nil
|
||||
case 28:
|
||||
return entity.NodeTypeBatch, nil
|
||||
case 29:
|
||||
return entity.NodeTypeContinue, nil
|
||||
case 30:
|
||||
return entity.NodeTypeInputReceiver, nil
|
||||
case 32:
|
||||
return entity.NodeTypeVariableAggregator, nil
|
||||
case 37:
|
||||
return entity.NodeTypeMessageList, nil
|
||||
case 38:
|
||||
return entity.NodeTypeClearMessage, nil
|
||||
case 39:
|
||||
return entity.NodeTypeCreateConversation, nil
|
||||
case 40:
|
||||
return entity.NodeTypeVariableAssigner, nil
|
||||
case 42:
|
||||
return entity.NodeTypeDatabaseUpdate, nil
|
||||
case 43:
|
||||
return entity.NodeTypeDatabaseQuery, nil
|
||||
case 44:
|
||||
return entity.NodeTypeDatabaseDelete, nil
|
||||
case 45:
|
||||
return entity.NodeTypeHTTPRequester, nil
|
||||
case 46:
|
||||
return entity.NodeTypeDatabaseInsert, nil
|
||||
case 58:
|
||||
return entity.NodeTypeJsonSerialization, nil
|
||||
case 59:
|
||||
return entity.NodeTypeJsonDeserialization, nil
|
||||
case 60:
|
||||
return entity.NodeTypeKnowledgeDeleter, nil
|
||||
default:
|
||||
// Handle all unknown or unsupported types here
|
||||
return "", fmt.Errorf("unsupported or unknown node type ID: %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
// entityNodeTypeToAPINodeTemplateType converts an entity.NodeType to the corresponding workflow.NodeTemplateType.
|
||||
func entityNodeTypeToAPINodeTemplateType(nodeType entity.NodeType) (workflow.NodeTemplateType, error) {
|
||||
switch nodeType {
|
||||
case entity.NodeTypeEntry:
|
||||
return workflow.NodeTemplateType_Start, nil
|
||||
case entity.NodeTypeExit:
|
||||
return workflow.NodeTemplateType_End, nil
|
||||
case entity.NodeTypeLLM:
|
||||
return workflow.NodeTemplateType_LLM, nil
|
||||
case entity.NodeTypePlugin:
|
||||
// Maps to Api type in the API model
|
||||
return workflow.NodeTemplateType_Api, nil
|
||||
case entity.NodeTypeCodeRunner:
|
||||
return workflow.NodeTemplateType_Code, nil
|
||||
case entity.NodeTypeKnowledgeRetriever:
|
||||
// Maps to Dataset type in the API model
|
||||
return workflow.NodeTemplateType_Dataset, nil
|
||||
case entity.NodeTypeSelector:
|
||||
// Maps to If type in the API model
|
||||
return workflow.NodeTemplateType_If, nil
|
||||
case entity.NodeTypeSubWorkflow:
|
||||
return workflow.NodeTemplateType_SubWorkflow, nil
|
||||
case entity.NodeTypeDatabaseCustomSQL:
|
||||
// Maps to the generic Database type in the API model
|
||||
return workflow.NodeTemplateType_Database, nil
|
||||
case entity.NodeTypeOutputEmitter:
|
||||
// Maps to Message type in the API model
|
||||
return workflow.NodeTemplateType_Message, nil
|
||||
case entity.NodeTypeTextProcessor:
|
||||
return workflow.NodeTemplateType_Text, nil
|
||||
case entity.NodeTypeQuestionAnswer:
|
||||
return workflow.NodeTemplateType_Question, nil
|
||||
case entity.NodeTypeBreak:
|
||||
return workflow.NodeTemplateType_Break, nil
|
||||
case entity.NodeTypeVariableAssigner:
|
||||
return workflow.NodeTemplateType_AssignVariable, nil
|
||||
case entity.NodeTypeVariableAssignerWithinLoop:
|
||||
return workflow.NodeTemplateType_LoopSetVariable, nil
|
||||
case entity.NodeTypeLoop:
|
||||
return workflow.NodeTemplateType_Loop, nil
|
||||
case entity.NodeTypeIntentDetector:
|
||||
return workflow.NodeTemplateType_Intent, nil
|
||||
case entity.NodeTypeKnowledgeIndexer:
|
||||
// Maps to DatasetWrite type in the API model
|
||||
return workflow.NodeTemplateType_DatasetWrite, nil
|
||||
case entity.NodeTypeBatch:
|
||||
return workflow.NodeTemplateType_Batch, nil
|
||||
case entity.NodeTypeContinue:
|
||||
return workflow.NodeTemplateType_Continue, nil
|
||||
case entity.NodeTypeInputReceiver:
|
||||
return workflow.NodeTemplateType_Input, nil
|
||||
case entity.NodeTypeMessageList:
|
||||
return workflow.NodeTemplateType(37), nil
|
||||
case entity.NodeTypeVariableAggregator:
|
||||
return workflow.NodeTemplateType(32), nil
|
||||
case entity.NodeTypeClearMessage:
|
||||
return workflow.NodeTemplateType(38), nil
|
||||
case entity.NodeTypeCreateConversation:
|
||||
return workflow.NodeTemplateType(39), nil
|
||||
// Note: entity.NodeTypeVariableAggregator (ID 32) has no direct mapping in NodeTemplateType
|
||||
// Note: entity.NodeTypeMessageList (ID 37) has no direct mapping in NodeTemplateType
|
||||
// Note: entity.NodeTypeClearMessage (ID 38) has no direct mapping in NodeTemplateType
|
||||
// Note: entity.NodeTypeCreateConversation (ID 39) has no direct mapping in NodeTemplateType
|
||||
case entity.NodeTypeDatabaseUpdate:
|
||||
return workflow.NodeTemplateType_DatabaseUpdate, nil
|
||||
case entity.NodeTypeDatabaseQuery:
|
||||
// Maps to DatabasesELECT (ID 43) in the API model (note potential typo)
|
||||
return workflow.NodeTemplateType_DatabasesELECT, nil
|
||||
case entity.NodeTypeDatabaseDelete:
|
||||
return workflow.NodeTemplateType_DatabaseDelete, nil
|
||||
|
||||
// Note: entity.NodeTypeHTTPRequester (ID 45) has no direct mapping in NodeTemplateType
|
||||
case entity.NodeTypeHTTPRequester:
|
||||
return workflow.NodeTemplateType(45), nil
|
||||
|
||||
case entity.NodeTypeDatabaseInsert:
|
||||
// Maps to DatabaseInsert (ID 41) in the API model, despite entity ID being 46.
|
||||
// return workflow.NodeTemplateType_DatabaseInsert, nil
|
||||
return workflow.NodeTemplateType(46), nil
|
||||
case entity.NodeTypeJsonSerialization:
|
||||
return workflow.NodeTemplateType_JsonSerialization, nil
|
||||
case entity.NodeTypeJsonDeserialization:
|
||||
return workflow.NodeTemplateType_JsonDeserialization, nil
|
||||
case entity.NodeTypeKnowledgeDeleter:
|
||||
return workflow.NodeTemplateType_DatasetDelete, nil
|
||||
case entity.NodeTypeLambda:
|
||||
return 0, nil
|
||||
default:
|
||||
// Handle entity types that don't have a corresponding NodeTemplateType
|
||||
return workflow.NodeTemplateType(0), fmt.Errorf("cannot map entity node type '%s' to a workflow.NodeTemplateType", nodeType)
|
||||
}
|
||||
}
|
||||
|
||||
func i64PtrToStringPtr(i *int64) *string {
|
||||
if i == nil {
|
||||
return nil
|
||||
@ -3813,3 +3680,357 @@ func checkUserSpace(ctx context.Context, uid int64, spaceID int64) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *ApplicationService) populateChatFlowRoleFields(role *workflow.ChatFlowRole, targetRole interface{}) error {
|
||||
var avatarUri, audioStr, bgStr, obStr, srStr, uiStr string
|
||||
var err error
|
||||
|
||||
if role.Avatar != nil {
|
||||
avatarUri = role.Avatar.ImageUri
|
||||
|
||||
}
|
||||
if role.AudioConfig != nil {
|
||||
audioStr, err = sonic.MarshalString(*role.AudioConfig)
|
||||
if err != nil {
|
||||
return vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
if role.BackgroundImageInfo != nil {
|
||||
bgStr, err = sonic.MarshalString(*role.BackgroundImageInfo)
|
||||
if err != nil {
|
||||
return vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
if role.OnboardingInfo != nil {
|
||||
obStr, err = sonic.MarshalString(*role.OnboardingInfo)
|
||||
if err != nil {
|
||||
return vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
if role.SuggestReplyInfo != nil {
|
||||
srStr, err = sonic.MarshalString(*role.SuggestReplyInfo)
|
||||
if err != nil {
|
||||
return vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
if role.UserInputConfig != nil {
|
||||
uiStr, err = sonic.MarshalString(*role.UserInputConfig)
|
||||
if err != nil {
|
||||
return vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
|
||||
switch r := targetRole.(type) {
|
||||
case *vo.ChatFlowRoleCreate:
|
||||
if role.Name != nil {
|
||||
r.Name = *role.Name
|
||||
}
|
||||
if role.Description != nil {
|
||||
r.Description = *role.Description
|
||||
}
|
||||
if avatarUri != "" {
|
||||
r.AvatarUri = avatarUri
|
||||
}
|
||||
if audioStr != "" {
|
||||
r.AudioConfig = audioStr
|
||||
}
|
||||
if bgStr != "" {
|
||||
r.BackgroundImageInfo = bgStr
|
||||
}
|
||||
if obStr != "" {
|
||||
r.OnboardingInfo = obStr
|
||||
}
|
||||
if srStr != "" {
|
||||
r.SuggestReplyInfo = srStr
|
||||
}
|
||||
if uiStr != "" {
|
||||
r.UserInputConfig = uiStr
|
||||
}
|
||||
case *vo.ChatFlowRoleUpdate:
|
||||
r.Name = role.Name
|
||||
r.Description = role.Description
|
||||
if avatarUri != "" {
|
||||
r.AvatarUri = ptr.Of(avatarUri)
|
||||
}
|
||||
if audioStr != "" {
|
||||
r.AudioConfig = ptr.Of(audioStr)
|
||||
}
|
||||
if bgStr != "" {
|
||||
r.BackgroundImageInfo = ptr.Of(bgStr)
|
||||
}
|
||||
if obStr != "" {
|
||||
r.OnboardingInfo = ptr.Of(obStr)
|
||||
}
|
||||
if srStr != "" {
|
||||
r.SuggestReplyInfo = ptr.Of(srStr)
|
||||
}
|
||||
if uiStr != "" {
|
||||
r.UserInputConfig = ptr.Of(uiStr)
|
||||
}
|
||||
default:
|
||||
return vo.WrapError(errno.ErrInvalidParameter, fmt.Errorf("invalid type for targetRole: %T", targetRole))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsChatFlow(wf *entity.Workflow) bool {
|
||||
if wf == nil || wf.ID == 0 {
|
||||
return false
|
||||
}
|
||||
return wf.Meta.Mode == workflow.WorkflowMode_ChatFlow
|
||||
}
|
||||
|
||||
func (w *ApplicationService) CreateChatFlowRole(ctx context.Context, req *workflow.CreateChatFlowRoleRequest) (
|
||||
_ *workflow.CreateChatFlowRoleResponse, err error) {
|
||||
defer func() {
|
||||
if panicErr := recover(); panicErr != nil {
|
||||
err = safego.NewPanicErr(panicErr, debug.Stack())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = vo.WrapIfNeeded(errno.ErrChatFlowRoleOperationFail, err, errorx.KV("cause", vo.UnwrapRootErr(err).Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
uID := ctxutil.MustGetUIDFromCtx(ctx)
|
||||
wf, err := GetWorkflowDomainSVC().Get(ctx, &vo.GetPolicy{
|
||||
ID: mustParseInt64(req.GetChatFlowRole().GetWorkflowID()),
|
||||
MetaOnly: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = checkUserSpace(ctx, uID, wf.Meta.SpaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
role := req.GetChatFlowRole()
|
||||
|
||||
if !IsChatFlow(wf) {
|
||||
logs.CtxWarnf(ctx, "CreateChatFlowRole not chat flow, workflowID: %d", wf.ID)
|
||||
return nil, vo.WrapError(errno.ErrChatFlowRoleOperationFail, fmt.Errorf("workflow %d is not a chat flow", wf.ID))
|
||||
}
|
||||
|
||||
oldRole, err := GetWorkflowDomainSVC().GetChatFlowRole(ctx, mustParseInt64(role.WorkflowID), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var roleID int64
|
||||
if oldRole != nil {
|
||||
role.ID = strconv.FormatInt(oldRole.ID, 10)
|
||||
roleID = oldRole.ID
|
||||
}
|
||||
|
||||
if role.GetID() == "" || role.GetID() == "0" {
|
||||
chatFlowRole := &vo.ChatFlowRoleCreate{
|
||||
WorkflowID: mustParseInt64(role.WorkflowID),
|
||||
CreatorID: uID,
|
||||
}
|
||||
if err = w.populateChatFlowRoleFields(role, chatFlowRole); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roleID, err = GetWorkflowDomainSVC().CreateChatFlowRole(ctx, chatFlowRole)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
chatFlowRole := &vo.ChatFlowRoleUpdate{
|
||||
WorkflowID: mustParseInt64(role.WorkflowID),
|
||||
}
|
||||
|
||||
if err = w.populateChatFlowRoleFields(role, chatFlowRole); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = GetWorkflowDomainSVC().UpdateChatFlowRole(ctx, chatFlowRole.WorkflowID, chatFlowRole)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &workflow.CreateChatFlowRoleResponse{
|
||||
ID: strconv.FormatInt(roleID, 10),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (w *ApplicationService) DeleteChatFlowRole(ctx context.Context, req *workflow.DeleteChatFlowRoleRequest) (
|
||||
_ *workflow.DeleteChatFlowRoleResponse, err error) {
|
||||
defer func() {
|
||||
if panicErr := recover(); panicErr != nil {
|
||||
err = safego.NewPanicErr(panicErr, debug.Stack())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = vo.WrapIfNeeded(errno.ErrChatFlowRoleOperationFail, err, errorx.KV("cause", vo.UnwrapRootErr(err).Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
uID := ctxutil.MustGetUIDFromCtx(ctx)
|
||||
wf, err := GetWorkflowDomainSVC().Get(ctx, &vo.GetPolicy{
|
||||
ID: mustParseInt64(req.GetWorkflowID()),
|
||||
MetaOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = checkUserSpace(ctx, uID, wf.Meta.SpaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = GetWorkflowDomainSVC().DeleteChatFlowRole(ctx, mustParseInt64(req.ID), mustParseInt64(req.WorkflowID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &workflow.DeleteChatFlowRoleResponse{}, nil
|
||||
}
|
||||
|
||||
func (w *ApplicationService) GetChatFlowRole(ctx context.Context, req *workflow.GetChatFlowRoleRequest) (
|
||||
_ *workflow.GetChatFlowRoleResponse, err error) {
|
||||
defer func() {
|
||||
if panicErr := recover(); panicErr != nil {
|
||||
err = safego.NewPanicErr(panicErr, debug.Stack())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = vo.WrapIfNeeded(errno.ErrChatFlowRoleOperationFail, err, errorx.KV("cause", vo.UnwrapRootErr(err).Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
uID := ctxutil.MustGetUIDFromCtx(ctx)
|
||||
wf, err := GetWorkflowDomainSVC().Get(ctx, &vo.GetPolicy{
|
||||
ID: mustParseInt64(req.GetWorkflowID()),
|
||||
MetaOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = checkUserSpace(ctx, uID, wf.Meta.SpaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !IsChatFlow(wf) {
|
||||
logs.CtxWarnf(ctx, "GetChatFlowRole not chat flow, workflowID: %d", wf.ID)
|
||||
return nil, vo.WrapError(errno.ErrChatFlowRoleOperationFail, fmt.Errorf("workflow %d is not a chat flow", wf.ID))
|
||||
}
|
||||
|
||||
var version string
|
||||
if wf.Meta.AppID != nil {
|
||||
vl, err := GetWorkflowDomainSVC().GetWorkflowVersionsByConnector(ctx, mustParseInt64(req.GetConnectorID()), wf.ID, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(vl) > 0 {
|
||||
version = vl[0]
|
||||
}
|
||||
}
|
||||
|
||||
role, err := GetWorkflowDomainSVC().GetChatFlowRole(ctx, mustParseInt64(req.WorkflowID), version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if role == nil {
|
||||
logs.CtxWarnf(ctx, "GetChatFlowRole role nil, workflowID: %d", wf.ID)
|
||||
// Return nil for the error to align with the production behavior,
|
||||
// where the GET API may be called before the CREATE API during chatflow creation.
|
||||
return &workflow.GetChatFlowRoleResponse{}, nil
|
||||
}
|
||||
|
||||
wfRole, err := w.convertChatFlowRole(ctx, role)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get chat flow role config, internal data processing error: %+v", err)
|
||||
}
|
||||
|
||||
return &workflow.GetChatFlowRoleResponse{
|
||||
Role: wfRole,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (w *ApplicationService) convertChatFlowRole(ctx context.Context, role *entity.ChatFlowRole) (*workflow.ChatFlowRole, error) {
|
||||
var err error
|
||||
res := &workflow.ChatFlowRole{
|
||||
ID: strconv.FormatInt(role.ID, 10),
|
||||
WorkflowID: strconv.FormatInt(role.WorkflowID, 10),
|
||||
Name: ptr.Of(role.Name),
|
||||
Description: ptr.Of(role.Description),
|
||||
}
|
||||
|
||||
if role.AvatarUri != "" {
|
||||
url, err := w.ImageX.GetResourceURL(ctx, role.AvatarUri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Avatar = &workflow.AvatarConfig{
|
||||
ImageUri: role.AvatarUri,
|
||||
ImageUrl: url.URL,
|
||||
}
|
||||
}
|
||||
|
||||
if role.AudioConfig != "" {
|
||||
err = sonic.UnmarshalString(role.AudioConfig, &res.AudioConfig)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetChatFlowRole AudioConfig UnmarshalString err: %+v", err)
|
||||
return nil, vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
|
||||
if role.OnboardingInfo != "" {
|
||||
err = sonic.UnmarshalString(role.OnboardingInfo, &res.OnboardingInfo)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetChatFlowRole OnboardingInfo UnmarshalString err: %+v", err)
|
||||
return nil, vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
|
||||
if role.SuggestReplyInfo != "" {
|
||||
err = sonic.UnmarshalString(role.SuggestReplyInfo, &res.SuggestReplyInfo)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetChatFlowRole SuggestReplyInfo UnmarshalString err: %+v", err)
|
||||
return nil, vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
|
||||
if role.UserInputConfig != "" {
|
||||
err = sonic.UnmarshalString(role.UserInputConfig, &res.UserInputConfig)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetChatFlowRole UserInputConfig UnmarshalString err: %+v", err)
|
||||
return nil, vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
}
|
||||
|
||||
if role.BackgroundImageInfo != "" {
|
||||
res.BackgroundImageInfo = &workflow.BackgroundImageInfo{}
|
||||
err = sonic.UnmarshalString(role.BackgroundImageInfo, res.BackgroundImageInfo)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "GetChatFlowRole BackgroundImageInfo UnmarshalString err: %+v", err)
|
||||
return nil, vo.WrapError(errno.ErrSerializationDeserializationFail, err)
|
||||
}
|
||||
if res.BackgroundImageInfo != nil {
|
||||
if res.BackgroundImageInfo.WebBackgroundImage != nil && res.BackgroundImageInfo.WebBackgroundImage.OriginImageUri != nil {
|
||||
url, err := w.ImageX.GetResourceURL(ctx, res.BackgroundImageInfo.WebBackgroundImage.GetOriginImageUri())
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "get url by uri err, err:%s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
res.BackgroundImageInfo.WebBackgroundImage.ImageUrl = &url.URL
|
||||
}
|
||||
|
||||
if res.BackgroundImageInfo.MobileBackgroundImage != nil && res.BackgroundImageInfo.MobileBackgroundImage.OriginImageUri != nil {
|
||||
url, err := w.ImageX.GetResourceURL(ctx, res.BackgroundImageInfo.MobileBackgroundImage.GetOriginImageUri())
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "get url by uri err, err:%s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
res.BackgroundImageInfo.MobileBackgroundImage.ImageUrl = &url.URL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ meta:
|
||||
top_k: 0
|
||||
stop: []
|
||||
openai:
|
||||
by_azure: true
|
||||
by_azure: false
|
||||
api_version: ""
|
||||
response_format:
|
||||
type: text
|
||||
|
||||
@ -20,10 +20,13 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/conversation"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/conversation/conversation/entity"
|
||||
)
|
||||
|
||||
type Conversation interface {
|
||||
GetCurrentConversation(ctx context.Context, req *conversation.GetCurrent) (*conversation.Conversation, error)
|
||||
Create(ctx context.Context, req *entity.CreateMeta) (*entity.Conversation, error)
|
||||
NewConversationCtx(ctx context.Context, req *entity.NewConversationCtxRequest) (*entity.NewConversationCtxResponse, error)
|
||||
}
|
||||
|
||||
var defaultSVC Conversation
|
||||
|
||||
@ -20,13 +20,16 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/message"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/conversation/message/entity"
|
||||
)
|
||||
|
||||
type Message interface {
|
||||
GetByRunIDs(ctx context.Context, conversationID int64, runIDs []int64) ([]*message.Message, error)
|
||||
PreCreate(ctx context.Context, msg *message.Message) (*message.Message, error)
|
||||
Create(ctx context.Context, msg *message.Message) (*message.Message, error)
|
||||
List(ctx context.Context, meta *entity.ListMeta) (*entity.ListResult, error)
|
||||
Edit(ctx context.Context, msg *message.Message) (*message.Message, error)
|
||||
Delete(ctx context.Context, req *entity.DeleteMeta) error
|
||||
}
|
||||
|
||||
var defaultSVC Message
|
||||
|
||||
@ -20,8 +20,10 @@ import (
|
||||
"context"
|
||||
|
||||
einoCompose "github.com/cloudwego/eino/compose"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow"
|
||||
|
||||
workflowEntity "github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
|
||||
)
|
||||
@ -37,10 +39,13 @@ type Workflow interface {
|
||||
GetWorkflowIDsByAppID(ctx context.Context, appID int64) ([]int64, error)
|
||||
SyncExecuteWorkflow(ctx context.Context, config vo.ExecuteConfig, input map[string]any) (*workflowEntity.WorkflowExecution, vo.TerminatePlan, error)
|
||||
WithExecuteConfig(cfg vo.ExecuteConfig) einoCompose.Option
|
||||
StreamExecute(ctx context.Context, config vo.ExecuteConfig, input map[string]any) (*schema.StreamReader[*workflowEntity.Message], error)
|
||||
InitApplicationDefaultConversationTemplate(ctx context.Context, spaceID int64, appID int64, userID int64) error
|
||||
}
|
||||
|
||||
type ExecuteConfig = vo.ExecuteConfig
|
||||
type ExecuteMode = vo.ExecuteMode
|
||||
type WorkflowMessage = workflowEntity.Message
|
||||
|
||||
const (
|
||||
ExecuteModeDebug ExecuteMode = "debug"
|
||||
|
||||
@ -21,6 +21,7 @@ import (
|
||||
|
||||
model "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/conversation"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossconversation"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/conversation/conversation/entity"
|
||||
conversation "github.com/coze-dev/coze-studio/backend/domain/conversation/conversation/service"
|
||||
)
|
||||
|
||||
@ -40,3 +41,11 @@ func InitDomainService(c conversation.Conversation) crossconversation.Conversati
|
||||
func (s *impl) GetCurrentConversation(ctx context.Context, req *model.GetCurrent) (*model.Conversation, error) {
|
||||
return s.DomainSVC.GetCurrentConversation(ctx, req)
|
||||
}
|
||||
|
||||
func (s *impl) Create(ctx context.Context, req *entity.CreateMeta) (*entity.Conversation, error) {
|
||||
return s.DomainSVC.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (s *impl) NewConversationCtx(ctx context.Context, req *entity.NewConversationCtxRequest) (*entity.NewConversationCtxResponse, error) {
|
||||
return s.DomainSVC.NewConversationCtx(ctx, req)
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import (
|
||||
|
||||
model "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/message"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossmessage"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/conversation/message/entity"
|
||||
message "github.com/coze-dev/coze-studio/backend/domain/conversation/message/service"
|
||||
)
|
||||
|
||||
@ -53,3 +54,11 @@ func (c *impl) Edit(ctx context.Context, msg *model.Message) (*model.Message, er
|
||||
func (c *impl) PreCreate(ctx context.Context, msg *model.Message) (*model.Message, error) {
|
||||
return c.DomainSVC.PreCreate(ctx, msg)
|
||||
}
|
||||
|
||||
func (c *impl) List(ctx context.Context, lm *entity.ListMeta) (*entity.ListResult, error) {
|
||||
return c.DomainSVC.List(ctx, lm)
|
||||
}
|
||||
|
||||
func (c *impl) Delete(ctx context.Context, req *entity.DeleteMeta) error {
|
||||
return c.DomainSVC.Delete(ctx, req)
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
|
||||
einoCompose "github.com/cloudwego/eino/compose"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossworkflow"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow"
|
||||
@ -72,6 +73,14 @@ func (i *impl) WithExecuteConfig(cfg vo.ExecuteConfig) einoCompose.Option {
|
||||
return i.DomainSVC.WithExecuteConfig(cfg)
|
||||
}
|
||||
|
||||
func (i *impl) StreamExecute(ctx context.Context, config vo.ExecuteConfig, input map[string]any) (*schema.StreamReader[*workflowEntity.Message], error) {
|
||||
return i.DomainSVC.StreamExecute(ctx, config, input)
|
||||
}
|
||||
|
||||
func (i *impl) InitApplicationDefaultConversationTemplate(ctx context.Context, spaceID int64, appID int64, userID int64) error {
|
||||
return i.DomainSVC.InitApplicationDefaultConversationTemplate(ctx, spaceID, appID, userID)
|
||||
}
|
||||
|
||||
func (i *impl) GetWorkflowIDsByAppID(ctx context.Context, appID int64) ([]int64, error) {
|
||||
metas, _, err := i.DomainSVC.MGet(ctx, &vo.MGetPolicy{
|
||||
MetaQuery: vo.MetaQuery{
|
||||
|
||||
201
backend/crossdomain/workflow/conversation/conversation.go
Normal file
201
backend/crossdomain/workflow/conversation/conversation.go
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package conversation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/cloudwego/eino/schema"
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/conversation/common"
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/message"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossconversation"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossmessage"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/conversation/conversation/entity"
|
||||
msgentity "github.com/coze-dev/coze-studio/backend/domain/conversation/message/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/conversation"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
)
|
||||
|
||||
type ConversationRepository struct {
|
||||
}
|
||||
|
||||
func NewConversationRepository() *ConversationRepository {
|
||||
return &ConversationRepository{}
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) CreateConversation(ctx context.Context, req *conversation.CreateConversationRequest) (int64, error) {
|
||||
ret, err := crossconversation.DefaultSVC().Create(ctx, &entity.CreateMeta{
|
||||
AgentID: req.AppID,
|
||||
UserID: req.UserID,
|
||||
ConnectorID: req.ConnectorID,
|
||||
Scene: common.Scene_SceneWorkflow,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ret.ID, nil
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) CreateMessage(ctx context.Context, req *conversation.CreateMessageRequest) (int64, error) {
|
||||
msg := &message.Message{
|
||||
ConversationID: req.ConversationID,
|
||||
Role: schema.RoleType(req.Role),
|
||||
Content: req.Content,
|
||||
ContentType: message.ContentType(req.ContentType),
|
||||
UserID: strconv.FormatInt(req.UserID, 10),
|
||||
AgentID: req.AppID,
|
||||
RunID: req.RunID,
|
||||
}
|
||||
if msg.Role == "user" {
|
||||
msg.MessageType = message.MessageTypeQuestion
|
||||
} else {
|
||||
msg.MessageType = message.MessageTypeAnswer
|
||||
}
|
||||
ret, err := crossmessage.DefaultSVC().Create(ctx, msg)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ret.ID, nil
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) MessageList(ctx context.Context, req *conversation.MessageListRequest) (*conversation.MessageListResponse, error) {
|
||||
lm := &msgentity.ListMeta{
|
||||
ConversationID: req.ConversationID,
|
||||
Limit: int(req.Limit), // Since the value of limit is checked inside the node, the type cast here is safe
|
||||
UserID: strconv.FormatInt(req.UserID, 10),
|
||||
AgentID: req.AppID,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
if req.BeforeID != nil {
|
||||
lm.Cursor, _ = strconv.ParseInt(*req.BeforeID, 10, 64)
|
||||
lm.Direction = msgentity.ScrollPageDirectionPrev
|
||||
}
|
||||
if req.AfterID != nil {
|
||||
lm.Cursor, _ = strconv.ParseInt(*req.AfterID, 10, 64)
|
||||
lm.Direction = msgentity.ScrollPageDirectionNext
|
||||
}
|
||||
lm.Direction = msgentity.ScrollPageDirectionNext
|
||||
lr, err := crossmessage.DefaultSVC().List(ctx, lm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := &conversation.MessageListResponse{}
|
||||
|
||||
if lr.PrevCursor > 0 {
|
||||
response.FirstID = strconv.FormatInt(lr.PrevCursor, 10)
|
||||
}
|
||||
if lr.NextCursor > 0 {
|
||||
response.LastID = strconv.FormatInt(lr.NextCursor, 10)
|
||||
}
|
||||
if len(lr.Messages) == 0 {
|
||||
return response, nil
|
||||
}
|
||||
messages, err := convertMessage(lr.Messages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response.Messages = messages
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) ClearConversationHistory(ctx context.Context, req *conversation.ClearConversationHistoryReq) error {
|
||||
_, err := crossconversation.DefaultSVC().NewConversationCtx(ctx, &entity.NewConversationCtxRequest{
|
||||
ID: req.ConversationID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) DeleteMessage(ctx context.Context, req *conversation.DeleteMessageRequest) error {
|
||||
return crossmessage.DefaultSVC().Delete(ctx, &msgentity.DeleteMeta{
|
||||
MessageIDs: []int64{req.MessageID},
|
||||
})
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) EditMessage(ctx context.Context, req *conversation.EditMessageRequest) error {
|
||||
_, err := crossmessage.DefaultSVC().Edit(ctx, &msgentity.Message{
|
||||
ID: req.MessageID,
|
||||
ConversationID: req.ConversationID,
|
||||
Content: req.Content,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) GetLatestRunIDs(ctx context.Context, req *conversation.GetLatestRunIDsRequest) ([]int64, error) {
|
||||
return []int64{0}, nil
|
||||
}
|
||||
|
||||
func (c *ConversationRepository) GetMessagesByRunIDs(ctx context.Context, req *conversation.GetMessagesByRunIDsRequest) (*conversation.GetMessagesByRunIDsResponse, error) {
|
||||
|
||||
messages, err := crossmessage.DefaultSVC().GetByRunIDs(ctx, req.ConversationID, req.RunIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msgs, err := convertMessage(messages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &conversation.GetMessagesByRunIDsResponse{
|
||||
Messages: msgs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertMessage(msgs []*msgentity.Message) ([]*conversation.Message, error) {
|
||||
messages := make([]*conversation.Message, 0, len(msgs))
|
||||
for _, m := range msgs {
|
||||
msg := &conversation.Message{
|
||||
ID: m.ID,
|
||||
Role: string(m.Role),
|
||||
ContentType: string(m.ContentType)}
|
||||
|
||||
if m.MultiContent != nil {
|
||||
var mcs []*conversation.Content
|
||||
for _, c := range m.MultiContent {
|
||||
if c.FileData != nil {
|
||||
for _, fd := range c.FileData {
|
||||
mcs = append(mcs, &conversation.Content{
|
||||
Type: string(c.Type),
|
||||
Uri: ptr.Of(fd.Url),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
mcs = append(mcs, &conversation.Content{
|
||||
Type: string(c.Type),
|
||||
Text: ptr.Of(c.Text),
|
||||
})
|
||||
}
|
||||
}
|
||||
msg.MultiContent = mcs
|
||||
} else {
|
||||
msg.Text = ptr.Of(m.Content)
|
||||
}
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
380
backend/crossdomain/workflow/conversation/conversation_test.go
Normal file
380
backend/crossdomain/workflow/conversation/conversation_test.go
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package conversation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
apimessage "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/message"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/conversation/message/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/conversation"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_convertMessage(t *testing.T) {
|
||||
type args struct {
|
||||
lr *entity.ListResult
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *conversation.MessageListResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "pure text",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 1,
|
||||
Role: "user",
|
||||
ContentType: "text",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "text",
|
||||
Text: "hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 1,
|
||||
Role: "user",
|
||||
ContentType: "text",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "text", Text: ptr.Of("hello")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "pure file",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 2,
|
||||
Role: "user",
|
||||
ContentType: "file",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "file",
|
||||
FileData: []*apimessage.FileData{
|
||||
{
|
||||
Url: "f_uri_1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "text",
|
||||
Text: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 2,
|
||||
Role: "user",
|
||||
ContentType: "file",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "file", Uri: ptr.Of("f_uri_1")},
|
||||
{Type: "text", Text: ptr.Of("")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "text and file",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 3,
|
||||
Role: "user",
|
||||
ContentType: "text_file",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "text",
|
||||
Text: "hello",
|
||||
},
|
||||
{
|
||||
Type: "file",
|
||||
FileData: []*apimessage.FileData{
|
||||
{
|
||||
Url: "f_uri_2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 3,
|
||||
Role: "user",
|
||||
ContentType: "text_file",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "text", Text: ptr.Of("hello")},
|
||||
{Type: "file", Uri: ptr.Of("f_uri_2")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple files",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 4,
|
||||
Role: "user",
|
||||
ContentType: "file",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "file",
|
||||
FileData: []*apimessage.FileData{
|
||||
{
|
||||
Url: "f_uri_3",
|
||||
},
|
||||
{
|
||||
Url: "f_uri_4",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "text",
|
||||
Text: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 4,
|
||||
Role: "user",
|
||||
ContentType: "file",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "file", Uri: ptr.Of("f_uri_3")},
|
||||
{Type: "file", Uri: ptr.Of("f_uri_4")},
|
||||
{Type: "text", Text: ptr.Of("")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty text",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 5,
|
||||
Role: "user",
|
||||
ContentType: "text",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "text",
|
||||
Text: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 5,
|
||||
Role: "user",
|
||||
ContentType: "text",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "text", Text: ptr.Of("")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "pure image",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 6,
|
||||
Role: "user",
|
||||
ContentType: "image",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "image",
|
||||
FileData: []*apimessage.FileData{
|
||||
{
|
||||
Url: "image_uri_5",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "text",
|
||||
Text: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 6,
|
||||
Role: "user",
|
||||
ContentType: "image",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "image", Uri: ptr.Of("image_uri_5")},
|
||||
{Type: "text", Text: ptr.Of("")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple images",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 7,
|
||||
Role: "user",
|
||||
ContentType: "image",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "image",
|
||||
FileData: []*apimessage.FileData{
|
||||
{
|
||||
Url: "file_id_6",
|
||||
},
|
||||
{
|
||||
Url: "file_id_7",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "text",
|
||||
Text: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 7,
|
||||
Role: "user",
|
||||
ContentType: "image",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "image", Uri: ptr.Of("file_id_6")},
|
||||
{Type: "image", Uri: ptr.Of("file_id_7")},
|
||||
{Type: "text", Text: ptr.Of("")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mixed content",
|
||||
args: args{
|
||||
lr: &entity.ListResult{
|
||||
Messages: []*entity.Message{
|
||||
{
|
||||
ID: 8,
|
||||
Role: "user",
|
||||
ContentType: "mix",
|
||||
MultiContent: []*apimessage.InputMetaData{
|
||||
{
|
||||
Type: "text",
|
||||
Text: "hello",
|
||||
},
|
||||
{
|
||||
Type: "image",
|
||||
FileData: []*apimessage.FileData{
|
||||
{
|
||||
Url: "file_id_8",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "file",
|
||||
FileData: []*apimessage.FileData{
|
||||
{
|
||||
Url: "file_id_9",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &conversation.MessageListResponse{
|
||||
Messages: []*conversation.Message{
|
||||
{
|
||||
ID: 8,
|
||||
Role: "user",
|
||||
ContentType: "mix",
|
||||
MultiContent: []*conversation.Content{
|
||||
{Type: "text", Text: ptr.Of("hello")},
|
||||
{Type: "image", Uri: ptr.Of("file_id_8")},
|
||||
{Type: "file", Uri: ptr.Of("file_id_9")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
msgs, err := convertMessage(tt.args.lr.Messages)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("convertMessage() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
for i, msg := range msgs {
|
||||
assert.Equal(t, msg.MultiContent, tt.want.Messages[i].MultiContent)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -127,6 +127,7 @@ func (k *Knowledge) Retrieve(ctx context.Context, r *crossknowledge.RetrieveRequ
|
||||
Query: r.Query,
|
||||
KnowledgeIDs: r.KnowledgeIDs,
|
||||
Strategy: rs,
|
||||
ChatHistory: r.ChatHistory,
|
||||
}
|
||||
|
||||
response, err := k.client.Retrieve(ctx, req)
|
||||
|
||||
@ -29,6 +29,7 @@ import (
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossdatabase"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossknowledge"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossplugin"
|
||||
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/crossworkflow"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/app/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/app/repository"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/idgen"
|
||||
@ -67,6 +68,11 @@ func (a *appServiceImpl) CreateDraftAPP(ctx context.Context, req *CreateDraftAPP
|
||||
return 0, errorx.Wrapf(err, "CreateDraftAPP failed, spaceID=%d", req.SpaceID)
|
||||
}
|
||||
|
||||
err = crossworkflow.DefaultSVC().InitApplicationDefaultConversationTemplate(ctx, req.SpaceID, appID, req.OwnerID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return appID, nil
|
||||
}
|
||||
|
||||
|
||||
@ -34,13 +34,13 @@ const (
|
||||
type RunEvent string
|
||||
|
||||
const (
|
||||
RunEventCreated RunEvent = "conversation.run.created"
|
||||
RunEventInProgress RunEvent = "conversation.run.in_progress"
|
||||
RunEventCompleted RunEvent = "conversation.run.completed"
|
||||
RunEventFailed RunEvent = "conversation.run.failed"
|
||||
RunEventExpired RunEvent = "conversation.run.expired"
|
||||
RunEventCancelled RunEvent = "conversation.run.cancelled"
|
||||
RunEventRequiredAction RunEvent = "conversation.run.required_action"
|
||||
RunEventCreated RunEvent = "conversation.chat.created"
|
||||
RunEventInProgress RunEvent = "conversation.chat.in_progress"
|
||||
RunEventCompleted RunEvent = "conversation.chat.completed"
|
||||
RunEventFailed RunEvent = "conversation.chat.failed"
|
||||
RunEventExpired RunEvent = "conversation.chat.expired"
|
||||
RunEventCancelled RunEvent = "conversation.chat.cancelled"
|
||||
RunEventRequiredAction RunEvent = "conversation.chat.required_action"
|
||||
|
||||
RunEventMessageDelta RunEvent = "conversation.message.delta"
|
||||
RunEventMessageCompleted RunEvent = "conversation.message.completed"
|
||||
|
||||
@ -58,9 +58,7 @@ func (dao *KnowledgeDocumentSliceDAO) BatchCreate(ctx context.Context, slices []
|
||||
func (dao *KnowledgeDocumentSliceDAO) BatchSetStatus(ctx context.Context, ids []int64, status int32, reason string) error {
|
||||
s := dao.Query.KnowledgeDocumentSlice
|
||||
updates := map[string]any{s.Status.ColumnName().String(): status}
|
||||
if reason != "" {
|
||||
updates[s.FailReason.ColumnName().String()] = reason
|
||||
}
|
||||
updates[s.FailReason.ColumnName().String()] = reason
|
||||
updates[s.UpdatedAt.ColumnName().String()] = time.Now().UnixMilli()
|
||||
_, err := s.WithContext(ctx).Where(s.ID.In(ids...)).Updates(updates)
|
||||
return err
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package model
|
||||
|
||||
type SliceStatus int32
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package model
|
||||
|
||||
import "github.com/coze-dev/coze-studio/backend/domain/knowledge/entity"
|
||||
|
||||
@ -166,11 +166,22 @@ func (k *knowledgeSVC) indexDocument(ctx context.Context, event *entity.Event) (
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
var errMsg string
|
||||
var statusError errorx.StatusError
|
||||
if errors.As(err, &statusError) && statusError.Code() == errno.ErrKnowledgeNonRetryableCode {
|
||||
if setStatusErr := k.documentRepo.SetStatus(ctx, event.Document.ID, int32(entity.DocumentStatusFailed), err.Error()); setStatusErr != nil {
|
||||
logs.CtxErrorf(ctx, "[indexDocument] set document status failed, err: %v", setStatusErr)
|
||||
var status int32
|
||||
if errors.As(err, &statusError) {
|
||||
errMsg = errorx.ErrorWithoutStack(statusError)
|
||||
if statusError.Code() == errno.ErrKnowledgeNonRetryableCode {
|
||||
status = int32(entity.DocumentStatusFailed)
|
||||
} else {
|
||||
status = int32(entity.DocumentStatusChunking)
|
||||
}
|
||||
} else {
|
||||
errMsg = err.Error()
|
||||
status = int32(entity.DocumentStatusChunking)
|
||||
}
|
||||
if setStatusErr := k.documentRepo.SetStatus(ctx, event.Document.ID, status, errMsg); setStatusErr != nil {
|
||||
logs.CtxErrorf(ctx, "[indexDocument] set document status failed, err: %v", setStatusErr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@ -545,6 +545,12 @@ func (k *knowledgeSVC) MGetDocumentProgress(ctx context.Context, request *MGetDo
|
||||
if documents[i].Status == int32(entity.DocumentStatusEnable) || documents[i].Status == int32(entity.DocumentStatusFailed) {
|
||||
item.Progress = progressbar.ProcessDone
|
||||
} else {
|
||||
if documents[i].FailReason != "" {
|
||||
item.StatusMsg = documents[i].FailReason
|
||||
item.Status = entity.DocumentStatusFailed
|
||||
progresslist = append(progresslist, &item)
|
||||
continue
|
||||
}
|
||||
err = k.getProgressFromCache(ctx, &item)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "get progress from cache failed, err: %v", err)
|
||||
@ -564,8 +570,9 @@ func (k *knowledgeSVC) getProgressFromCache(ctx context.Context, documentProgres
|
||||
documentProgress.Progress = int(percent)
|
||||
documentProgress.RemainingSec = int64(remainSec)
|
||||
if len(errMsg) != 0 {
|
||||
documentProgress.Progress = 0
|
||||
documentProgress.Status = entity.DocumentStatusChunking
|
||||
documentProgress.Status = entity.DocumentStatusFailed
|
||||
documentProgress.StatusMsg = errMsg
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
@ -1276,6 +1283,16 @@ func (k *knowledgeSVC) fromModelDocument(ctx context.Context, document *model.Kn
|
||||
documentEntity.TableInfo.Columns = append(documentEntity.TableInfo.Columns, document.TableInfo.Columns[i])
|
||||
}
|
||||
}
|
||||
switch document.Status {
|
||||
case int32(entity.DocumentStatusChunking), int32(entity.DocumentStatusInit), int32(entity.DocumentStatusUploading):
|
||||
if document.FailReason != "" {
|
||||
documentEntity.Status = entity.DocumentStatusFailed
|
||||
documentEntity.StatusMsg = document.FailReason
|
||||
}
|
||||
case int32(entity.DocumentStatusFailed):
|
||||
documentEntity.StatusMsg = document.FailReason
|
||||
default:
|
||||
}
|
||||
if len(document.URI) != 0 {
|
||||
objUrl, err := k.storage.GetObjectUrl(ctx, document.URI)
|
||||
if err != nil {
|
||||
|
||||
@ -145,7 +145,7 @@ func (suite *KnowledgeTestSuite) SetupSuite() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
emb, err := hembed.NewEmbedding(embEndpoint)
|
||||
emb, err := hembed.NewEmbedding(embEndpoint, 1024)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ const (
|
||||
func SwitchToDataType(itemType table.FieldItemType) entity.DataType {
|
||||
switch itemType {
|
||||
case table.FieldItemType_Text:
|
||||
return entity.TypeVarchar
|
||||
return entity.TypeText
|
||||
case table.FieldItemType_Number:
|
||||
return entity.TypeBigInt
|
||||
case table.FieldItemType_Date:
|
||||
|
||||
@ -157,7 +157,6 @@ func NewDefaultPluginManifest() *PluginManifest {
|
||||
Value: "Coze/1.0",
|
||||
},
|
||||
},
|
||||
model.ParamInPath: {},
|
||||
model.ParamInQuery: {},
|
||||
},
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import (
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/plugin_develop_common"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/conf"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/model"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/query"
|
||||
@ -88,7 +89,7 @@ func (p *PluginDraftDAO) getSelected(opt *PluginSelectedOption) (selected []fiel
|
||||
}
|
||||
|
||||
func (p *PluginDraftDAO) Create(ctx context.Context, plugin *entity.PluginInfo) (pluginID int64, err error) {
|
||||
id, err := p.idGen.GenID(ctx)
|
||||
id, err := p.genPluginID(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -117,6 +118,25 @@ func (p *PluginDraftDAO) Create(ctx context.Context, plugin *entity.PluginInfo)
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (p *PluginDraftDAO) genPluginID(ctx context.Context) (id int64, err error) {
|
||||
|
||||
retryTimes := 5
|
||||
for i := 0; i < retryTimes; i++ {
|
||||
id, err = p.idGen.GenID(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if _, ok := conf.GetPluginProduct(id); !ok {
|
||||
break
|
||||
}
|
||||
if i == retryTimes-1 {
|
||||
return 0, fmt.Errorf("id %d is confilict with product plugin id.", id)
|
||||
}
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (p *PluginDraftDAO) Get(ctx context.Context, pluginID int64, opt *PluginSelectedOption) (plugin *entity.PluginInfo, exist bool, err error) {
|
||||
table := p.query.PluginDraft
|
||||
pl, err := table.WithContext(ctx).
|
||||
@ -262,7 +282,7 @@ func (p *PluginDraftDAO) Update(ctx context.Context, plugin *entity.PluginInfo)
|
||||
}
|
||||
|
||||
func (p *PluginDraftDAO) CreateWithTX(ctx context.Context, tx *query.QueryTx, plugin *entity.PluginInfo) (pluginID int64, err error) {
|
||||
id, err := p.idGen.GenID(ctx)
|
||||
id, err := p.genPluginID(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import (
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
|
||||
common "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop_common"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/conf"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/model"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/query"
|
||||
@ -90,7 +91,8 @@ func (t *ToolDraftDAO) getSelected(opt *ToolSelectedOption) (selected []field.Ex
|
||||
}
|
||||
|
||||
func (t *ToolDraftDAO) Create(ctx context.Context, tool *entity.ToolInfo) (toolID int64, err error) {
|
||||
id, err := t.idGen.GenID(ctx)
|
||||
|
||||
id, err := t.genToolID(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -111,6 +113,27 @@ func (t *ToolDraftDAO) Create(ctx context.Context, tool *entity.ToolInfo) (toolI
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (t *ToolDraftDAO) genToolID(ctx context.Context) (id int64, err error) {
|
||||
|
||||
retryTimes := 5
|
||||
|
||||
for i := 0; i < retryTimes; i++ {
|
||||
id, err = t.idGen.GenID(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if _, ok := conf.GetToolProduct(id); !ok {
|
||||
break
|
||||
}
|
||||
if i == retryTimes-1 {
|
||||
return 0, fmt.Errorf("id %d is confilict with product tool id.", id)
|
||||
}
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (t *ToolDraftDAO) Get(ctx context.Context, toolID int64) (tool *entity.ToolInfo, exist bool, err error) {
|
||||
table := t.query.ToolDraft
|
||||
tl, err := table.WithContext(ctx).
|
||||
@ -335,7 +358,7 @@ func (t *ToolDraftDAO) BatchCreateWithTX(ctx context.Context, tx *query.QueryTx,
|
||||
tls := make([]*model.ToolDraft, 0, len(tools))
|
||||
|
||||
for _, tool := range tools {
|
||||
id, err := t.idGen.GenID(ctx)
|
||||
id, err := t.genToolID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ import (
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/tidwall/sjson"
|
||||
|
||||
einoCompose "github.com/cloudwego/eino/compose"
|
||||
|
||||
@ -479,11 +480,6 @@ func (t *toolExecutor) execute(ctx context.Context, argumentsInJson string) (res
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestStr, err := sonic.MarshalString(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpReq, err := t.buildHTTPRequest(ctx, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -504,18 +500,29 @@ func (t *toolExecutor) execute(ctx context.Context, argumentsInJson string) (res
|
||||
}
|
||||
|
||||
var reqBodyBytes []byte
|
||||
if httpReq.Body != nil {
|
||||
reqBodyBytes, err = io.ReadAll(httpReq.Body)
|
||||
if httpReq.GetBody != nil {
|
||||
reqBody, err := httpReq.GetBody()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reqBody.Close()
|
||||
|
||||
reqBodyBytes, err = io.ReadAll(reqBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
requestStr, err := genRequestString(httpReq, reqBodyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
restyReq := t.svc.httpCli.NewRequest()
|
||||
restyReq.Header = httpReq.Header
|
||||
restyReq.Method = httpReq.Method
|
||||
restyReq.URL = httpReq.URL.String()
|
||||
if len(reqBodyBytes) > 0 {
|
||||
if reqBodyBytes != nil {
|
||||
restyReq.SetBody(reqBodyBytes)
|
||||
}
|
||||
restyReq.SetContext(ctx)
|
||||
@ -559,6 +566,46 @@ func (t *toolExecutor) execute(ctx context.Context, argumentsInJson string) (res
|
||||
}, nil
|
||||
}
|
||||
|
||||
func genRequestString(req *http.Request, body []byte) (string, error) {
|
||||
type Request struct {
|
||||
Path string `json:"path"`
|
||||
Header map[string]string `json:"header"`
|
||||
Query map[string]string `json:"query"`
|
||||
Body *[]byte `json:"body"`
|
||||
}
|
||||
|
||||
req_ := &Request{
|
||||
Path: req.URL.Path,
|
||||
Header: map[string]string{},
|
||||
Query: map[string]string{},
|
||||
}
|
||||
|
||||
if len(req.Header) > 0 {
|
||||
for k, v := range req.Header {
|
||||
req_.Header[k] = v[0]
|
||||
}
|
||||
}
|
||||
if len(req.URL.Query()) > 0 {
|
||||
for k, v := range req.URL.Query() {
|
||||
req_.Query[k] = v[0]
|
||||
}
|
||||
}
|
||||
|
||||
requestStr, err := sonic.MarshalString(req_)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("[genRequestString] marshal failed, err=%s", err)
|
||||
}
|
||||
|
||||
if body != nil {
|
||||
requestStr, err = sjson.SetRaw(requestStr, "body", string(body))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("[genRequestString] set body failed, err=%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return requestStr, nil
|
||||
}
|
||||
|
||||
func (t *toolExecutor) preprocessArgumentsInJson(ctx context.Context, argumentsInJson string) (args map[string]any, err error) {
|
||||
args, err = t.prepareArguments(ctx, argumentsInJson)
|
||||
if err != nil {
|
||||
@ -653,23 +700,13 @@ func (t *toolExecutor) buildHTTPRequest(ctx context.Context, argMaps map[string]
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqURL, err := locArgs.buildHTTPRequestURL(ctx, rawURL)
|
||||
commonParams := t.plugin.Manifest.CommonParams
|
||||
|
||||
reqURL, err := locArgs.buildHTTPRequestURL(ctx, rawURL, commonParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpReq, err = http.NewRequestWithContext(ctx, tool.GetMethod(), reqURL.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header, err := locArgs.buildHTTPRequestHeader(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpReq.Header = header
|
||||
|
||||
bodyArgs := map[string]any{}
|
||||
for k, v := range argMaps {
|
||||
if _, ok := locArgs.header[k]; ok {
|
||||
@ -684,13 +721,27 @@ func (t *toolExecutor) buildHTTPRequest(ctx context.Context, argMaps map[string]
|
||||
bodyArgs[k] = v
|
||||
}
|
||||
|
||||
bodyBytes, contentType, err := t.buildRequestBody(ctx, tool.Operation, bodyArgs)
|
||||
commonBody := commonParams[model.ParamInBody]
|
||||
bodyBytes, contentType, err := t.buildRequestBody(ctx, tool.Operation, bodyArgs, commonBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpReq, err = http.NewRequestWithContext(ctx, tool.GetMethod(), reqURL.String(), bytes.NewBuffer(bodyBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
commonHeader := commonParams[model.ParamInHeader]
|
||||
header, err := locArgs.buildHTTPRequestHeader(ctx, commonHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpReq.Header = header
|
||||
|
||||
if len(bodyBytes) > 0 {
|
||||
httpReq.Header.Set("Content-Type", contentType)
|
||||
httpReq.Body = io.NopCloser(bytes.NewReader(bodyBytes))
|
||||
}
|
||||
|
||||
return httpReq, nil
|
||||
@ -698,13 +749,6 @@ func (t *toolExecutor) buildHTTPRequest(ctx context.Context, argMaps map[string]
|
||||
|
||||
func (t *toolExecutor) prepareArguments(_ context.Context, argumentsInJson string) (map[string]any, error) {
|
||||
args := map[string]any{}
|
||||
for loc, params := range t.plugin.Manifest.CommonParams {
|
||||
for _, p := range params {
|
||||
if loc != model.ParamInBody {
|
||||
args[p.Name] = p.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decoder := sonic.ConfigDefault.NewDecoder(bytes.NewBufferString(argumentsInJson))
|
||||
decoder.UseNumber()
|
||||
@ -1175,7 +1219,9 @@ type valueWithSchema struct {
|
||||
paramSchema *openapi3.Parameter
|
||||
}
|
||||
|
||||
func (l *locationArguments) buildHTTPRequestURL(_ context.Context, rawURL string) (reqURL *url.URL, err error) {
|
||||
func (l *locationArguments) buildHTTPRequestURL(_ context.Context, rawURL string,
|
||||
commonParams map[model.HTTPParamLocation][]*common.CommonParamSchema) (reqURL *url.URL, err error) {
|
||||
|
||||
if len(l.path) > 0 {
|
||||
for k, v := range l.path {
|
||||
vStr, err := encoder.EncodeParameter(v.paramSchema, v.argValue)
|
||||
@ -1186,9 +1232,8 @@ func (l *locationArguments) buildHTTPRequestURL(_ context.Context, rawURL string
|
||||
}
|
||||
}
|
||||
|
||||
encodeQuery := ""
|
||||
query := url.Values{}
|
||||
if len(l.query) > 0 {
|
||||
query := url.Values{}
|
||||
for k, val := range l.query {
|
||||
switch v := val.argValue.(type) {
|
||||
case []any:
|
||||
@ -1199,10 +1244,18 @@ func (l *locationArguments) buildHTTPRequestURL(_ context.Context, rawURL string
|
||||
query.Add(k, encoder.MustString(v))
|
||||
}
|
||||
}
|
||||
|
||||
encodeQuery = query.Encode()
|
||||
}
|
||||
|
||||
commonQuery := commonParams[model.ParamInQuery]
|
||||
for _, v := range commonQuery {
|
||||
if _, ok := l.query[v.Name]; ok {
|
||||
continue
|
||||
}
|
||||
query.Add(v.Name, v.Value)
|
||||
}
|
||||
|
||||
encodeQuery := query.Encode()
|
||||
|
||||
reqURL, err = url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1217,7 +1270,7 @@ func (l *locationArguments) buildHTTPRequestURL(_ context.Context, rawURL string
|
||||
return reqURL, nil
|
||||
}
|
||||
|
||||
func (l *locationArguments) buildHTTPRequestHeader(_ context.Context) (http.Header, error) {
|
||||
func (l *locationArguments) buildHTTPRequestHeader(_ context.Context, commonHeaders []*common.CommonParamSchema) (http.Header, error) {
|
||||
header := http.Header{}
|
||||
if len(l.header) > 0 {
|
||||
for k, v := range l.header {
|
||||
@ -1232,44 +1285,64 @@ func (l *locationArguments) buildHTTPRequestHeader(_ context.Context) (http.Head
|
||||
}
|
||||
}
|
||||
|
||||
for _, h := range commonHeaders {
|
||||
if header.Get(h.Name) != "" {
|
||||
continue
|
||||
}
|
||||
header.Add(h.Name, h.Value)
|
||||
}
|
||||
|
||||
return header, nil
|
||||
}
|
||||
|
||||
func (t *toolExecutor) buildRequestBody(ctx context.Context, op *model.Openapi3Operation, bodyArgs map[string]any) (body []byte, contentType string, err error) {
|
||||
func (t *toolExecutor) buildRequestBody(ctx context.Context, op *model.Openapi3Operation, bodyArgs map[string]any,
|
||||
commonBody []*common.CommonParamSchema) (body []byte, contentType string, err error) {
|
||||
|
||||
var bodyMap map[string]any
|
||||
|
||||
contentType, bodySchema := t.getReqBodySchema(op)
|
||||
if bodySchema == nil || bodySchema.Value == nil {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
if len(bodySchema.Value.Properties) == 0 {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
bodyMap, err := t.injectRequestBodyDefaultValue(ctx, bodySchema.Value, bodyArgs)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
for paramName, prop := range bodySchema.Value.Properties {
|
||||
value, ok := bodyMap[paramName]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
_value, err := encoder.TryFixValueType(paramName, prop, value)
|
||||
if bodySchema != nil && len(bodySchema.Value.Properties) > 0 {
|
||||
bodyMap, err = t.injectRequestBodyDefaultValue(ctx, bodySchema.Value, bodyArgs)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
bodyMap[paramName] = _value
|
||||
for paramName, prop := range bodySchema.Value.Properties {
|
||||
value, ok := bodyMap[paramName]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
_value, err := encoder.TryFixValueType(paramName, prop, value)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
bodyMap[paramName] = _value
|
||||
}
|
||||
|
||||
body, err = encoder.EncodeBodyWithContentType(contentType, bodyMap)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("[buildRequestBody] EncodeBodyWithContentType failed, err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
reqBodyStr, err := encoder.EncodeBodyWithContentType(contentType, bodyMap)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("[buildRequestBody] EncodeBodyWithContentType failed, err=%v", err)
|
||||
commonBody_ := make([]*common.CommonParamSchema, 0, len(commonBody))
|
||||
for _, v := range commonBody {
|
||||
if _, ok := bodyMap[v.Name]; ok {
|
||||
continue
|
||||
}
|
||||
commonBody_ = append(commonBody_, v)
|
||||
}
|
||||
|
||||
return reqBodyStr, contentType, nil
|
||||
for _, v := range commonBody_ {
|
||||
body, err = sjson.SetRawBytes(body, v.Name, []byte(v.Value))
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("[buildRequestBody] SetRawBytes failed, err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return body, contentType, nil
|
||||
}
|
||||
|
||||
func (t *toolExecutor) injectRequestBodyDefaultValue(ctx context.Context, sc *openapi3.Schema, vals map[string]any) (newVals map[string]any, err error) {
|
||||
@ -1327,7 +1400,7 @@ func (t *toolExecutor) injectRequestBodyDefaultValue(ctx context.Context, sc *op
|
||||
}
|
||||
|
||||
func (t *toolExecutor) getReqBodySchema(op *model.Openapi3Operation) (string, *openapi3.SchemaRef) {
|
||||
if op.RequestBody == nil || op.RequestBody.Value == nil || len(op.RequestBody.Value.Content) == 0 {
|
||||
if op.RequestBody == nil || len(op.RequestBody.Value.Content) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
|
||||
49
backend/domain/plugin/service/exec_tool_test.go
Normal file
49
backend/domain/plugin/service/exec_tool_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
. "github.com/bytedance/mockey"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGenRequestString(t *testing.T) {
|
||||
PatchConvey("", t, func() {
|
||||
requestStr, err := genRequestString(&http.Request{
|
||||
Header: http.Header{
|
||||
"Content-Type": []string{"application/json"},
|
||||
},
|
||||
Method: http.MethodPost,
|
||||
URL: &url.URL{Path: "/test"},
|
||||
}, []byte(`{"a": 1}`))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"header":{"Content-Type":["application/json"]},"query":null,"path":"/test","body":{"a": 1}}`, requestStr)
|
||||
})
|
||||
|
||||
PatchConvey("", t, func() {
|
||||
var body []byte
|
||||
requestStr, err := genRequestString(&http.Request{
|
||||
URL: &url.URL{Path: "/test"},
|
||||
}, body)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"header":null,"query":null,"path":"/test","body":null}`, requestStr)
|
||||
})
|
||||
}
|
||||
@ -46,6 +46,7 @@ import (
|
||||
|
||||
func (p *pluginServiceImpl) CreateDraftPlugin(ctx context.Context, req *CreateDraftPluginRequest) (pluginID int64, err error) {
|
||||
mf := entity.NewDefaultPluginManifest()
|
||||
mf.CommonParams = map[model.HTTPParamLocation][]*plugin_develop_common.CommonParamSchema{}
|
||||
mf.NameForHuman = req.Name
|
||||
mf.NameForModel = req.Name
|
||||
mf.DescriptionForHuman = req.Desc
|
||||
@ -65,11 +66,11 @@ func (p *pluginServiceImpl) CreateDraftPlugin(ctx context.Context, req *CreateDr
|
||||
return 0, fmt.Errorf("invalid location '%s'", loc.String())
|
||||
}
|
||||
for _, param := range params {
|
||||
mParams := mf.CommonParams[location]
|
||||
mParams = append(mParams, &plugin_develop_common.CommonParamSchema{
|
||||
Name: param.Name,
|
||||
Value: param.Value,
|
||||
})
|
||||
mf.CommonParams[location] = append(mf.CommonParams[location],
|
||||
&plugin_develop_common.CommonParamSchema{
|
||||
Name: param.Name,
|
||||
Value: param.Value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -194,7 +194,7 @@ func (p *pluginServiceImpl) getAccessTokenByAuthorizationCode(ctx context.Contex
|
||||
meta := ci.Meta
|
||||
info, exist, err := p.oauthRepo.GetAuthorizationCode(ctx, ci.Meta)
|
||||
if err != nil {
|
||||
return "", errorx.Wrapf(err, "GetAuthorizationCode failed, userID=%s, pluginID=%d, isDraft=%p",
|
||||
return "", errorx.Wrapf(err, "GetAuthorizationCode failed, userID=%s, pluginID=%d, isDraft=%t",
|
||||
meta.UserID, meta.PluginID, meta.IsDraft)
|
||||
}
|
||||
if !exist {
|
||||
|
||||
@ -53,6 +53,20 @@ type AsTool interface {
|
||||
allInterruptEvents map[string]*entity.ToolInterruptEvent) compose.Option
|
||||
}
|
||||
|
||||
type ConversationService interface {
|
||||
CreateDraftConversationTemplate(ctx context.Context, template *vo.CreateConversationTemplateMeta) (int64, error)
|
||||
UpdateDraftConversationTemplateName(ctx context.Context, appID int64, userID int64, templateID int64, name string) error
|
||||
DeleteDraftConversationTemplate(ctx context.Context, templateID int64, wfID2ConversationName map[int64]string) (int64, error)
|
||||
|
||||
CheckWorkflowsToReplace(ctx context.Context, appID int64, templateID int64) ([]*entity.Workflow, error)
|
||||
DeleteDynamicConversation(ctx context.Context, env vo.Env, templateID int64) (int64, error)
|
||||
ListConversationTemplate(ctx context.Context, env vo.Env, policy *vo.ListConversationTemplatePolicy) ([]*entity.ConversationTemplate, error)
|
||||
MGetStaticConversation(ctx context.Context, env vo.Env, userID, connectorID int64, templateIDs []int64) ([]*entity.StaticConversation, error)
|
||||
ListDynamicConversation(ctx context.Context, env vo.Env, policy *vo.ListConversationPolicy) ([]*entity.DynamicConversation, error)
|
||||
ReleaseConversationTemplate(ctx context.Context, appID int64, version string) error
|
||||
InitApplicationDefaultConversationTemplate(ctx context.Context, spaceID int64, appID int64, userID int64) error
|
||||
}
|
||||
|
||||
type InterruptEventStore interface {
|
||||
SaveInterruptEvents(ctx context.Context, wfExeID int64, events []*entity.InterruptEvent) error
|
||||
GetFirstInterruptEvent(ctx context.Context, wfExeID int64) (*entity.InterruptEvent, bool, error)
|
||||
@ -90,3 +104,22 @@ type ToolFromWorkflow interface {
|
||||
TerminatePlan() vo.TerminatePlan
|
||||
GetWorkflow() *entity.Workflow
|
||||
}
|
||||
|
||||
type ConversationIDGenerator func(ctx context.Context, appID int64, userID, connectorID int64) (int64, error)
|
||||
|
||||
type ConversationRepository interface {
|
||||
CreateDraftConversationTemplate(ctx context.Context, template *vo.CreateConversationTemplateMeta) (int64, error)
|
||||
UpdateDraftConversationTemplateName(ctx context.Context, templateID int64, name string) error
|
||||
DeleteDraftConversationTemplate(ctx context.Context, templateID int64) (int64, error)
|
||||
GetConversationTemplate(ctx context.Context, env vo.Env, policy vo.GetConversationTemplatePolicy) (*entity.ConversationTemplate, bool, error)
|
||||
DeleteDynamicConversation(ctx context.Context, env vo.Env, id int64) (int64, error)
|
||||
ListConversationTemplate(ctx context.Context, env vo.Env, policy *vo.ListConversationTemplatePolicy) ([]*entity.ConversationTemplate, error)
|
||||
MGetStaticConversation(ctx context.Context, env vo.Env, userID, connectorID int64, templateIDs []int64) ([]*entity.StaticConversation, error)
|
||||
GetOrCreateStaticConversation(ctx context.Context, env vo.Env, idGen ConversationIDGenerator, meta *vo.CreateStaticConversation) (int64, bool, error)
|
||||
GetOrCreateDynamicConversation(ctx context.Context, env vo.Env, idGen ConversationIDGenerator, meta *vo.CreateDynamicConversation) (int64, bool, error)
|
||||
GetDynamicConversationByName(ctx context.Context, env vo.Env, appID, connectorID, userID int64, name string) (*entity.DynamicConversation, bool, error)
|
||||
GetStaticConversationByTemplateID(ctx context.Context, env vo.Env, userID, connectorID, templateID int64) (*entity.StaticConversation, bool, error)
|
||||
ListDynamicConversation(ctx context.Context, env vo.Env, policy *vo.ListConversationPolicy) ([]*entity.DynamicConversation, error)
|
||||
BatchCreateOnlineConversationTemplate(ctx context.Context, templates []*entity.ConversationTemplate, version string) error
|
||||
UpdateDynamicConversationNameByID(ctx context.Context, env vo.Env, templateID int64, name string) error
|
||||
}
|
||||
|
||||
@ -16,46 +16,116 @@
|
||||
|
||||
package conversation
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ClearMessageRequest struct {
|
||||
Name string
|
||||
}
|
||||
type ClearMessageResponse struct {
|
||||
IsSuccess bool
|
||||
}
|
||||
type CreateConversationRequest struct {
|
||||
Name string
|
||||
AppID int64
|
||||
UserID int64
|
||||
ConnectorID int64
|
||||
}
|
||||
|
||||
type CreateConversationResponse struct {
|
||||
Result map[string]any
|
||||
type CreateMessageRequest struct {
|
||||
ConversationID int64
|
||||
Role string
|
||||
Content string
|
||||
ContentType string
|
||||
UserID int64
|
||||
AppID int64
|
||||
RunID int64
|
||||
}
|
||||
|
||||
type ListMessageRequest struct {
|
||||
ConversationName string
|
||||
Limit *int
|
||||
BeforeID *string
|
||||
AfterID *string
|
||||
}
|
||||
type Message struct {
|
||||
ID string `json:"id"`
|
||||
Role string `json:"role"`
|
||||
ContentType string `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
type MessageListRequest struct {
|
||||
ConversationID int64
|
||||
Limit int64
|
||||
BeforeID *string
|
||||
AfterID *string
|
||||
UserID int64
|
||||
AppID int64
|
||||
OrderBy *string
|
||||
}
|
||||
|
||||
type ListMessageResponse struct {
|
||||
type MessageListResponse struct {
|
||||
Messages []*Message
|
||||
FirstID string
|
||||
LastID string
|
||||
HasMore bool
|
||||
}
|
||||
|
||||
var ConversationManagerImpl ConversationManager
|
||||
var conversationManagerImpl ConversationManager
|
||||
|
||||
type ConversationManager interface {
|
||||
ClearMessage(context.Context, *ClearMessageRequest) (*ClearMessageResponse, error)
|
||||
CreateConversation(ctx context.Context, c *CreateConversationRequest) (*CreateConversationResponse, error)
|
||||
MessageList(ctx context.Context, req *ListMessageRequest) (*ListMessageResponse, error)
|
||||
func GetConversationManager() ConversationManager {
|
||||
return conversationManagerImpl
|
||||
}
|
||||
|
||||
func SetConversationManager(c ConversationManager) {
|
||||
conversationManagerImpl = c
|
||||
}
|
||||
|
||||
type ConversationHistoryRequest struct {
|
||||
ConversationID int64
|
||||
AppID int64
|
||||
UserID int64
|
||||
Rounds int64
|
||||
}
|
||||
|
||||
type Content struct {
|
||||
Type string `json:"type"`
|
||||
Text *string `json:"text,omitempty"`
|
||||
Uri *string `json:"uri,omitempty"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID int64
|
||||
Role string `json:"role"` // user or assistant
|
||||
MultiContent []*Content `json:"multi_content"`
|
||||
Text *string `json:"text,omitempty"`
|
||||
ContentType string `json:"content_type"`
|
||||
}
|
||||
|
||||
type ConversationHistoryResponse struct {
|
||||
Messages []*Message
|
||||
}
|
||||
|
||||
type GetLatestRunIDsRequest struct {
|
||||
ConversationID int64
|
||||
UserID int64
|
||||
AppID int64
|
||||
Rounds int64
|
||||
}
|
||||
type ClearConversationHistoryReq struct {
|
||||
ConversationID int64
|
||||
}
|
||||
|
||||
type DeleteMessageRequest struct {
|
||||
ConversationID int64
|
||||
MessageID int64
|
||||
}
|
||||
|
||||
type EditMessageRequest struct {
|
||||
ConversationID int64
|
||||
MessageID int64
|
||||
Content string
|
||||
}
|
||||
|
||||
type GetMessagesByRunIDsRequest struct {
|
||||
ConversationID int64
|
||||
RunIDs []int64
|
||||
}
|
||||
|
||||
type GetMessagesByRunIDsResponse struct {
|
||||
Messages []*Message
|
||||
}
|
||||
|
||||
//go:generate mockgen -destination conversationmock/conversation_mock.go --package conversationmock -source conversation.go
|
||||
type ConversationManager interface {
|
||||
CreateConversation(ctx context.Context, req *CreateConversationRequest) (int64, error)
|
||||
CreateMessage(ctx context.Context, req *CreateMessageRequest) (int64, error)
|
||||
MessageList(ctx context.Context, req *MessageListRequest) (*MessageListResponse, error)
|
||||
GetLatestRunIDs(ctx context.Context, req *GetLatestRunIDsRequest) ([]int64, error)
|
||||
GetMessagesByRunIDs(ctx context.Context, req *GetMessagesByRunIDsRequest) (*GetMessagesByRunIDsResponse, error)
|
||||
ClearConversationHistory(ctx context.Context, req *ClearConversationHistoryReq) error
|
||||
DeleteMessage(ctx context.Context, req *DeleteMessageRequest) error
|
||||
EditMessage(ctx context.Context, req *EditMessageRequest) error
|
||||
}
|
||||
|
||||
@ -0,0 +1,159 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: conversation.go
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -destination conversationmock/conversation_mock.go --package conversationmock -source conversation.go
|
||||
//
|
||||
|
||||
// Package conversationmock is a generated GoMock package.
|
||||
package conversationmock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
conversation "github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/conversation"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockConversationManager is a mock of ConversationManager interface.
|
||||
type MockConversationManager struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockConversationManagerMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockConversationManagerMockRecorder is the mock recorder for MockConversationManager.
|
||||
type MockConversationManagerMockRecorder struct {
|
||||
mock *MockConversationManager
|
||||
}
|
||||
|
||||
// NewMockConversationManager creates a new mock instance.
|
||||
func NewMockConversationManager(ctrl *gomock.Controller) *MockConversationManager {
|
||||
mock := &MockConversationManager{ctrl: ctrl}
|
||||
mock.recorder = &MockConversationManagerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockConversationManager) EXPECT() *MockConversationManagerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// ClearConversationHistory mocks base method.
|
||||
func (m *MockConversationManager) ClearConversationHistory(ctx context.Context, req *conversation.ClearConversationHistoryReq) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ClearConversationHistory", ctx, req)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ClearConversationHistory indicates an expected call of ClearConversationHistory.
|
||||
func (mr *MockConversationManagerMockRecorder) ClearConversationHistory(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearConversationHistory", reflect.TypeOf((*MockConversationManager)(nil).ClearConversationHistory), ctx, req)
|
||||
}
|
||||
|
||||
// CreateConversation mocks base method.
|
||||
func (m *MockConversationManager) CreateConversation(ctx context.Context, req *conversation.CreateConversationRequest) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateConversation", ctx, req)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateConversation indicates an expected call of CreateConversation.
|
||||
func (mr *MockConversationManagerMockRecorder) CreateConversation(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConversation", reflect.TypeOf((*MockConversationManager)(nil).CreateConversation), ctx, req)
|
||||
}
|
||||
|
||||
// CreateMessage mocks base method.
|
||||
func (m *MockConversationManager) CreateMessage(ctx context.Context, req *conversation.CreateMessageRequest) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateMessage", ctx, req)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateMessage indicates an expected call of CreateMessage.
|
||||
func (mr *MockConversationManagerMockRecorder) CreateMessage(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMessage", reflect.TypeOf((*MockConversationManager)(nil).CreateMessage), ctx, req)
|
||||
}
|
||||
|
||||
// DeleteMessage mocks base method.
|
||||
func (m *MockConversationManager) DeleteMessage(ctx context.Context, req *conversation.DeleteMessageRequest) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteMessage", ctx, req)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteMessage indicates an expected call of DeleteMessage.
|
||||
func (mr *MockConversationManagerMockRecorder) DeleteMessage(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteMessage", reflect.TypeOf((*MockConversationManager)(nil).DeleteMessage), ctx, req)
|
||||
}
|
||||
|
||||
// EditMessage mocks base method.
|
||||
func (m *MockConversationManager) EditMessage(ctx context.Context, req *conversation.EditMessageRequest) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EditMessage", ctx, req)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// EditMessage indicates an expected call of EditMessage.
|
||||
func (mr *MockConversationManagerMockRecorder) EditMessage(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditMessage", reflect.TypeOf((*MockConversationManager)(nil).EditMessage), ctx, req)
|
||||
}
|
||||
|
||||
// GetLatestRunIDs mocks base method.
|
||||
func (m *MockConversationManager) GetLatestRunIDs(ctx context.Context, req *conversation.GetLatestRunIDsRequest) ([]int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetLatestRunIDs", ctx, req)
|
||||
ret0, _ := ret[0].([]int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetLatestRunIDs indicates an expected call of GetLatestRunIDs.
|
||||
func (mr *MockConversationManagerMockRecorder) GetLatestRunIDs(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLatestRunIDs", reflect.TypeOf((*MockConversationManager)(nil).GetLatestRunIDs), ctx, req)
|
||||
}
|
||||
|
||||
// GetMessagesByRunIDs mocks base method.
|
||||
func (m *MockConversationManager) GetMessagesByRunIDs(ctx context.Context, req *conversation.GetMessagesByRunIDsRequest) (*conversation.GetMessagesByRunIDsResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMessagesByRunIDs", ctx, req)
|
||||
ret0, _ := ret[0].(*conversation.GetMessagesByRunIDsResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMessagesByRunIDs indicates an expected call of GetMessagesByRunIDs.
|
||||
func (mr *MockConversationManagerMockRecorder) GetMessagesByRunIDs(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessagesByRunIDs", reflect.TypeOf((*MockConversationManager)(nil).GetMessagesByRunIDs), ctx, req)
|
||||
}
|
||||
|
||||
// MessageList mocks base method.
|
||||
func (m *MockConversationManager) MessageList(ctx context.Context, req *conversation.MessageListRequest) (*conversation.MessageListResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MessageList", ctx, req)
|
||||
ret0, _ := ret[0].(*conversation.MessageListResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// MessageList indicates an expected call of MessageList.
|
||||
func (mr *MockConversationManagerMockRecorder) MessageList(ctx, req any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MessageList", reflect.TypeOf((*MockConversationManager)(nil).MessageList), ctx, req)
|
||||
}
|
||||
@ -19,6 +19,7 @@ package knowledge
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cloudwego/eino/schema"
|
||||
"github.com/coze-dev/coze-studio/backend/infra/contract/document/parser"
|
||||
)
|
||||
|
||||
@ -87,6 +88,7 @@ type RetrieveRequest struct {
|
||||
Query string
|
||||
KnowledgeIDs []int64
|
||||
RetrievalStrategy *RetrievalStrategy
|
||||
ChatHistory []*schema.Message
|
||||
}
|
||||
|
||||
type Slice struct {
|
||||
|
||||
@ -35,6 +35,7 @@ type LLMParams struct {
|
||||
TopP *float64 `json:"topP"`
|
||||
TopK *int `json:"topK"`
|
||||
EnableChatHistory bool `json:"enableChatHistory"`
|
||||
ChatHistoryRound int64 `json:"chatHistoryRound"`
|
||||
SystemPrompt string `json:"systemPrompt"`
|
||||
ResponseFormat ResponseFormat `json:"responseFormat"`
|
||||
}
|
||||
|
||||
37
backend/domain/workflow/entity/chatflow_role.go
Normal file
37
backend/domain/workflow/entity/chatflow_role.go
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package entity
|
||||
|
||||
import "time"
|
||||
|
||||
type ChatFlowRole struct {
|
||||
ID int64
|
||||
WorkflowID int64
|
||||
ConnectorID int64
|
||||
Name string
|
||||
Description string
|
||||
Version string
|
||||
AvatarUri string
|
||||
BackgroundImageInfo string
|
||||
OnboardingInfo string
|
||||
SuggestReplyInfo string
|
||||
AudioConfig string
|
||||
UserInputConfig string
|
||||
CreatorID int64
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
39
backend/domain/workflow/entity/conversation.go
Normal file
39
backend/domain/workflow/entity/conversation.go
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package entity
|
||||
|
||||
type ConversationTemplate struct {
|
||||
SpaceID int64
|
||||
AppID int64
|
||||
Name string
|
||||
TemplateID int64
|
||||
}
|
||||
|
||||
type StaticConversation struct {
|
||||
UserID int64
|
||||
ConnectorID int64
|
||||
TemplateID int64
|
||||
ConversationID int64
|
||||
}
|
||||
|
||||
type DynamicConversation struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
ConnectorID int64
|
||||
ConversationID int64
|
||||
Name string
|
||||
}
|
||||
@ -16,6 +16,15 @@
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/workflow"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
|
||||
"github.com/coze-dev/coze-studio/backend/types/errno"
|
||||
)
|
||||
|
||||
type NodeType string
|
||||
|
||||
type NodeTypeMeta struct {
|
||||
@ -116,8 +125,11 @@ const (
|
||||
NodeTypeCodeRunner NodeType = "CodeRunner"
|
||||
NodeTypePlugin NodeType = "Plugin"
|
||||
NodeTypeCreateConversation NodeType = "CreateConversation"
|
||||
NodeTypeConversationList NodeType = "ConversationList"
|
||||
NodeTypeMessageList NodeType = "MessageList"
|
||||
NodeTypeClearMessage NodeType = "ClearMessage"
|
||||
NodeTypeCreateMessage NodeType = "CreateMessage"
|
||||
NodeTypeEditMessage NodeType = "EditMessage"
|
||||
NodeTypeDeleteMessage NodeType = "DeleteMessage"
|
||||
NodeTypeLambda NodeType = "Lambda"
|
||||
NodeTypeLLM NodeType = "LLM"
|
||||
NodeTypeSelector NodeType = "Selector"
|
||||
@ -125,9 +137,93 @@ const (
|
||||
NodeTypeSubWorkflow NodeType = "SubWorkflow"
|
||||
NodeTypeJsonSerialization NodeType = "JsonSerialization"
|
||||
NodeTypeJsonDeserialization NodeType = "JsonDeserialization"
|
||||
NodeTypeConversationUpdate NodeType = "ConversationUpdate"
|
||||
NodeTypeConversationDelete NodeType = "ConversationDelete"
|
||||
NodeTypeClearConversationHistory NodeType = "ClearConversationHistory"
|
||||
NodeTypeConversationHistory NodeType = "ConversationHistory"
|
||||
NodeTypeComment NodeType = "Comment"
|
||||
)
|
||||
|
||||
const (
|
||||
EntryNodeKey = "100001"
|
||||
ExitNodeKey = "900001"
|
||||
)
|
||||
|
||||
var blockType2NodeType = map[vo.BlockType]NodeType{
|
||||
vo.BlockTypeBotStart: NodeTypeEntry,
|
||||
vo.BlockTypeBotEnd: NodeTypeExit,
|
||||
vo.BlockTypeBotLLM: NodeTypeLLM,
|
||||
vo.BlockTypeBotAPI: NodeTypePlugin,
|
||||
vo.BlockTypeBotCode: NodeTypeCodeRunner,
|
||||
vo.BlockTypeBotDataset: NodeTypeKnowledgeRetriever,
|
||||
vo.BlockTypeCondition: NodeTypeSelector,
|
||||
vo.BlockTypeBotSubWorkflow: NodeTypeSubWorkflow,
|
||||
vo.BlockTypeDatabase: NodeTypeDatabaseCustomSQL,
|
||||
vo.BlockTypeBotMessage: NodeTypeOutputEmitter,
|
||||
vo.BlockTypeBotText: NodeTypeTextProcessor,
|
||||
vo.BlockTypeQuestion: NodeTypeQuestionAnswer,
|
||||
vo.BlockTypeBotBreak: NodeTypeBreak,
|
||||
vo.BlockTypeBotLoopSetVariable: NodeTypeVariableAssignerWithinLoop,
|
||||
vo.BlockTypeBotLoop: NodeTypeLoop,
|
||||
vo.BlockTypeBotIntent: NodeTypeIntentDetector,
|
||||
vo.BlockTypeBotDatasetWrite: NodeTypeKnowledgeIndexer,
|
||||
vo.BlockTypeBotInput: NodeTypeInputReceiver,
|
||||
vo.BlockTypeBotBatch: NodeTypeBatch,
|
||||
vo.BlockTypeBotContinue: NodeTypeContinue,
|
||||
vo.BlockTypeBotComment: NodeTypeComment,
|
||||
vo.BlockTypeBotVariableMerge: NodeTypeVariableAggregator,
|
||||
vo.BlockTypeCreateConversation: NodeTypeCreateConversation,
|
||||
vo.BlockTypeBotAssignVariable: NodeTypeVariableAssigner,
|
||||
vo.BlockTypeDatabaseUpdate: NodeTypeDatabaseUpdate,
|
||||
vo.BlockTypeDatabaseSelect: NodeTypeDatabaseQuery,
|
||||
vo.BlockTypeDatabaseDelete: NodeTypeDatabaseDelete,
|
||||
vo.BlockTypeDatabaseInsert: NodeTypeDatabaseInsert,
|
||||
vo.BlockTypeBotHttp: NodeTypeHTTPRequester,
|
||||
vo.BlockTypeConversationUpdate: NodeTypeConversationUpdate,
|
||||
vo.BlockTypeConversationDelete: NodeTypeConversationDelete,
|
||||
vo.BlockTypeJsonSerialization: NodeTypeJsonSerialization,
|
||||
vo.BlockTypeJsonDeserialization: NodeTypeJsonDeserialization,
|
||||
vo.BlockTypeBotDatasetDelete: NodeTypeKnowledgeDeleter,
|
||||
vo.BlockTypeConversationList: NodeTypeConversationList,
|
||||
vo.BlockTypeClearConversationHistory: NodeTypeClearConversationHistory,
|
||||
vo.BlockTypeConversationHistory: NodeTypeConversationHistory,
|
||||
vo.BlockTypeBotMessageList: NodeTypeMessageList,
|
||||
vo.BlockTypeCreateMessage: NodeTypeCreateMessage,
|
||||
vo.BlockTypeEditeMessage: NodeTypeEditMessage,
|
||||
vo.BlockTypeDeleteMessage: NodeTypeDeleteMessage,
|
||||
}
|
||||
var nodeType2BlockType = func() map[NodeType]vo.BlockType {
|
||||
nodeType2BlockType := make(map[NodeType]vo.BlockType, len(blockType2NodeType))
|
||||
for k, v := range blockType2NodeType {
|
||||
nodeType2BlockType[v] = k
|
||||
}
|
||||
return nodeType2BlockType
|
||||
}()
|
||||
|
||||
func BlockType2EntityNodeType(t string) (NodeType, error) {
|
||||
blockType := vo.BlockType(t)
|
||||
if nodeType, ok := blockType2NodeType[blockType]; ok {
|
||||
return nodeType, nil
|
||||
}
|
||||
return "", fmt.Errorf("cannot map block type'%s' to a node type", t)
|
||||
}
|
||||
|
||||
func NodeTypeToAPINodeTemplateType(nodeType NodeType) (workflow.NodeTemplateType, error) {
|
||||
if blockType, ok := nodeType2BlockType[nodeType]; ok {
|
||||
blockTypeInt, err := strconv.ParseInt(string(blockType), 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return workflow.NodeTemplateType(blockTypeInt), nil
|
||||
}
|
||||
return workflow.NodeTemplateType(0), fmt.Errorf("cannot map entity node type '%s' to a workflow.NodeTemplateType", nodeType)
|
||||
}
|
||||
|
||||
func NodeTypeToBlockType(nodeType NodeType) (vo.BlockType, error) {
|
||||
if t, ok := nodeType2BlockType[nodeType]; ok {
|
||||
return t, nil
|
||||
}
|
||||
return "", vo.WrapError(errno.ErrSchemaConversionFail,
|
||||
fmt.Errorf("cannot map entity node type '%s' to a block type", nodeType))
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/i18n"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ternary"
|
||||
)
|
||||
@ -481,7 +483,6 @@ var NodeTypeMetas = []*NodeTypeMeta{
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-Conversation-List.jpeg",
|
||||
SupportBatch: false, // supportBatch: 1
|
||||
Disabled: true,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
@ -492,14 +493,13 @@ var NodeTypeMetas = []*NodeTypeMeta{
|
||||
},
|
||||
{
|
||||
ID: 38,
|
||||
Name: "清除上下文",
|
||||
Type: NodeTypeClearMessage,
|
||||
Name: "清空会话历史",
|
||||
Type: NodeTypeClearConversationHistory,
|
||||
Category: "conversation_history", // Mapped from cate_list
|
||||
Desc: "用于清空会话历史,清空后LLM看到的会话历史为空",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-Conversation-Delete.jpeg",
|
||||
SupportBatch: false, // supportBatch: 1
|
||||
Disabled: true,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
@ -508,6 +508,25 @@ var NodeTypeMetas = []*NodeTypeMeta{
|
||||
EnUSName: "Clear conversation history",
|
||||
EnUSDescription: "Used to clear conversation history. After clearing, the conversation history visible to the LLM node will be empty.",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 54,
|
||||
Name: "查询会话历史",
|
||||
Type: NodeTypeConversationHistory,
|
||||
Category: "conversation_history", // Mapped from cate_list
|
||||
Desc: "用于查询会话历史,返回LLM可见的会话消息",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-查询会话历史.jpg",
|
||||
SupportBatch: false,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Query Conversation History",
|
||||
EnUSDescription: "Used to query conversation history, returns conversation messages visible to the LLM",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 39,
|
||||
Name: "创建会话",
|
||||
@ -517,15 +536,51 @@ var NodeTypeMetas = []*NodeTypeMeta{
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-Conversation-Create.jpeg",
|
||||
SupportBatch: false, // supportBatch: 1
|
||||
Disabled: true,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Create conversation",
|
||||
EnUSName: "Create Conversation",
|
||||
EnUSDescription: "This node is used to create a conversation.",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 51,
|
||||
Name: "修改会话",
|
||||
Type: NodeTypeConversationUpdate,
|
||||
Category: "conversation_management", // Mapped from cate_list
|
||||
Desc: "用于修改会话的名字",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-编辑会话.jpg",
|
||||
SupportBatch: false,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Edit Conversation",
|
||||
EnUSDescription: "Used to modify the name of a conversation.",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 52,
|
||||
Name: "删除会话",
|
||||
Type: NodeTypeConversationDelete,
|
||||
Category: "conversation_management", // Mapped from cate_list
|
||||
Desc: "用于删除会话",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-删除会话.jpg",
|
||||
SupportBatch: false,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Delete Conversation",
|
||||
EnUSDescription: "Used to delete a conversation.",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 40,
|
||||
Name: "变量赋值",
|
||||
@ -632,13 +687,83 @@ var NodeTypeMetas = []*NodeTypeMeta{
|
||||
EnUSName: "Add Data",
|
||||
EnUSDescription: "Add new data records to the table, and insert them into the database after the user enters the data content",
|
||||
},
|
||||
{
|
||||
ID: 53,
|
||||
Name: "查询会话列表",
|
||||
Type: NodeTypeConversationList,
|
||||
Category: "conversation_management",
|
||||
Desc: "用于查询所有会话,包含静态会话、动态会话",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-查询会话.jpg",
|
||||
SupportBatch: false,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Query Conversation List",
|
||||
EnUSDescription: "Used to query all conversations, including static conversations and dynamic conversations",
|
||||
},
|
||||
{
|
||||
ID: 55,
|
||||
Name: "创建消息",
|
||||
Type: NodeTypeCreateMessage,
|
||||
Category: "message",
|
||||
Desc: "用于创建消息",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-创建消息.jpg",
|
||||
SupportBatch: false, // supportBatch: 1
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Create message",
|
||||
EnUSDescription: "Used to create messages",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 56,
|
||||
Name: "修改消息",
|
||||
Type: NodeTypeEditMessage,
|
||||
Category: "message",
|
||||
Desc: "用于修改消息",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-修改消息.jpg",
|
||||
SupportBatch: false, // supportBatch: 1
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Edit message",
|
||||
EnUSDescription: "Used to edit messages",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 57,
|
||||
Name: "删除消息",
|
||||
Type: NodeTypeDeleteMessage,
|
||||
Category: "message",
|
||||
Desc: "用于删除消息",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-删除消息.jpg",
|
||||
SupportBatch: false, // supportBatch: 1
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
PreFillZero: true,
|
||||
PostFillNil: true,
|
||||
StreamingParadigms: map[StreamingParadigm]bool{Invoke: true},
|
||||
},
|
||||
EnUSName: "Delete message",
|
||||
EnUSDescription: "Used to delete messages",
|
||||
},
|
||||
|
||||
{
|
||||
ID: 58,
|
||||
Name: "JSON 序列化",
|
||||
Type: NodeTypeJsonSerialization,
|
||||
Category: "utilities",
|
||||
Desc: "用于把变量转化为JSON字符串",
|
||||
Color: "F2B600",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-to_json.png",
|
||||
SupportBatch: false,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
@ -656,7 +781,7 @@ var NodeTypeMetas = []*NodeTypeMeta{
|
||||
Type: NodeTypeJsonDeserialization,
|
||||
Category: "utilities",
|
||||
Desc: "用于将JSON字符串解析为变量",
|
||||
Color: "F2B600",
|
||||
Color: "#F2B600",
|
||||
IconURL: "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-from_json.png",
|
||||
SupportBatch: false,
|
||||
ExecutableMeta: ExecutableMeta{
|
||||
@ -862,6 +987,133 @@ const defaultEnUSInitCanvasJsonSchema = `{
|
||||
}
|
||||
}`
|
||||
|
||||
const defaultZhCNInitCanvasJsonSchemaChat = `{
|
||||
"nodes": [{
|
||||
"id": "100001",
|
||||
"type": "1",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"outputs": [{
|
||||
"type": "string",
|
||||
"name": "USER_INPUT",
|
||||
"required": true
|
||||
}, {
|
||||
"type": "string",
|
||||
"name": "CONVERSATION_NAME",
|
||||
"required": false,
|
||||
"description": "本次请求绑定的会话,会自动写入消息、会从该会话读对话历史。",
|
||||
"defaultValue": "%s"
|
||||
}],
|
||||
"nodeMeta": {
|
||||
"title": "开始",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-Start.png",
|
||||
"description": "工作流的起始节点,用于设定启动工作流需要的信息",
|
||||
"subTitle": ""
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"id": "900001",
|
||||
"type": "2",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 1000,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"nodeMeta": {
|
||||
"title": "结束",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-End.png",
|
||||
"description": "工作流的最终节点,用于返回工作流运行后的结果信息",
|
||||
"subTitle": ""
|
||||
},
|
||||
"inputs": {
|
||||
"terminatePlan": "useAnswerContent",
|
||||
"streamingOutput": true,
|
||||
"inputParameters": [{
|
||||
"name": "output",
|
||||
"input": {
|
||||
"type": "string",
|
||||
"value": {
|
||||
"type": "ref"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}`
|
||||
const defaultEnUSInitCanvasJsonSchemaChat = `{
|
||||
"nodes": [{
|
||||
"id": "100001",
|
||||
"type": "1",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"outputs": [{
|
||||
"type": "string",
|
||||
"name": "USER_INPUT",
|
||||
"required": true
|
||||
}, {
|
||||
"type": "string",
|
||||
"name": "CONVERSATION_NAME",
|
||||
"required": false,
|
||||
"description": "The conversation bound to this request will automatically write messages and read conversation history from that conversation.",
|
||||
"defaultValue": "%s"
|
||||
}],
|
||||
"nodeMeta": {
|
||||
"title": "Start",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-Start.png",
|
||||
"description": "The starting node of the workflow, used to set the information needed to initiate the workflow.",
|
||||
"subTitle": ""
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"id": "900001",
|
||||
"type": "2",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 1000,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"nodeMeta": {
|
||||
"title": "End",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-End.png",
|
||||
"description": "The final node of the workflow, used to return the result information after the workflow runs.",
|
||||
"subTitle": ""
|
||||
},
|
||||
"inputs": {
|
||||
"terminatePlan": "useAnswerContent",
|
||||
"streamingOutput": true,
|
||||
"inputParameters": [{
|
||||
"name": "output",
|
||||
"input": {
|
||||
"type": "string",
|
||||
"value": {
|
||||
"type": "ref"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}`
|
||||
|
||||
func GetDefaultInitCanvasJsonSchema(locale i18n.Locale) string {
|
||||
return ternary.IFElse(locale == i18n.LocaleEN, defaultEnUSInitCanvasJsonSchema, defaultZhCNInitCanvasJsonSchema)
|
||||
}
|
||||
|
||||
func GetDefaultInitCanvasJsonSchemaChat(locale i18n.Locale, name string) string {
|
||||
return ternary.IFElse(locale == i18n.LocaleEN, fmt.Sprintf(defaultEnUSInitCanvasJsonSchemaChat, name), fmt.Sprintf(defaultZhCNInitCanvasJsonSchemaChat, name))
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user