Compare commits

...

43 Commits

Author SHA1 Message Date
e3930873c6 feat: Chat supports Q&A nodes (#207)
Co-authored-by: yangyu.1 <yangyu.1@bytedance.com>
2025-07-30 03:41:27 +00:00
2ed2a60479 fix(plugin): parameter convert failed (#274) 2025-07-29 14:35:59 +00:00
f589bb94bb feat: add redis password (#201) 2025-07-29 13:34:44 +00:00
02b4171576 fix: error when parsing tables with only headers in docx/pdf (#271) 2025-07-29 13:16:17 +00:00
0d83a5e7bc docs: update CONTRIBUTING.md to reflect main branch usage (#172) 2025-07-29 13:09:32 +00:00
14ca189316 fix: escape '$' to '$$' in docker-compose.yml file (#234) 2025-07-29 12:58:05 +00:00
Ryo
4310dee4c2 feat(backend): Optimize HTTPS certificate path (#265) 2025-07-29 12:34:25 +00:00
4ca3e597ff fix: release http embedding (#214) 2025-07-29 11:44:02 +00:00
53345f58c2 fix(backend_plugin): plugin common header and parameter default value (#181) 2025-07-29 11:29:36 +00:00
8137b0aee5 feat: init improvements (#174) 2025-07-29 11:02:03 +00:00
b48c4c2792 feat(ci): update helm (#222) 2025-07-29 11:01:48 +00:00
ski
f8840810ce chore: add licenses to json stringify related files (#250) 2025-07-29 17:31:38 +08:00
Ryo
9b68bd5387 chore(ci): add default reviewer (#220) 2025-07-29 06:54:35 +00:00
a6f97f61f8 feat: add --es-address parameter to setup_es_index with .env support (#177) 2025-07-29 06:23:54 +00:00
ski
0965d69acc feat: add json-stringify node (#215)
Co-authored-by: zengxiaohui <zengxiaohui@bytedance.com>
2025-07-29 06:11:49 +00:00
183d0324bb feat(user): add ENV to control DISABLE_USER_REGISTRATION and ALLOW_REGISTRATION_EMAIL (#208) 2025-07-29 04:36:44 +00:00
04f0491454 docs: Add an explanation of how the frontend code is used (#182) 2025-07-29 00:53:39 +08:00
9ed2f8be67 feat: add s3 service (#188) 2025-07-28 15:19:52 +00:00
403128b5d3 fix: Optimize knowledge domain error codes to expose previous errors during retries (#185) 2025-07-28 14:53:53 +00:00
db7c95885d fix: Optimize the GetDraftIntelligenceList function and reduce the use of goroutine (#171) 2025-07-28 12:45:10 +00:00
2ee3fa68ab fix: user name (#180) 2025-07-28 12:28:02 +00:00
Ryo
a0d3bcf998 feat(ci): update helm config (#157) 2025-07-28 11:17:56 +00:00
cc593fc270 chore: backend owners (#170) 2025-07-28 11:13:33 +00:00
6e961bb60d fix: remove setup_es_index in makefile (#166) 2025-07-28 10:03:28 +00:00
f93b60512f feat: disable image_ocr by default in text processing stores (#149) 2025-07-28 10:03:03 +00:00
9dcdb70508 chore: setup increment ci env (#109) 2025-07-28 09:51:31 +00:00
4a44c0ddbd fix(memory): Use text as the underlying type of string (#129) 2025-07-28 09:40:33 +00:00
b299adacf3 fix(search): Fix logical issues with search domain code (#151) 2025-07-28 09:11:00 +00:00
0ce6a4da4c chore: add author (#113)
Co-authored-by: wenming.2020 <wenming.2020@bytedance.com>
2025-07-28 08:01:44 +00:00
be5178d57b docs: openapi token description (#130) 2025-07-28 06:40:39 +00:00
2d925ca241 fix: CODEOWNERS (#117) 2025-07-28 06:20:52 +00:00
Ryo
60a9c7a281 docs: update readme (#126) 2025-07-28 06:08:01 +00:00
376e563e4f fix: add plugin id conflict checker (#78) 2025-07-28 06:07:03 +00:00
Ryo
f0c339d231 chore(ci): Optimize Elasticsearch index init script, remove Docker im… (#106) 2025-07-28 04:26:58 +00:00
81b5867a62 chore: add author (#123)
Co-authored-by: tanjizhen <tanjizhen@bytedance.com>
2025-07-28 04:25:18 +00:00
5ac7b8d26e chore: allow all type email (#115) 2025-07-28 03:55:58 +00:00
48b52c3592 docs: add FAQ link (#94) 2025-07-28 01:29:04 +08:00
033df3f8ee fix: field about time type (#92) 2025-07-28 00:36:14 +08:00
Ryo
f294e19af5 docs: update readme (#85) 2025-07-27 21:25:34 +08:00
23a1f1cab0 docs: recommend use issues first, add discord and telegram (#57) 2025-07-27 11:41:11 +08:00
c3d8def0e6 docs: add acknowledgments for eino, hertz (#40) 2025-07-26 19:24:48 +08:00
32d9bf9a39 docs: add new acknowledgment (#25) 2025-07-26 15:04:45 +08:00
Ryo
be4aa3f2ca chore(ci): remove unused tool (#26) 2025-07-26 15:02:57 +08:00
127 changed files with 2822 additions and 1051 deletions

540
.github/CODEOWNERS vendored
View File

@ -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

294
.github/workflows/ci.yml vendored Normal file
View 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
View 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
View 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.

View File

@ -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>

View File

@ -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/).

View File

@ -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."

View File

@ -72,8 +72,9 @@ 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.
@ -83,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.
@ -107,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:
![Image](https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/0a49081e8f3743e8bf3dcdded4bb571a~tplv-goo7wpa0wc-image.image)
**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

View File

@ -25,6 +25,7 @@
Coze Studio源自服务了上万家企业、数百万开发者的「扣子开发平台」我们将它的核心引擎完全开放。它是一个一站式的 AI Agent 可视化开发工具,让 AI Agent 的创建、调试和部署变得前所未有的简单。通过 Coze Studio 提供的可视化设计与编排工具,开发者可以通过零代码或低代码的方式,快速打造和调试智能体、应用和工作流,实现强大的 AI 应用开发和更多定制化业务逻辑,是构建低代码 AI 产品的理想选择。Coze Studio 致力于降低 AI Agent 开发与应用门槛,鼓励社区共建和分享交流,助你在 AI 领域进行更深层次的探索与实践。
Coze Studio 的后端采用 Golang 开发,前端使用 React + TypeScript整体基于微服务架构并遵循领域驱动设计DDD原则构建。为开发者提供一个高性能、高扩展性、易于二次开发的底层框架助力开发者应对复杂的业务需求。
## 功能清单
| **功能模块** | **功能点** |
| --- | --- |
@ -71,8 +72,10 @@ 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)
### 💬 技术交流与讨论
加入我们的技术交流群,与其他开发者分享经验、获取项目最新动态:
**飞书群聊**
使用飞书移动端扫描下方二维码加入:
![Image](https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/0a49081e8f3743e8bf3dcdded4bb571a~tplv-goo7wpa0wc-image.image)
**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 框架,用于构建微服务
* 所有参与测试和反馈的用户

View File

@ -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"]

View File

@ -263,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))
}

View File

@ -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) {

View File

@ -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
}

View File

@ -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,
}
})

View File

@ -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)

View File

@ -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,
}

View File

@ -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")
}

View File

@ -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,

View File

@ -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
}

View File

@ -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())
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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,

View File

@ -3497,7 +3497,7 @@ func entityNodeTypeToAPINodeTemplateType(nodeType entity.NodeType) (workflow.Nod
// return workflow.NodeTemplateType_DatabaseInsert, nil
return workflow.NodeTemplateType(46), nil
case entity.NodeTypeJsonSerialization:
return workflow.NodeTemplateType_JsonSerialization, nil
return workflow.NodeTemplateType(58), nil
case entity.NodeTypeJsonDeserialization:
return workflow.NodeTemplateType_JsonDeserialization, nil
case entity.NodeTypeKnowledgeDeleter:

View File

@ -157,7 +157,7 @@ meta:
top_k: 0
stop: []
openai:
by_azure: true
by_azure: false
api_version: ""
response_format:
type: text

View File

@ -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

View File

@ -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)
}
}
}()

View File

@ -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 {

View File

@ -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)
}

View File

@ -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:

View File

@ -157,7 +157,6 @@ func NewDefaultPluginManifest() *PluginManifest {
Value: "Coze/1.0",
},
},
model.ParamInPath: {},
model.ParamInQuery: {},
},
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View 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)
})
}

View File

@ -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,
})
}
}

View File

@ -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 {

View File

@ -12,7 +12,7 @@ require (
github.com/apache/thrift v0.21.0
github.com/bytedance/mockey v1.2.14
github.com/bytedance/sonic v1.13.2
github.com/cloudwego/eino v0.3.51
github.com/cloudwego/eino v0.3.55
github.com/cloudwego/eino-ext/components/model/ark v0.1.15
github.com/cloudwego/eino-ext/components/model/claude v0.1.1
github.com/cloudwego/eino-ext/components/model/deepseek v0.0.0-20250715055739-0d0e28441a2f
@ -54,10 +54,12 @@ require github.com/alicebob/miniredis/v2 v2.34.0
require (
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1
github.com/cloudwego/eino-ext/components/embedding/ark v0.0.0-20250522060253-ddb617598b09
github.com/cloudwego/eino-ext/components/embedding/ollama v0.0.0-20250728060543-79ec300857b8
github.com/cloudwego/eino-ext/components/embedding/openai v0.0.0-20250522060253-ddb617598b09
github.com/cloudwego/eino-ext/components/model/gemini v0.1.2
github.com/cloudwego/eino-ext/components/model/ollama v0.0.0-20250610035057-2c4e7c8488a5
github.com/cloudwego/eino-ext/components/model/ollama v0.1.0
github.com/cloudwego/eino-ext/components/model/qwen v0.0.0-20250612061754-5a3deb091dc5
github.com/dimchansky/utfbom v1.1.1
github.com/elastic/go-elasticsearch/v7 v7.17.10
@ -66,7 +68,7 @@ require (
github.com/jinzhu/copier v0.4.0
github.com/mattn/go-shellwords v1.0.12
github.com/nsqio/go-nsq v1.1.0
github.com/ollama/ollama v0.6.5
github.com/ollama/ollama v0.9.6
github.com/rbretecher/go-postman-collection v0.9.0
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.17
github.com/yuin/goldmark v1.4.13
@ -80,6 +82,9 @@ require (
cloud.google.com/go/auth v0.9.3 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // indirect
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 // indirect
github.com/cloudwego/gopkg v0.1.4 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 // indirect
@ -106,20 +111,20 @@ require (
require (
github.com/anthropics/anthropic-sdk-go v1.4.0 // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/aws/aws-sdk-go-v2 v1.33.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
github.com/aws/aws-sdk-go-v2/config v1.29.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.54 // indirect
github.com/aws/aws-sdk-go-v2 v1.36.6
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect
github.com/aws/aws-sdk-go-v2/config v1.29.1
github.com/aws/aws-sdk-go-v2/credentials v1.17.54
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.9 // indirect
github.com/aws/smithy-go v1.22.1 // indirect
github.com/aws/smithy-go v1.22.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bytedance/gopkg v0.1.1 // indirect
@ -242,7 +247,7 @@ require (
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
github.com/volcengine/volcengine-go-sdk v1.1.20 // indirect
github.com/volcengine/volcengine-go-sdk v1.1.20
github.com/x448/float16 v0.8.4 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect

View File

@ -822,27 +822,35 @@ github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHS
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2 v1.33.0 h1:Evgm4DI9imD81V0WwD+TN4DCwjUMdc94TrduMLbgZJs=
github.com/aws/aws-sdk-go-v2 v1.33.0/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
github.com/aws/aws-sdk-go-v2 v1.36.6 h1:zJqGjVbRdTPojeCGWn5IR5pbJwSQSBh5RWFTQcEQGdU=
github.com/aws/aws-sdk-go-v2 v1.36.6/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY=
github.com/aws/aws-sdk-go-v2/config v1.29.1 h1:JZhGawAyZ/EuJeBtbQYnaoftczcb2drR2Iq36Wgz4sQ=
github.com/aws/aws-sdk-go-v2/config v1.29.1/go.mod h1:7bR2YD5euaxBhzt2y/oDkt3uNRb6tjFp98GlTFueRwk=
github.com/aws/aws-sdk-go-v2/credentials v1.17.54 h1:4UmqeOqJPvdvASZWrKlhzpRahAulBfyTJQUaYy4+hEI=
github.com/aws/aws-sdk-go-v2/credentials v1.17.54/go.mod h1:RTdfo0P0hbbTxIhmQrOsC/PquBZGabEPnCaxxKRPSnI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 h1:5grmdTdMsovn9kPZPI23Hhvp0ZyNm5cRO+IZFIYiAfw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24/go.mod h1:zqi7TVKTswH3Ozq28PkmBmgzG1tona7mo9G2IJg4Cis=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 h1:igORFSiH3bfq4lxKFkTSYDhJEUCYo6C8VKiWJjYwQuQ=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28/go.mod h1:3So8EA/aAYm36L7XIvCVwLa0s5N0P7o2b1oqnx/2R4g=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 h1:1mOW9zAUMhTSrMDssEHS/ajx8JcAj/IcftzcmNlmVLI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28/go.mod h1:kGlXVIWDfvt2Ox5zEaNglmq0hXPHgQFNMix33Tw22jA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 h1:osMWfm/sC/L4tvEdQ65Gri5ZZDCUpuYJZbTTDrsn4I0=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37/go.mod h1:ZV2/1fbjOPr4G4v38G3Ww5TBT4+hmsK45s/rxu1fGy0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 h1:v+X21AvTb2wZ+ycg1gx+orkB/9U6L7AOp93R7qYxsxM=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37/go.mod h1:G0uM1kyssELxmJ2VZEfG0q2npObR3BAkF3c1VsfVnfs=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37 h1:XTZZ0I3SZUHAtBLBU6395ad+VOblE0DwQP6MuaNeics=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.37/go.mod h1:Pi6ksbniAWVwu2S8pEzcYPyhUkAcLaufxN7PfAUQjBk=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 h1:TQmKDyETFGiXVhZfQ/I0cCFziqqX58pi4tKJGYGFSz0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9/go.mod h1:HVLPK2iHQBUx7HfZeOQSEu3v2ubZaAY2YPbAm5/WUyY=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5 h1:M5/B8JUaCI8+9QD+u3S/f4YHpvqE9RpSkV3rf0Iks2w=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.5/go.mod h1:Bktzci1bwdbpuLiu3AOksiNPMl/LLKmX1TWmqp2xbvs=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 h1:vvbXsA2TVO80/KT7ZqCbx934dt6PY+vQ8hZpUZ/cpYg=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18/go.mod h1:m2JJHledjBGNMsLOF1g9gbAxprzq3KjC8e4lxtn+eWg=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18 h1:OS2e0SKqsU2LiJPqL8u9x41tKc6MMEHrWjLVLn3oysg=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.18/go.mod h1:+Yrk+MDGzlNGxCXieljNeWpoZTCQUQVL+Jk9hGGJ8qM=
github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1 h1:RkHXU9jP0DptGy7qKI8CBGsUJruWz0v5IgwBa2DwWcU=
github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1/go.mod h1:3xAOf7tdKF+qbb+XpU+EPhNXAdun3Lu1RcDrj8KC24I=
github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 h1:kuIyu4fTT38Kj7YCC7ouNbVZSSpqkZ+LzIfhCr6Dg+I=
github.com/aws/aws-sdk-go-v2/service/sso v1.24.11/go.mod h1:Ro744S4fKiCCuZECXgOi760TiYylUM8ZBf6OGiZzJtY=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 h1:l+dgv/64iVlQ3WsBbnn+JSbkj01jIi+SM0wYsj3y/hY=
@ -850,8 +858,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10/go.mod h1:Fzsj6lZEb8AkTE5S
github.com/aws/aws-sdk-go-v2/service/sts v1.33.9 h1:BRVDbewN6VZcwr+FBOszDKvYeXY1kJ+GGMCcpghlw0U=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.9/go.mod h1:f6vjfZER1M17Fokn0IzssOTMT2N8ZSq+7jnNF0tArvw=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw=
github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/bazelbuild/rules_go v0.49.0/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@ -916,10 +924,12 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/eino v0.3.51 h1:emSaDu49v9EEJYOusL42Li/VL5QBSyBvhxO9ZcKPZvs=
github.com/cloudwego/eino v0.3.51/go.mod h1:wUjz990apdsaOraOXdh6CdhVXq8DJsOvLsVlxNTcNfY=
github.com/cloudwego/eino v0.3.55 h1:lMZrGtEh0k3qykQTLNXSXuAa98OtF2tS43GMHyvN7nA=
github.com/cloudwego/eino v0.3.55/go.mod h1:wUjz990apdsaOraOXdh6CdhVXq8DJsOvLsVlxNTcNfY=
github.com/cloudwego/eino-ext/components/embedding/ark v0.0.0-20250522060253-ddb617598b09 h1:hZScBE/Etiji2RqjlABcAkq6n1uzYPu+jo4GV5TF8Hc=
github.com/cloudwego/eino-ext/components/embedding/ark v0.0.0-20250522060253-ddb617598b09/go.mod h1:pLtH5BZKgb7/bB8+P3W5/f1d46gTl9K77+08j88Gb4k=
github.com/cloudwego/eino-ext/components/embedding/ollama v0.0.0-20250728060543-79ec300857b8 h1:uJrs6SmfYnca8A+k9+3qJ4MYwYHMncUlGac1mYQT+Ak=
github.com/cloudwego/eino-ext/components/embedding/ollama v0.0.0-20250728060543-79ec300857b8/go.mod h1:nav79aUcd+UR24dLA+7l7RcHCMlg26zbDAKvjONdrw0=
github.com/cloudwego/eino-ext/components/embedding/openai v0.0.0-20250522060253-ddb617598b09 h1:C8RjF193iguUuevkuv0q4SC+XGlM/DlJEgic7l8OUAI=
github.com/cloudwego/eino-ext/components/embedding/openai v0.0.0-20250522060253-ddb617598b09/go.mod h1:S09z/CAQNyx+AbgfJRQXLUAYlPpxQWWLVuQxO34F90A=
github.com/cloudwego/eino-ext/components/model/ark v0.1.15 h1:ydOvtEK67VI5DvNgg64eTxbjxMYhGBMOVP2okaZKk18=
@ -932,6 +942,8 @@ github.com/cloudwego/eino-ext/components/model/gemini v0.1.2 h1:bt9xftOQhP0Nuh1P
github.com/cloudwego/eino-ext/components/model/gemini v0.1.2/go.mod h1:1tv89uZ9hR/4AyQ+9yxFWLn52GaJDKtPXdEY7WZdyZc=
github.com/cloudwego/eino-ext/components/model/ollama v0.0.0-20250610035057-2c4e7c8488a5 h1:GkAAQHQkb1cOTwm6uRokj4lM//wrt/3AkMwTxyFJUg4=
github.com/cloudwego/eino-ext/components/model/ollama v0.0.0-20250610035057-2c4e7c8488a5/go.mod h1:giNUFqA+V7xrm/EDvH7JFnDqoWI+e2m1SVAnReU+Fd8=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.0 h1:FW067iMfg3EZbUaZIo8v3i2ILBAZDzY23/9pbprvE0M=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.0/go.mod h1:+qA5kkUCM0mIrXGSNzxLcjxh6K1AghPNigtEyyMdkOc=
github.com/cloudwego/eino-ext/components/model/openai v0.0.0-20250715055739-0d0e28441a2f h1:ovS39vuN2JW+C/O9jtEmOUuLEY4fw0yYh8//yhMfJNM=
github.com/cloudwego/eino-ext/components/model/openai v0.0.0-20250715055739-0d0e28441a2f/go.mod h1:2mFQQnlhJrNgbW6YX1MOUUfXkGSbTz9Ylx37fbR0xBo=
github.com/cloudwego/eino-ext/components/model/qwen v0.0.0-20250612061754-5a3deb091dc5 h1:4zAZiNo/PkeVc0Gw8YLpzpbR8zDzccL7H5PLqTuGhv4=
@ -1594,8 +1606,8 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
github.com/nyaruka/phonenumbers v1.0.55 h1:bj0nTO88Y68KeUQ/n3Lo2KgK7lM1hF7L9NFuwcCl3yg=
github.com/nyaruka/phonenumbers v1.0.55/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/ollama/ollama v0.6.5 h1:vXKkVX57ql/1ZzMw4SVK866Qfd6pjwEcITVyEpF0QXQ=
github.com/ollama/ollama v0.6.5/go.mod h1:pGgtoNyc9DdM6oZI6yMfI6jTk2Eh4c36c2GpfQCH7PY=
github.com/ollama/ollama v0.9.6 h1:HZNJmB52pMt6zLkGkkheBuXBXM5478eiSAj7GR75AMc=
github.com/ollama/ollama v0.9.6/go.mod h1:zLwx3iZ3AI4Rc/egsrx3u1w4RU2MHQ/Ylxse48jvyt4=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

View File

@ -27,9 +27,11 @@ type Client = redis.Client
func New() *redis.Client {
addr := os.Getenv("REDIS_ADDR")
password := os.Getenv("REDIS_PASSWORD")
rdb := redis.NewClient(&redis.Options{
Addr: addr, // Redis地址
DB: 0, // 默认数据库
Password: password,
// 连接池配置
PoolSize: 100, // 最大连接数建议设置为CPU核心数*10
MinIdleConns: 10, // 最小空闲连接

View File

@ -18,14 +18,18 @@ package veocr
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"github.com/volcengine/volc-sdk-golang/service/visual"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
"github.com/coze-dev/coze-studio/backend/infra/contract/document/ocr"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/types/errno"
)
type Config struct {
@ -52,10 +56,14 @@ func (o *ocrImpl) FromBase64(ctx context.Context, b64 string) ([]string, error)
resp, statusCode, err := o.config.Client.OCRNormal(form)
if err != nil {
return nil, err
return nil, o.handleError(fmt.Errorf("[ve_ocr][FromBase64] OCRNormal err: %w", err))
}
if statusCode != http.StatusOK {
return nil, fmt.Errorf("[FromBase64] failed, status code=%d", statusCode)
err = fmt.Errorf("[ve_ocr][FromBase64] OCRNormal failed, status code=%d", statusCode)
if statusCode == http.StatusBadRequest {
return nil, errorx.WrapByCode(err, errno.ErrKnowledgeNonRetryableCode)
}
return nil, err
}
return resp.Data.LineTexts, nil
@ -67,10 +75,14 @@ func (o *ocrImpl) FromURL(ctx context.Context, url string) ([]string, error) {
resp, statusCode, err := o.config.Client.OCRNormal(form)
if err != nil {
return nil, err
return nil, o.handleError(fmt.Errorf("[ve_ocr][FromURL] OCRNormal error: %w", err))
}
if statusCode != http.StatusOK {
return nil, fmt.Errorf("[FromBase64] failed, status code=%d", statusCode)
err = fmt.Errorf("[ve_ocr][FromURL] OCRNormal failed, status code=%d", statusCode)
if statusCode == http.StatusBadRequest {
return nil, errorx.WrapByCode(err, errno.ErrKnowledgeNonRetryableCode)
}
return nil, err
}
return resp.Data.LineTexts, nil
@ -94,3 +106,21 @@ func (o *ocrImpl) newForm() url.Values {
}
return form
}
func (o *ocrImpl) handleError(err error) error {
var (
apiErr = &model.APIError{}
reqErr = &model.RequestError{}
)
if errors.As(err, &apiErr) {
if apiErr.HTTPStatusCode >= http.StatusInternalServerError ||
apiErr.HTTPStatusCode == http.StatusTooManyRequests {
return err
}
} else if errors.As(err, &reqErr) {
if reqErr.HTTPStatusCode >= http.StatusInternalServerError {
return err
}
}
return errorx.WrapByCode(err, errno.ErrKnowledgeNonRetryableCode)
}

View File

@ -249,6 +249,11 @@ func formatTablesInDocument(input []*schema.Document) (output []*schema.Document
values = append(values, col.Name)
}
write(values)
if colOnly, err := document.GetDocumentColumnsOnly(doc); err != nil {
return nil, err
} else if colOnly {
break
}
}
data, err := document.GetDocumentColumnData(doc)

View File

@ -18,14 +18,19 @@ package ark
import (
"context"
"errors"
"fmt"
"math"
"net/http"
"github.com/cloudwego/eino-ext/components/embedding/ark"
"github.com/cloudwego/eino/components/embedding"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
contract "github.com/coze-dev/coze-studio/backend/infra/contract/embedding"
"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"
)
func NewArkEmbedder(ctx context.Context, config *ark.EmbeddingConfig, dimensions int64) (contract.Embedder, error) {
@ -51,7 +56,21 @@ func (d embWrap) EmbedStrings(ctx context.Context, texts []string, opts ...embed
}
normed, err := d.slicedNormL2(partResult)
if err != nil {
return nil, err
var (
apiErr = &model.APIError{}
reqErr = &model.RequestError{}
)
if errors.As(err, &apiErr) {
if apiErr.HTTPStatusCode >= http.StatusInternalServerError ||
apiErr.HTTPStatusCode == http.StatusTooManyRequests {
return nil, err
}
} else if errors.As(err, &reqErr) {
if reqErr.HTTPStatusCode >= http.StatusInternalServerError {
return nil, err
}
}
return nil, errorx.WrapByCode(err, errno.ErrKnowledgeNonRetryableCode)
}
resp = append(resp, normed...)
}

View File

@ -22,7 +22,6 @@ import (
"encoding/json"
"io"
"net/http"
"strconv"
"time"
opt "github.com/cloudwego/eino/components/embedding"
@ -30,10 +29,7 @@ import (
"github.com/coze-dev/coze-studio/backend/infra/contract/embedding"
)
const (
pathDim = "/dimension"
pathEmbed = "/embedding"
)
const pathEmbed = "/embedding"
type embedReq struct {
Texts []string `json:"texts"`
@ -45,32 +41,12 @@ type embedResp struct {
Sparse []map[int]float64 `json:"sparse"`
}
func NewEmbedding(addr string) (embedding.Embedder, error) {
func NewEmbedding(addr string, dims int64) (embedding.Embedder, error) {
cli := &http.Client{Timeout: time.Second * 30}
req, err := http.NewRequest(http.MethodGet, addr+pathDim, nil)
if err != nil {
return nil, err
}
resp, err := cli.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
dim, err := strconv.ParseInt(string(b), 10, 64)
if err != nil {
return nil, err
}
return &embedder{
cli: cli,
addr: addr,
dim: dim,
dim: dims,
}, nil
}

View File

@ -31,7 +31,7 @@ func TestHTTPEmbedding(t *testing.T) {
}
ctx := context.Background()
emb, err := NewEmbedding("http://127.0.0.1:6543")
emb, err := NewEmbedding("http://127.0.0.1:6543", 1024)
assert.NoError(t, err)
texts := []string{
"hello",

View File

@ -0,0 +1,33 @@
/*
* Copyright 2024 CloudWeGo 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 wrap
import (
"context"
"github.com/cloudwego/eino-ext/components/embedding/ollama"
contract "github.com/coze-dev/coze-studio/backend/infra/contract/embedding"
)
func NewOllamaEmbedder(ctx context.Context, config *ollama.EmbeddingConfig, dimensions int64) (contract.Embedder, error) {
emb, err := ollama.NewEmbedder(ctx, config)
if err != nil {
return nil, err
}
return &denseOnlyWrap{dims: dimensions, Embedder: emb}, nil
}

View File

@ -24,9 +24,14 @@ import (
"github.com/coze-dev/coze-studio/backend/infra/contract/modelmgr"
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
"github.com/coze-dev/coze-studio/backend/pkg/lang/sets"
"github.com/coze-dev/coze-studio/backend/pkg/logs"
)
func NewModelMgr(staticModels []*modelmgr.Model) (modelmgr.Manager, error) {
if len(staticModels) == 0 {
logs.Warnf("[NewModelMgr] no static models found, please check if the config has been loaded correctly")
}
mapping := make(map[int64]*modelmgr.Model, len(staticModels))
for i := range staticModels {
mapping[staticModels[i].ID] = staticModels[i]

View File

@ -64,6 +64,8 @@ func (m *mysqlService) CreateTable(ctx context.Context, req *rdb.CreateTableRequ
if col.DefaultValue != nil {
if col.DataType == entity2.TypeTimestamp {
colDef += fmt.Sprintf(" DEFAULT %s", *col.DefaultValue)
} else if col.DataType == entity2.TypeText {
// do nothing
} else {
colDef += fmt.Sprintf(" DEFAULT '%s'", *col.DefaultValue)
}

View File

@ -23,9 +23,7 @@ import (
"io"
"log"
"math/rand"
"net"
"net/url"
"os"
"time"
"github.com/minio/minio-go/v7"
@ -33,6 +31,7 @@ import (
"github.com/coze-dev/coze-studio/backend/infra/contract/imagex"
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/proxy"
"github.com/coze-dev/coze-studio/backend/pkg/ctxcache"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/types/consts"
@ -211,27 +210,9 @@ func (m *minioClient) GetObjectUrl(ctx context.Context, objectKey string, opts .
}
// logs.CtxDebugf(ctx, "[GetObjectUrl] origin presignedURL.String = %s", presignedURL.String())
proxyPort := os.Getenv(consts.MinIOProxyEndpoint) // :8889
if len(proxyPort) > 0 {
currentHost, ok := ctxcache.Get[string](ctx, consts.HostKeyInCtx)
if !ok {
return presignedURL.String(), nil
}
currentScheme, ok := ctxcache.Get[string](ctx, consts.RequestSchemeKeyInCtx)
if !ok {
return presignedURL.String(), nil
}
host, _, err := net.SplitHostPort(currentHost)
if err != nil {
host = currentHost
}
minioProxyHost := host + proxyPort
presignedURL.Host = minioProxyHost
presignedURL.Scheme = currentScheme
// logs.CtxDebugf(ctx, "[GetObjectUrl] reset presignedURL.String = %s", presignedURL.String())
ok, proxyURL := proxy.CheckIfNeedReplaceHost(ctx, presignedURL.String())
if ok {
return proxyURL, nil
}
return presignedURL.String(), nil
@ -265,7 +246,6 @@ func (m *minioClient) GetUploadAuth(ctx context.Context, opt ...imagex.UploadAut
}
func (m *minioClient) GetResourceURL(ctx context.Context, uri string, opts ...imagex.GetResourceOpt) (*imagex.ResourceURL, error) {
url, err := m.GetObjectUrl(ctx, uri)
if err != nil {
return nil, err
@ -273,11 +253,12 @@ func (m *minioClient) GetResourceURL(ctx context.Context, uri string, opts ...im
return &imagex.ResourceURL{
URL: url,
}, nil
}
func (m *minioClient) Upload(ctx context.Context, data []byte, opts ...imagex.UploadAuthOpt) (*imagex.UploadResult, error) {
return nil, nil
}
func (m *minioClient) GetUploadAuthWithExpire(ctx context.Context, expire time.Duration, opt ...imagex.UploadAuthOpt) (*imagex.SecurityToken, error) {
return nil, nil
}

View File

@ -0,0 +1,63 @@
/*
* 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 proxy
import (
"context"
"net"
"net/url"
"os"
"github.com/coze-dev/coze-studio/backend/pkg/ctxcache"
"github.com/coze-dev/coze-studio/backend/pkg/logs"
"github.com/coze-dev/coze-studio/backend/types/consts"
)
func CheckIfNeedReplaceHost(ctx context.Context, originURLStr string) (ok bool, proxyURL string) {
// url parse
originURL, err := url.Parse(originURLStr)
if err != nil {
logs.CtxWarnf(ctx, "[CheckIfNeedReplaceHost] url parse failed, err: %v", err)
return false, ""
}
proxyPort := os.Getenv(consts.MinIOProxyEndpoint) // :8889
if proxyPort == "" {
return false, ""
}
currentHost, ok := ctxcache.Get[string](ctx, consts.HostKeyInCtx)
if !ok {
return false, ""
}
currentScheme, ok := ctxcache.Get[string](ctx, consts.RequestSchemeKeyInCtx)
if !ok {
return false, ""
}
host, _, err := net.SplitHostPort(currentHost)
if err != nil {
host = currentHost
}
minioProxyHost := host + proxyPort
originURL.Host = minioProxyHost
originURL.Scheme = currentScheme
logs.CtxDebugf(ctx, "[CheckIfNeedReplaceHost] reset originURL.String = %s", originURL.String())
return true, originURL.String()
}

View File

@ -0,0 +1,271 @@
/*
* 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 s3
import (
"bytes"
"context"
"fmt"
"io"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/coze-dev/coze-studio/backend/infra/contract/imagex"
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/proxy"
"github.com/coze-dev/coze-studio/backend/pkg/ctxcache"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/pkg/logs"
"github.com/coze-dev/coze-studio/backend/types/consts"
"github.com/coze-dev/coze-studio/backend/types/errno"
)
type s3Client struct {
client *s3.Client
bucketName string
}
func NewStorageImagex(ctx context.Context, ak, sk, bucketName, endpoint, region string) (imagex.ImageX, error) {
t, err := getS3Client(ctx, ak, sk, bucketName, endpoint, region)
if err != nil {
return nil, err
}
return t, nil
}
func getS3Client(ctx context.Context, ak, sk, bucketName, endpoint, region string) (*s3Client, error) {
creds := credentials.NewStaticCredentialsProvider(ak, sk, "")
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
PartitionID: "aws",
URL: endpoint,
SigningRegion: region,
HostnameImmutable: true,
Source: aws.EndpointSourceCustom,
}, nil
})
cfg, err := config.LoadDefaultConfig(
context.TODO(),
config.WithCredentialsProvider(creds),
config.WithEndpointResolverWithOptions(customResolver),
config.WithRegion("auto"),
)
if err != nil {
return nil, fmt.Errorf("init config failed, bucketName: %s, endpoint: %s, region: %s, err: %v", bucketName, endpoint, region, err)
}
c := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.UsePathStyle = false // virtual-host mode
o.RequestChecksumCalculation = aws.RequestChecksumCalculationWhenRequired
})
t := &s3Client{
client: c,
bucketName: bucketName,
}
err = t.CheckAndCreateBucket(ctx)
if err != nil {
return nil, err
}
return t, nil
}
func New(ctx context.Context, ak, sk, bucketName, endpoint, region string) (storage.Storage, error) {
t, err := getS3Client(ctx, ak, sk, bucketName, endpoint, region)
if err != nil {
return nil, err
}
return t, nil
}
func (t *s3Client) test() {
// test upload
objectKey := fmt.Sprintf("test-%s.txt", time.Now().Format("20060102150405"))
err := t.PutObject(context.Background(), objectKey, []byte("hello world"))
if err != nil {
logs.CtxErrorf(context.Background(), "PutObject failed, objectKey: %s, err: %v", objectKey, err)
}
// test download
content, err := t.GetObject(context.Background(), objectKey)
if err != nil {
logs.CtxErrorf(context.Background(), "GetObject failed, objectKey: %s, err: %v", objectKey, err)
}
logs.CtxInfof(context.Background(), "GetObject content: %s", string(content))
// test get presigned url
url, err := t.GetObjectUrl(context.Background(), objectKey)
if err != nil {
logs.CtxErrorf(context.Background(), "GetObjectUrl failed, objectKey: %s, err: %v", objectKey, err)
}
logs.CtxInfof(context.Background(), "GetObjectUrl url: %s", url)
// test delete
err = t.DeleteObject(context.Background(), objectKey)
if err != nil {
logs.CtxErrorf(context.Background(), "DeleteObject failed, objectKey: %s, err: %v", objectKey, err)
}
}
func (t *s3Client) CheckAndCreateBucket(ctx context.Context) error {
client := t.client
bucket := t.bucketName
_, err := client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: aws.String(bucket)})
if err == nil {
return nil // already exist
}
if err != nil {
// bucket not exist
if awsErr, ok := err.(interface{ ErrorCode() string }); ok && awsErr.ErrorCode() == "404" {
input := &s3.CreateBucketInput{
Bucket: aws.String(bucket),
}
// create bucket
_, err := client.CreateBucket(ctx, input)
return err
}
// other case
return err
}
return nil
}
func (t *s3Client) PutObject(ctx context.Context, objectKey string, content []byte, opts ...storage.PutOptFn) error {
client := t.client
body := bytes.NewReader(content)
bucket := t.bucketName
// upload object
_, err := client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectKey),
Body: body,
})
return err
}
func (t *s3Client) GetObject(ctx context.Context, objectKey string) ([]byte, error) {
client := t.client
bucket := t.bucketName
result, err := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectKey),
})
if err != nil {
return nil, fmt.Errorf("get object failed : %v", err)
}
defer result.Body.Close()
body, err := io.ReadAll(result.Body)
if err != nil {
return nil, err
}
return body, nil
}
func (t *s3Client) DeleteObject(ctx context.Context, objectKey string) error {
client := t.client
bucket := t.bucketName
_, err := client.DeleteObject(ctx, &s3.DeleteObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectKey),
})
return err
}
func (t *s3Client) GetObjectUrl(ctx context.Context, objectKey string, opts ...storage.GetOptFn) (string, error) {
client := t.client
bucket := t.bucketName
presignClient := s3.NewPresignClient(client)
req, err := presignClient.PresignGetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectKey),
}, func(options *s3.PresignOptions) {
options.Expires = time.Duration(60*60*24) * time.Second
})
if err != nil {
return "", fmt.Errorf("get object presigned url failed: %v", err)
}
ok, proxyURL := proxy.CheckIfNeedReplaceHost(ctx, req.URL)
if ok {
return proxyURL, nil
}
return req.URL, nil
}
func (i *s3Client) GetUploadHost(ctx context.Context) string {
currentHost, ok := ctxcache.Get[string](ctx, consts.HostKeyInCtx)
if !ok {
return ""
}
return currentHost + consts.ApplyUploadActionURI
}
func (t *s3Client) GetServerID() string {
return ""
}
func (t *s3Client) GetUploadAuth(ctx context.Context, opt ...imagex.UploadAuthOpt) (*imagex.SecurityToken, error) {
scheme, ok := ctxcache.Get[string](ctx, consts.RequestSchemeKeyInCtx)
if !ok {
return nil, errorx.New(errno.ErrUploadHostSchemaNotExistCode)
}
return &imagex.SecurityToken{
AccessKeyID: "",
SecretAccessKey: "",
SessionToken: "",
ExpiredTime: time.Now().Add(time.Hour).Format("2006-01-02 15:04:05"),
CurrentTime: time.Now().Format("2006-01-02 15:04:05"),
HostScheme: scheme,
}, nil
}
func (t *s3Client) GetResourceURL(ctx context.Context, uri string, opts ...imagex.GetResourceOpt) (*imagex.ResourceURL, error) {
url, err := t.GetObjectUrl(ctx, uri)
if err != nil {
return nil, err
}
return &imagex.ResourceURL{
URL: url,
}, nil
}
func (t *s3Client) Upload(ctx context.Context, data []byte, opts ...imagex.UploadAuthOpt) (*imagex.UploadResult, error) {
return nil, nil
}
func (t *s3Client) GetUploadAuthWithExpire(ctx context.Context, expire time.Duration, opt ...imagex.UploadAuthOpt) (*imagex.SecurityToken, error) {
return nil, nil
}

View File

@ -24,6 +24,7 @@ import (
"github.com/coze-dev/coze-studio/backend/infra/contract/imagex"
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/minio"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/s3"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/tos"
"github.com/coze-dev/coze-studio/backend/types/consts"
)
@ -51,6 +52,15 @@ func New(ctx context.Context) (Storage, error) {
os.Getenv(consts.TOSEndpoint),
os.Getenv(consts.TOSRegion),
)
case "s3":
return s3.New(
ctx,
os.Getenv(consts.S3AccessKey),
os.Getenv(consts.S3SecretKey),
os.Getenv(consts.StorageBucket),
os.Getenv(consts.S3Endpoint),
os.Getenv(consts.S3Region),
)
}
return nil, fmt.Errorf("unknown storage type: %s", storageType)
@ -77,6 +87,15 @@ func NewImagex(ctx context.Context) (imagex.ImageX, error) {
os.Getenv(consts.TOSEndpoint),
os.Getenv(consts.TOSRegion),
)
case "s3":
return s3.NewStorageImagex(
ctx,
os.Getenv(consts.S3AccessKey),
os.Getenv(consts.S3SecretKey),
os.Getenv(consts.StorageBucket),
os.Getenv(consts.S3Endpoint),
os.Getenv(consts.S3Region),
)
}
return nil, fmt.Errorf("unknown storage type: %s", storageType)
}

View File

@ -21,10 +21,7 @@ import (
"context"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"time"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
@ -32,6 +29,7 @@ import (
"github.com/coze-dev/coze-studio/backend/infra/contract/imagex"
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/proxy"
"github.com/coze-dev/coze-studio/backend/pkg/ctxcache"
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
"github.com/coze-dev/coze-studio/backend/pkg/lang/conv"
@ -213,34 +211,9 @@ func (t *tosClient) GetObjectUrl(ctx context.Context, objectKey string, opts ...
return "", err
}
// url parse
url, err := url.Parse(output.SignedUrl)
if err != nil {
logs.CtxWarnf(ctx, "[GetObjectUrl] url parse failed, err: %v", err)
return output.SignedUrl, nil
}
proxyPort := os.Getenv(consts.MinIOProxyEndpoint) // :8889
if len(proxyPort) > 0 {
currentHost, ok := ctxcache.Get[string](ctx, consts.HostKeyInCtx)
if !ok {
return output.SignedUrl, nil
}
currentScheme, ok := ctxcache.Get[string](ctx, consts.RequestSchemeKeyInCtx)
if !ok {
return output.SignedUrl, nil
}
host, _, err := net.SplitHostPort(currentHost)
if err != nil {
host = currentHost
}
minioProxyHost := host + proxyPort
url.Host = minioProxyHost
url.Scheme = currentScheme
// logs.CtxDebugf(ctx, "[GetObjectUrl] reset \n ORG.URL = %s \n TOS.URL = %s", output.SignedUrl, url.String())
return url.String(), nil
ok, proxyURL := proxy.CheckIfNeedReplaceHost(ctx, output.SignedUrl)
if ok {
return proxyURL, nil
}
return output.SignedUrl, nil

View File

@ -74,9 +74,10 @@ func startHttpServer() {
server.WithMaxRequestBodySize(int(maxSize)),
}
useSSL := getEnv("USE_SSL", "0")
useSSL := getEnv(consts.UseSSL, "0")
if useSSL == "1" {
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
cert, err := tls.LoadX509KeyPair(getEnv(consts.SSLCertFile, ""),
getEnv(consts.SSLKeyFile, ""))
if err != nil {
fmt.Println(err.Error())
}
@ -168,6 +169,10 @@ func asyncStartMinioProxyServer(ctx context.Context) {
proxyURL = getEnv(consts.TOSBucketEndpoint, "https://opencoze.tos-cn-beijing.volces.com")
}
if storageType == "s3" {
proxyURL = getEnv(consts.S3BucketEndpoint, "")
}
minioProxyEndpoint := getEnv(consts.MinIOProxyEndpoint, "")
if len(minioProxyEndpoint) == 0 {
return
@ -189,10 +194,12 @@ func asyncStartMinioProxyServer(ctx context.Context) {
originDirector(req)
req.Host = req.URL.Host
}
useSSL := getEnv("USE_SSL", "0")
useSSL := getEnv(consts.UseSSL, "0")
if useSSL == "1" {
logs.Infof("Minio proxy server is listening on %s with SSL", minioProxyEndpoint)
err := http.ListenAndServeTLS(minioProxyEndpoint, "cert.pem", "key.pem", proxy)
err := http.ListenAndServeTLS(minioProxyEndpoint,
getEnv(consts.SSLCertFile, ""),
getEnv(consts.SSLKeyFile, ""), proxy)
if err != nil {
log.Fatal(err)
}

View File

@ -1,5 +1,9 @@
#!/bin/sh
# Set up Elasticsearch
echo "Setting up Elasticsearch..."
/app/setup_es.sh --index-dir /app/es_index_schemas
# Start the proxy application in the background
echo "Starting proxy application..."
/app/proxy >/tmp/proxy.log 2>&1 &

View File

@ -44,6 +44,11 @@ const (
TOSRegion = "TOS_REGION"
TOSEndpoint = "TOS_ENDPOINT"
TOSBucketEndpoint = "TOS_BUCKET_ENDPOINT"
S3AccessKey = "S3_ACCESS_KEY"
S3SecretKey = "S3_SECRET_KEY"
S3Region = "S3_REGION"
S3Endpoint = "S3_ENDPOINT"
S3BucketEndpoint = "S3_BUCKET_ENDPOINT"
HostKeyInCtx = "HOST_KEY_IN_CTX"
RequestSchemeKeyInCtx = "REQUEST_SCHEME_IN_CTX"
@ -76,6 +81,10 @@ const (
CodeRunnerNodeModulesDir = "CODE_RUNNER_NODE_MODULES_DIR"
CodeRunnerTimeoutSeconds = "CODE_RUNNER_TIMEOUT_SECONDS"
CodeRunnerMemoryLimitMB = "CODE_RUNNER_MEMORY_LIMIT_MB"
UseSSL = "USE_SSL"
SSLCertFile = "SSL_CERT_FILE"
SSLKeyFile = "SSL_KEY_FILE"
)
const (
@ -107,3 +116,8 @@ const (
ApplyUploadActionURI = "/api/common/upload/apply_upload_action"
UploadURI = "/api/common/upload"
)
const (
DisableUserRegistration = "DISABLE_USER_REGISTRATION"
AllowRegistrationEmail = "ALLOW_REGISTRATION_EMAIL"
)

View File

@ -38,6 +38,8 @@ const (
ErrPluginToolsCheckFailed = 109000011
ErrPluginParseToolRespFailed = 109000012
ErrPluginOAuthFailed = 109000013
ErrPluginIDExist = 109000014
ErrToolIDExist = 109000015
)
const (
@ -45,6 +47,17 @@ const (
)
func init() {
code.Register(
ErrPluginIDExist,
"Plugin ID already exists : {plugin_id}",
code.WithAffectStability(false),
)
code.Register(
ErrToolIDExist,
"Tool ID already exists : {tool_id}",
code.WithAffectStability(false),
)
code.Register(
ErrPluginPermissionCode,
fmt.Sprintf("unauthorized access : {%s}", PluginMsgKey),

View File

@ -31,9 +31,17 @@ const (
ErrUserResourceNotFound = 700000005
ErrUserInvalidParamCode = 700000006
ErrUserPermissionCode = 700000007
ErrNotAllowedRegisterCode = 700000008
)
func init() {
code.Register(
ErrNotAllowedRegisterCode,
"The user registration has been disabled by the administrator. Please contact the administrator!",
code.WithAffectStability(false),
)
code.Register(
ErrUserPermissionCode,
"unauthorized access : {msg}",

View File

@ -15,7 +15,7 @@
"ignoreMissingScript": true,
"enableParallelism": true,
"incremental": true,
"shellCommand": "eslint ./ --cache",
"shellCommand": "eslint ./ --cache --quiet",
"allowWarningsInSuccessfulBuild": true,
"summary": "⭐️️ Run lint command for each package",
"safeForSimultaneousRushProcesses": true

View File

@ -19030,8 +19030,8 @@ importers:
specifier: workspace:*
version: link:../../../arch/i18n
'@coze/chat-sdk':
specifier: 0.1.11-beta.17
version: 0.1.11-beta.17(@types/react@18.2.37)(axios@1.10.0)(debug@4.3.3)(lodash-es@4.17.21)(react-dom@18.2.0)(react@18.2.0)
specifier: 0.1.11-beta.19
version: 0.1.11-beta.19(@types/react@18.2.37)(axios@1.10.0)(debug@4.3.3)(lodash-es@4.17.21)(react-dom@18.2.0)(react@18.2.0)
react:
specifier: 18.2.0
version: 18.2.0
@ -26106,8 +26106,8 @@ packages:
- utf-8-validate
dev: false
/@coze/chat-sdk@0.1.11-beta.17(@types/react@18.2.37)(axios@1.10.0)(debug@4.3.3)(lodash-es@4.17.21)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-nrev9w8IeW9mPqVhl4nT/8Z6fnaja4RlNqXj5e+MPjJugPTOw1brXuHTN2sVKUuFEsc5qse0U531qKJDg34zkA==}
/@coze/chat-sdk@0.1.11-beta.19(@types/react@18.2.37)(axios@1.10.0)(debug@4.3.3)(lodash-es@4.17.21)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-DRZ1yuWhYiiOZfbAiD9ifCVA7TiC8Wia4SfkJs5O8kCgbujF2nJrekEWUD6nzt9ivY8oT6Ve/eXfq/jK4CSq6g==}
requiresBuild: true
peerDependencies:
axios: ^1.7.1
@ -26133,6 +26133,7 @@ packages:
micromark-extension-misc-radio-list-item: 2.1.0
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
xss: 1.0.15
zustand: 4.5.7(@types/react@18.2.37)(immer@10.1.1)(react@18.2.0)
transitivePeerDependencies:
- '@types/react'
@ -35368,7 +35369,7 @@ packages:
resolution: {integrity: sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==}
dependencies:
'@types/node': 18.18.9
'@types/unist': 2.0.11
'@types/unist': 3.0.3
'@types/vfile-message': 2.0.0
dev: true
@ -38170,7 +38171,7 @@ packages:
path-case: 3.0.4
sentence-case: 3.0.4
snake-case: 3.0.4
tslib: 2.6.3
tslib: 2.8.1
/character-entities-html4@1.1.4:
resolution: {integrity: sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==}
@ -49817,7 +49818,7 @@ packages:
dependencies:
'@types/react': 18.2.37
react: 18.2.0
tslib: 2.6.3
tslib: 2.8.1
dev: false
/react-virtualized-auto-sizer@1.0.26(react-dom@18.2.0)(react@18.2.0):
@ -53487,6 +53488,7 @@ packages:
/tslib@2.6.3:
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
dev: false
/tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@ -55619,7 +55621,7 @@ packages:
'@types/ws': 8.18.1
ansi-html-community: 0.0.8
bonjour-service: 1.3.0
chokidar: 3.5.3
chokidar: 3.6.0
colorette: 2.0.19
compression: 1.8.0
connect-history-api-fallback: 2.0.0

View File

@ -4,6 +4,9 @@ export LOG_LEVEL="debug"
export MAX_REQUEST_BODY_SIZE=1073741824
export SERVER_HOST="localhost${LISTEN_ADDR}"
export MINIO_PROXY_ENDPOINT=":8889"
export USE_SSL="0"
export SSL_CERT_FILE=""
export SSL_KEY_FILE=""
# MySQL
export MYSQL_ROOT_PASSWORD=root
@ -20,6 +23,7 @@ export REDIS_AOF_ENABLED=no
export REDIS_IO_THREADS=4
export ALLOW_EMPTY_PASSWORD=yes
export REDIS_ADDR="localhost:6379"
export REDIS_PASSWORD=""
# This Upload component used in Agent / workflow File/Image With LLM , support the component of imagex / storage
# default: storage, use the settings of storage component
@ -35,7 +39,7 @@ export VE_IMAGEX_TEMPLATE=""
export VE_IMAGEX_UPLOAD_HOST="https://imagex.volcengineapi.com"
# Storage component
export STORAGE_TYPE="minio" # minio / tos
export STORAGE_TYPE="minio" # minio / tos / s3
export STORAGE_BUCKET="opencoze"
# MiniIO
export MINIO_ROOT_USER=minioadmin
@ -53,6 +57,13 @@ export TOS_ENDPOINT=https://tos-cn-beijing.volces.com
export TOS_BUCKET_ENDPOINT=https://opencoze.tos-cn-beijing.volces.com
export TOS_REGION=cn-beijing
# S3
export S3_ACCESS_KEY=
export S3_SECRET_KEY=
export S3_ENDPOINT=
export S3_BUCKET_ENDPOINT=
export S3_REGION=
# Elasticsearch
export ES_ADDR="http://localhost:9200"
export ES_VERSION="v8"
@ -83,8 +94,8 @@ export VIKING_DB_MODEL_NAME="" # if vikingdb model name is not set, you need to
# Settings for Embedding
# The Embedding model relied on by knowledge base vectorization does not need to be configured
# if the vector database comes with built-in Embedding functionality (such as VikingDB). Currently,
# Coze Studio supports three access methods: openai, ark, and custom http. Users can simply choose one of them when using
# embedding type: openai / ark / http
# Coze Studio supports three access methods: openai, ark, ollama, and custom http. Users can simply choose one of them when using
# embedding type: openai / ark / ollama / http
export EMBEDDING_TYPE="ark"
# openai embedding
export OPENAI_EMBEDDING_BASE_URL="" # (string) OpenAI base_url
@ -101,9 +112,14 @@ export ARK_EMBEDDING_AK=""
export ARK_EMBEDDING_DIMS="2048"
export ARK_EMBEDDING_BASE_URL=""
# ollama embedding
export OLLAMA_EMBEDDING_BASE_URL=""
export OLLAMA_EMBEDDING_MODEL=""
export OLLAMA_EMBEDDING_DIMS=""
# http embedding
export HTTP_EMBEDDING_ADDR="http://127.0.0.1:6543"
export HTTP_EMBEDDING_DIMS=1024
# Settings for OCR
# If you want to use the OCR-related functions in the knowledge base featureYou need to set up the OCR configuration.
@ -190,4 +206,10 @@ export CODE_RUNNER_NODE_MODULES_DIR=""
# Code execution timeout, default 60 seconds. e.g. "2.56"
export CODE_RUNNER_TIMEOUT_SECONDS=""
# Code execution memory limit, default 100MB. e.g. "256"
export CODE_RUNNER_MEMORY_LIMIT_MB=""
export CODE_RUNNER_MEMORY_LIMIT_MB=""
# The function of registration controller
# If you want to disable the registration feature, set DISABLE_USER_REGISTRATION to true. You can then control allowed registrations via a whitelist with ALLOW_REGISTRATION_EMAIL.
export DISABLE_USER_REGISTRATION="" # default "", if you want to disable, set to true
export ALLOW_REGISTRATION_EMAIL="" # is a list of email addresses, separated by ",". Example: "11@example.com,22@example.com"

View File

@ -65,8 +65,6 @@ services:
depends_on:
minio-setup:
condition: service_completed_successfully
elasticsearch-setup:
condition: service_completed_successfully
mysql-setup-schema:
condition: service_completed_successfully
mysql-setup-init-sql:
@ -232,7 +230,7 @@ services:
cp /opt/bitnami/elasticsearch/analysis-smartcn.zip /tmp/analysis-smartcn.zip
elasticsearch-plugin install file:///tmp/analysis-smartcn.zip
if [[ "$?" != "0" ]]; then
if [[ "$$?" != "0" ]]; then
echo 'Plugin installation failed, exiting operation';
rm -rf /opt/bitnami/elasticsearch/plugins/analysis-smartcn
exit 1;
@ -409,27 +407,6 @@ services:
networks:
- coze-network
elasticsearch-setup:
image: alpine/curl:8.12.1
container_name: coze-elasticsearch-setup
profiles: ['middleware', 'volcano-setup']
env_file: *env_file
depends_on:
elasticsearch:
condition: service_healthy
volumes:
- ./volumes/elasticsearch/setup_es.sh:/setup_es.sh
- ./volumes/elasticsearch/es_index_schema:/es_index_schema
command:
- /bin/sh
- -c
- |
set -ex
/setup_es.sh
echo 'Elasticsearch setup complete.'
networks:
- coze-network
restart: 'no'
minio-setup:
image: minio/mc:RELEASE.2025-05-21T01-59-54Z-cpuv1
container_name: coze-minio-setup
@ -504,7 +481,7 @@ services:
- -c
- |
set -ex
for i in $(seq 1 60); do
for i in $$(seq 1 60); do
DB_HOST="$${MYSQL_HOST}"
if [ "$${MYSQL_HOST}" = "localhost" ] || [ "$${MYSQL_HOST}" = "127.0.0.1" ]; then
DB_HOST="mysql"
@ -562,8 +539,6 @@ services:
condition: service_healthy
minio-setup:
condition: service_completed_successfully
elasticsearch-setup:
condition: service_completed_successfully
mysql-setup-init-sql:
condition: service_completed_successfully
command: ['/app/bootstrap.sh']

View File

@ -1,14 +1,61 @@
#!/bin/sh
set -e
if [[ "$ES_ADDR" == *"localhost"* || "$ES_ADDR" == *"127.0.0.1"* ]]; then
echo "ES_ADDR is localhost, using docker address: http://elasticsearch:9200"
ES_ADDR="http://elasticsearch:9200"
# Parse command-line arguments
while [ $# -gt 0 ]; do
case "$1" in
--es-address)
case "$2" in
"" | -*) echo "Error: Missing value for $1" >&2; exit 1;;
esac
ES_ADDR_ARG="$2"
shift 2
;;
--index-dir)
case "$2" in
"" | -*) echo "Error: Missing value for $1" >&2; exit 1;;
esac
INDEX_DIR_ARG="$2"
shift 2
;;
--docker-host)
case "$2" in
"true" | "false") REPLACE_ES_ADDR_WITH_DOCKER_HOST_ARG="$2" ;;
*) echo "Error: Invalid value for $1. Must be 'true' or 'false'" >&2; exit 1;;
esac
shift 2
;;
*)
# unknown option
shift
;;
esac
done
# If ES_ADDR_ARG argument is provided, use it. Otherwise, use environment variable or default logic.
if [ -n "$ES_ADDR_ARG" ]; then
ES_ADDR=$ES_ADDR_ARG
fi
REPLACE_ES_ADDR=${REPLACE_ES_ADDR_WITH_DOCKER_HOST_ARG:-true}
if [ "$REPLACE_ES_ADDR" = "true" ]; then
case "$ES_ADDR" in
*localhost*|*"127.0.0.1"*)
echo "ES_ADDR is localhost, using docker address: http://elasticsearch:9200"
ES_ADDR="http://elasticsearch:9200"
;;
esac
fi
# If INDEX_DIR_ARG argument is provided, use it. Otherwise, use the default.
if [ -n "$INDEX_DIR_ARG" ]; then
INDEX_DIR=$INDEX_DIR_ARG
else
INDEX_DIR=/es_index_schema
fi
# ES_ADDR=http://localhost:31160
INDEX_DIR=/es_index_schema
echo "ES_ADDR: $ES_ADDR"
echo "INDEX_DIR: $INDEX_DIR"
AUTH_PARAM=""
if [ -n "$ES_USERNAME" ]; then
@ -38,30 +85,32 @@ if [ -z "$ES_TEMPLATES" ]; then
exit 1
else
# Add index creation logic
echo -e "🔄 Creating Elasticsearch indexes..."
for template_file in $ES_TEMPLATES; do
template_name=$(basename "$template_file" | sed 's/\.index-template\.json$//')
echo -e "➡️ Registering template: $template_name"
# Attempt to register index template
response=$(curl -s $AUTH_PARAM -X PUT "${ES_ADDR}/_index_template/$template_name" \
-H "Content-Type: application/json" \
-d @"$template_file" 2>&1)
# Check if successful
if echo "$response" | grep -q '"acknowledged":true'; then
echo -e "✅ Template $template_name registered successfully"
# Check if index template exists
if curl -s -f $AUTH_PARAM -I "${ES_ADDR}/_index_template/$template_name" >/dev/null; then
echo -e " Index template $template_name already exists"
else
echo -e "❌ Failed to register template $template_name. Response: $response"
exit 1
echo -e "➡️ Registering template: $template_name"
# Attempt to register index template
response=$(curl -s $AUTH_PARAM -X PUT "${ES_ADDR}/_index_template/$template_name" \
-H "Content-Type: application/json" \
-d @"$template_file" 2>&1)
# Check if successful
if echo "$response" | grep -q '"acknowledged":true'; then
echo -e "✅ Template $template_name registered successfully"
else
echo -e "❌ Failed to register template $template_name. Response: $response"
exit 1
fi
fi
index_name=$(basename "$template_file" | sed 's/\.index-template\.json$//')
echo -e "➡️ Creating index: $index_name"
# Check if index exists
if ! curl -s -f $AUTH_PARAM "${ES_ADDR}/_cat/indices/$index_name" >/dev/null; then
echo -e "➡️ Creating index: $index_name"
# Create index (matching template's index_patterns)
curl $AUTH_PARAM -X PUT "${ES_ADDR}/$index_name" -H "Content-Type: application/json"
echo ""
@ -90,4 +139,4 @@ else
fi
echo "Elasticsearch setup completed."
exit 0
exit 0

Binary file not shown.

View File

@ -1 +1,122 @@
TODO: something here
# Coze Studio Frontend
This is the frontend project of Coze Studio, an AI Agent development platform built with monorepo architecture, based on React 18 and modern frontend technology stack.
## 🏗️ Project Architecture
### Core Technology Stack
- **Framework**: React 18 + TypeScript
- **Build Tool**: Rsbuild
- **Package Manager**: Rush + PNPM
- **Routing**: React Router v6
- **State Management**: Zustand
- **UI Components**: @coze-arch/coze-design
- **Internationalization**: @coze-arch/i18n
### Directory Structure
```
frontend/
├── apps/ # Application layer
│ └── coze-studio/ # Main application
├── packages/ # Core packages
│ ├── agent-ide/ # AI Agent development environment
│ ├── arch/ # Architecture infrastructure
│ ├── common/ # Common components and utilities
│ ├── components/ # UI component library
│ ├── data/ # Data layer
│ ├── devops/ # DevOps tools
│ ├── foundation/ # Foundation infrastructure
│ ├── project-ide/ # Project development environment
│ ├── studio/ # Studio core features
│ └── workflow/ # Workflow engine
├── config/ # Configuration files
│ ├── eslint-config/ # ESLint configuration
│ ├── rsbuild-config/ # Rsbuild build configuration
│ ├── ts-config/ # TypeScript configuration
│ ├── postcss-config/ # PostCSS configuration
│ ├── stylelint-config/ # Stylelint configuration
│ ├── tailwind-config/ # Tailwind CSS configuration
│ └── vitest-config/ # Vitest testing configuration
└── infra/ # Infrastructure tools
├── idl/ # Interface Definition Language tools
├── plugins/ # Build plugins
└── utils/ # Utility libraries
```
## 🚀 Quick Start
### Prerequisites
- Node.js >= 21
- PNPM 8.15.8
- Rush 5.147.1
### Install Dependencies
```bash
# Run in project root directory
rush install
# update
rush update
```
### Development Mode
```bash
# Start development server
cd apps/coze-studio
npm run dev
# or use rushx
rushx dev
```
### Production Build
```bash
# Build application
cd apps/coze-studio
npm run build
# or use rushx
rushx build
```
## 📦 Core Modules
### Agent IDE
- **agent-ide**: AI Agent integrated development environment
- **prompt**: Prompt editor
- **tool**: Tool configuration management
- **workflow**: Workflow integration
### Architecture Layer (arch)
- **bot-api**: API interface layer
- **bot-hooks**: React Hooks library
- **foundation-sdk**: Foundation SDK
- **i18n**: Internationalization support
- **bot-flags**: Feature flags management
- **web-context**: Web context utilities
### Workflow Engine (workflow)
- **fabric-canvas**: Canvas rendering engine
- **nodes**: Node component library
- **sdk**: Workflow SDK
- **playground**: Debug runtime environment
### Data Layer (data)
- **knowledge**: Knowledge base management
- **memory**: Memory system
- **common**: Common data processing
## 🔧 Development Standards
### Code Quality
- Code formatting with ESLint + Prettier
- TypeScript strict mode
- Unit test coverage requirements
- Team-based tier management (level-1 to level-4)
### Team Collaboration
- Rush-based monorepo management
- Workspace dependency management
- Unified build and release process
## 📄 License
Apache License 2.0

View File

@ -1,19 +1,3 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import OriginPkgRootWebpackPlugin from '@coze-arch/pkg-root-webpack-plugin-origin';
type PkgRootWebpackPluginOptions = Record<string, unknown>;
declare class PkgRootWebpackPlugin extends OriginPkgRootWebpackPlugin {

View File

@ -1,4 +1,19 @@
"use strict";
/*
* 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.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};

View File

@ -13,25 +13,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useState, type FC } from 'react';
import { groupBy } from 'lodash-es';
import { ToolGroupKey, ToolKey } from '@coze-agent-ide/tool-config';
import {
type useRegisteredToolKeyConfigList,
abilityKey2ModelFunctionConfigType,
} from '@coze-agent-ide/tool';
import { useBotSkillStore } from '@coze-studio/bot-detail-store/bot-skill';
import { I18n } from '@coze-arch/i18n';
import { IconCozCross } from '@coze-arch/coze-design/icons';
import {
Button,
Checkbox,
Modal,
IconButton,
Space,
} from '@coze-arch/coze-design';
import {
type Model,
ModelFuncConfigStatus,
ModelFuncConfigType,
} from '@coze-arch/bot-api/developer_api';
import { useBotSkillStore } from '@coze-studio/bot-detail-store/bot-skill';
import { ToolGroupKey, ToolKey } from '@coze-agent-ide/tool-config';
import {
type useRegisteredToolKeyConfigList,
abilityKey2ModelFunctionConfigType,
} from '@coze-agent-ide/tool';
import { mergeModelFuncConfigStatus } from '@coze-agent-ide/bot-editor-context-store';
import { IconCozCross } from '@coze-arch/coze-design/icons';
import { Button, Checkbox, Modal, IconButton, Space } from '@coze-arch/coze-design';
type IRegisteredToolKeyConfig = ReturnType<
typeof useRegisteredToolKeyConfigList
@ -196,6 +202,7 @@ export const checkModelAbility = (
: ModelFuncConfigType.KnowledgeOnDemandCall
];
modelFunctionConfigStatus = mergeModelFuncConfigStatus(
// @ts-expect-error fix me late
autoConfigStatus,
modelFunctionConfigStatus,
);
@ -263,6 +270,7 @@ export const confirm = ({
};
const getGroupTittleByConfigType = (type: ModelFuncConfigType): string =>
// @ts-expect-error fix me late
({
[ModelFuncConfigType.Plugin]: I18n.t('bot_edit_type_skills'),
[ModelFuncConfigType.Workflow]: I18n.t('bot_edit_type_skills'),
@ -291,6 +299,7 @@ const getGroupTittleByConfigType = (type: ModelFuncConfigType): string =>
})[type];
const getTitleByConfigType = (type: ModelFuncConfigType): string =>
// @ts-expect-error fix me late
({
[ModelFuncConfigType.Plugin]: I18n.t('Plugins'),
[ModelFuncConfigType.Workflow]: I18n.t('Workflows'),

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import path from 'path';
import {
@ -65,7 +65,22 @@ const updateDTS = ({
// 创建一个新的文件,用来保存生成的类型定义
const typeDefs = project.createSourceFile(
outputFileName,
`/* eslint-disable */
`/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable */
/* prettier-ignore */
// 基于${path.relative(baseDir, inputFileName)}自动生成,请勿手动修改`,
{

View File

@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable */
/* prettier-ignore */
// 基于src/index.ts自动生成请勿手动修改

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import dayjs from 'dayjs';
import { I18n } from '@coze-arch/i18n';
@ -56,8 +56,16 @@ describe('Date', () => {
expect(getCurrentTZ().utcOffset()).toBe(60 * 8);
});
it('#formatDate', () => {
const date = formatDate(1718782764);
expect(date).toBe('2024/06/19 15:39:24');
// 使用固定的时间戳,但验证格式而不是具体的时区值
const timestamp = 1718782764;
const date = formatDate(timestamp);
// 验证格式是否正确YYYY/MM/DD HH:mm:ss
expect(date).toMatch(/^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}$/);
// 验证时间戳转换的一致性格式化后再解析应该得到相同的dayjs对象的日期部分
const formattedDayjs = dayjs(date, 'YYYY/MM/DD HH:mm:ss');
const originalDayjs = dayjs.unix(timestamp);
expect(formattedDayjs.unix()).toBe(originalDayjs.unix());
});
it('#getRemainTime', () => {
vi.useFakeTimers();
@ -80,7 +88,7 @@ describe('Date', () => {
describe('format timestamp', () => {
beforeEach(() => {
const MOCK_NOW = dayjs('2024-09-24 20:00:00');
vi.setSystemTime(MOCK_NOW);
vi.setSystemTime(MOCK_NOW.toDate());
});
it('just now', () => {

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { devtools } from 'zustand/middleware';
import { create } from 'zustand';
import { merge } from 'lodash-es';
@ -49,7 +49,7 @@ const getDefaultTextLocalAddUpdateState: () => UploadTextLocalAddUpdateState =
parsing_type: ParsingType.AccurateParsing,
image_extraction: true,
table_extraction: true,
image_ocr: true,
image_ocr: false,
},
indexStrategy: {},
filterStrategy: [],

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { devtools } from 'zustand/middleware';
import { create } from 'zustand';
import { merge } from 'lodash-es';
@ -48,7 +48,7 @@ const getDefaultTextLocalResegmentState: () => UploadTextLocalResegmentState =
parsing_type: ParsingType.AccurateParsing,
image_extraction: true,
table_extraction: true,
image_ocr: true,
image_ocr: false,
},
indexStrategy: {},
filterStrategy: [],

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { devtools } from 'zustand/middleware';
import { create } from 'zustand';
import { merge } from 'lodash-es';
@ -36,7 +36,7 @@ const getDefaultTextResegmentState: () => UploadTextResegmentState = () => ({
parsingStrategy: {
parsing_type: ParsingType.AccurateParsing,
image_extraction: true,
image_ocr: true,
image_ocr: false,
table_extraction: true,
},
filterStrategy: [],

View File

@ -18,4 +18,12 @@ module.exports = defineConfig({
},
],
},
overrides: [
{
files: ['src/**/namespaces/*.ts'],
rules: {
'unicorn/filename-case': 'off',
},
},
],
});

View File

@ -1,3 +1,4 @@
// eslint-disable unicorn/filename-case
/*
* Copyright 2025 coze-dev Authors
*
@ -13,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable */
/* tslint:disable */
// @ts-nocheck

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import classNames from 'classnames';
import { type TableMemoryItem } from '@coze-studio/bot-detail-store';
import {
@ -22,7 +22,6 @@ import {
} from '@coze-data/database-v2-base/constants';
import { DatabaseFieldTitle } from '@coze-data/database-v2-base/components/database-field-title';
import { I18n } from '@coze-arch/i18n';
import { FieldItemType } from '@coze-arch/bot-api/memory';
import { IconCozEdit, IconCozTrashCan } from '@coze-arch/coze-design/icons';
import {
type ColumnProps,
@ -31,12 +30,14 @@ import {
Space,
Typography,
} from '@coze-arch/coze-design';
import { FieldItemType } from '@coze-arch/bot-api/memory';
import { type TableRow, type TableField, type TableFieldData } from './type';
export function formatTableStructList(
structList: TableMemoryItem[],
): TableFieldData[] {
// @ts-expect-error fix me late
return structList.map(item => ({
fieldName: item.name ?? '',
fieldDescription: item.desc ?? '',
@ -173,6 +174,7 @@ export const getTableColumns = ({
title: () => (
<DatabaseFieldTitle
field={item.name}
// @ts-expect-error fix me late
type={item.type}
tip={item.desc}
required

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect, useRef, useState } from 'react';
import dayjs from 'dayjs';
@ -25,7 +25,6 @@ import {
} from '@coze-data/database-v2-base/constants';
import { DatabaseFieldTitle } from '@coze-data/database-v2-base/components/database-field-title';
import { I18n } from '@coze-arch/i18n';
import { FieldItemType, TableType } from '@coze-arch/bot-api/memory';
import {
CozInputNumber,
type DatePickerProps,
@ -37,6 +36,7 @@ import {
withField,
type CommonFieldProps,
} from '@coze-arch/coze-design';
import { FieldItemType, TableType } from '@coze-arch/bot-api/memory';
import {
type TableRow,
@ -250,6 +250,7 @@ function getSystemFieldCommonProps(field: TableMemoryItem): FieldCommonProps {
<DatabaseFieldTitle
field={field.name}
textType="primary"
// @ts-expect-error fix me late
type={field.type}
tip={field.desc}
required

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useMemo } from 'react';
import {
@ -79,6 +79,7 @@ export const SpanInfoArea = (props: SpanInfoAreaProps) => {
const { rootSpan, spans } = useSpanTransform({
orgSpans: orgDetailSpans ?? [],
traceAdvanceInfo,
// @ts-expect-error fix me late
spanCategoryMeta: spanCategory,
});

View File

@ -5,7 +5,8 @@
"stories",
"./src/**/*.test.ts",
"vitest.config.ts",
"setup-vitest.ts"
"setup-vitest.ts",
"__mocks__/*.ts"
],
"exclude": ["./dist"],
"references": [

View File

@ -21,7 +21,7 @@
},
"dependencies": {
"@coze-arch/i18n": "workspace:*",
"@coze/chat-sdk": "0.1.11-beta.17",
"@coze/chat-sdk": "0.1.11-beta.19",
"react": "~18.2.0"
},
"devDependencies": {

View File

@ -13,5 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export function useInitOpenPremiumManage(_props: { open: () => void }) {}
export function useInitOpenPremiumManage(_props: { open: () => void }) {
// allow empty function
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { merge } from 'lodash-es';
import {
REPORT_EVENTS as ReportEventNames,
@ -87,6 +87,7 @@ export const getBotDetailDtoInfo = () => {
onboarding_info: botSkill.transformVo2Dto.onboarding(onboardingContent),
background_image_info_list: backgroundImageInfoList,
shortcut_sort: botSkill.transformVo2Dto.shortcut(shortcut),
// @ts-expect-error fix me late
voices_info: merge(
{},
botSkill.transformVo2Dto.tts(tts),

View File

@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { nanoid } from 'nanoid';
import { isNumber, mapValues } from 'lodash-es';
import { type ShortCutStruct } from '@coze-agent-ide/tool-config';
import {
type PluginStatus,
type PluginType,
@ -50,6 +49,7 @@ import {
DisablePromptCalling,
} from '@coze-arch/bot-api/playground_api';
import { SuggestReplyMode } from '@coze-arch/bot-api/developer_api';
import { type ShortCutStruct } from '@coze-agent-ide/tool-config';
import {
type WorkFlowItemType,
@ -369,6 +369,7 @@ export const transformVo2Dto = {
databaseList: (
databaseList: DatabaseList,
): BotInfoForUpdate['database_list'] =>
// @ts-expect-error fix me late
databaseList.map(d => ({
table_id: d.tableId,
table_name: d.name,

View File

@ -13,21 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type PropsWithChildren } from 'react';
import {
PictureUpload,
type RenderAutoGenerateParams,
} from '@coze-common/biz-components/picture-upload';
import {
type DraftProjectCopyRequest,
type DraftProjectUpdateRequest,
type DraftProjectCreateRequest,
} from '@coze-arch/idl/intelligence_api';
import { I18n } from '@coze-arch/i18n';
import { FileBizType, IconType } from '@coze-arch/bot-api/developer_api';
import {
PictureUpload,
type RenderAutoGenerateParams,
} from '@coze-common/biz-components/picture-upload';
import { botInputLengthService } from '@coze-agent-ide/bot-input-length-limit';
import { IconCozUpload } from '@coze-arch/coze-design/icons';
import {
type BaseFormProps,
@ -37,6 +35,8 @@ import {
useFormApi,
withField,
} from '@coze-arch/coze-design';
import { FileBizType, IconType } from '@coze-arch/bot-api/developer_api';
import { botInputLengthService } from '@coze-agent-ide/bot-input-length-limit';
import { SwitchWithDesc } from '../switch-with-desc';
import { type ModifyUploadValueType } from '../../type';
@ -66,6 +66,7 @@ export const ProjectForm: React.FC<PropsWithChildren<ProjectFormProps>> = ({
...formProps
}) => <Form<ProjectFormValues> {...formProps}>{children}</Form>;
// @ts-expect-error fix me late
export const filedKeyMap: Record<
keyof ProjectFormValues,
keyof ProjectFormValues

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { StandardNodeType } from '@coze-workflow/base';
// 默认所有节点可用,可以自定义
@ -56,7 +56,7 @@ export const getEnabledNodeTypes = (_params: {
[StandardNodeType.DatabaseDelete]: true,
[StandardNodeType.DatabaseCreate]: true,
// [StandardNodeType.JsonParser]: true,
// [StandardNodeType.JsonStringify]: true,
[StandardNodeType.JsonStringify]: true,
// [StandardNodeType.UpdateConversation]: true,
// [StandardNodeType.DeleteConversation]: true,
// [StandardNodeType.QueryConversationList]: true,

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { StandardNodeType, useWorkflowNode } from '@coze-workflow/base';
import { VariableContent } from '@/node-registries/variable';
@ -27,6 +27,7 @@ import { PluginContent } from '@/node-registries/plugin';
import { OutputContent } from '@/node-registries/output';
import { LtmContent } from '@/node-registries/ltm';
import { LoopContent } from '@/node-registries/loop';
import { JsonStringifyContent } from '@/node-registries/json-stringify';
import { IntentContent } from '@/node-registries/intent';
import { InputContent } from '@/node-registries/input';
import { ImageCanvasContent } from '@/node-registries/image-canvas';
@ -89,6 +90,7 @@ const ContentMap = {
[StandardNodeType.TriggerRead]: TriggerReadContent,
[StandardNodeType.Api]: PluginContent,
[StandardNodeType.Variable]: VariableContent,
[StandardNodeType.JsonStringify]: JsonStringifyContent,
// cli 脚本插入标识registry请勿修改/删除此行注释
};

View File

@ -1,3 +1,4 @@
/* eslint-disable unicorn/filename-case */
/*
* Copyright 2025 coze-dev Authors
*
@ -13,8 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable unicorn/filename-case */
import { type ViewVariableType } from '@coze-workflow/base';
import { useNodeAvailableVariablesWithNode } from '../../hooks/use-node-available-variables';

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useShallow } from 'zustand/react/shallow';
import { type WorkflowDatabase, ViewVariableType } from '@coze-workflow/base';
import { FieldItemType, type DatabaseInfo } from '@coze-arch/bot-api/memory';
@ -54,6 +54,7 @@ function transformRawDatabaseToDatabase(
fields: rawDatabase.field_list?.map(field => ({
id: field.alterId as number,
name: field.name,
// @ts-expect-error fix me late
type: fieldItemTypeToViewVariableType(field.type),
required: field.must_required,
description: field.desc,

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { CODE_NODE_REGISTRY } from './code';
export { COMMENT_NODE_REGISTRY } from './comment';
export { DATABASE_NODE_REGISTRY } from './database/database-base';
@ -47,4 +47,5 @@ export { IF_NODE_REGISTRY } from './if';
export { PLUGIN_NODE_REGISTRY } from './plugin';
export { SUB_WORKFLOW_NODE_REGISTRY } from './sub-workflow';
export { VARIABLE_NODE_REGISTRY } from './variable';
export { JSON_STRINGIFY_NODE_REGISTRY } from './json-stringify';
// cli 脚本插入标识registry请勿修改/删除此行注释

View File

@ -0,0 +1,84 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
FieldArray,
type FieldArrayRenderProps,
} from '@flowgram-adapter/free-layout-editor';
import type { ViewVariableType, InputValueVO } from '@coze-workflow/base';
import { I18n } from '@coze-arch/i18n';
import { useReadonly } from '@/nodes-v2/hooks/use-readonly';
import { ValueExpressionInputField } from '@/node-registries/common/fields';
import { FieldArrayItem, FieldRows, Section, type FieldProps } from '@/form';
interface InputsFieldProps extends FieldProps<InputValueVO[]> {
title?: string;
paramsTitle?: string;
expressionTitle?: string;
disabledTypes?: ViewVariableType[];
onAppend?: () => InputValueVO;
inputPlaceholder?: string;
literalDisabled?: boolean;
showEmptyText?: boolean;
nthCannotDeleted?: number;
}
export const InputsField = ({
name,
defaultValue,
title,
tooltip,
disabledTypes,
inputPlaceholder,
literalDisabled,
showEmptyText = true,
}: InputsFieldProps) => {
const readonly = useReadonly();
return (
<FieldArray<InputValueVO> name={name} defaultValue={defaultValue}>
{({ field }: FieldArrayRenderProps<InputValueVO>) => {
const { value = [] } = field;
const length = value?.length ?? 0;
const isEmpty = !length;
return (
<Section
title={title}
tooltip={tooltip}
isEmpty={showEmptyText && isEmpty}
emptyText={I18n.t('workflow_inputs_empty')}
>
<FieldRows>
{field.map((item, index) => (
<FieldArrayItem key={item.key} disableRemove hiddenRemove>
<div style={{ flex: 3 }}>
<ValueExpressionInputField
name={`${name}.${index}.input`}
disabledTypes={disabledTypes}
readonly={readonly}
inputPlaceholder={inputPlaceholder}
literalDisabled={literalDisabled}
/>
</div>
</FieldArrayItem>
))}
</FieldRows>
</Section>
);
}}
</FieldArray>
);
};

View File

@ -0,0 +1,32 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { nanoid } from 'nanoid';
import { ViewVariableType } from '@coze-workflow/variable';
// 入参路径,试运行等功能依赖该路径提取参数
export const INPUT_PATH = 'inputs.inputParameters';
// 定义固定出参
export const OUTPUTS = [
{
key: nanoid(),
name: 'output',
type: ViewVariableType.String,
},
];
export const DEFAULT_INPUTS = [{ name: 'input' }];

View File

@ -0,0 +1,36 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type NodeDataDTO } from '@coze-workflow/base';
import { type FormData } from './types';
import { OUTPUTS } from './constants';
/**
* 节点后端数据 -> 前端表单数据
*/
export const transformOnInit = (value: NodeDataDTO) => ({
...(value ?? {}),
outputs: value?.outputs ?? OUTPUTS,
});
/**
* 前端表单数据 -> 节点后端数据
* @param value
* @returns
*/
export const transformOnSubmit = (value: FormData): NodeDataDTO =>
value as unknown as NodeDataDTO;

View File

@ -0,0 +1,58 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
ValidateTrigger,
type FormMetaV2,
} from '@flowgram-adapter/free-layout-editor';
import { createValueExpressionInputValidate } from '@/node-registries/common/validators';
import {
fireNodeTitleChange,
provideNodeOutputVariablesEffect,
} from '@/node-registries/common/effects';
import { type FormData } from './types';
import { FormRender } from './form';
import { transformOnInit, transformOnSubmit } from './data-transformer';
export const JSON_STRINGIFY_FORM_META: FormMetaV2<FormData> = {
// 节点表单渲染
render: () => <FormRender />,
// 验证触发时机
validateTrigger: ValidateTrigger.onChange,
// 验证规则
validate: {
// 必填
'inputs.inputParameters.0.input': createValueExpressionInputValidate({
required: true,
}),
},
// 副作用管理
effect: {
nodeMeta: fireNodeTitleChange,
outputs: provideNodeOutputVariablesEffect,
},
// 节点后端数据 -> 前端表单数据
formatOnInit: transformOnInit,
// 前端表单数据 -> 节点后端数据
formatOnSubmit: transformOnSubmit,
};

View File

@ -0,0 +1,46 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { I18n } from '@coze-arch/i18n';
import { NodeConfigForm } from '@/node-registries/common/components';
import { OutputsField } from '../common/fields';
import { INPUT_PATH } from './constants';
import { InputsField } from './components/inputs';
export const FormRender = () => (
<NodeConfigForm>
<InputsField
name={INPUT_PATH}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
defaultValue={[{ name: 'input' } as any]}
title={I18n.t('node_http_request_params')}
tooltip={I18n.t('workflow_250429_03')}
required={false}
layout="horizontal"
/>
<OutputsField
title={I18n.t('workflow_detail_node_output')}
tooltip={I18n.t('node_http_response_data')}
id="jsonStringify-node-outputs"
name="outputs"
topLevelReadonly={true}
customReadonly
/>
</NodeConfigForm>
);

View File

@ -0,0 +1,18 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { JSON_STRINGIFY_NODE_REGISTRY } from './node-registry';
export { JsonStringifyContent } from './node-content';

View File

@ -0,0 +1,26 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { InputParameters, Outputs } from '../common/components';
export function JsonStringifyContent() {
return (
<>
<InputParameters />
<Outputs />
</>
);
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
DEFAULT_NODE_META_PATH,
DEFAULT_OUTPUTS_PATH,
} from '@coze-workflow/nodes';
import {
StandardNodeType,
type WorkflowNodeRegistry,
} from '@coze-workflow/base';
import { test, type NodeTestMeta } from './node-test';
import { JSON_STRINGIFY_FORM_META } from './form-meta';
import { INPUT_PATH } from './constants';
export const JSON_STRINGIFY_NODE_REGISTRY: WorkflowNodeRegistry<NodeTestMeta> =
{
type: StandardNodeType.JsonStringify,
meta: {
nodeDTOType: StandardNodeType.JsonStringify,
size: { width: 360, height: 130.7 },
nodeMetaPath: DEFAULT_NODE_META_PATH,
outputsPath: DEFAULT_OUTPUTS_PATH,
inputParametersPath: INPUT_PATH,
test,
},
formMeta: JSON_STRINGIFY_FORM_META,
};

View File

@ -0,0 +1,36 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { FlowNodeFormData } from '@flowgram-adapter/free-layout-editor';
import {
type NodeTestMeta,
generateParametersToProperties,
} from '@/test-run-kit';
export const test: NodeTestMeta = {
generateFormInputProperties(node) {
const formData = node
.getData(FlowNodeFormData)
.formModel.getFormItemValueByPath('/');
const parameters = formData?.inputs?.inputParameters;
return generateParametersToProperties(parameters, {
node,
});
},
};
export type { NodeTestMeta };

View File

@ -0,0 +1,21 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type InputValueVO } from '@coze-workflow/base';
export interface FormData {
inputs: { inputParameters: InputValueVO[] };
}

Some files were not shown because too many files have changed in this diff Show More