Copy disabled (too large)
Download .txt
Showing preview only (26,647K chars total). Download the full file to get everything.
Repository: 53AI/53AIHub
Branch: main
Commit: 6e2b683e02b3
Files: 1265
Total size: 25.2 MB
Directory structure:
gitextract_88ren__n/
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── README_CN.md
├── README_JA.md
├── api/
│ ├── .gitattributes
│ ├── .gitignore
│ ├── Dockerfile
│ ├── Makefile
│ ├── README.md
│ ├── bin/
│ │ ├── restart.sh
│ │ └── version.txt
│ ├── build.sh
│ ├── common/
│ │ ├── cache.go
│ │ ├── ctxkey/
│ │ │ └── key.go
│ │ ├── email.go
│ │ ├── init.go
│ │ ├── lock.go
│ │ ├── logger/
│ │ │ └── logger.go
│ │ ├── permission.go
│ │ ├── redis.go
│ │ ├── session/
│ │ │ └── key.go
│ │ ├── storage/
│ │ │ ├── storage.go
│ │ │ └── storage_test.go
│ │ ├── utils/
│ │ │ ├── ai53/
│ │ │ │ └── api.go
│ │ │ ├── appbuilder/
│ │ │ │ └── api.go
│ │ │ ├── coze/
│ │ │ │ └── api.go
│ │ │ ├── env/
│ │ │ │ └── env.go
│ │ │ ├── helper/
│ │ │ │ ├── helper.go
│ │ │ │ ├── key.go
│ │ │ │ └── sso_sign.go
│ │ │ ├── huawei_cloud/
│ │ │ │ ├── model.go
│ │ │ │ └── signature.go
│ │ │ ├── ip.go
│ │ │ ├── jwt/
│ │ │ │ └── jwt.go
│ │ │ ├── random.go
│ │ │ ├── snowflake.go
│ │ │ ├── system/
│ │ │ │ ├── machine.go
│ │ │ │ └── version.go
│ │ │ └── wxbizjsonmsgcrypt/
│ │ │ └── wxbizjsonmsgcrypt.go
│ │ └── validate.go
│ ├── config/
│ │ ├── config.go
│ │ ├── database.go
│ │ ├── encryption.go
│ │ └── storage.go
│ ├── controller/
│ │ ├── agent.go
│ │ ├── ai53.go
│ │ ├── ai_link.go
│ │ ├── appbuilder.go
│ │ ├── auth_sso.go
│ │ ├── channel-test.go
│ │ ├── channel.go
│ │ ├── conversation.go
│ │ ├── coze.go
│ │ ├── department.go
│ │ ├── dify.go
│ │ ├── email.go
│ │ ├── enterprise.go
│ │ ├── enterprise_config.go
│ │ ├── group.go
│ │ ├── maxkb.go
│ │ ├── message.go
│ │ ├── model.go
│ │ ├── navigation.go
│ │ ├── navigation_icons.go
│ │ ├── order.go
│ │ ├── pay.go
│ │ ├── pay_setting.go
│ │ ├── prompt.go
│ │ ├── provider.go
│ │ ├── provider_callback.go
│ │ ├── relay.go
│ │ ├── rerank.go
│ │ ├── response_handler.go
│ │ ├── setting.go
│ │ ├── share.go
│ │ ├── status.go
│ │ ├── subscription.go
│ │ ├── sync_organization.go
│ │ ├── system_log.go
│ │ ├── tencent.go
│ │ ├── upload.go
│ │ └── user.go
│ ├── docker/
│ │ └── docker-compose.yml
│ ├── docs/
│ │ └── .gitignore
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ ├── middleware/
│ │ ├── auth.go
│ │ ├── cors.go
│ │ ├── distributor.go
│ │ ├── logger.go
│ │ └── relay_auth.go
│ ├── model/
│ │ ├── agent.go
│ │ ├── ai_link.go
│ │ ├── base.go
│ │ ├── cache.go
│ │ ├── channel.go
│ │ ├── channel_file_mapping.go
│ │ ├── conversation.go
│ │ ├── department.go
│ │ ├── dingtalk_corp.go
│ │ ├── dingtalk_suite.go
│ │ ├── enterprise.go
│ │ ├── enterprise_config.go
│ │ ├── enterprise_sync.go
│ │ ├── group.go
│ │ ├── like.go
│ │ ├── main.go
│ │ ├── member_binding.go
│ │ ├── member_department_relation.go
│ │ ├── message.go
│ │ ├── navigation.go
│ │ ├── navigation_content.go
│ │ ├── order.go
│ │ ├── pay_setting.go
│ │ ├── prompt.go
│ │ ├── provider.go
│ │ ├── resource_permission.go
│ │ ├── response.go
│ │ ├── setting.go
│ │ ├── share_record.go
│ │ ├── subscription.go
│ │ ├── system_log.go
│ │ ├── upload_file.go
│ │ ├── user.go
│ │ ├── verification_code.go
│ │ ├── wecom_corp.go
│ │ └── wecom_suite.go
│ ├── router/
│ │ ├── api.go
│ │ ├── main.go
│ │ ├── static.go
│ │ └── web.go
│ ├── service/
│ │ ├── adaptor.go
│ │ ├── ai53_provider.go
│ │ ├── appbuilder_provider.go
│ │ ├── channel_service.go
│ │ ├── coze_provider.go
│ │ ├── enterprise_config_service.go
│ │ ├── hub_adaptor/
│ │ │ ├── 53AI/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── appbuilder/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ └── model.go
│ │ │ ├── bailian/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ ├── rerank.go
│ │ │ │ └── rerank_model.go
│ │ │ ├── coze/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constant/
│ │ │ │ │ ├── contenttype/
│ │ │ │ │ │ └── define.go
│ │ │ │ │ ├── event/
│ │ │ │ │ │ └── define.go
│ │ │ │ │ └── messagetype/
│ │ │ │ │ └── define.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── helper.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── custom/
│ │ │ │ ├── common.go
│ │ │ │ ├── config.go
│ │ │ │ └── workflow.go
│ │ │ ├── dify/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── info.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── fastgpt/
│ │ │ │ └── workflow.go
│ │ │ ├── n8n/
│ │ │ │ ├── README.md
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── openai/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── compatible.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── helper.go
│ │ │ │ ├── image.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ ├── token.go
│ │ │ │ └── util.go
│ │ │ ├── tencent/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── helper.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── sdk/
│ │ │ │ ├── client.go
│ │ │ │ ├── errors.go
│ │ │ │ └── models.go
│ │ │ ├── volcengine/
│ │ │ │ └── main.go
│ │ │ └── yuanqi/
│ │ │ ├── adaptor.go
│ │ │ ├── constants.go
│ │ │ ├── main.go
│ │ │ └── model.go
│ │ ├── organizational_service.go
│ │ ├── payment/
│ │ │ ├── alipay.go
│ │ │ ├── manual.go
│ │ │ ├── payment.go
│ │ │ ├── paypal.go
│ │ │ └── wechatpay.go
│ │ ├── rerank_service.go
│ │ ├── resource_permission_service.go
│ │ ├── user_service.go
│ │ └── version_feature.go
│ ├── static/
│ │ └── libs/
│ │ └── js/
│ │ ├── UEditor/
│ │ │ ├── dialogs/
│ │ │ │ ├── anchor/
│ │ │ │ │ └── anchor.html
│ │ │ │ ├── attachment/
│ │ │ │ │ ├── attachment.css
│ │ │ │ │ ├── attachment.html
│ │ │ │ │ └── attachment.js
│ │ │ │ ├── background/
│ │ │ │ │ ├── background.css
│ │ │ │ │ ├── background.html
│ │ │ │ │ └── background.js
│ │ │ │ ├── charts/
│ │ │ │ │ ├── chart.config.js
│ │ │ │ │ ├── charts.css
│ │ │ │ │ ├── charts.html
│ │ │ │ │ └── charts.js
│ │ │ │ ├── emotion/
│ │ │ │ │ ├── emotion.css
│ │ │ │ │ ├── emotion.html
│ │ │ │ │ └── emotion.js
│ │ │ │ ├── gmap/
│ │ │ │ │ └── gmap.html
│ │ │ │ ├── help/
│ │ │ │ │ ├── help.css
│ │ │ │ │ ├── help.html
│ │ │ │ │ └── help.js
│ │ │ │ ├── image/
│ │ │ │ │ ├── image.css
│ │ │ │ │ ├── image.html
│ │ │ │ │ └── image.js
│ │ │ │ ├── insertframe/
│ │ │ │ │ └── insertframe.html
│ │ │ │ ├── internal.js
│ │ │ │ ├── link/
│ │ │ │ │ └── link.html
│ │ │ │ ├── map/
│ │ │ │ │ ├── map.html
│ │ │ │ │ └── show.html
│ │ │ │ ├── music/
│ │ │ │ │ ├── music.css
│ │ │ │ │ ├── music.html
│ │ │ │ │ └── music.js
│ │ │ │ ├── preview/
│ │ │ │ │ └── preview.html
│ │ │ │ ├── scrawl/
│ │ │ │ │ ├── scrawl.css
│ │ │ │ │ ├── scrawl.html
│ │ │ │ │ └── scrawl.js
│ │ │ │ ├── searchreplace/
│ │ │ │ │ ├── searchreplace.html
│ │ │ │ │ └── searchreplace.js
│ │ │ │ ├── snapscreen/
│ │ │ │ │ └── snapscreen.html
│ │ │ │ ├── spechars/
│ │ │ │ │ ├── spechars.html
│ │ │ │ │ └── spechars.js
│ │ │ │ ├── table/
│ │ │ │ │ ├── edittable.css
│ │ │ │ │ ├── edittable.html
│ │ │ │ │ ├── edittable.js
│ │ │ │ │ ├── edittd.html
│ │ │ │ │ └── edittip.html
│ │ │ │ ├── template/
│ │ │ │ │ ├── config.js
│ │ │ │ │ ├── template.css
│ │ │ │ │ ├── template.html
│ │ │ │ │ └── template.js
│ │ │ │ ├── video/
│ │ │ │ │ ├── video.css
│ │ │ │ │ ├── video.html
│ │ │ │ │ └── video.js
│ │ │ │ ├── webapp/
│ │ │ │ │ └── webapp.html
│ │ │ │ └── wordimage/
│ │ │ │ ├── fClipboard_ueditor.swf
│ │ │ │ ├── imageUploader.swf
│ │ │ │ ├── tangram.js
│ │ │ │ ├── wordimage.html
│ │ │ │ └── wordimage.js
│ │ │ ├── index.html
│ │ │ ├── lang/
│ │ │ │ ├── en/
│ │ │ │ │ └── en.js
│ │ │ │ └── zh-cn/
│ │ │ │ └── zh-cn.js
│ │ │ ├── themes/
│ │ │ │ ├── default/
│ │ │ │ │ ├── css/
│ │ │ │ │ │ └── ueditor.css
│ │ │ │ │ └── dialogbase.css
│ │ │ │ └── iframe.css
│ │ │ ├── third-party/
│ │ │ │ ├── SyntaxHighlighter/
│ │ │ │ │ ├── shCore.js
│ │ │ │ │ └── shCoreDefault.css
│ │ │ │ ├── codemirror/
│ │ │ │ │ ├── codemirror.css
│ │ │ │ │ └── codemirror.js
│ │ │ │ ├── highcharts/
│ │ │ │ │ ├── adapters/
│ │ │ │ │ │ ├── mootools-adapter.js
│ │ │ │ │ │ ├── mootools-adapter.src.js
│ │ │ │ │ │ ├── prototype-adapter.js
│ │ │ │ │ │ ├── prototype-adapter.src.js
│ │ │ │ │ │ ├── standalone-framework.js
│ │ │ │ │ │ └── standalone-framework.src.js
│ │ │ │ │ ├── highcharts-more.js
│ │ │ │ │ ├── highcharts-more.src.js
│ │ │ │ │ ├── highcharts.js
│ │ │ │ │ ├── highcharts.src.js
│ │ │ │ │ ├── modules/
│ │ │ │ │ │ ├── annotations.js
│ │ │ │ │ │ ├── annotations.src.js
│ │ │ │ │ │ ├── canvas-tools.js
│ │ │ │ │ │ ├── canvas-tools.src.js
│ │ │ │ │ │ ├── data.js
│ │ │ │ │ │ ├── data.src.js
│ │ │ │ │ │ ├── drilldown.js
│ │ │ │ │ │ ├── drilldown.src.js
│ │ │ │ │ │ ├── exporting.js
│ │ │ │ │ │ ├── exporting.src.js
│ │ │ │ │ │ ├── funnel.js
│ │ │ │ │ │ ├── funnel.src.js
│ │ │ │ │ │ ├── heatmap.js
│ │ │ │ │ │ ├── heatmap.src.js
│ │ │ │ │ │ ├── map.js
│ │ │ │ │ │ ├── map.src.js
│ │ │ │ │ │ ├── no-data-to-display.js
│ │ │ │ │ │ └── no-data-to-display.src.js
│ │ │ │ │ └── themes/
│ │ │ │ │ ├── dark-blue.js
│ │ │ │ │ ├── dark-green.js
│ │ │ │ │ ├── gray.js
│ │ │ │ │ ├── grid.js
│ │ │ │ │ └── skies.js
│ │ │ │ ├── jquery-1.10.2.js
│ │ │ │ ├── video-js/
│ │ │ │ │ ├── video-js.css
│ │ │ │ │ ├── video-js.swf
│ │ │ │ │ ├── video.dev.js
│ │ │ │ │ └── video.js
│ │ │ │ ├── webuploader/
│ │ │ │ │ ├── Uploader.swf
│ │ │ │ │ ├── webuploader.css
│ │ │ │ │ ├── webuploader.custom.js
│ │ │ │ │ ├── webuploader.flashonly.js
│ │ │ │ │ ├── webuploader.html5only.js
│ │ │ │ │ ├── webuploader.min.bak.js
│ │ │ │ │ └── webuploader.withoutimage.js
│ │ │ │ └── zeroclipboard/
│ │ │ │ ├── ZeroClipboard.js
│ │ │ │ └── ZeroClipboard.swf
│ │ │ ├── ueditor.all.min.bak.js
│ │ │ ├── ueditor.config.js
│ │ │ └── ueditor.parse.js
│ │ └── vditor/
│ │ └── dist/
│ │ ├── content-theme/
│ │ │ ├── ant-design.css
│ │ │ ├── dark.css
│ │ │ ├── light.css
│ │ │ └── wechat.css
│ │ ├── css/
│ │ │ └── content-theme/
│ │ │ ├── ant-design.css
│ │ │ ├── dark.css
│ │ │ ├── light.css
│ │ │ └── wechat.css
│ │ ├── index.css
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── js/
│ │ │ ├── graphviz/
│ │ │ │ ├── full.render.js
│ │ │ │ └── viz.js
│ │ │ ├── highlight.js/
│ │ │ │ ├── LICENSE
│ │ │ │ └── third-languages.js
│ │ │ ├── i18n/
│ │ │ │ ├── en_US.js
│ │ │ │ ├── fr_FR.js
│ │ │ │ ├── ja_JP.js
│ │ │ │ ├── ko_KR.js
│ │ │ │ ├── pt_BR.js
│ │ │ │ ├── ru_RU.js
│ │ │ │ ├── sv_SE.js
│ │ │ │ ├── zh_CN.js
│ │ │ │ └── zh_TW.js
│ │ │ ├── icons/
│ │ │ │ ├── ant.js
│ │ │ │ └── material.js
│ │ │ ├── markmap/
│ │ │ │ └── prism.css
│ │ │ └── mathjax/
│ │ │ ├── LICENSE
│ │ │ ├── a11y/
│ │ │ │ ├── assistive-mml.js
│ │ │ │ ├── complexity.js
│ │ │ │ ├── explorer.js
│ │ │ │ └── semantic-enrich.js
│ │ │ ├── input/
│ │ │ │ ├── asciimath.js
│ │ │ │ ├── mml/
│ │ │ │ │ └── entities.js
│ │ │ │ ├── mml.js
│ │ │ │ ├── tex/
│ │ │ │ │ └── extensions/
│ │ │ │ │ ├── action.js
│ │ │ │ │ ├── all-packages.js
│ │ │ │ │ ├── ams.js
│ │ │ │ │ ├── amscd.js
│ │ │ │ │ ├── autoload.js
│ │ │ │ │ ├── bbox.js
│ │ │ │ │ ├── boldsymbol.js
│ │ │ │ │ ├── braket.js
│ │ │ │ │ ├── bussproofs.js
│ │ │ │ │ ├── cancel.js
│ │ │ │ │ ├── color.js
│ │ │ │ │ ├── colorV2.js
│ │ │ │ │ ├── configMacros.js
│ │ │ │ │ ├── enclose.js
│ │ │ │ │ ├── extpfeil.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── mhchem.js
│ │ │ │ │ ├── newcommand.js
│ │ │ │ │ ├── noerrors.js
│ │ │ │ │ ├── noundefined.js
│ │ │ │ │ ├── physics.js
│ │ │ │ │ ├── require.js
│ │ │ │ │ ├── tagFormat.js
│ │ │ │ │ ├── textmacros.js
│ │ │ │ │ ├── unicode.js
│ │ │ │ │ └── verb.js
│ │ │ │ ├── tex-base.js
│ │ │ │ ├── tex-full.js
│ │ │ │ └── tex.js
│ │ │ ├── output/
│ │ │ │ ├── chtml/
│ │ │ │ │ └── fonts/
│ │ │ │ │ └── tex.js
│ │ │ │ ├── chtml.js
│ │ │ │ ├── svg/
│ │ │ │ │ └── fonts/
│ │ │ │ │ └── tex.js
│ │ │ │ └── svg.js
│ │ │ ├── sre/
│ │ │ │ ├── mathmaps/
│ │ │ │ │ ├── de.js
│ │ │ │ │ ├── en.js
│ │ │ │ │ ├── es.js
│ │ │ │ │ ├── fr.js
│ │ │ │ │ ├── mathmaps_ie.js
│ │ │ │ │ └── nemeth.js
│ │ │ │ ├── sre-node.js
│ │ │ │ └── sre_browser.js
│ │ │ ├── tex-mml-chtml.js
│ │ │ └── tex-svg-full.js
│ │ ├── method.d.ts
│ │ ├── method.js
│ │ ├── ts/
│ │ │ ├── constants.d.ts
│ │ │ ├── devtools/
│ │ │ │ └── index.d.ts
│ │ │ ├── export/
│ │ │ │ └── index.d.ts
│ │ │ ├── hint/
│ │ │ │ └── index.d.ts
│ │ │ ├── ir/
│ │ │ │ ├── expandMarker.d.ts
│ │ │ │ ├── highlightToolbarIR.d.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── input.d.ts
│ │ │ │ ├── process.d.ts
│ │ │ │ └── processKeydown.d.ts
│ │ │ ├── markdown/
│ │ │ │ ├── SMILESRender.d.ts
│ │ │ │ ├── abcRender.d.ts
│ │ │ │ ├── adapterRender.d.ts
│ │ │ │ ├── anchorRender.d.ts
│ │ │ │ ├── chartRender.d.ts
│ │ │ │ ├── codeRender.d.ts
│ │ │ │ ├── flowchartRender.d.ts
│ │ │ │ ├── getHTML.d.ts
│ │ │ │ ├── getMarkdown.d.ts
│ │ │ │ ├── graphvizRender.d.ts
│ │ │ │ ├── highlightRender.d.ts
│ │ │ │ ├── lazyLoadImageRender.d.ts
│ │ │ │ ├── markmapRender.d.ts
│ │ │ │ ├── mathRender.d.ts
│ │ │ │ ├── mediaRender.d.ts
│ │ │ │ ├── mermaidRender.d.ts
│ │ │ │ ├── mindmapRender.d.ts
│ │ │ │ ├── outlineRender.d.ts
│ │ │ │ ├── plantumlRender.d.ts
│ │ │ │ ├── previewRender.d.ts
│ │ │ │ ├── setLute.d.ts
│ │ │ │ └── speechRender.d.ts
│ │ │ ├── outline/
│ │ │ │ └── index.d.ts
│ │ │ ├── preview/
│ │ │ │ ├── image.d.ts
│ │ │ │ └── index.d.ts
│ │ │ ├── resize/
│ │ │ │ └── index.d.ts
│ │ │ ├── sv/
│ │ │ │ ├── combineFootnote.d.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── inputEvent.d.ts
│ │ │ │ ├── process.d.ts
│ │ │ │ └── processKeydown.d.ts
│ │ │ ├── tip/
│ │ │ │ └── index.d.ts
│ │ │ ├── toolbar/
│ │ │ │ ├── Both.d.ts
│ │ │ │ ├── Br.d.ts
│ │ │ │ ├── CodeTheme.d.ts
│ │ │ │ ├── ContentTheme.d.ts
│ │ │ │ ├── Copy.d.ts
│ │ │ │ ├── Counter.d.ts
│ │ │ │ ├── Custom.d.ts
│ │ │ │ ├── Devtools.d.ts
│ │ │ │ ├── Divider.d.ts
│ │ │ │ ├── EditMode.d.ts
│ │ │ │ ├── Emoji.d.ts
│ │ │ │ ├── Export.d.ts
│ │ │ │ ├── Fullscreen.d.ts
│ │ │ │ ├── Headings.d.ts
│ │ │ │ ├── Help.d.ts
│ │ │ │ ├── Indent.d.ts
│ │ │ │ ├── Info.d.ts
│ │ │ │ ├── InsertAfter.d.ts
│ │ │ │ ├── InsertBefore.d.ts
│ │ │ │ ├── InsertCode.d.ts
│ │ │ │ ├── MenuItem.d.ts
│ │ │ │ ├── Outdent.d.ts
│ │ │ │ ├── Outline.d.ts
│ │ │ │ ├── Preview.d.ts
│ │ │ │ ├── Record.d.ts
│ │ │ │ ├── Redo.d.ts
│ │ │ │ ├── Undo.d.ts
│ │ │ │ ├── Upload.d.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ └── setToolbar.d.ts
│ │ │ ├── ui/
│ │ │ │ ├── initUI.d.ts
│ │ │ │ ├── setCodeTheme.d.ts
│ │ │ │ ├── setContentTheme.d.ts
│ │ │ │ ├── setPreviewMode.d.ts
│ │ │ │ └── setTheme.d.ts
│ │ │ ├── undo/
│ │ │ │ └── index.d.ts
│ │ │ ├── util/
│ │ │ │ ├── Options.d.ts
│ │ │ │ ├── RecordMedia.d.ts
│ │ │ │ ├── addScript.d.ts
│ │ │ │ ├── addStyle.d.ts
│ │ │ │ ├── code160to32.d.ts
│ │ │ │ ├── compatibility.d.ts
│ │ │ │ ├── editorCommonEvent.d.ts
│ │ │ │ ├── fixBrowserBehavior.d.ts
│ │ │ │ ├── function.d.ts
│ │ │ │ ├── getSelectText.d.ts
│ │ │ │ ├── hasClosest.d.ts
│ │ │ │ ├── hasClosestByHeadings.d.ts
│ │ │ │ ├── highlightToolbar.d.ts
│ │ │ │ ├── hotKey.d.ts
│ │ │ │ ├── log.d.ts
│ │ │ │ ├── merge.d.ts
│ │ │ │ ├── processCode.d.ts
│ │ │ │ ├── selection.d.ts
│ │ │ │ └── toc.d.ts
│ │ │ └── wysiwyg/
│ │ │ ├── afterRenderEvent.d.ts
│ │ │ ├── highlightToolbarWYSIWYG.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── inlineTag.d.ts
│ │ │ ├── input.d.ts
│ │ │ ├── processKeydown.d.ts
│ │ │ ├── renderDomByMd.d.ts
│ │ │ ├── setHeading.d.ts
│ │ │ ├── showCode.d.ts
│ │ │ └── toolbarEvent.d.ts
│ │ └── types/
│ │ └── index.d.ts
│ └── tasks/
│ ├── channel_update_key.go
│ ├── main.go
│ └── order_tasks.go
├── docker/
│ └── docker-compose.yml
└── web/
├── README.md
├── console/
│ ├── .editorconfig
│ ├── .eslintignore
│ ├── .eslintrc.cjs
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .husky/
│ │ ├── commit-msg
│ │ └── pre-commit
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc.js
│ ├── LINT_SETUP.md
│ ├── README.md
│ ├── auto-imports.d.ts
│ ├── commitlint.config.js
│ ├── components.d.ts
│ ├── index.html
│ ├── lint-staged.config.js
│ ├── package.json
│ ├── postcss.config.js
│ ├── public/
│ │ ├── UEditor/
│ │ │ ├── dialogs/
│ │ │ │ ├── anchor/
│ │ │ │ │ └── anchor.html
│ │ │ │ ├── attachment/
│ │ │ │ │ ├── attachment.css
│ │ │ │ │ ├── attachment.html
│ │ │ │ │ └── attachment.js
│ │ │ │ ├── background/
│ │ │ │ │ ├── background.css
│ │ │ │ │ ├── background.html
│ │ │ │ │ └── background.js
│ │ │ │ ├── charts/
│ │ │ │ │ ├── chart.config.js
│ │ │ │ │ ├── charts.css
│ │ │ │ │ ├── charts.html
│ │ │ │ │ └── charts.js
│ │ │ │ ├── emotion/
│ │ │ │ │ ├── emotion.css
│ │ │ │ │ ├── emotion.html
│ │ │ │ │ └── emotion.js
│ │ │ │ ├── gmap/
│ │ │ │ │ └── gmap.html
│ │ │ │ ├── help/
│ │ │ │ │ ├── help.css
│ │ │ │ │ ├── help.html
│ │ │ │ │ └── help.js
│ │ │ │ ├── image/
│ │ │ │ │ ├── image.css
│ │ │ │ │ ├── image.html
│ │ │ │ │ └── image.js
│ │ │ │ ├── insertframe/
│ │ │ │ │ └── insertframe.html
│ │ │ │ ├── internal.js
│ │ │ │ ├── link/
│ │ │ │ │ └── link.html
│ │ │ │ ├── map/
│ │ │ │ │ ├── map.html
│ │ │ │ │ └── show.html
│ │ │ │ ├── music/
│ │ │ │ │ ├── music.css
│ │ │ │ │ ├── music.html
│ │ │ │ │ └── music.js
│ │ │ │ ├── preview/
│ │ │ │ │ └── preview.html
│ │ │ │ ├── scrawl/
│ │ │ │ │ ├── scrawl.css
│ │ │ │ │ ├── scrawl.html
│ │ │ │ │ └── scrawl.js
│ │ │ │ ├── searchreplace/
│ │ │ │ │ ├── searchreplace.html
│ │ │ │ │ └── searchreplace.js
│ │ │ │ ├── snapscreen/
│ │ │ │ │ └── snapscreen.html
│ │ │ │ ├── spechars/
│ │ │ │ │ ├── spechars.html
│ │ │ │ │ └── spechars.js
│ │ │ │ ├── table/
│ │ │ │ │ ├── edittable.css
│ │ │ │ │ ├── edittable.html
│ │ │ │ │ ├── edittable.js
│ │ │ │ │ ├── edittd.html
│ │ │ │ │ └── edittip.html
│ │ │ │ ├── template/
│ │ │ │ │ ├── config.js
│ │ │ │ │ ├── template.css
│ │ │ │ │ ├── template.html
│ │ │ │ │ └── template.js
│ │ │ │ ├── video/
│ │ │ │ │ ├── video.css
│ │ │ │ │ ├── video.html
│ │ │ │ │ └── video.js
│ │ │ │ ├── webapp/
│ │ │ │ │ └── webapp.html
│ │ │ │ └── wordimage/
│ │ │ │ ├── tangram.js
│ │ │ │ ├── wordimage.html
│ │ │ │ └── wordimage.js
│ │ │ ├── index.html
│ │ │ ├── lang/
│ │ │ │ ├── en/
│ │ │ │ │ └── en.js
│ │ │ │ └── zh-cn/
│ │ │ │ └── zh-cn.js
│ │ │ ├── themes/
│ │ │ │ ├── default/
│ │ │ │ │ ├── css/
│ │ │ │ │ │ └── ueditor.css
│ │ │ │ │ └── dialogbase.css
│ │ │ │ └── iframe.css
│ │ │ ├── third-party/
│ │ │ │ ├── SyntaxHighlighter/
│ │ │ │ │ ├── shCore.js
│ │ │ │ │ └── shCoreDefault.css
│ │ │ │ ├── codemirror/
│ │ │ │ │ ├── codemirror.css
│ │ │ │ │ └── codemirror.js
│ │ │ │ ├── highcharts/
│ │ │ │ │ ├── adapters/
│ │ │ │ │ │ ├── mootools-adapter.js
│ │ │ │ │ │ ├── mootools-adapter.src.js
│ │ │ │ │ │ ├── prototype-adapter.js
│ │ │ │ │ │ ├── prototype-adapter.src.js
│ │ │ │ │ │ ├── standalone-framework.js
│ │ │ │ │ │ └── standalone-framework.src.js
│ │ │ │ │ ├── highcharts-more.js
│ │ │ │ │ ├── highcharts-more.src.js
│ │ │ │ │ ├── highcharts.js
│ │ │ │ │ ├── highcharts.src.js
│ │ │ │ │ ├── modules/
│ │ │ │ │ │ ├── annotations.js
│ │ │ │ │ │ ├── annotations.src.js
│ │ │ │ │ │ ├── canvas-tools.js
│ │ │ │ │ │ ├── canvas-tools.src.js
│ │ │ │ │ │ ├── data.js
│ │ │ │ │ │ ├── data.src.js
│ │ │ │ │ │ ├── drilldown.js
│ │ │ │ │ │ ├── drilldown.src.js
│ │ │ │ │ │ ├── exporting.js
│ │ │ │ │ │ ├── exporting.src.js
│ │ │ │ │ │ ├── funnel.js
│ │ │ │ │ │ ├── funnel.src.js
│ │ │ │ │ │ ├── heatmap.js
│ │ │ │ │ │ ├── heatmap.src.js
│ │ │ │ │ │ ├── map.js
│ │ │ │ │ │ ├── map.src.js
│ │ │ │ │ │ ├── no-data-to-display.js
│ │ │ │ │ │ └── no-data-to-display.src.js
│ │ │ │ │ └── themes/
│ │ │ │ │ ├── dark-blue.js
│ │ │ │ │ ├── dark-green.js
│ │ │ │ │ ├── gray.js
│ │ │ │ │ ├── grid.js
│ │ │ │ │ └── skies.js
│ │ │ │ ├── jquery-1.10.2.js
│ │ │ │ ├── video-js/
│ │ │ │ │ ├── video-js.css
│ │ │ │ │ ├── video.dev.js
│ │ │ │ │ └── video.js
│ │ │ │ ├── webuploader/
│ │ │ │ │ ├── webuploader.css
│ │ │ │ │ ├── webuploader.custom.js
│ │ │ │ │ ├── webuploader.flashonly.js
│ │ │ │ │ ├── webuploader.html5only.js
│ │ │ │ │ ├── webuploader.min.bak.js
│ │ │ │ │ └── webuploader.withoutimage.js
│ │ │ │ └── zeroclipboard/
│ │ │ │ └── ZeroClipboard.js
│ │ │ ├── ueditor.all.min.bak.js
│ │ │ ├── ueditor.config.js
│ │ │ └── ueditor.parse.js
│ │ ├── km-login/
│ │ │ └── index.html
│ │ ├── manifest.json
│ │ ├── oauth_login.html
│ │ └── saas-login/
│ │ └── index.html
│ ├── src/
│ │ ├── App.vue
│ │ ├── api/
│ │ │ ├── code.ts
│ │ │ ├── config.ts
│ │ │ ├── errorHandler.ts
│ │ │ ├── index.ts
│ │ │ ├── modules/
│ │ │ │ ├── agent.ts
│ │ │ │ ├── agents/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── ai-link.ts
│ │ │ │ ├── auth.ts
│ │ │ │ ├── banner/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── channel/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── channel.ts
│ │ │ │ ├── chunk-setting.ts
│ │ │ │ ├── common.ts
│ │ │ │ ├── conversation.ts
│ │ │ │ ├── department.ts
│ │ │ │ ├── dingtalk.ts
│ │ │ │ ├── domain/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── enterprise.ts
│ │ │ │ ├── group.ts
│ │ │ │ ├── libraries/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── message.ts
│ │ │ │ ├── navigation/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── order.ts
│ │ │ │ ├── payment/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── permissions.ts
│ │ │ │ ├── platform-settings/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── prompt.ts
│ │ │ │ ├── provider.ts
│ │ │ │ ├── providers/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── saas.ts
│ │ │ │ ├── setting.ts
│ │ │ │ ├── spaces/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── subscription.ts
│ │ │ │ ├── system-log/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── template-style.ts
│ │ │ │ ├── upload.ts
│ │ │ │ ├── user.ts
│ │ │ │ └── wecom.ts
│ │ │ ├── readme.md
│ │ │ ├── signature.ts
│ │ │ └── types.ts
│ │ ├── apis/
│ │ │ ├── index.ts
│ │ │ ├── modules/
│ │ │ │ ├── conversation.ts
│ │ │ │ ├── enterprise.ts
│ │ │ │ ├── group.ts
│ │ │ │ ├── qyy.ts
│ │ │ │ ├── setting.ts
│ │ │ │ └── user.ts
│ │ │ └── readme.md
│ │ ├── components/
│ │ │ ├── AgentPicker/
│ │ │ │ └── index.vue
│ │ │ ├── CropperDialog/
│ │ │ │ └── index.vue
│ │ │ ├── DeptMemberPicker/
│ │ │ │ └── index.vue
│ │ │ ├── DialogueRecord/
│ │ │ │ ├── drawer.vue
│ │ │ │ └── index.vue
│ │ │ ├── EntityDisplay/
│ │ │ │ ├── README.md
│ │ │ │ ├── index.vue
│ │ │ │ └── types.ts
│ │ │ ├── Filter/
│ │ │ │ ├── date-range.vue
│ │ │ │ ├── select.vue
│ │ │ │ └── user.vue
│ │ │ ├── Fullscreen/
│ │ │ │ └── index.vue
│ │ │ ├── GroupDialog/
│ │ │ │ └── index.vue
│ │ │ ├── GroupSelect/
│ │ │ │ └── index.vue
│ │ │ ├── GroupTabs/
│ │ │ │ └── index.vue
│ │ │ ├── Header/
│ │ │ │ └── index.vue
│ │ │ ├── LanguageDropdown/
│ │ │ │ └── LanguageDropdown.vue
│ │ │ ├── Layout/
│ │ │ │ └── index.vue
│ │ │ ├── Markdown/
│ │ │ │ └── editor.vue
│ │ │ ├── Model/
│ │ │ │ ├── dialog.vue
│ │ │ │ ├── index.ts
│ │ │ │ ├── select.vue
│ │ │ │ └── view.vue
│ │ │ ├── OpenData/
│ │ │ │ └── index.vue
│ │ │ ├── Pagination/
│ │ │ │ ├── index.vue
│ │ │ │ └── simple.vue
│ │ │ ├── Permission/
│ │ │ │ ├── constant.ts
│ │ │ │ ├── data.ts
│ │ │ │ ├── member-selector.vue
│ │ │ │ └── selector.vue
│ │ │ ├── Prompt/
│ │ │ │ ├── README.md
│ │ │ │ ├── generate.vue
│ │ │ │ ├── input.vue
│ │ │ │ ├── optimize.vue
│ │ │ │ └── test/
│ │ │ │ ├── component.vue
│ │ │ │ └── index.ts
│ │ │ ├── ResourcePicker/
│ │ │ │ └── index.vue
│ │ │ ├── Scroller/
│ │ │ │ └── index.vue
│ │ │ ├── Search/
│ │ │ │ └── index.vue
│ │ │ ├── SelectPlus/
│ │ │ │ └── index.vue
│ │ │ ├── ServiceDialog/
│ │ │ │ └── index.vue
│ │ │ ├── Sortable/
│ │ │ │ └── index.vue
│ │ │ ├── SvgIcon/
│ │ │ │ └── index.vue
│ │ │ ├── TablePlus/
│ │ │ │ ├── create-slots.ts
│ │ │ │ └── index.vue
│ │ │ ├── TipConfirm/
│ │ │ │ ├── index.vue
│ │ │ │ └── setup.ts
│ │ │ ├── UEditor/
│ │ │ │ └── index.vue
│ │ │ ├── Upload/
│ │ │ │ ├── certificate.vue
│ │ │ │ ├── image.vue
│ │ │ │ └── index.vue
│ │ │ ├── UserLoginDialog/
│ │ │ │ ├── index.vue
│ │ │ │ └── setup.ts
│ │ │ └── VerificationCodeInput/
│ │ │ └── index.vue
│ │ ├── constants/
│ │ │ ├── .gitkeep
│ │ │ ├── agent.ts
│ │ │ ├── banner.ts
│ │ │ ├── chunk.ts
│ │ │ ├── domain.ts
│ │ │ ├── enterprise.ts
│ │ │ ├── group.ts
│ │ │ ├── navigation.ts
│ │ │ ├── order.ts
│ │ │ ├── payment.ts
│ │ │ ├── platform/
│ │ │ │ ├── agent.ts
│ │ │ │ ├── channel.ts
│ │ │ │ ├── config.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── model.ts
│ │ │ │ └── provider.ts
│ │ │ ├── sync.ts
│ │ │ ├── system-log.ts
│ │ │ └── user.ts
│ │ ├── directive/
│ │ │ ├── copy.ts
│ │ │ ├── debounce.ts
│ │ │ ├── index.ts
│ │ │ ├── overflow-tooltip.ts
│ │ │ ├── readme.md
│ │ │ ├── router.ts
│ │ │ ├── tooltip.ts
│ │ │ ├── truncate.ts
│ │ │ └── version.ts
│ │ ├── global/
│ │ │ ├── filters.ts
│ │ │ ├── index.ts
│ │ │ ├── methods.ts
│ │ │ └── readme.md
│ │ ├── hooks/
│ │ │ ├── useBasicLayout.ts
│ │ │ ├── useEntityInfo.ts
│ │ │ ├── useEnv.ts
│ │ │ ├── useMobile.ts
│ │ │ ├── useScroll.ts
│ │ │ ├── useSso.ts
│ │ │ ├── useTooltip.ts
│ │ │ └── useVmodel.ts
│ │ ├── icons/
│ │ │ ├── 403.vue
│ │ │ └── 500.vue
│ │ ├── layout/
│ │ │ ├── Child.vue
│ │ │ ├── Layout.vue
│ │ │ └── Sider.vue
│ │ ├── locales/
│ │ │ ├── en-v2.json
│ │ │ ├── en.json
│ │ │ ├── index.ts
│ │ │ ├── ja.json
│ │ │ ├── zh-cn.json
│ │ │ └── zh-tw.json
│ │ ├── main.ts
│ │ ├── plugins/
│ │ │ ├── assets.ts
│ │ │ └── index.ts
│ │ ├── router/
│ │ │ └── index.ts
│ │ ├── stores/
│ │ │ ├── index.ts
│ │ │ └── modules/
│ │ │ ├── channel.ts
│ │ │ ├── conversation.ts
│ │ │ ├── domain.ts
│ │ │ ├── enterprise.ts
│ │ │ ├── group.ts
│ │ │ ├── setting.ts
│ │ │ └── user.ts
│ │ ├── styles/
│ │ │ ├── element/
│ │ │ │ ├── _variables.scss
│ │ │ │ ├── override.scss
│ │ │ │ └── vars.scss
│ │ │ ├── global.scss
│ │ │ └── lib/
│ │ │ └── tailwind.css
│ │ ├── types/
│ │ │ ├── agent.d.ts
│ │ │ ├── ai-link.d.ts
│ │ │ ├── category.d.ts
│ │ │ ├── channel.d.ts
│ │ │ ├── domain.d.ts
│ │ │ ├── enterprise.d.ts
│ │ │ ├── entity.ts
│ │ │ ├── env.d.ts
│ │ │ ├── global.d.ts
│ │ │ ├── payment.d.ts
│ │ │ ├── platform.d.ts
│ │ │ ├── settings.d.ts
│ │ │ ├── subscription.d.ts
│ │ │ └── vue-template.d.ts
│ │ ├── utils/
│ │ │ ├── cache.ts
│ │ │ ├── config.ts
│ │ │ ├── copy.ts
│ │ │ ├── event-bus.ts
│ │ │ ├── filter.ts
│ │ │ ├── form-rule.ts
│ │ │ ├── form-rule.v2.ts
│ │ │ ├── form-validator.ts
│ │ │ ├── functions/
│ │ │ │ ├── debounce.ts
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── is/
│ │ │ │ └── index.ts
│ │ │ ├── loadLib.ts
│ │ │ ├── md5.ts
│ │ │ ├── moment.ts
│ │ │ ├── request/
│ │ │ │ ├── axios.ts
│ │ │ │ ├── blob.ts
│ │ │ │ ├── code.ts
│ │ │ │ ├── helper.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── signature.ts
│ │ │ ├── timer-manager.ts
│ │ │ ├── url.ts
│ │ │ ├── version.ts
│ │ │ └── wecom.ts
│ │ └── views/
│ │ ├── agent/
│ │ │ ├── create/
│ │ │ │ ├── components/
│ │ │ │ │ ├── agent-info.vue
│ │ │ │ │ ├── agent-type.vue
│ │ │ │ │ ├── base-config.vue
│ │ │ │ │ ├── expand-config.vue
│ │ │ │ │ ├── field-input-setting.vue
│ │ │ │ │ ├── field-input.vue
│ │ │ │ │ ├── limit-config.vue
│ │ │ │ │ ├── relate-agents-dialog.vue
│ │ │ │ │ ├── relate-agents-setting.vue
│ │ │ │ │ ├── relate-agents.vue
│ │ │ │ │ └── use-scope.vue
│ │ │ │ ├── drawer.vue
│ │ │ │ ├── guide.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── platform/
│ │ │ │ │ ├── 53ai-agent.vue
│ │ │ │ │ ├── app-builder-agent.vue
│ │ │ │ │ ├── bailian.vue
│ │ │ │ │ ├── coze-cn.vue
│ │ │ │ │ ├── coze-osv.vue
│ │ │ │ │ ├── dify-agent.vue
│ │ │ │ │ ├── fastgpt-agent.vue
│ │ │ │ │ ├── index.vue
│ │ │ │ │ ├── maxkb-agent.vue
│ │ │ │ │ ├── n8n.vue
│ │ │ │ │ ├── prompt.vue
│ │ │ │ │ ├── tencent.vue
│ │ │ │ │ ├── volcengine.vue
│ │ │ │ │ └── yuanqi.vue
│ │ │ │ ├── response/
│ │ │ │ │ ├── chat.vue
│ │ │ │ │ └── completion.vue
│ │ │ │ └── store.ts
│ │ │ └── index.vue
│ │ ├── banner/
│ │ │ └── index.vue
│ │ ├── chunk/
│ │ │ └── index.vue
│ │ ├── domain/
│ │ │ ├── components/
│ │ │ │ ├── exclusive-setting-dialog.vue
│ │ │ │ └── independent-setting-dialog.vue
│ │ │ └── index.vue
│ │ ├── exception/
│ │ │ ├── 404/
│ │ │ │ └── index.vue
│ │ │ ├── 500/
│ │ │ │ └── index.vue
│ │ │ └── mobile-tip/
│ │ │ └── index.vue
│ │ ├── index.vue
│ │ ├── info/
│ │ │ └── index.vue
│ │ ├── login/
│ │ │ ├── components/
│ │ │ │ ├── apply-form.vue
│ │ │ │ ├── create-enterprise-form.vue
│ │ │ │ ├── enterprise-list.vue
│ │ │ │ ├── forget-form.vue
│ │ │ │ ├── login-form.vue
│ │ │ │ ├── register-form.vue
│ │ │ │ └── wechat.vue
│ │ │ └── index.vue
│ │ ├── model/
│ │ │ └── index.vue
│ │ ├── navigation/
│ │ │ ├── components/
│ │ │ │ ├── nav-create-dialog.vue
│ │ │ │ ├── nav-create-drawer.vue
│ │ │ │ ├── pc-navigation-pane.vue
│ │ │ │ └── seo-setting-dialog.vue
│ │ │ ├── index.vue
│ │ │ └── web-setting.vue
│ │ ├── order/
│ │ │ ├── components/
│ │ │ │ └── order-add-dialog.vue
│ │ │ └── index.vue
│ │ ├── parse/
│ │ │ └── index.vue
│ │ ├── payment/
│ │ │ ├── components/
│ │ │ │ ├── alipay-setting-dialog.vue
│ │ │ │ ├── manual-setting-dialog.vue
│ │ │ │ ├── payment-card.vue
│ │ │ │ └── wechat-setting-dialog.vue
│ │ │ └── index.vue
│ │ ├── platform/
│ │ │ ├── components/
│ │ │ │ ├── agent-list-drawer.vue
│ │ │ │ ├── auth-list-drawer.vue
│ │ │ │ ├── model-group.vue
│ │ │ │ ├── model-save-dialog.vue
│ │ │ │ ├── model-select-dialog.vue
│ │ │ │ ├── model-setting-dialog.vue
│ │ │ │ ├── provider-authorize-dialog.vue
│ │ │ │ └── provider-card.vue
│ │ │ ├── componentsv2/
│ │ │ │ ├── model-group.vue
│ │ │ │ ├── model-save-dialog.vue
│ │ │ │ └── model-select-dialog.vue
│ │ │ ├── index.vue
│ │ │ ├── km.vue
│ │ │ └── view/
│ │ │ ├── file-editor.vue
│ │ │ ├── file-parser.vue
│ │ │ ├── model.vue
│ │ │ └── web-search.vue
│ │ ├── prompt/
│ │ │ ├── components/
│ │ │ │ ├── create-drawer.vue
│ │ │ │ ├── form.vue
│ │ │ │ └── links-dialog.vue
│ │ │ ├── create/
│ │ │ │ ├── guide.vue
│ │ │ │ ├── index.vue
│ │ │ │ └── store.ts
│ │ │ └── index.vue
│ │ ├── search/
│ │ │ └── index.vue
│ │ ├── smtp/
│ │ │ ├── components/
│ │ │ │ └── email-form.vue
│ │ │ └── index.vue
│ │ ├── space/
│ │ │ ├── components/
│ │ │ │ ├── info-save-dialog.vue
│ │ │ │ └── knowledge-list-drawer.vue
│ │ │ └── index.vue
│ │ ├── sso/
│ │ │ ├── components/
│ │ │ │ ├── access-dialog.vue
│ │ │ │ └── api-access-dialog.vue
│ │ │ └── index.vue
│ │ ├── statistics/
│ │ │ └── index.vue
│ │ ├── subscription/
│ │ │ ├── index.vue
│ │ │ └── utils.ts
│ │ ├── svg/
│ │ │ └── index.vue
│ │ ├── system-log/
│ │ │ └── index.vue
│ │ ├── template-style/
│ │ │ └── index.vue
│ │ ├── toolbox/
│ │ │ ├── components/
│ │ │ │ ├── add-account.vue
│ │ │ │ ├── create-dialog.vue
│ │ │ │ ├── create-drawer.vue
│ │ │ │ ├── store-dialog.vue
│ │ │ │ ├── store-view.vue
│ │ │ │ └── use-group.vue
│ │ │ └── index.vue
│ │ ├── user/
│ │ │ ├── admin/
│ │ │ │ └── index.vue
│ │ │ ├── components/
│ │ │ │ ├── department-add-dialog.vue
│ │ │ │ ├── department-tree-select.vue
│ │ │ │ ├── department-tree.vue
│ │ │ │ ├── group-add-dialog.vue
│ │ │ │ ├── user-add-dialog.vue
│ │ │ │ ├── user-internal-add-dialog.vue
│ │ │ │ ├── user-internal-edit-drawer.vue
│ │ │ │ ├── user-internal-status.vue
│ │ │ │ └── user-select-dialog.vue
│ │ │ ├── dialogue-record/
│ │ │ │ └── index.vue
│ │ │ ├── internal/
│ │ │ │ ├── account.vue
│ │ │ │ ├── group.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── member.vue
│ │ │ │ └── organization.vue
│ │ │ └── register/
│ │ │ └── index.vue
│ │ └── viewer/
│ │ └── index.vue
│ ├── stylelint.config.js
│ ├── tailwind.config.js
│ ├── tsconfig.json
│ ├── vite-plugins/
│ │ └── conditional-compilation.ts
│ └── vite.config.ts
└── front/
├── .editorconfig
├── .eslintignore
├── .eslintrc.cjs
├── .gitattributes
├── .gitignore
├── .husky/
│ ├── commit-msg
│ └── pre-commit
├── .npmrc
├── .prettierignore
├── .prettierrc.js
├── LINT_SETUP.md
├── README.md
├── build/
│ ├── entitlements.mac.plist
│ └── icon.icns
├── commitlint.config.js
├── dev-app-update.yml
├── electron-builder.yml
├── electron.vite.config.ts
├── lint-staged.config.js
├── native/
│ ├── binding.gyp
│ ├── mouse_select_status_mac.mm
│ └── mouse_select_status_win.cpp
├── package.json
├── postcss.config.js
├── src/
│ ├── main/
│ │ ├── enums/
│ │ │ └── SystemTypeEnum.ts
│ │ ├── helper/
│ │ │ └── web.ts
│ │ ├── host.ts
│ │ ├── index.ts
│ │ ├── service/
│ │ │ ├── AutoUpdater.ts
│ │ │ ├── Bookmarks.ts
│ │ │ ├── Container.ts
│ │ │ ├── FileSystem.ts
│ │ │ ├── GlobalShortcutEvent.ts
│ │ │ ├── Main.ts
│ │ │ ├── MouseEventsHandler.ts
│ │ │ └── Pages.ts
│ │ ├── utils/
│ │ │ ├── index.ts
│ │ │ └── validate.ts
│ │ └── window/
│ │ ├── FastChat.ts
│ │ ├── HoverMenu.ts
│ │ └── Main.ts
│ ├── preload/
│ │ ├── fastChat.ts
│ │ ├── hoverMenu.ts
│ │ └── index.ts
│ └── renderer/
│ ├── index.html
│ ├── main/
│ │ ├── App.vue
│ │ ├── api/
│ │ │ ├── code.ts
│ │ │ ├── config.ts
│ │ │ ├── errorHandler.ts
│ │ │ ├── host.ts
│ │ │ ├── index.ts
│ │ │ ├── modules/
│ │ │ │ ├── agent.ts
│ │ │ │ ├── chat.ts
│ │ │ │ ├── common.ts
│ │ │ │ ├── conversation.ts
│ │ │ │ ├── enterprise.ts
│ │ │ │ ├── group.ts
│ │ │ │ ├── links.ts
│ │ │ │ ├── navigation.ts
│ │ │ │ ├── order.ts
│ │ │ │ ├── payment.ts
│ │ │ │ ├── prompt.ts
│ │ │ │ ├── setting.ts
│ │ │ │ ├── share/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── subscription.ts
│ │ │ │ ├── system.ts
│ │ │ │ ├── upload.ts
│ │ │ │ └── user.ts
│ │ │ ├── signature.ts
│ │ │ └── types.ts
│ │ ├── assets/
│ │ │ └── styles/
│ │ │ ├── animate.css
│ │ │ ├── custom.css
│ │ │ ├── element-plus.css
│ │ │ ├── global.css
│ │ │ └── tailwind.css
│ │ ├── components/
│ │ │ ├── AuthTagGroup/
│ │ │ │ └── index.vue
│ │ │ ├── CropperDialog/
│ │ │ │ └── index.vue
│ │ │ ├── ExpireModal/
│ │ │ │ └── index.vue
│ │ │ ├── FileUpload/
│ │ │ │ └── index.vue
│ │ │ ├── Filter/
│ │ │ │ └── date-range.vue
│ │ │ ├── Fullscreen/
│ │ │ │ └── index.vue
│ │ │ ├── LazyComponent/
│ │ │ │ └── index.vue
│ │ │ ├── Lead/
│ │ │ │ └── index.vue
│ │ │ ├── LoginModal/
│ │ │ │ ├── email.vue
│ │ │ │ ├── forgetPassword.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── register.vue
│ │ │ │ ├── resetPassword.vue
│ │ │ │ ├── wechat.vue
│ │ │ │ └── wecom.vue
│ │ │ ├── MarkMap/
│ │ │ │ ├── index.ts
│ │ │ │ ├── index.vue
│ │ │ │ └── vis.vue
│ │ │ ├── Markdown/
│ │ │ │ ├── editor.vue
│ │ │ │ ├── helper.ts
│ │ │ │ └── preview.vue
│ │ │ ├── Pagination/
│ │ │ │ └── index.vue
│ │ │ ├── Prompt/
│ │ │ │ └── input.vue
│ │ │ ├── RelatedScene/
│ │ │ │ └── index.vue
│ │ │ ├── Search/
│ │ │ │ └── index.vue
│ │ │ ├── Slider/
│ │ │ │ └── index.vue
│ │ │ ├── Sortable/
│ │ │ │ └── index.vue
│ │ │ ├── SvgIcon.vue
│ │ │ ├── TablePlus/
│ │ │ │ ├── create-slots.ts
│ │ │ │ └── index.vue
│ │ │ ├── Upgrade/
│ │ │ │ ├── index.vue
│ │ │ │ └── payment-qrcode.vue
│ │ │ ├── Upload/
│ │ │ │ ├── image.vue
│ │ │ │ └── index.vue
│ │ │ ├── VersionModal/
│ │ │ │ └── index.vue
│ │ │ └── modals/
│ │ │ └── .editorconfig
│ │ ├── constants/
│ │ │ ├── currency.ts
│ │ │ ├── events.ts
│ │ │ ├── navigation.ts
│ │ │ ├── payment.ts
│ │ │ ├── storage.ts
│ │ │ └── website.ts
│ │ ├── directive/
│ │ │ ├── README.md
│ │ │ ├── copy.ts
│ │ │ ├── debounce.ts
│ │ │ ├── index.ts
│ │ │ ├── permission.ts
│ │ │ ├── tooltip.ts
│ │ │ └── trim.ts
│ │ ├── global/
│ │ │ └── index.ts
│ │ ├── hooks/
│ │ │ ├── README.md
│ │ │ ├── useBasicLayout.ts
│ │ │ ├── useEmail.ts
│ │ │ ├── useEnv.ts
│ │ │ ├── useMobile.ts
│ │ │ ├── useScroll.ts
│ │ │ └── useVmodel.ts
│ │ ├── layout/
│ │ │ ├── header.vue
│ │ │ ├── index.vue
│ │ │ ├── m-footer.vue
│ │ │ └── sider.vue
│ │ ├── locales/
│ │ │ ├── en.ts
│ │ │ ├── index.ts
│ │ │ ├── jp.ts
│ │ │ ├── zh-cn.ts
│ │ │ └── zh-tw.ts
│ │ ├── main.ts
│ │ ├── plugins/
│ │ │ └── index.ts
│ │ ├── router/
│ │ │ └── index.ts
│ │ ├── stores/
│ │ │ ├── index.ts
│ │ │ └── modules/
│ │ │ ├── agent.ts
│ │ │ ├── browser-setting.ts
│ │ │ ├── conversation.ts
│ │ │ ├── enterprise.ts
│ │ │ ├── global.ts
│ │ │ ├── links.ts
│ │ │ ├── navigation.ts
│ │ │ ├── prompt.ts
│ │ │ └── user.ts
│ │ ├── typings/
│ │ │ ├── Browser.d.ts
│ │ │ ├── agent.d.ts
│ │ │ ├── category.d.ts
│ │ │ ├── conversation.d.ts
│ │ │ ├── enterprise.d.ts
│ │ │ ├── global.d.ts
│ │ │ ├── link.d.ts
│ │ │ ├── navigation.d.ts
│ │ │ ├── order.d.ts
│ │ │ ├── prompt.ts
│ │ │ ├── subscription.d.ts
│ │ │ └── user.d.ts
│ │ ├── utils/
│ │ │ ├── cache.ts
│ │ │ ├── copy.ts
│ │ │ ├── event-bus.ts
│ │ │ ├── file.ts
│ │ │ ├── filter.ts
│ │ │ ├── form-rules.ts
│ │ │ ├── functions/
│ │ │ │ ├── debounce.ts
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── loadLib.ts
│ │ │ ├── md5.ts
│ │ │ ├── moment.ts
│ │ │ ├── permission.ts
│ │ │ ├── router.ts
│ │ │ ├── scroll.ts
│ │ │ ├── storage.ts
│ │ │ └── url.ts
│ │ └── views/
│ │ ├── agent/
│ │ │ ├── components/
│ │ │ │ └── list.vue
│ │ │ └── index.vue
│ │ ├── chat/
│ │ │ ├── chat/
│ │ │ │ ├── components/
│ │ │ │ │ ├── agent-tooltip.vue
│ │ │ │ │ └── history.vue
│ │ │ │ └── index.vue
│ │ │ ├── completion/
│ │ │ │ └── index.vue
│ │ │ ├── helper.vue
│ │ │ ├── index.vue
│ │ │ └── store.ts
│ │ ├── custom/
│ │ │ └── index.vue
│ │ ├── desktop/
│ │ │ ├── components/
│ │ │ │ ├── BookMarks.vue
│ │ │ │ ├── Browser.vue
│ │ │ │ ├── Error.vue
│ │ │ │ ├── GNBTabs.vue
│ │ │ │ ├── MultiBrowser.vue
│ │ │ │ └── Reader/
│ │ │ │ ├── html.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── markdown.vue
│ │ │ │ └── summarize.vue
│ │ │ ├── index.vue
│ │ │ ├── stores/
│ │ │ │ ├── tabs.ts
│ │ │ │ └── user.ts
│ │ │ └── tools/
│ │ │ ├── index.vue
│ │ │ └── toolbox.vue
│ │ ├── discover/
│ │ │ └── index.vue
│ │ ├── index/
│ │ │ ├── agent/
│ │ │ │ ├── chat.vue
│ │ │ │ └── index.vue
│ │ │ ├── index.vue
│ │ │ ├── layout.vue
│ │ │ ├── prompt/
│ │ │ │ ├── detail.vue
│ │ │ │ └── index.vue
│ │ │ ├── redirect.vue
│ │ │ └── toolkit.vue
│ │ ├── order/
│ │ │ └── index.vue
│ │ ├── profile/
│ │ │ ├── about.vue
│ │ │ ├── changeMobile.vue
│ │ │ ├── common.vue
│ │ │ ├── glider.vue
│ │ │ ├── index.vue
│ │ │ ├── password.vue
│ │ │ ├── toolbar.vue
│ │ │ └── userinfo.vue
│ │ ├── prompt/
│ │ │ ├── detail/
│ │ │ │ └── index.vue
│ │ │ ├── index.vue
│ │ │ └── view.vue
│ │ ├── share/
│ │ │ └── chat.vue
│ │ ├── svglist/
│ │ │ └── index.vue
│ │ └── toolkit/
│ │ ├── components/
│ │ │ ├── account-dialog.vue
│ │ │ ├── group-list.vue
│ │ │ └── list.vue
│ │ └── index.vue
│ └── public/
│ └── oauth_login.html
├── stylelint.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.web.json
├── vite.common.ts
└── vite.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: CONTRIBUTING.md
================================================
# 贡献指南
感谢您考虑为53AI Hub项目做出贡献!以下是一些指导方针,帮助您参与到项目中来。
## 行为准则
请尊重所有项目参与者,保持专业和友好的交流环境。
## 如何贡献
### 报告问题
如果您发现了bug或有新功能建议,请通过以下步骤提交问题:
1. 检查是否已存在相同或类似的问题
2. 使用清晰的标题和详细描述创建新问题
3. 包含重现步骤、预期行为和实际行为
4. 如可能,添加截图或错误日志
### 提交代码
1. Fork项目仓库
2. 创建您的特性分支 (`git checkout -b feature/amazing-feature`)
3. 提交您的更改 (`git commit -m '添加一些功能'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 创建一个Pull Request
### 代码风格
- 遵循项目现有的代码风格和约定
- 使用ESLint和Prettier保持代码格式一致
- 为新功能编写测试
- 保持代码简洁可读
## 开发设置
请参考README.md中的项目设置部分,了解如何设置开发环境。
## Pull Request流程
1. 确保您的PR描述清晰地说明了更改内容和原因
2. 可能需要进行代码审查和修改
3. 一旦获得批准,您的PR将被合并
## 许可证
通过贡献代码,您同意您的贡献将在项目的[许可和贡献者协议](./LICENSE)下发布。
================================================
FILE: LICENSE
================================================
## 53AI 开源许可证
**53AI Open Source License**
53AI Hub 基于 Apache License 2.0 的开源协议,并附加以下条件:
53AI Hub is licensed under the Apache License 2.0, with the following additional conditions:
小微企业与创业团队**可将 53AI Hub 源码用于商业用途**。
Small and micro enterprises, as well as startup teams, are permitted to use the 53AI Hub source code for commercial purposes.
若满足以下任一条件,须从 53AI 获得商业许可:
However, if any of the following conditions apply, a commercial license must be obtained from 53AI:
- **中大型企业使用**:员工数 300 人以上或年营收 6,000 万以上属于中大型企业。
- **Medium and large enterprises**: Companies with **300 or more employees** or **annual revenue exceeding 60 million RMB** are considered medium or large enterprises.
- **移除 Logo 与版权**:不得删除或修改 53AI 的 Logo 及版权信息。
- **Removal of logo and copyright**: The 53AI logo and copyright information **must not be removed or altered**.
- **多租户 SaaS 服务**:不得使用 53AI Hub 的源代码运营多租户环境。
- **Multi-tenant SaaS services**: The source code of 53AI Hub **must not be used to operate multi-tenant environments**.
作为贡献者,需同意:
As a contributor, you agree to:
- 产品方可根据需要调整开源协议,使其更严格或更宽松。
- Allow the product team to adjust the open-source license as needed, making it either stricter or more permissive.
- 贡献的代码可用于商业用途,包括但不限于云服务运营。
- Permit the contributed code to be used for commercial purposes, including but not limited to cloud service operations.
除上述特定条件外,其他所有权利和限制遵循 Apache License 2.0。
Except for the specific conditions mentioned above, all other rights and restrictions shall follow the Apache License 2.0.
关于 Apache License 2.0 的详细信息,请访问 [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)。
For detailed information about the Apache License 2.0, please visit [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0).
================================================
FILE: README.md
================================================
<div align="center">
<a href="https://www.53ai.com/products/53AIHub"><img alt="Product Introduction Page" src="https://oss.ibos.cn/53ai/common/53AIHub_banner.png"></a>
</div>
<div align="center">
<a href="./README.md"><img alt="README in English" src="https://img.shields.io/badge/English-d9d9d9"></a>
<a href="./README_CN.md"><img alt="Simplified Chinese README" src="https://img.shields.io/badge/简体中文-d9d9d9"></a>
<a href="./README_JA.md"><img alt="Japanese README" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
</div>
<div>
<a href="https://hub.53ai.com">Cloud Service</a> ·
<a href="https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2">Local Deployment</a> ·
<a href="https://docs.53ai.com/">Documentation</a> ·
<a href="https://aihub.53ai.com">Demo Site</a>
</div>
**53AI Hub** is an **open-source AI portal**, which enables you to quickly build a operational-level AI portal to launch and operate AI agents, prompts, and AI tools. It supports seamless integration with development platforms like **Coze, Dify, FastGPT, RAGFlow, and 53AI Studio**, and cloud platforms such as **Aliyun , Tencent Cloud , and Baidu Cloud**, helping developers and enterprises build production-grade AI portals without complex integrations. Even users with no technical background can participate easily, significantly lowering the barrier to AI inplementation.
Key features are as follows:
**1. Platform Integration**:
Supports integration with mainstream agent development platforms, cloud services, and large language model platforms. Users can choose from site templates and styles, and customize the interface as needed.
**2. Application Management**:
Provides full lifecycle management for AI agents, prompts, and AI tools, including publishing, grouping, sorting, and user permission configuration.
**3. User Operations**:
Supports the operation of both registered users and internal users, with the ability to manage and view login and usage records.
**4. Independent Deployment**:
Supports one-click deployment on both cloud and local environments, and binding to a custom domain name.
## Product Comparison
| Feature | 53AI Hub | NextChat | lobehub | Cherry Studio |
| ------------------ | ----------------------- | ----------- | ----------- | ------------- |
| Custom Interface | Multiple styles | Fixed style | Fixed style | Fixed style |
| Access Permissions | Enterprise-grade | None | None | None |
| Agent Integration | ✅ | ❌ | ❌ | ❌ |
| LLM Integration | ✅ | ✅ | ✅ | ✅ |
| Registered Users | ✅ | ✅ | ✅ | ✅ |
| Internal Users | ✅ | ❌ | ❌ | ❌ |
| SSO Support | WeCom, DingTalk, Feishu | ❌ | ❌ | ❌ |
| Local Deployment | ✅ | ✅ | ✅ | ✅ |
## Usage
* **Cloud Service**
Visit [53AI Hub Cloud Service](https://hub.53ai.com) to apply. The cloud service includes Free, Standard, and Enterprise editions. The Enterprise version offers all features, and the Free version supports 10 agents and 100 registered users.
* **Community Open Source Edition**
Refer to our [Getting Started Guide](https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E6%AC%A2%E8%BF%8E%E4%BD%BF%E7%94%A8) for quick local deployment and our [Documentation](https://docs.53ai.com) for in-depth usage.
* **Enterprise Customized Edition**
We offer enterprise custom versions with features like integration with WeCom, DingTalk, and Feishu org structures. For custom needs, contact us via [email](mailto:hub@53ai.com?subject=[GitHub]Customization).
## Installing the Community Edition
### System Requirements
Minimum configuration for installing 53AI Hub:
* CPU ≥ 1 Core
* RAM ≥ 2 GiB
### Quick Installation
The simplest way to install 53AI Hub Community Edition is to run our docker/docker-compose.yaml file. Before running the installation command, ensure that https://docs.docker.com/get-docker/ and https://docs.docker.com/compose/install/ are installed on your machine. :
1. Clone the repository
```bash
git clone https://github.com/53ai/53aihub.git
cd 53aihub
```
2. Run the following command
```bash
cd docker
docker compose up -d
```
Then visit [`http://localhost:3000`](http://localhost:3000) to access the administration panel and begin setup.
### Custom Configuration
Refer to the comments in `.env.example`, copy and rename it to `.env`, and edit the values. You may also modify `docker-compose.yaml` for things like image versions, port mappings, or volume mounts. After changes, rerun `docker-compose up -d`. You can find the full list of available environment variables here.
## Star History
[](https://star-history.com/#53AI/53AIhub&Date)
## Contributing
> We're seeking contributors to help translate 53AI Hub into more languages. Interested? Get in touch!
We welcome your contributions—whether code, ideas, or issues. Feel free to share 53AI Hub at events, in talks, or on social media.
* [GitHub Discussion](https://github.com/53ai/53aihub/discussions): Share your apps and ideas with the community.
* [GitHub Issues](https://github.com/53ai/53aihub/issues): Report bugs or problems.
## Compliance Certifications
53AI has obtained the following certifications:
* **ISO/IEC 27001:2022 – Information Security Management Systems**
* **ISO 9001:2015 – Quality Management Systems**
## License
This repository is licensed under the [53AI Open Source License](https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E5%BC%80%E6%BA%90%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE), which is based on Apache 2.0 with additional restrictions.
## Follow Us
Star 53AI Hub on GitHub to get notified about updates and new releases.
================================================
FILE: README_CN.md
================================================
<div align="center">
<a href="https://www.53ai.com/products/53AIHub"><img alt="产品介绍页" src="https://oss.ibos.cn/53ai/common/53AIHub_banner.png"></a>
</div>
<div align="center">
<a href="./README.md"><img alt="README in English" src="https://img.shields.io/badge/English-d9d9d9"></a>
<a href="./README_CN.md"><img alt="简体中文版自述文件" src="https://img.shields.io/badge/简体中文-d9d9d9"></a>
<a href="./README_JA.md"><img alt="日本語のREADME" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
</div>
<div>
<a href="https://hub.53ai.com">云服务</a> ·
<a href="https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2">本地部署</a> ·
<a href="https://docs.53ai.com/">产品文档</a> ·
<a href="https://aihub.53ai.com">演示站</a>
</div>
**53AI Hub** 是一款**开源的AI门户**。它可以让你快速搭建一个运营级的AI门户,实现对智能体、提示词与AI工具的发布与运营。它支持无缝对接**字节扣子、腾讯元器、Dify、FastGPT、RAGFlow、53AI Studio**等智能体开发平台,以及**阿里百炼、腾讯云智能体开发平台、火山方舟、百度千帆 AppBuild**等云计算平台,让开发者和企业能够快速搭建生产运营级的 AI 门户,无需复杂的技术整合流程。即使是没有技术背景的人员,也能轻松参与智能体发布和运营,极大降低了 AI 应用落地的门槛。
以下是核心功能列表: </br> </br>
**1. 平台接入**:
主流的智能体开发平台、云计算平台、大模型平台的接入,可选择站点模板及风格,并进行自定义界面。
**2. 应用管理**:
支持智能体、提示词、AI工具的发布、管理、分组、排序、使用权限等设置。
**3. 用户运营**:
支持注册用户、内部用户两类用户的运营,可以管理和查看用户登录、使用记录,
**4. 独立部署**:
可在云平台及本地一键安装部署,支持绑定独立域名。
## 产品对比
<table style="width:100%;">
<tr>
<th align="center">功能</th>
<th align="center">53AI Hub</th>
<th align="center">NextChat</th>
<th align="center">lobehub</th>
<th align="center">Cherry Studio</th>
</tr>
<tr>
<td align="center">自定义界面</td>
<td align="center">多风格及样式</td>
<td align="center">固定风格</td>
<td align="center">固定风格</td>
<td align="center">固定风格</td>
</tr>
<tr>
<td align="center">使用权限</td>
<td align="center">企业级权限</td>
<td align="center">无</td>
<td align="center">无</td>
<td align="center">无</td>
</tr>
<tr>
<td align="center">智能体接入</td>
<td align="center">✅</td>
<td align="center">❌</td>
<td align="center">❌</td>
<td align="center">❌</td>
</tr>
<tr>
<td align="center">大模型接入</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
</tr>
<tr>
<td align="center">注册用户</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
</tr>
<tr>
<td align="center">内部用户</td>
<td align="center">✅</td>
<td align="center">❌</td>
<td align="center">❌</td>
<td align="center">❌</td>
</tr>
<tr>
<td align="center">单点登录</td>
<td align="center">企微、钉钉、飞书</td>
<td align="center">❌</td>
<td align="center">❌</td>
<td align="center">❌</td>
</tr>
<tr>
<td align="center">本地部署</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
<td align="center">✅</td>
</tr>
</table>
## 使用方式
* **在线云服务 </br>**
我们提供[ 53AI Hub 云服务](https://hub.53ai.com),用户可以在线申请开通。云服务包含免费版、标准版和企业版,企业版提供了53AI Hub的全部功能,在免费版本中支持接入10个智能体及100个注册用户。
* **社区开源版</br>**
通过[入门指南](https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E6%AC%A2%E8%BF%8E%E4%BD%BF%E7%94%A8)快速进行本地部署,阅读[产品文档](https://docs.53ai.com)进行更深入的了解。
* **企业定制版</br>**
我们提供可以企业定制版,具有包括不限于打通企微、钉钉、飞书组织架构等企业级产品特性,如果你需要个性化定制,也可以通过[电子邮件](mailto\:hub@53ai.com?subject=\[GitHub]个性定制)讨论你的个性化需求。 </br>
## 安装社区版
### 系统要求
53AI Hub 的最低安装配置:
* CPU >= 1 Core
* RAM >= 2 GiB
### 快速安装
安装 53AI Hub 社区版最简单方法是运行我们的 [docker-compose.yml](docker/docker-compose.yaml) 文件。在运行安装命令之前,请确保您的机器上安装了 [Docker](https://docs.docker.com/get-docker/) 和 [Docker Compose](https://docs.docker.com/compose/install/):
1. 克隆仓库:
```bash
git clone https://github.com/53ai/53aihub.git
cd 53aihub
```
2. 运行安装命令:
```bash
cd docker
docker compose up -d
```
运行后,可以在浏览器上访问 [`http://localhost:3000`](http://localhost:3000) 进入 53AI Hub 并开始初始化配置操作,默认账号通常是`admin@53ai.com` 密码`admin888`。
### 自定义配置
如果您需要自定义配置,请参考 `.env.example`文件中的注释,复制一个改名为 `.env`并更新文件中对应的值。
此外,您可能需要根据您的具体部署环境和需求对 `docker-compose.yaml`文件本身进行调整,例如更改镜像版本、端口映射或卷挂载。完成任何更改后,请重新运行 `docker-compose up -d`。您可以在此处找到可用环境变量的完整列表。
## Star History
[](https://star-history.com/#53AI/53AIhub&Date)
## 参与项目
> 我们在寻找贡献者来帮助将 53AI Hub 翻译成英文之外的其他语言,如果您有兴趣参与,请通联系我们。
我们欢迎您为 53AI Hub做出贡献,包括不限于:提交代码、提交问题、你的新想法。我们也欢迎您在不同的活动、会议和社交媒体上分享 53AI Hub。
* [Github Discussion](https://github.com/53ai/53aihub/discussions)👉:分享您的应用程序并与社区交流。
* [GitHub Issues](https://github.com/53ai/53aihub/issues)👉:使用 53AI Hub 时遇到的错误和问题。
## 合规认证
53AI 已获取以下认证:
* **ISO/IEC 27001:2022 Information security management systems**
* **ISO 9001:2015 Quality management systems**
## 开源协议
本仓库遵循 [53AI Open Source License](https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E5%BC%80%E6%BA%90%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE) 开源协议,该许可证本质上是 Apache 2.0,但有一些额外的限制。
## 关注我们
在 GitHub 上给 53AI Hub Star,我们更新产品你将第一时间收到新版本更新的通知。
## 商务合作
联系人:杨先生
📮:hub@53ai.com
📱:18688881185 (非客服电话)

> 使用问题咨询,可以在官网首页底部加入用户交流群,也可邮件 hub@53ai.com
>
> 如果您需要更多开发和运营指导,可以联系购买商业版本及交付服务
================================================
FILE: README_JA.md
================================================
<div align="center">
<a href="https://www.53ai.com/products/53AIHub"><img alt="製品紹介ページ" src="https://oss.ibos.cn/53ai/common/53AIHub_banner.png"></a>
</div>
<div align="center">
<a href="./README.md"><img alt="README(英語)" src="https://img.shields.io/badge/English-d9d9d9"></a>
<a href="./README_CN.md"><img alt="簡体字中国語README" src="https://img.shields.io/badge/简体中文-d9d9d9"></a>
<a href="./README_JA.md"><img alt="日本語README" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
</div>
<div>
<a href="https://hub.53ai.com">クラウドサービス</a> ·
<a href="https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2">ローカル導入</a> ·
<a href="https://docs.53ai.com/">製品ドキュメント</a> ·
<a href="https://aihub.53ai.com">デモサイト</a>
</div>
**53AI Hub** は、**オープンソースのAIポータル**です。AIエージェント、プロンプト、AIツールの公開・運用を迅速に構築できます。**ByteDance Coze、Tencent Yuanqi、Dify、FastGPT、RAGFlow、53AI Studio**などの開発プラットフォーム、**Aliyun ModelScope、Tencent Cloud、Volcano Ark、Baidu Qianfan AppBuild**などのクラウドプラットフォームとシームレスに連携できます。技術的な統合作業を必要とせず、非技術者でもAIエージェントの運用に参加できるため、AI活用のハードルを大幅に下げることができます。
主な機能:
**1. プラットフォーム連携**:
主流のエージェント開発・クラウド・大規模言語モデル(LLM)との接続。サイトテンプレートやスタイルを選択し、UIをカスタマイズ可能。
**2. アプリケーション管理**:
AIエージェント、プロンプト、ツールの公開、管理、分類、順序、アクセス権限などを設定。
**3. ユーザー管理**:
登録ユーザーと内部ユーザーのログインや利用履歴を確認・管理。
**4. 独立導入**:
クラウドまたはローカル環境にワンクリックで導入可能。独自ドメインも設定可能。
## 製品比較
| 機能 | 53AI Hub | NextChat | lobehub | Cherry Studio |
| ---------------- | ----------------------- | ------------ | ------------ | ------------- |
| UIカスタマイズ | 多様なスタイル | 固定スタイル | 固定スタイル | 固定スタイル |
| アクセス制御 | 企業レベル | なし | なし | なし |
| エージェント統合 | ✅ | ❌ | ❌ | ❌ |
| LLM統合 | ✅ | ✅ | ✅ | ✅ |
| 登録ユーザー | ✅ | ✅ | ✅ | ✅ |
| 内部ユーザー | ✅ | ❌ | ❌ | ❌ |
| SSO対応 | WeCom、DingTalk、Feishu | ❌ | ❌ | ❌ |
| ローカル導入 | ✅ | ✅ | ✅ | ✅ |
## 利用方法
* **クラウドサービス**
[53AI Hubクラウドサービス](https://hub.53ai.com)から申請可能。無料版、標準版、企業版を提供。無料版では10個のAIエージェントと100人のユーザーが利用可能。
* **オープンソース版**
[入門ガイド](https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E6%AC%A2%E8%BF%8E%E4%BD%BF%E7%94%A8)を参照し、ローカルに迅速導入可能。[製品ドキュメント](https://docs.53ai.com)で詳細を確認。
* **企業向けカスタム版**
WeCom、DingTalk、Feishuとの組織連携など企業向け機能に対応。カスタマイズのご希望は[メール](mailto:hub@53ai.com?subject=[GitHub]カスタマイズ要望)にてご相談ください。
## コミュニティ版の導入
### システム要件
最小構成:
* CPU:1コア以上
* メモリ:2GiB以上
### クイックインストール
[docker-compose.yml](docker/docker-compose.yaml) を使用すると簡単にインストールできます。事前に [Docker](https://docs.docker.com/get-docker/) と [Docker Compose](https://docs.docker.com/compose/install/) をインストールしてください。:
1. `git clone` でリポジトリをクローン
```bash
git clone https://github.com/53ai/53aihub.git
cd 53aihub
```
2. Docker Composeを実行
```bash
cd docker
docker compose up -d
```
ブラウザで [`http://localhost:3000`](http://localhost:3000) にアクセスし、管理画面で初期設定を行います。
### カスタム設定
`.env.example` を `.env` にコピーし、コメントを参考に必要な値を設定。`docker-compose.yaml`の内容も環境に応じて調整可能です。
## Star History
[](https://star-history.com/#53AI/53AIhub&Date)
## コミュニティへの参加
> 他言語翻訳の貢献者も募集中です。興味のある方はご連絡ください。
コード、アイデア、フィードバックの提供など、あらゆる形での貢献を歓迎します。
* [GitHub Discussion](https://github.com/53ai/53aihub/discussions):アプリの共有や交流
* [GitHub Issues](https://github.com/53ai/53aihub/issues):バグ報告・提案
## 認証取得
53AIは以下の国際認証を取得済み:
* **ISO/IEC 27001:2022 – 情報セキュリティマネジメントシステム**
* **ISO 9001:2015 – 品質マネジメントシステム**
## ライセンス
このリポジトリは [53AI オープンソースライセンス](https://docs.53ai.com/%E5%85%A5%E9%97%A8/%E5%BC%80%E6%BA%90%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE) の下で提供されており、Apache 2.0をベースに追加制限が加えられています。
## フォローしよう
GitHubで53AI Hubにスターを付けると、最新のアップデート通知を受け取ることができます。
================================================
FILE: api/.gitattributes
================================================
saas/** merge=ours
================================================
FILE: api/.gitignore
================================================
.idea
.vscode
upload
*.exe
*.db
build
*.db-journal
logs
data
/web/node_modules
cmd.md
.env
temp
.DS_Store
__debug_bin*
static/uploads/*
static/console/*
static/front/*
bin/.env
bin/*hub
docs/*
saas/
build-restart-develop.sh
send-build-msg.sh
.envkm
.envhub
53AIHub
AI_TASK.txt
.tasks/*
.env*
================================================
FILE: api/Dockerfile
================================================
FROM golang:1.24.1 as builder
# 设置工作目录
WORKDIR /app
# 设置GOPROXY为中国大陆代理
ENV GOPROXY=https://goproxy.cn,direct
# 安装构建依赖(使用阿里云Debian镜像源)
RUN echo "deb https://mirrors.aliyun.com/debian/ bookworm main contrib non-free\n\
deb https://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free\n\
deb https://mirrors.aliyun.com/debian-security bookworm-security main" > /etc/apt/sources.list && \
apt-get update -o Acquire::Retries=3 -o Acquire::http::Timeout=10 && \
apt-get install -y --no-install-recommends gcc libc6-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 复制go.mod和go.sum文件
COPY go.mod go.sum ./
# 下载依赖
RUN go mod download
# 复制源代码
COPY . .
# 构建应用 (修正CGO设置)
RUN CGO_ENABLED=1 go build -a -o /app/53AIHub -ldflags '-X "github.com/53AI/53AIHub/config.VersionTime=$(date +%Y%m%d%H%M%S)" -extldflags "-static"' ./main.go
# 使用精简的Alpine镜像作为运行时
FROM alpine:3.18
# 安装SQLite运行时依赖和C库
RUN apk --no-cache add ca-certificates sqlite libc6-compat
# 从构建阶段复制可执行文件
COPY --from=builder /app/53AIHub /app/
# 暴露端口
EXPOSE 3000
# 设置启动命令
CMD ["/app/53AIHub"]
================================================
FILE: api/Makefile
================================================
# Go parameters
GOBIN = go
GOFMT = gofmt
GOLINT = golangci-lint
GOTEST = go test
GOBUILD = go build
GOCLEAN = go clean
# Binary name
BINARY_NAME = 53aihub
BINARY_UNIX = $(BINARY_NAME)_unix
# Output directory
BIN_DIR = bin
# Build flags
BUILD_FLAGS = -v
.PHONY: all build clean test lint fmt
all: clean fmt lint test build
build:
$(GOBUILD) $(BUILD_FLAGS) -o $(BIN_DIR)/$(BINARY_NAME) ./main.go
sbuild:
$(GOBUILD) $(BUILD_FLAGS) -o $(BIN_DIR)/$(BINARY_NAME) -v -ldflags="-X 'github.com/53AI/53AIHub/config.VersionTime=$(shell date +%Y%m%d%H%M%S)' -linkmode external -extldflags '-static'" ./main.go
test:
$(GOTEST) -v ./...
clean:
$(GOCLEAN)
rm -f $(BIN_DIR)/*
lint:
$(GOLINT) run
fmt:
$(GOFMT) -w .
# Cross compilation
build-linux:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) $(BUILD_FLAGS) -o $(BIN_DIR)/$(BINARY_UNIX) -v ./...
# Static build with no glibc dependency
swagger-init:
swag init -g router/main.go --output docs/
static-build: swagger-init
CGO_ENABLED=0 $(GOBUILD) -trimpath $(BUILD_FLAGS) -o $(BIN_DIR)/$(BINARY_NAME) -a -ldflags '-X "github.com/53AI/53AIHub/config.VersionTime=$(shell date +%Y%m%d%H%M%S)" -extldflags "-static"' ./main.go
# 交叉编译 Windows 版本 (启用 CGO 支持 go-sqlite3)
WIN_OS := windows
WIN_BITS := 64
WIN_DATE := $(shell date +%Y%m%d%H%M)
WIN_OUTPUT := $(BIN_DIR)/$(BINARY_NAME)_$(WIN_OS)_$(WIN_BITS)_$(WIN_DATE).exe
LINUX_OS := linux
LINUX_BITS := 64
LINUX_DATE := $(shell date +%Y%m%d%H%M)
LINUX_OUTPUT := $(BIN_DIR)/$(BINARY_NAME)_$(LINUX_OS)_$(LINUX_BITS)_$(LINUX_DATE)
static-build-with-info: swagger-init
GOMAXPROCS=1 CGO_ENABLED=0 $(GOBUILD) -trimpath $(BUILD_FLAGS) -o $(LINUX_OUTPUT) -a -ldflags '-X "github.com/53AI/53AIHub/config.VersionTime=$(LINUX_DATE)" -extldflags "-static"' ./main.go
build-windows-cgo:
@echo "开始交叉编译 Windows 可执行文件 (启用 CGO)..."
@if ! command -v x86_64-w64-mingw32-gcc > /dev/null; then \
echo "请先安装 MinGW 交叉编译工具链: sudo apt-get install -y gcc-mingw-w64"; \
exit 1; \
fi
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="-static -static-libgcc" $(GOBUILD) -trimpath $(BUILD_FLAGS) -o $(WIN_OUTPUT) -ldflags '-X "github.com/53AI/53AIHub/config.VersionTime=$(WIN_DATE)" -s -w' ./main.go
@echo "Windows 可执行文件已生成: $(WIN_OUTPUT)"
# 静态编译 Windows 版本 (完全静态链接,启用 CGO)
build-windows-static-cgo:
@echo "开始静态编译 Windows 可执行文件 (启用 CGO)..."
@if ! command -v x86_64-w64-mingw32-gcc > /dev/null; then \
echo "请先安装 MinGW 交叉编译工具链: sudo apt-get install -y gcc-mingw-w64"; \
exit 1; \
fi
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="-static -static-libgcc -static-libstdc++" $(GOBUILD) -trimpath $(BUILD_FLAGS) -o $(WIN_OUTPUT) -ldflags '-X "github.com/53AI/53AIHub/config.VersionTime=$(WIN_DATE)" -s -w -H=windowsgui' ./main.go
@echo "Windows 静态可执行文件已生成: $(WIN_OUTPUT)"
================================================
FILE: api/README.md
================================================
# 53AIHub 后端接口
53AIHub 是一个强大的 AI 代理管理平台,支持多种 AI 模型的接入和管理。本指南将帮助您快速上手并开始使用 53AIHub。
## 目录
- [53AIHub 后端接口](#53aihub-后端接口)
- [目录](#目录)
- [环境要求](#环境要求)
- [快速开始](#快速开始)
- [使用 Docker Compose 启动](#使用-docker-compose-启动)
- [使用 Go 源码编译启动](#使用-go-源码编译启动)
- [源代码编译启动](#源代码编译启动)
- [使用预编译文件启动](#使用预编译文件启动)
- [配置说明](#配置说明)
- [常见问题排查](#常见问题排查)
- [1. 服务无法启动](#1-服务无法启动)
- [2. 数据库问题](#2-数据库问题)
- [3. 微信支付配置](#3-微信支付配置)
- [4. Token 编码器初始化失败](#4-token-编码器初始化失败)
## 环境要求
- Docker 和 Docker Compose (如使用容器化部署)
- Go 1.24+ (如从源码编译)
## 快速开始
1. 克隆仓库到本地
```bash
git clone https://github.com/53AI/53AIHub.git
cd 53AIHub
```
### 使用 Docker Compose 启动
2. 进入 docker 目录并启动服务
```bash
cd docker
docker compose up -d
```
这将启动 53AIHub 应用 (端口 3000 可在docker-compose.yml中修改)。
服务将在 `http://localhost:3000` 上运行。
### 使用 Go 源码编译启动
1. 确保你本地有 Go 语言环境和构建工具,以及node和npm环境
2. 先进入web目录构建前端的网页前台与管理后台(**非常重要**)
3. 再进入本目录,执行构建
```bash
make build-windows-cgo
```
4. 构建完成后,可执行文件将生成在 `bin` 目录下。
5. 运行可执行文件
### 源代码编译启动
1. 安装依赖并编译
```bash
go mod tidy
go build -o bin/53aihub main.go
```
3. 启动 53AIHub 服务
```bash
./bin/53aihub
```
服务将在默认端口上运行(通常是 3000,可通过.evn文件的 PORT 环境变量修改)。
### 使用预编译文件启动
1. 从 GitHub Releases 页面下载预编译文件
访问 [GitHub Releases](https://github.com/53AI/53AIHub/releases) 下载适合您操作系统的预编译文件。
2. 启动 53AIHub
- Linux/MacOS:
```bash
chmod +x 53AIHub_linux
./53AIHub_linux
```
- Windows:
双击 `53AIHub_install.exe` 文件安装运行启动
服务将在默认端口上`3000`运行。
## 配置说明
53AIHub 默认不需要任何配置即可启动,它使用以下默认配置:
- 数据库:SQLite(默认,无需配置)
- 端口:默认为 3000(可通过.env的 PORT 环境变量修改)
如果需要特定功能,可以配置以下环境变量:
- `SQL_DSN`: 数据库连接字符串,默认使用 SQLite
- `PORT`: 服务监听端口,默认为 3000
- `LOG_LEVEL`: 日志级别,可选值为 DEBUG、INFO(默认)
- `API_HOST`: API 主机地址,如需支持微信支付,必须配置此项
## 常见问题排查
### 1. 服务无法启动
- 检查端口是否被占用
- 查看日志文件中的错误信息
```bash
cat logs/53aihub.log
```
### 2. 数据库问题
默认情况下,53AIHub 使用 SQLite 数据库,无需额外配置。如果您配置了 MySQL 数据库但连接失败:
- 确认 MySQL 服务是否正常运行
- 检查数据库连接参数是否正确
- 确认数据库用户是否有足够的权限
### 3. 支付配置
如需支持微信支付功能、支付宝支付功能,必须配置 `API_HOST` 环境变量:
```bash
export API_HOST="http://your-domain.com"
```
或在启动时指定:
```bash
API_HOST="http://your-domain.com" ./53aihub
```
### 4. Token 编码器初始化失败
错误信息示例:
```
panic: runtime error: invalid memory address or nil pointer dereference
```
可能原因:
- billingratio.ModelRatio 为 nil
- logger 未正确初始化
解决方法:
- 确保在使用 logger 前已正确初始化
请注意:静态编译需要安装一些额外的依赖项(例如 GCC、G++、Git、Make),请查看 Makefile 中的静态编译命令,以获得更多信息。如果您的环境缺少这些依赖项,可能会导致静态编译失败。
错误信息示例2:
```
CGO_ENABLED=0 go build -trimpath -v -o bin/53aihub -a -ldflags '-X "github.com/53AI/53AIHub/config.VersionTime=20250817222030" -extldflags "-static"' ./main.go
main.go:18:29: pattern all:static/console: no matching files found
make: *** [Makefile:48: static-build] Error 1
可能原因:
- 没有先编绎前端
//go:embed all:static/front all:static/console static/images all:static/libs
上面这句的意思是打包前端资源,注意要先将前端打包成出来,分别放在static/front和static/console里
不熟悉go的请注意它就是这种注释语法
如果您遇到其他问题,请提交 GitHub Issue 获取支持。
```
```
================================================
FILE: api/bin/restart.sh
================================================
#!/bin/bash
# 1. 找到 53aihub 运行的 pid
PID=$(ps aux | grep '[5]3aihub' | awk '{print $2}')
# 2. 优雅 kill 掉
if [ -n "$PID" ]; then
echo "找到 53aihub 进程 PID: $PID,正在停止..."
kill -15 $PID
sleep 2 # 等待进程结束
else
echo "未找到正在运行的 53aihub 进程"
fi
# 3. 后台运行 53aihub 并且输出日志到当前目录位置
echo "启动 53aihub..."
nohup ./53aihub > ./53aihub.log 2>&1 &
echo "53aihub 已启动,日志输出到 ./53aihub.log"
================================================
FILE: api/bin/version.txt
================================================
v0.1.0
================================================
FILE: api/build.sh
================================================
#!/bin/bash
make static-build
================================================
FILE: api/common/cache.go
================================================
package common
================================================
FILE: api/common/ctxkey/key.go
================================================
package ctxkey
const (
Config = "config"
Id = "id"
Username = "username"
Role = "role"
Status = "status"
Channel = "channel"
ChannelId = "channel_id"
SpecificChannelId = "specific_channel_id"
RequestModel = "request_model"
ConvertedRequest = "converted_request"
OriginalModel = "original_model"
Group = "group"
ModelMapping = "model_mapping"
ChannelName = "channel_name"
TokenId = "token_id"
TokenName = "token_name"
BaseURL = "base_url"
AvailableModels = "available_models"
KeyRequestBody = "key_request_body"
SystemPrompt = "system_prompt"
)
================================================
FILE: api/common/email.go
================================================
package common
import (
"crypto/rand"
"crypto/tls"
"errors"
"fmt"
"net/smtp"
"regexp"
"strings"
"time"
"github.com/53AI/53AIHub/model"
"github.com/jordan-wright/email"
"gorm.io/gorm"
)
// ValidateEmailFormat 验证基础邮箱格式(通用版)
func ValidateEmailFormat(email string) bool {
pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` // 通用邮箱格式验证(如user@domain.com)
return regexp.MustCompile(pattern).MatchString(email)
}
// sendQQMailWithTLS 使用手动TLS连接发送QQ邮件
func sendQQMailWithTLS(e *email.Email, auth smtp.Auth, host string, port int) error {
// 创建 TLS 配置
tlsconfig := &tls.Config{
InsecureSkipVerify: false,
ServerName: host,
}
// 连接到 SMTP 服务器
addr := fmt.Sprintf("%s:%d", host, port)
conn, err := tls.Dial("tcp", addr, tlsconfig)
if err != nil {
return fmt.Errorf("TLS connection failed: %v", err)
}
defer conn.Close()
// 创建 SMTP 客户端
client, err := smtp.NewClient(conn, host)
if err != nil {
return fmt.Errorf("SMTP client creation failed: %v", err)
}
defer client.Quit()
// 认证
if err = client.Auth(auth); err != nil {
return fmt.Errorf("authentication failed: %v", err)
}
// 设置发件人和收件人
if err = client.Mail(e.From); err != nil {
return fmt.Errorf("sender setup failed: %v", err)
}
for _, recipient := range e.To {
if err = client.Rcpt(recipient); err != nil {
return fmt.Errorf("recipient setup failed: %v", err)
}
}
// 写入邮件内容
wc, err := client.Data()
if err != nil {
return fmt.Errorf("data writer creation failed: %v", err)
}
defer wc.Close()
// 构建邮件内容
var msg strings.Builder
// 添加From
msg.WriteString(fmt.Sprintf("From: %s\r\n", e.From))
// 添加To
msg.WriteString(fmt.Sprintf("To: %s\r\n", strings.Join(e.To, ", ")))
// 添加Subject
msg.WriteString(fmt.Sprintf("Subject: %s\r\n", e.Subject))
// 添加其他头部信息
for key, values := range e.Headers {
for _, value := range values {
msg.WriteString(fmt.Sprintf("%s: %s\r\n", key, value))
}
}
// 添加空行分隔头部和正文
msg.WriteString("\r\n")
// 添加正文
if len(e.HTML) > 0 {
msg.Write(e.HTML)
} else if len(e.Text) > 0 {
msg.Write(e.Text)
}
// 发送邮件内容
_, err = wc.Write([]byte(msg.String()))
if err != nil {
return fmt.Errorf("message sending failed: %v", err)
}
return nil
}
// SendEmail 使用jordan-wright/email库通过通用SMTP服务发送邮件
func SendEmail(e *email.Email, auth smtp.Auth, isSsl bool, host string, port int) error {
addr := fmt.Sprintf("%s:%d", host, port)
fmt.Printf("Sending email to %v via %s, SSL: %v, Port: %d\n", e.To, addr, isSsl, port)
// 针对QQ邮箱等特殊处理
isQQMail := strings.Contains(host, "qq.com")
// 对于QQ邮箱且使用465端口,使用特殊处理方式
if isQQMail && port == 465 {
fmt.Printf("Using special handling for QQ mail on port 465\n")
return sendQQMailWithTLS(e, auth, host, port)
}
if isSsl {
tlsConfig := &tls.Config{
InsecureSkipVerify: false,
ServerName: host,
}
if err := e.SendWithTLS(addr, auth, tlsConfig); err != nil {
return fmt.Errorf("failed to send email via %s:%d: %w", host, port, err)
}
} else {
if err := e.Send(addr, auth); err != nil {
return fmt.Errorf("failed to send email via %s:%d: %w", host, port, err)
}
}
return nil
}
// VerifyEmailCode 验证邮箱验证码有效性
func VerifyEmailCode(email, code string) (bool, error) {
if email == "" || code == "" {
return false, errors.New("missing email or code parameter")
}
now := time.Now().UTC().UnixMilli()
var storedCode string
// 优先从Redis获取验证码
storedCode, err := RedisGet("email_verification:" + email)
if err != nil || storedCode == "" {
// Redis不存在时查询数据库
var vc model.VerificationCode
err = model.DB.Where("target = ? AND type = 'email' AND code = ? AND expires_at > ?", email, code, now).First(&vc).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return false, errors.New("verification code expired or invalid")
}
return false, fmt.Errorf("database query error: %w", err)
}
storedCode = code
}
if storedCode != code {
return false, errors.New(model.InvalidVerificationCode)
}
_ = RedisDel("email_verification:" + email)
return true, nil
}
func GenerateRandomCode(length int) (string, error) {
bytes := make([]byte, length)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
for i := 0; i < length; i++ {
bytes[i] = byte(48 + int(bytes[i])%10) // 0-9
}
return string(bytes), nil
}
================================================
FILE: api/common/init.go
================================================
package common
import (
"flag"
"fmt"
"os"
"github.com/53AI/53AIHub/config"
)
var (
Port = flag.Int("1port", 3000, "the listening port")
PrintVersion = flag.Bool("1version", false, "print version and exit")
PrintHelp = flag.Bool("1help", false, "print help and exit")
LogDir = flag.String("1log-dir", "./logs", "specify the log directory")
)
func printHelp() {
// TODO: print help
fmt.Println("53AIHub Api " + config.Version + " - Fast, simple, and efficient AI WebSite.")
fmt.Println("Copyright (C) 2025 Liuzimu. All rights reserved.")
fmt.Println("GitHub: xxx")
fmt.Println("Usage: 53AIHub [--port <port>] [--log-dir <log directory>] [--version] [--help]")
}
func Init() {
flag.Parse()
if *PrintHelp {
printHelp()
os.Exit(0) // 仅在 --help 参数存在时退出
}
if *PrintVersion {
fmt.Println(config.Version)
os.Exit(0) // 仅在 --version 参数存在时退出
}
// Initialize the logger
InitRedisClient()
InitLocker()
}
================================================
FILE: api/common/lock.go
================================================
package common
import (
"context"
"sync"
"time"
"github.com/53AI/53AIHub/common/logger"
"github.com/go-redis/redis/v8"
)
var LOCKER Locker
func InitLocker() {
if RedisEnabled {
LOCKER = NewRedisLock(RDB)
} else {
LOCKER = NewLocalLock()
}
}
type Locker interface {
// TryLock 尝试获取锁
// name: 锁名称
// ttl: 锁的存活时间
// 返回是否获取成功
TryLock(name string, ttl time.Duration) bool
// Unlock 释放锁
Unlock(name string)
}
func NewLocalLock() *LocalLock {
return &LocalLock{}
}
type LocalLock struct {
locks sync.Map // key: lockName, value: *lockEntry
}
type lockEntry struct {
mu sync.Mutex
expiresAt time.Time
}
// TryLock 尝试获取锁,如果成功返回true,否则返回false
// name: 锁名称
// ttl: 锁的存活时间
func (ll *LocalLock) TryLock(name string, ttl time.Duration) bool {
now := time.Now()
entry, loaded := ll.locks.LoadOrStore(name, &lockEntry{
expiresAt: now.Add(ttl),
})
le := entry.(*lockEntry)
le.mu.Lock()
logger.SysLogf("lock: %s", name)
// 检查锁是否已过期
if now.After(le.expiresAt) {
le.expiresAt = now.Add(ttl)
le.mu.Unlock()
return true
}
if loaded {
le.mu.Unlock()
return false
}
// 新创建的锁,启动定时器自动释放
time.AfterFunc(ttl, func() {
le.mu.Lock()
defer le.mu.Unlock()
ll.locks.Delete(name)
logger.SysLogf("lock %s expired, unlock", name)
})
le.mu.Unlock()
return true
}
// Unlock 手动释放锁
func (ll *LocalLock) Unlock(name string) {
if entry, ok := ll.locks.Load(name); ok {
le := entry.(*lockEntry)
le.mu.Lock()
defer le.mu.Unlock()
ll.locks.Delete(name)
}
}
type RedisLock struct {
client redis.Cmdable
}
func NewRedisLock(client redis.Cmdable) *RedisLock {
return &RedisLock{client: client}
}
func (rl *RedisLock) TryLock(name string, ttl time.Duration) bool {
ctx := context.Background()
// 使用SET NX EX实现原子操作
result, err := rl.client.SetNX(ctx, "lock:"+name, "1", ttl).Result()
return err == nil && result
}
func (rl *RedisLock) Unlock(name string) {
ctx := context.Background()
rl.client.Del(ctx, "lock:"+name)
}
================================================
FILE: api/common/logger/logger.go
================================================
package logger
import (
"context"
"fmt"
"io"
"log"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
"github.com/53AI/53AIHub/common/utils/helper"
"github.com/53AI/53AIHub/config"
"github.com/gin-gonic/gin"
)
type loggerLevel string
const (
loggerDEBUG loggerLevel = "DEBUG"
loggerINFO loggerLevel = "INFO"
loggerWARN loggerLevel = "WARN"
loggerERROR loggerLevel = "ERROR"
loggerFATAL loggerLevel = "FATAL"
loggerNONE loggerLevel = "NONE"
)
var (
setupLogOnce sync.Once
// Current log level, initialized from environment variable
currentLogLevel loggerLevel = loggerINFO
)
// Initialize the logger system with environment variables
func init() {
// Get log level from environment variable, default to INFO if not set
envLogLevel := os.Getenv("LOG_LEVEL")
if envLogLevel != "" {
switch strings.ToUpper(envLogLevel) {
case string(loggerDEBUG):
currentLogLevel = loggerDEBUG
case string(loggerINFO):
currentLogLevel = loggerINFO
case string(loggerWARN):
currentLogLevel = loggerWARN
case string(loggerERROR):
currentLogLevel = loggerERROR
case string(loggerFATAL):
currentLogLevel = loggerFATAL
case string(loggerNONE):
currentLogLevel = loggerNONE
default:
// If invalid level is provided, default to INFO
currentLogLevel = loggerINFO
}
}
}
// SetLogLevel allows programmatically setting the log level
func SetLogLevel(level string) {
switch strings.ToUpper(level) {
case string(loggerDEBUG):
currentLogLevel = loggerDEBUG
case string(loggerINFO):
currentLogLevel = loggerINFO
case string(loggerWARN):
currentLogLevel = loggerWARN
case string(loggerERROR):
currentLogLevel = loggerERROR
case string(loggerFATAL):
currentLogLevel = loggerFATAL
case string(loggerNONE):
currentLogLevel = loggerNONE
default:
// If invalid level is provided, default to INFO
currentLogLevel = loggerINFO
}
}
// GetLogLevel returns the current log level
func GetLogLevel() string {
return string(currentLogLevel)
}
// shouldLog determines if a log message should be output based on its level
func shouldLog(level loggerLevel) bool {
if currentLogLevel == loggerNONE {
return false
}
switch currentLogLevel {
case loggerDEBUG:
return true
case loggerINFO:
return level != loggerDEBUG
case loggerWARN:
return level != loggerDEBUG && level != loggerINFO
case loggerERROR:
return level == loggerERROR || level == loggerFATAL
case loggerFATAL:
return level == loggerFATAL
default:
return true
}
}
func SetupLogger() {
setupLogOnce.Do(func() {
if config.LogDir != "" {
var logPath string
if config.OnlyOneLogFile {
logPath = filepath.Join(config.LogDir, "53AIHub.log")
} else {
logPath = filepath.Join(config.LogDir, fmt.Sprintf("53AIHub-%s.log", time.Now().Format("20060102")))
}
fd, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal("failed to open log file")
}
gin.DefaultWriter = io.MultiWriter(os.Stdout, fd)
gin.DefaultErrorWriter = io.MultiWriter(os.Stderr, fd)
}
})
}
func SysLog(s string) {
logHelper(nil, loggerINFO, s)
}
func SysLogf(format string, a ...any) {
logHelper(nil, loggerINFO, fmt.Sprintf(format, a...))
}
func SysWarn(s string) {
logHelper(nil, loggerWARN, s)
}
func SysWarnf(format string, a ...any) {
logHelper(nil, loggerWARN, fmt.Sprintf(format, a...))
}
func SysError(s string) {
logHelper(nil, loggerERROR, s)
}
func SysErrorf(format string, a ...any) {
logHelper(nil, loggerERROR, fmt.Sprintf(format, a...))
}
func Debug(ctx context.Context, msg string) {
logHelper(ctx, loggerDEBUG, msg)
}
func Info(ctx context.Context, msg string) {
logHelper(ctx, loggerINFO, msg)
}
func Warn(ctx context.Context, msg string) {
logHelper(ctx, loggerWARN, msg)
}
func Error(ctx context.Context, msg string) {
logHelper(ctx, loggerERROR, msg)
}
func Debugf(ctx context.Context, format string, a ...any) {
logHelper(ctx, loggerDEBUG, fmt.Sprintf(format, a...))
}
func Infof(ctx context.Context, format string, a ...any) {
logHelper(ctx, loggerINFO, fmt.Sprintf(format, a...))
}
func Warnf(ctx context.Context, format string, a ...any) {
logHelper(ctx, loggerWARN, fmt.Sprintf(format, a...))
}
func Errorf(ctx context.Context, format string, a ...any) {
logHelper(ctx, loggerERROR, fmt.Sprintf(format, a...))
}
func FatalLog(s string) {
logHelper(nil, loggerFATAL, s)
}
func FatalLogf(format string, a ...any) {
logHelper(nil, loggerFATAL, fmt.Sprintf(format, a...))
}
func logHelper(ctx context.Context, level loggerLevel, msg string) {
// Check if this log level should be output
if !shouldLog(level) {
return
}
writer := gin.DefaultErrorWriter
if level == loggerINFO {
writer = gin.DefaultWriter
}
var requestId string
if ctx != nil {
rawRequestId := helper.GetRequestID(ctx)
if rawRequestId != "" {
requestId = fmt.Sprintf(" | %s", rawRequestId)
}
}
lineInfo, funcName := getLineInfo()
now := time.Now()
_, _ = fmt.Fprintf(writer, "[%s] %v%s%s %s%s \n", level, now.Format("2006/01/02 - 15:04:05"), requestId, lineInfo, funcName, msg)
SetupLogger()
if level == loggerFATAL {
os.Exit(1)
}
}
func getLineInfo() (string, string) {
funcName := "[unknown] "
pc, file, line, ok := runtime.Caller(3)
if ok {
if fn := runtime.FuncForPC(pc); fn != nil {
parts := strings.Split(fn.Name(), ".")
funcName = "[" + parts[len(parts)-1] + "] "
}
} else {
file = "unknown"
line = 0
}
parts := strings.Split(file, "one-api/")
if len(parts) > 1 {
file = parts[1]
}
return fmt.Sprintf(" | %s:%d", file, line), funcName
}
================================================
FILE: api/common/permission.go
================================================
package common
import (
"github.com/53AI/53AIHub/model"
"github.com/gin-gonic/gin"
)
func IsAdmin(c *gin.Context) bool {
role, success := c.Get("SESSION_USER_ROLE")
if success && role != nil {
return role.(int64) >= model.RoleAdminUser
}
return false
}
================================================
FILE: api/common/redis.go
================================================
package common
import (
"context"
"errors"
"strconv"
"time"
"github.com/53AI/53AIHub/common/logger"
"github.com/53AI/53AIHub/config"
"github.com/go-redis/redis/v8"
)
var RDB redis.Cmdable
var RedisEnabled = true
var ErrRedisNotEnabled = errors.New("redis is not enabled")
// InitRedisClient
func InitRedisClient() error {
if config.REDIS_CONN == "" {
RedisEnabled = false
logger.SysLog("REDIS_CONN not set, Redis is not enabled")
return nil
}
logger.SysLog("Redis is enabled")
opt, err := redis.ParseURL(config.REDIS_CONN)
if err != nil {
logger.FatalLog("Redis connection error: " + err.Error())
}
RDB = redis.NewClient(opt)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err = RDB.Ping(ctx).Result()
if err != nil {
logger.FatalLog("Redis test failed: " + err.Error())
}
return err
}
// checkRedisEnabled checks if Redis is enabled and logs a warning if not
// Returns true if Redis is enabled, false otherwise
func checkRedisEnabled() bool {
if !RedisEnabled {
logger.SysWarn("Redis operation attempted but Redis is not enabled")
return false
}
return true
}
func IsRedisEnabled() bool {
return RedisEnabled
}
func RedisSet(key string, value string, expiration time.Duration) error {
if !checkRedisEnabled() {
return ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.Set(ctx, key, value, expiration).Err()
}
func RedisGet(key string) (string, error) {
if !checkRedisEnabled() {
return "", ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.Get(ctx, key).Result()
}
func RedisDel(key string) error {
if !checkRedisEnabled() {
return ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.Del(ctx, key).Err()
}
func RedisDecrease(key string, value int64) error {
if !checkRedisEnabled() {
return ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.DecrBy(ctx, key, value).Err()
}
// RedisZAdd adds a member to a sorted set
// key: the key of the sorted set
// score: the score used for ordering
// member: the member to be added
// Returns the number of new members added and any error that occurred
func RedisZAdd(key string, score int64, member string) (int64, error) {
if !checkRedisEnabled() {
return 0, ErrRedisNotEnabled
}
ctx := context.Background()
z := redis.Z{
Score: float64(score),
Member: member,
}
return RDB.ZAdd(ctx, key, &z).Result()
}
// RedisZRangeByScore gets elements within a score range from a sorted set
// key: the key of the sorted set
// min: minimum score
// max: maximum score
// Returns all members in the specified range and any error that occurred
func RedisZRangeByScore(key string, min, max int64) ([]string, error) {
if !checkRedisEnabled() {
return nil, ErrRedisNotEnabled
}
ctx := context.Background()
opt := &redis.ZRangeBy{
Min: strconv.FormatInt(min, 10),
Max: strconv.FormatInt(max, 10),
}
return RDB.ZRangeByScore(ctx, key, opt).Result()
}
// RedisZRem removes a member from a sorted set
// key: the key of the sorted set
// member: the member to be removed
// Returns the number of members removed and any error that occurred
func RedisZRem(key string, member string) (int64, error) {
if !checkRedisEnabled() {
return 0, ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.ZRem(ctx, key, member).Result()
}
// RedisZRemRangeByScore removes all elements within a score range from a sorted set
// key: the key of the sorted set
// min: minimum score
// max: maximum score
// Returns the number of members removed and any error that occurred
func RedisZRemRangeByScore(key string, min, max int64) (int64, error) {
if !checkRedisEnabled() {
return 0, ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.ZRemRangeByScore(ctx, key, strconv.FormatInt(min, 10), strconv.FormatInt(max, 10)).Result()
}
// RedisZCount counts the number of elements within a score range in a sorted set
// key: the key of the sorted set
// min: minimum score
// max: maximum score
// Returns the count of members in the specified range and any error that occurred
func RedisZCount(key string, min, max int64) (int64, error) {
if !checkRedisEnabled() {
return 0, ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.ZCount(ctx, key, strconv.FormatInt(min, 10), strconv.FormatInt(max, 10)).Result()
}
// RedisExists checks if a key exists
// key: the key to check
// Returns the number of existing keys and any error that occurred
func RedisExists(key string) (int64, error) {
if !checkRedisEnabled() {
return 0, ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.Exists(ctx, key).Result()
}
// RedisExpire sets an expiration time for a key
// key: the key to set expiration for
// expiration: the expiration duration
// Returns whether the expiration was set successfully and any error that occurred
func RedisExpire(key string, expiration time.Duration) (bool, error) {
if !checkRedisEnabled() {
return false, ErrRedisNotEnabled
}
ctx := context.Background()
return RDB.Expire(ctx, key, expiration).Result()
}
================================================
FILE: api/common/session/key.go
================================================
package session
const (
SESSION_USER_ID = "SESSION_USER_ID"
SESSION_USER_NICKNAME = "SESSION_USER_NICKNAME"
SESSION_USER_ROLE = "SESSION_USER_ROLE"
SESSION_USER_GROUP_ID = "SESSION_USER_GROUP_ID"
ENV_EID = "ENV_EID"
SESSION_AGENT_MODEL = "SESSION_AGENT_MODEL"
SESSION_AGENT_ID = "SESSION_AGENT_ID"
SESSION_AGENT = "SESSION_AGENT"
SESSION_CONVERSATION_ID = "SESSION_CONVERSATION_ID"
SESSION_CONVERSATION = "SESSION_CONVERSATION"
SESSION_SAAS_USER = "SESSION_SAAS_USER"
SESSION_REQUEST_PROTOCOL = "SESSION_REQUEST_PROTOCOL"
SESSION_REQUEST_DOMAIN = "SESSION_REQUEST_DOMAIN"
SESSION_ENV_VERSION = "SESSION_ENV_VERSION"
)
================================================
FILE: api/common/storage/storage.go
================================================
package storage
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"mime/multipart"
"os"
"path"
"path/filepath"
"sync"
"github.com/53AI/53AIHub/config"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
var StorageInstance Storage = NewStorage()
type Storage interface {
Save(file []byte, fileName string) error
Exists(fileName string) bool
Delete(fileName string) error
Load(fileName string) ([]byte, error)
GetBasePath() string
}
type LocalStorage struct {
BasePath string
mu sync.RWMutex
}
type AliyunOSSStorage struct {
client *oss.Client
bucket *oss.Bucket
Endpoint string
AccessKeyID string
AccessKeySecret string
BucketName string
BasePath string
}
func NewStorage() Storage {
switch config.StorageType {
case "aliyun_oss":
client, err := oss.New(config.AliyunOssEndpoint, config.AliyunOssAccessKeyID, config.AliyunOssAccessKeySecret)
if err != nil {
panic(fmt.Errorf("failed to create oss client: %w", err))
}
bucket, err := client.Bucket(config.AliyunOssBucketName)
if err != nil {
panic(fmt.Errorf("failed to get oss bucket: %w", err))
}
return &AliyunOSSStorage{
client: client,
bucket: bucket,
Endpoint: config.AliyunOssEndpoint,
AccessKeyID: config.AliyunOssAccessKeyID,
AccessKeySecret: config.AliyunOssAccessKeySecret,
BucketName: config.AliyunOssBucketName,
BasePath: config.StorageBasePath,
}
default:
return &LocalStorage{BasePath: config.StorageBasePath}
}
}
func (l *LocalStorage) Save(file []byte, fileName string) error {
l.mu.Lock()
defer l.mu.Unlock()
if err := os.MkdirAll(path.Dir(fileName), 0755); err != nil {
return fmt.Errorf("create dir error: %w", err)
}
if err := os.WriteFile(fileName, file, 0666); err != nil {
return fmt.Errorf("write file error: %w", err)
}
return nil
}
func (l *LocalStorage) Exists(fileName string) bool {
l.mu.RLock()
defer l.mu.RUnlock()
_, err := os.Stat(fileName)
return !os.IsNotExist(err)
}
func (l *LocalStorage) Delete(fileName string) error {
l.mu.Lock()
defer l.mu.Unlock()
err := os.Remove(fileName)
if err != nil {
return fmt.Errorf("remove file error: %w", err)
}
return nil
}
func (l *LocalStorage) Load(fileName string) ([]byte, error) {
l.mu.RLock()
defer l.mu.RUnlock()
data, err := os.ReadFile(fileName)
if err != nil {
return nil, fmt.Errorf("read file error: %w", err)
}
return data, nil
}
func GetFileHash(file multipart.File) (string, error) {
hash := sha256.New()
if _, err := io.Copy(hash, file); err != nil {
return "", err
}
if seeker, ok := file.(io.Seeker); ok {
if _, err := seeker.Seek(0, io.SeekStart); err != nil {
return "", fmt.Errorf("file seek error: %w", err)
}
}
hashInBytes := hash.Sum(nil)
return hex.EncodeToString(hashInBytes), nil
}
func (l *LocalStorage) GetBasePath() string {
return l.BasePath
}
func (a *AliyunOSSStorage) Save(file []byte, fileName string) error {
objectName := filepath.ToSlash(fileName)
reader := bytes.NewReader(file)
err := a.bucket.PutObject(objectName, reader)
if err != nil {
return fmt.Errorf("oss upload error: %w", err)
}
return nil
}
func (a *AliyunOSSStorage) Load(fileName string) ([]byte, error) {
objectName := filepath.ToSlash(fileName)
reader, err := a.bucket.GetObject(objectName)
if err != nil {
return nil, fmt.Errorf("oss file download error: %w", err)
}
defer reader.Close()
return io.ReadAll(reader)
}
func (a *AliyunOSSStorage) Exists(fileName string) bool {
objectName := filepath.ToSlash(fileName)
exist, err := a.bucket.IsObjectExist(objectName)
return err == nil && exist
}
func (a *AliyunOSSStorage) Delete(fileName string) error {
objectName := filepath.ToSlash(fileName)
if err := a.bucket.DeleteObject(objectName); err != nil {
return fmt.Errorf("oss file delete error: %w", err)
}
return nil
}
func (a *AliyunOSSStorage) GetBasePath() string {
return a.BasePath
}
================================================
FILE: api/common/storage/storage_test.go
================================================
package storage
import (
"os"
"path/filepath"
"testing"
)
func TestSaveFile(t *testing.T) {
// 创建 LocalStorage 实例
tempDir := "../../static/uploads"
localStorage := &LocalStorage{
BasePath: "../../static/uploads",
}
fileContent := []byte("测试文件内容")
fileName := "test.txt"
err := localStorage.Save(fileContent, fileName)
if err != nil {
t.Errorf("保存文件失败: %v", err)
}
filePath := filepath.Join(tempDir, fileName)
_, err = os.Stat(filePath)
if err != nil {
t.Errorf("文件不存在: %v", err)
}
localStorage.BasePath = "/invalid/path"
err = localStorage.Save(fileContent, fileName)
if err == nil {
t.Errorf("创建目录失败时应返回错误")
}
}
================================================
FILE: api/common/utils/ai53/api.go
================================================
package ai53
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"strings"
)
type AI53Api struct {
BaseUrl string
AuthToken string
}
type AppResponse struct {
BotID string `json:"bot_id"`
Name string `json:"name"`
Nickname string `json:"nickname"`
Description *string `json:"description"`
Logo string `json:"logo"`
OpeningStatement string `json:"opening_statement"`
SuggestedQuestions []string `json:"suggested_questions"`
UpdatedAt int64 `json:"updated_at"`
}
func (a *AI53Api) GetBaseURL() string {
url := a.BaseUrl
url = strings.TrimSuffix(url, "/")
url = strings.TrimSuffix(url, "/v3")
return url
}
func (a *AI53Api) GetApps(offset, limit int) ([]AppResponse, error) {
url := a.GetBaseURL() + "/v3/apps"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("offset", strconv.Itoa(offset))
q.Add("limit", strconv.Itoa(limit))
req.URL.RawQuery = q.Encode()
req.Header.Set("Authorization", "Bearer "+a.AuthToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("API request failed with status %d", resp.StatusCode)
}
body, _ := io.ReadAll(resp.Body)
// logger.SysLogf("AI53 GetApps response: %s", string(body))
var result []AppResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return result, nil
}
func (a *AI53Api) GetWorkflows(offset, limit int) ([]AppResponse, error) {
url := a.GetBaseURL() + "/v3/workflows"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("offset", strconv.Itoa(offset))
q.Add("limit", strconv.Itoa(limit))
req.URL.RawQuery = q.Encode()
req.Header.Set("Authorization", "Bearer "+a.AuthToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("API request failed with status %d", resp.StatusCode)
}
body, _ := io.ReadAll(resp.Body)
// logger.SysLogf("AI53 GetWorkflows response: %s", string(body))
var result []AppResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return result, nil
}
// cleanBotId 清理 botId,去掉可能的前缀
func (a *AI53Api) cleanBotId(botId string) string {
// 去掉 "bot-" 前缀
if strings.HasPrefix(botId, "bot-") {
return strings.TrimPrefix(botId, "bot-")
}
// 去掉 "workflow-" 前缀
if strings.HasPrefix(botId, "workflow-") {
return strings.TrimPrefix(botId, "workflow-")
}
// 直接返回原始 botId
return botId
}
// GetAppParameters 获取 53AI 应用参数配置
func (a *AI53Api) GetAppParameters(botId string) (interface{}, error) {
// 清理 botId (去掉可能的前缀)
cleanBotId := a.cleanBotId(botId)
// 构建 URL (使用 53AI 的 v3 端点)
url := a.GetBaseURL() + "/v3/parameters"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+a.AuthToken)
req.Header.Set("Bot-Id", cleanBotId)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("API request failed with status %d", resp.StatusCode)
}
body, _ := io.ReadAll(resp.Body)
var result interface{}
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return result, nil
}
================================================
FILE: api/common/utils/appbuilder/api.go
================================================
package appbuilder
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"github.com/53AI/53AIHub/common/logger"
)
type AppBuilderApi struct {
BaseUrl string
AuthToken string
}
// AppInfo represents application information
// @Description Application information structure
type AppInfo struct {
// ID is the unique identifier of the application
// @Example "app_1234567890"
ID string `json:"id"`
// Name is the display name of the application
// @Example "My Awesome App"
Name string `json:"name"`
// Description provides details about the application
// @Example "This is a sample application for demonstration purposes"
Description string `json:"description"`
// AppType indicates the type of the application
// @Example "chatbot"
AppType string `json:"appType"`
// IsPublished shows whether the application is published
// @Example true
IsPublished bool `json:"isPublished"`
// UpdateTime is the last update timestamp in Unix time format
// @Example 1672531200
UpdateTime int64 `json:"updateTime"`
}
type DescribeAppsResponse struct {
RequestId string `json:"requestId"`
Data []AppInfo `json:"data"`
Marker string `json:"marker"`
IsTruncated bool `json:"isTruncated"`
NextMarker string `json:"nextMarker"`
MaxKeys int `json:"maxKeys"`
}
func (a *AppBuilderApi) DescribeApps(marker string, maxKeys int) (*DescribeAppsResponse, error) {
url := a.BaseUrl + "/v2/app?Action=DescribeApps"
var payload interface{}
if marker == "" {
payload = map[string]interface{}{
"maxKeys": maxKeys,
}
} else {
payload = map[string]interface{}{
"marker": marker,
"maxKeys": maxKeys,
}
}
headers := map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer " + a.AuthToken,
}
resp, err := a.doRequest("POST", url, payload, headers)
if err != nil {
return nil, err
}
payloadBytes, _ := json.Marshal(payload)
logger.SysLogf("AppBuilder DescribeApps request: URL: %s, Payload: %s", url, string(payloadBytes))
logger.SysLogf("AppBuilder DescribeApps response: Body: %s", string(resp))
var result DescribeAppsResponse
err = json.Unmarshal(resp, &result)
if err != nil {
return nil, err
}
return &result, nil
}
type ConversationResponse struct {
RequestId string `json:"request_id"`
ConversationId string `json:"conversation_id"`
}
type ErrorResponse struct {
RequestId string `json:"request_id"`
Code string `json:"code"`
Message string `json:"message"`
}
func (a *AppBuilderApi) CreateConversation(appId string) (*ConversationResponse, error) {
url := a.BaseUrl + "/v2/app/conversation"
payload := map[string]interface{}{
"app_id": appId,
}
headers := map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer " + a.AuthToken,
}
resp, err := a.doRequest("POST", url, payload, headers)
if err != nil {
return nil, err
}
payloadBytes, _ := json.Marshal(payload)
logger.SysLogf("AppBuilder CreateConversation request: URL: %s, Payload: %s", url, string(payloadBytes))
logger.SysLogf("AppBuilder CreateConversation response: Body: %s", string(resp))
if strings.Contains(string(resp), "code") {
var errorResp ErrorResponse
err = json.Unmarshal(resp, &errorResp)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("API error: %s (%s)", errorResp.Message, errorResp.Code)
}
var result ConversationResponse
err = json.Unmarshal(resp, &result)
if err != nil {
return nil, err
}
return &result, nil
}
func (a *AppBuilderApi) doRequest(method, url string, payload interface{}, headers map[string]string) ([]byte, error) {
payloadBytes, err := json.Marshal(payload)
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, url, bytes.NewBuffer(payloadBytes))
if err != nil {
return nil, err
}
for key, value := range headers {
req.Header.Set(key, value)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, string(body))
}
return body, nil
}
================================================
FILE: api/common/utils/coze/api.go
================================================
package coze
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/53AI/53AIHub/model"
)
type CozeApi struct {
BaseUrl string
}
const (
CozeCnUrl = "https://api.coze.cn"
CozeComUrl = "https://api.coze.com"
)
type CozeApiTokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int64 `json:"expires_in"`
}
func (c *CozeApi) doRequest(method, url string, payload interface{}, headers map[string]string) ([]byte, error) {
payloadBytes, err := json.Marshal(payload)
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, url, bytes.NewBuffer(payloadBytes))
if err != nil {
return nil, err
}
for key, value := range headers {
req.Header.Set(key, value)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, string(body))
}
return body, nil
}
func (c *CozeApi) GetOAuthToken(clientID, clientSecret, code, redirectURI string) (*CozeApiTokenResponse, error) {
url := c.BaseUrl + "/api/permission/oauth2/token"
payload := map[string]string{
"grant_type": "authorization_code",
"code": code,
"client_id": clientID,
"redirect_uri": redirectURI,
}
headers := map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer " + clientSecret,
}
resp, err := c.doRequest("POST", url, payload, headers)
if err != nil {
return nil, err
}
var result CozeApiTokenResponse
err = json.Unmarshal(resp, &result)
if err != nil {
return nil, err
}
if result.AccessToken == "" || result.RefreshToken == "" || result.ExpiresIn == 0 {
return nil, fmt.Errorf("invalid token response: %s", string(resp))
}
return &result, nil
}
func (c *CozeApi) RefreshOAuthToken(clientID, clientSecret, refreshToken string) (*CozeApiTokenResponse, error) {
url := c.BaseUrl + "/api/permission/oauth2/token"
payload := map[string]string{
"grant_type": "refresh_token",
"refresh_token": refreshToken,
"client_id": clientID,
}
headers := map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer " + clientSecret,
}
resp, err := c.doRequest("POST", url, payload, headers)
if err != nil {
return nil, err
}
var result CozeApiTokenResponse
err = json.Unmarshal(resp, &result)
if err != nil {
return nil, err
}
if result.AccessToken == "" || result.RefreshToken == "" || result.ExpiresIn == 0 {
return nil, fmt.Errorf("invalid token response: %s", string(resp))
}
return &result, nil
}
type Workspace struct {
ID string `json:"id"`
Name string `json:"name"`
IconURL string `json:"icon_url"`
RoleType string `json:"role_type"`
WorkspaceType string `json:"workspace_type"`
}
type WorkspacesResponse struct {
TotalCount int `json:"total_count"`
Workspaces []Workspace `json:"workspaces"`
}
type Bot struct {
BotID string `json:"bot_id"`
BotName string `json:"bot_name"`
Description string `json:"description"`
IconURL string `json:"icon_url"`
PublishTime string `json:"publish_time"`
}
type PublishedBotsResponse struct {
SpaceBots []Bot `json:"space_bots"`
Total int `json:"total"`
}
// IsTokenExpired checks if token is expired (with 5 minutes buffer time)
func IsTokenExpired(provider *model.Provider) bool {
return time.Now().Unix()+300 >= provider.CreatedTime+provider.ExpiresIn
}
// RefreshTokenIfNeeded refreshes token if it's about to expire
func (c *CozeApi) RefreshTokenIfNeeded(provider *model.Provider) error {
if !IsTokenExpired(provider) {
return nil
}
var config model.CozeConfig
if err := json.Unmarshal([]byte(provider.Configs), &config); err != nil {
return fmt.Errorf("failed to parse provider config: %w", err)
}
resp, err := c.RefreshOAuthToken(config.ClientID, config.ClientSecret, provider.RefreshToken)
if err != nil {
// If refresh token expired, mark provider as unauthorized
if strings.Contains(err.Error(), "invalid_grant") || strings.Contains(err.Error(), "invalid_refresh_token") {
provider.IsAuthorized = false
if updateErr := model.UpdateProvider(provider); updateErr != nil {
return fmt.Errorf("failed to update provider authorization status: %w", updateErr)
}
return fmt.Errorf("refresh token expired, reauthorization required: %w", err)
}
return fmt.Errorf("failed to refresh token: %w", err)
}
provider.AccessToken = resp.AccessToken
provider.RefreshToken = resp.RefreshToken
provider.ExpiresIn = resp.ExpiresIn
provider.CreatedTime = time.Now().Unix()
return model.UpdateProvider(provider)
}
// GetWorkspaces retrieves list of workspaces
func (c *CozeApi) GetWorkspaces(provider *model.Provider, pageNum int, pageSize int) (*WorkspacesResponse, error) {
if err := c.RefreshTokenIfNeeded(provider); err != nil {
return nil, err
}
url := c.BaseUrl + "/v1/workspaces"
query := fmt.Sprintf("?page_num=%d&page_size=%d", pageNum, pageSize)
url = url + query
// Log request details
fmt.Printf("GetWorkspaces: Provider ID %d, URL: %s\n", provider.ProviderID, url)
fmt.Printf("GetWorkspaces: AccessToken: %s...\n", provider.AccessToken[:min(len(provider.AccessToken), 20)])
headers := map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer " + provider.AccessToken,
}
resp, err := c.doRequest("GET", url, nil, headers)
if err != nil {
fmt.Printf("GetWorkspaces: Request failed for provider %d: %v\n", provider.ProviderID, err)
return nil, err
}
fmt.Printf("GetWorkspaces: Raw response for provider %d: %s\n", provider.ProviderID, string(resp))
var result struct {
Data WorkspacesResponse `json:"data"`
Code int `json:"code"`
Msg string `json:"msg"`
}
if err := json.Unmarshal(resp, &result); err != nil {
return nil, err
}
if result.Code != 0 {
return nil, fmt.Errorf("request failed with code %d: %s", result.Code, result.Msg)
}
fmt.Printf("GetWorkspaces: Found %d workspaces for provider %d\n", len(result.Data.Workspaces), provider.ProviderID)
return &result.Data, nil
}
// GetPublishedBots retrieves list of published bots
func (c *CozeApi) GetPublishedBots(provider *model.Provider, spaceID string, pageIndex int, pageSize int) (*PublishedBotsResponse, error) {
if err := c.RefreshTokenIfNeeded(provider); err != nil {
return nil, err
}
url := c.BaseUrl + "/v1/space/published_bots_list"
query := fmt.Sprintf("?space_id=%s&page_size=%d&page_index=%d", spaceID, pageSize, pageIndex)
url = url + query
headers := map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer " + provider.AccessToken,
}
resp, err := c.doRequest("GET", url, nil, headers)
if err != nil {
return nil, err
}
var result struct {
Data PublishedBotsResponse `json:"data"`
Code int `json:"code"`
Msg string `json:"msg"`
}
if err := json.Unmarshal(resp, &result); err != nil {
return nil, err
}
if result.Code != 0 {
return nil, fmt.Errorf("request failed with code %d: %s", result.Code, result.Msg)
}
return &result.Data, nil
}
================================================
FILE: api/common/utils/env/env.go
================================================
package env
import (
"os"
"strconv"
_ "github.com/joho/godotenv/autoload"
)
func Int(env string, defaultValue int) int {
if env == "" || os.Getenv(env) == "" {
return defaultValue
}
num, err := strconv.Atoi(os.Getenv(env))
if err != nil {
return defaultValue
}
return num
}
func Int64(env string, defaultValue int64) int64 {
if env == "" || os.Getenv(env) == "" {
return defaultValue
}
num, err := strconv.ParseInt(os.Getenv(env), 10, 64)
if err != nil {
return defaultValue
}
return num
}
func Float64(env string, defaultValue float64) float64 {
if env == "" || os.Getenv(env) == "" {
return defaultValue
}
num, err := strconv.ParseFloat(os.Getenv(env), 64)
if err != nil {
return defaultValue
}
return num
}
func String(env string, defaultValue string) string {
if env == "" || os.Getenv(env) == "" {
return defaultValue
}
return os.Getenv(env)
}
func Bool(env string, defaultValue bool) bool {
if env == "" || os.Getenv(env) == "" {
return defaultValue
}
return os.Getenv(env) == "true"
}
================================================
FILE: api/common/utils/helper/helper.go
================================================
package helper
import (
"context"
"crypto/md5"
"fmt"
"math/rand"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
func GetRequestID(ctx context.Context) string {
rawRequestId := ctx.Value(RequestIdKey)
if rawRequestId == nil {
return ""
}
return rawRequestId.(string)
}
const Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func RandomString(n int) string {
rand.Seed(time.Now().UnixNano())
key := make([]byte, n)
for i := 0; i < n; i++ {
key[i] = Chars[rand.Intn(len(Chars))]
}
return string(key)
}
func PasswordHash(password string, salt string) (string, error) {
// md5(password+salt)
combined := password + salt
hash := md5.Sum([]byte(combined))
return fmt.Sprintf("%x", hash), nil
}
var sizeKB = 1024
var sizeMB = sizeKB * 1024
var sizeGB = sizeMB * 1024
func Bytes2Size(num int64) string {
numStr := ""
unit := "B"
if num/int64(sizeGB) > 1 {
numStr = fmt.Sprintf("%.2f", float64(num)/float64(sizeGB))
unit = "GB"
} else if num/int64(sizeMB) > 1 {
numStr = fmt.Sprintf("%d", int(float64(num)/float64(sizeMB)))
unit = "MB"
} else if num/int64(sizeKB) > 1 {
numStr = fmt.Sprintf("%d", int(float64(num)/float64(sizeKB)))
unit = "KB"
} else {
numStr = fmt.Sprintf("%d", num)
}
return numStr + " " + unit
}
func ParseSize(sizeStr string) (int64, error) {
sizeStr = strings.TrimSpace(sizeStr)
unitIndex := strings.IndexAny(sizeStr, "kKmMgG")
if unitIndex == -1 {
return strconv.ParseInt(sizeStr, 10, 64)
}
numStr := sizeStr[:unitIndex]
num, err := strconv.ParseInt(numStr, 10, 64)
if err != nil {
return 0, err
}
unit := strings.ToUpper(sizeStr[unitIndex:])
switch unit {
case "K", "KB":
return num * 1024, nil
case "M", "MB":
return num * 1024 * 1024, nil
case "G", "GB":
return num * 1024 * 1024 * 1024, nil
default:
return 0, nil
}
}
func CalcElapsedTime(start time.Time) int64 {
return time.Now().Sub(start).Milliseconds()
}
// IsValidPhone validates if the input is a valid phone number
// Supports international phone numbers in various formats
func IsValidPhone(phone string) bool {
phone = regexp.MustCompile(`[\s\-\(\)]`).ReplaceAllString(phone, "")
if phone == "" {
return false
}
if strings.HasPrefix(phone, "+") {
numPart := phone[1:]
if regexp.MustCompile(`^\d{7,15}$`).MatchString(numPart) {
return true
}
}
if regexp.MustCompile(`^1[3-9]\d{9}$`).MatchString(phone) {
return true
}
if regexp.MustCompile(`^\d{7,15}$`).MatchString(phone) {
return true
}
return false
}
// IsValidEmail validates if the input is a valid email address
func IsValidEmail(email string) bool {
// Simple email format validation
match, _ := regexp.MatchString(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`, email)
return match
}
func HasIntersection(a, b []int64) bool {
if len(a) > len(b) {
a, b = b, a
}
set := make(map[int64]struct{}, len(a))
for _, v := range a {
set[v] = struct{}{}
}
for _, v := range b {
if _, ok := set[v]; ok {
return true
}
}
return false
}
func GetHost(u string) (string, error) {
parsed, err := url.Parse(u)
if err != nil {
return "", err
}
host := parsed.Scheme + "://" + parsed.Host
return host, nil
}
func StrInArray(str string, arr []string) bool {
for _, v := range arr {
if v == str {
return true
}
}
return false
}
================================================
FILE: api/common/utils/helper/key.go
================================================
package helper
const (
RequestIdKey = "X-Request-Id"
)
================================================
FILE: api/common/utils/helper/sso_sign.go
================================================
package helper
import (
"crypto/md5"
"fmt"
)
// BuildSSORawString 构造原始签名串:timestamp={10位}&username={规范化用户名}{secret}
func BuildSSORawString(timestamp string, normalizedUsername string, secret string) string {
return fmt.Sprintf("timestamp=%s&username=%s%s", timestamp, normalizedUsername, secret)
}
// CalcSSOSignLowerHex 计算 MD5 并返回小写十六进制字符串(UTF-8)
func CalcSSOSignLowerHex(raw string) string {
sum := md5.Sum([]byte(raw))
return fmt.Sprintf("%x", sum)
}
================================================
FILE: api/common/utils/huawei_cloud/model.go
================================================
package huawei_cloud
type HuaweicloudBaseResponse struct {
ResultCode string `json:"resultCode"`
ResultMsg string `json:"resultMsg"`
}
type HuaweicloudCallbackRequest struct {
Activity string `json:"activity"`
TestFlag string `json:"testFlag"`
}
type HuaweicloudCallbackQuery struct {
Signature string `form:"signature"`
Timestamp int64 `form:"timestamp"`
Nonce string `form:"nonce"`
}
const (
SUCCESS = "000000"
)
const (
SUCCESS_MSG = "success"
)
type CreateInstanceResponse struct {
HuaweicloudBaseResponse
InstanceId string `json:"instanceId"`
}
func GetSuccess() HuaweicloudBaseResponse {
return HuaweicloudBaseResponse{
ResultCode: SUCCESS,
ResultMsg: SUCCESS_MSG,
}
}
type HuaweiCloudBody struct {
Activity string `json:"activity"`
BusinessId string `json:"businessId"`
OrderId string `json:"orderId"`
OrderLineId string `json:"orderLineId"`
InstanceId string `json:"instanceId"` // 查询实例信息时使用
TestFlag string `json:"testFlag"`
// 更新实例相关字段
Scene string `json:"scene"` // 场景:TRIAL_TO_FORMAL, RENEWAL, UNSUBSCRIBE_RENEWAL_PERIOD
ProductId string `json:"productId"` // 产品标识
ExpireTime string `json:"expireTime"` // 过期时间 yyyyMMddHHmmss
// 更新实例状态相关字段
Status string `json:"status"` // 状态:FROZEN, UNFROZEN
// 升级实例相关字段
NewProductId string `json:"newProductId"` // 新产品标识
}
// 查询实例信息响应结构
type QueryInstanceResponse struct {
HuaweicloudBaseResponse
Info []InstanceInfo `json:"info"`
}
type InstanceInfo struct {
InstanceId string `json:"instanceId"`
AppInfo AppInfo `json:"appInfo"`
}
type AppInfo struct {
FrontEndUrl string `json:"frontEndUrl"` // 前台地址
AdminUrl string `json:"adminUrl"` // 管理地址
UserName string `json:"userName"` // 管理员账号
Password string `json:"password"` // 管理员密码
Memo string `json:"memo"` // 备注
}
================================================
FILE: api/common/utils/huawei_cloud/signature.go
================================================
package huawei_cloud
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"math"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
)
type IMessageResp struct {
ResultCode string
ResultMsg string
}
const (
TIMESTAMP = "timestamp"
NONCE = "nonce"
SIGNATURE = "signature"
TIME_DIFF = 60 * time.Second
)
func VerifySignature(c *gin.Context, accessKey string) error {
// 从请求中获取时间戳
timestamp := c.Query("timestamp")
if timestamp == "" {
return errors.New("缺少时间戳")
}
// 获取请求体
body, err := c.GetRawData()
if err != nil {
return errors.New("获取请求体失败")
}
// 验证时间
if !validateReqTime(timestamp) {
return errors.New("时间戳无效")
}
// 获取随机字符串
nonce := c.Query("nonce")
if nonce == "" {
return errors.New("缺少随机字符串")
}
// 获取签名
signature := c.Query("signature")
if signature == "" {
return errors.New("缺少签名")
}
// 生成签名并验证
generatedSig := generateSignature(accessKey, body, timestamp, nonce)
if !strings.EqualFold(signature, generatedSig) {
return errors.New("签名验证失败")
}
return nil
}
func generateSignature(accessKey string, body []byte, timestamp string, nonce string) string {
// 计算请求体HMAC-SHA256哈希
bodyHash := hmacSHA256(body, accessKey)
// 构建规范请求字符串
canonicalRequest := fmt.Sprintf("%s%s%s%s",
accessKey, nonce, timestamp, strings.ToLower(hex.EncodeToString(bodyHash)))
// 计算最终签名
signature := hmacSHA256([]byte(canonicalRequest), accessKey)
return strings.ToLower(hex.EncodeToString(signature))
}
// 辅助函数:计算HMAC-SHA256
func hmacSHA256(data []byte, key string) []byte {
h := hmac.New(sha256.New, []byte(key))
h.Write(data)
return h.Sum(nil)
}
func validateReqTime(timestamp string) bool {
reqTime, err := strconv.ParseInt(timestamp, 10, 64)
if err != nil {
return false
}
// 华为云时间戳是毫秒级,转换为秒
reqTime = reqTime / 1000
currentTime := time.Now().Unix()
// 允许60秒的时间差
return math.Abs(float64(currentTime-reqTime)) <= 60
}
================================================
FILE: api/common/utils/ip.go
================================================
package utils
import (
"strings"
"github.com/gin-gonic/gin"
)
// GetClientIP 获取请求客户端真实IP
// 优先级:X-Real-Ip > X-Forwarded-For > RemoteAddr
func GetClientIP(c *gin.Context) string {
// 尝试从X-Real-Ip获取
ip := c.GetHeader("X-Real-Ip")
if ip != "" {
return ip
}
// 尝试从X-Forwarded-For获取(取第一个IP)
xForwardedFor := c.GetHeader("X-Forwarded-For")
if xForwardedFor != "" {
ips := strings.Split(xForwardedFor, ",")
if len(ips) > 0 {
ip = strings.TrimSpace(ips[0])
if ip != "" {
return ip
}
}
}
// 尝试从X-Client-Ip获取(兼容部分代理)
ip = c.GetHeader("X-Client-Ip")
if ip != "" {
return ip
}
// 最后使用RemoteAddr(可能包含端口,需要解析)
remoteAddr := c.Request.RemoteAddr
if idx := strings.LastIndex(remoteAddr, ":"); idx > 0 {
return remoteAddr[:idx]
}
return remoteAddr
}
================================================
FILE: api/common/utils/jwt/jwt.go
================================================
package jwt
import (
"time"
"github.com/53AI/53AIHub/common/utils/env"
"github.com/golang-jwt/jwt/v5"
)
var secretKey = []byte(env.String("JWT_SECRET", "secret"))
func UserGenerateJWT(userID int64, eid int64) (string, error) {
claims := jwt.MapClaims{
"user_id": userID,
"eid": eid,
"exp": time.Now().Add(168 * time.Hour).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(secretKey)
}
func UserParseJWT(tokenString string) (int64, int64, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return secretKey, nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
// 判断是否存在 eid,如果不存在则是 saas 用户 token,这里登录无效
if _, ok := claims["eid"]; !ok {
// 返回无效 token 错误
return 0, 0, jwt.ErrTokenInvalidClaims
}
return int64(claims["user_id"].(float64)),
int64(claims["eid"].(float64)), nil
}
return 0, 0, err
}
================================================
FILE: api/common/utils/random.go
================================================
package utils
import (
"math/rand"
"time"
)
var randomGenerator *rand.Rand
func init() {
source := rand.NewSource(time.Now().UnixNano())
randomGenerator = rand.New(source)
}
func GetRandomInt64(n int64) int64 {
if n <= 0 {
return 0
}
return randomGenerator.Int63n(n)
}
================================================
FILE: api/common/utils/snowflake.go
================================================
package utils
import (
"strconv"
"sync"
"time"
)
// Snowflake ID generator
type Snowflake struct {
mutex sync.Mutex
timestamp int64
workerId int64
sequence int64
startEpoch int64
}
// NewSnowflake creates a new Snowflake ID generator
func NewSnowflake(workerId int64) *Snowflake {
// Use 2023-01-01 00:00:00 as start epoch
startEpoch := int64(1672531200000)
return &Snowflake{
timestamp: 0,
workerId: workerId & 0x3FF, // 10-bit worker ID
sequence: 0,
startEpoch: startEpoch,
}
}
// NextId generates the next ID
func (s *Snowflake) NextId() int64 {
s.mutex.Lock()
defer s.mutex.Unlock()
currentTimestamp := time.Now().UnixNano() / 1e6 // Timestamp in milliseconds
// If current time is less than last timestamp, system clock has moved backwards
if currentTimestamp < s.timestamp {
// Simple handling: use the last timestamp
currentTimestamp = s.timestamp
}
// If generating ID in same millisecond, increment sequence
if currentTimestamp == s.timestamp {
s.sequence = (s.sequence + 1) & 0xFFF // 12-bit sequence
// Sequence overflow in same millisecond
if s.sequence == 0 {
// Block until next millisecond
currentTimestamp = s.waitNextMillis(currentTimestamp)
}
} else {
// Reset sequence for different timestamp
s.sequence = 0
}
// Update last timestamp
s.timestamp = currentTimestamp
// Combine timestamp, worker ID and sequence to generate 64-bit ID
// timestamp bits | worker ID bits | sequence bits
return ((currentTimestamp - s.startEpoch) << 22) | (s.workerId << 12) | s.sequence
}
// waitNextMillis blocks until next millisecond
func (s *Snowflake) waitNextMillis(lastTimestamp int64) int64 {
timestamp := time.Now().UnixNano() / 1e6
for timestamp <= lastTimestamp {
timestamp = time.Now().UnixNano() / 1e6
}
return timestamp
}
// Global Snowflake generator instance
var defaultSnowflake = NewSnowflake(1) // Using worker ID = 1
// GenerateOrderId generates a unique order ID that complies with WeChat Pay requirements
// Must be 6-32 characters, can only contain numbers, letters and specific symbols
func GenerateOrderId() string {
// Generate base ID using Snowflake algorithm
snowflakeId := defaultSnowflake.NextId()
// Convert to base36 string (contains numbers and letters)
// Base36: 0-9 and a-z
baseId := strconv.FormatInt(snowflakeId, 36)
// Add prefix for better identification
prefix := "AH"
// Combine order ID
orderId := prefix + baseId
// Ensure length is between 6-32
if len(orderId) < 6 {
// Add timestamp if too short
orderId = orderId + time.Now().Format("150405")
} else if len(orderId) > 32 {
// Truncate if too long
orderId = orderId[:32]
}
return orderId
}
================================================
FILE: api/common/utils/system/machine.go
================================================
package system
import (
"bufio"
"crypto/md5"
"fmt"
"net"
"os"
"runtime"
"strings"
"github.com/53AI/53AIHub/common/logger"
)
const (
EnvFilePath = ".env"
)
// MachineInfo 机器信息结构
type MachineInfo struct {
MachineCode string `json:"machine_code"`
OS string `json:"os"`
Arch string `json:"arch"`
Hostname string `json:"hostname"`
Version string `json:"version"`
}
// GenerateMachineCode 生成唯一机器码
func GenerateMachineCode() (string, error) {
// 获取系统信息
hostname, _ := os.Hostname()
// 获取网络接口MAC地址
interfaces, err := net.Interfaces()
if err != nil {
logger.SysLogf("Failed to get network interfaces: %v", err)
return "", err
}
var macAddresses []string
for _, iface := range interfaces {
// 跳过回环接口和虚拟接口
if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 {
continue
}
mac := iface.HardwareAddr.String()
if mac != "" && mac != "00:00:00:00:00:00" {
macAddresses = append(macAddresses, mac)
}
}
// 构建唯一标识字符串
identifier := fmt.Sprintf("%s-%s-%s-%s",
hostname,
runtime.GOOS,
runtime.GOARCH,
strings.Join(macAddresses, "-"))
// 生成MD5哈希作为机器码
hash := md5.New()
hash.Write([]byte(identifier))
machineCode := fmt.Sprintf("%x", hash.Sum(nil))
logger.SysLogf("Generated machine code: %s", machineCode)
return machineCode, nil
}
// GetMachineInfo 获取完整的机器信息
func GetMachineInfo() (*MachineInfo, error) {
// 从环境变量或生成新的机器码
machineCode, err := GetOrGenerateMachineCode()
if err != nil {
return nil, err
}
hostname, _ := os.Hostname()
version := GetVersion()
return &MachineInfo{
MachineCode: machineCode,
OS: runtime.GOOS,
Arch: runtime.GOARCH,
Hostname: hostname,
Version: version,
}, nil
}
// GetOrGenerateMachineCode 获取或生成机器码
func GetOrGenerateMachineCode() (string, error) {
// 先尝试从环境变量中获取
existingCode := os.Getenv("MACHINE_CODE")
if existingCode != "" {
logger.SysLogf("Using existing machine code from environment: %s", existingCode)
return existingCode, nil
}
// 尝试从.env文件中读取
envMap, err := readEnvFile()
if err != nil {
logger.SysLogf("Failed to read .env file: %v", err)
} else {
if code, exists := envMap["MACHINE_CODE"]; exists && code != "" {
logger.SysLogf("Using existing machine code from .env file: %s", code)
return code, nil
}
}
// 生成新的机器码
machineCode, err := GenerateMachineCode()
if err != nil {
return "", err
}
// 保存到.env文件
if err := saveMachineCodeToEnv(machineCode); err != nil {
logger.SysLogf("Failed to save machine code to .env file: %v", err)
// 不返回错误,因为机器码已经生成成功
}
return machineCode, nil
}
// GetVersion 获取版本信息
func GetVersion() string {
// 尝试从版本文件读取
if content, err := os.ReadFile("bin/version.txt"); err == nil {
version := strings.TrimSpace(string(content))
if version != "" {
return version
}
}
// 尝试从环境变量读取
if version := os.Getenv("VERSION"); version != "" {
return version
}
// 默认版本
return "1.0.0"
}
// readEnvFile 读取.env文件
func readEnvFile() (map[string]string, error) {
file, err := os.Open(EnvFilePath)
if err != nil {
return nil, err
}
defer file.Close()
envMap := make(map[string]string)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
// 移除可能的引号
value = strings.Trim(value, "\"'")
envMap[key] = value
}
}
return envMap, scanner.Err()
}
// writeEnvFile 写入.env文件
func writeEnvFile(envMap map[string]string) error {
file, err := os.Create(EnvFilePath)
if err != nil {
return err
}
defer file.Close()
writer := bufio.NewWriter(file)
defer writer.Flush()
for key, value := range envMap {
_, err := writer.WriteString(fmt.Sprintf("%s=\"%s\"\n", key, value))
if err != nil {
return err
}
}
return nil
}
// saveMachineCodeToEnv 保存机器码到.env文件
func saveMachineCodeToEnv(machineCode string) error {
envMap, err := readEnvFile()
if err != nil {
// 如果文件不存在,创建新的映射
envMap = make(map[string]string)
}
// 检查是否已存在
if existingCode, exists := envMap["MACHINE_CODE"]; exists && existingCode != "" {
logger.SysLogf("MACHINE_CODE already exists in .env file: %s, skipping update", existingCode)
return nil
}
// 添加机器码
envMap["MACHINE_CODE"] = machineCode
// 写回文件
if err := writeEnvFile(envMap); err != nil {
return fmt.Errorf("failed to write .env file: %v", err)
}
logger.SysLogf("Successfully saved MACHINE_CODE=%s to %s", machineCode, EnvFilePath)
return nil
}
// AppendToEnvFile 追加内容到.env文件(如果不存在的话)
func AppendToEnvFile(key, value string) error {
envMap, err := readEnvFile()
if err != nil {
envMap = make(map[string]string)
}
// 检查是否已存在
if existingValue, exists := envMap[key]; exists && existingValue != "" {
logger.SysLogf("%s already exists in .env file: %s, skipping update", key, existingValue)
return nil
}
// 添加新值
envMap[key] = value
// 写回文件
if err := writeEnvFile(envMap); err != nil {
return fmt.Errorf("failed to write .env file: %v", err)
}
logger.SysLogf("Successfully saved %s=%s to %s", key, value, EnvFilePath)
return nil
}
================================================
FILE: api/common/utils/system/version.go
================================================
package system
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/53AI/53AIHub/common/logger"
)
const (
// VersionCheckURL 版本检查URL
VersionCheckURL = "https://update.53ai.net/checkversion/53aihub/"
)
// VersionCheckResponse 版本检查响应
type VersionCheckResponse struct {
CurrentVersion string `json:"current_version"`
LatestVersion string `json:"latest_version"`
HasUpdate bool `json:"has_update"`
UpdateURL string `json:"update_url"`
ReleaseNotes string `json:"release_notes"`
WebsiteId string `json:"websiteid"`
ServerURL string `json:"serverurl"`
Action string `json:"action"`
}
// CheckVersion 检查版本更新
func CheckVersion() (*VersionCheckResponse, error) {
logger.SysLog("Checking for version updates...")
// 获取机器信息
machineInfo, err := GetMachineInfo()
if err != nil {
logger.SysLogf("Failed to get machine info: %v", err)
return nil, fmt.Errorf("获取机器信息失败: %v", err)
}
// 准备请求数据
requestData := map[string]interface{}{
"machine_code": machineInfo.MachineCode,
"version": machineInfo.Version,
"os": machineInfo.OS,
"arch": machineInfo.Arch,
"hostname": machineInfo.Hostname,
"timestamp": time.Now().Unix(),
"action": "install",
}
// 序列化请求数据
jsonData, err := json.Marshal(requestData)
if err != nil {
logger.SysLogf("Failed to marshal request data: %v", err)
return nil, fmt.Errorf("序列化请求数据失败: %v", err)
}
// 创建 HTTP 客户端
client := &http.Client{
Timeout: 10 * time.Second,
}
// 发送 POST 请求
resp, err := client.Post(VersionCheckURL, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
logger.SysLogf("Failed to check version: %v", err)
return nil, fmt.Errorf("无法连接到版本检查服务器: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
logger.SysLogf("Version check failed with status %d: %s", resp.StatusCode, string(body))
return nil, fmt.Errorf("版本检查失败,状态码: %d", resp.StatusCode)
}
var versionResp VersionCheckResponse
if err := json.NewDecoder(resp.Body).Decode(&versionResp); err != nil {
logger.SysLogf("Failed to parse version response: %v", err)
return nil, fmt.Errorf("解析版本响应失败: %v", err)
}
logger.SysLogf("Version check completed. Current: %s, Latest: %s, HasUpdate: %v",
versionResp.CurrentVersion, versionResp.LatestVersion, versionResp.HasUpdate)
return &versionResp, nil
}
// CheckVersionAsync 异步检查版本更新
func CheckVersionAndReturn() (*VersionCheckResponse, string, error) {
if resp, err := CheckVersion(); err != nil {
logger.SysLogf("Async version check failed: %v", err)
return resp, "", err
} else {
logger.SysLog("Async version check completed.")
if resp.HasUpdate {
logger.SysLogf("New version: %s, URL: %s", resp.LatestVersion, resp.UpdateURL)
}
if resp.ReleaseNotes != "" {
logger.SysLogf("Release Notes:\n%s", resp.ReleaseNotes)
}
if resp.Action == "install" {
logger.SysLog("开始执行站点配置流程...")
// 1. 检查 .env 文件中是否已有 WEBSITE_ID
existingID, exists, err := checkWebsiteIdExists()
if err != nil {
logger.SysErrorf("检查 WEBSITE_ID 失败: %v", err)
}
if exists {
logger.SysLogf("检测到已配置的 WEBSITE_ID: %s,跳过创建流程", existingID)
} else {
addWebsiteIdToEnv(resp.WebsiteId)
// 生成统计脚本
statisticScript := fmt.Sprintf(`<script src="%s/script.js" data-website-id="%s"></script>`, resp.ServerURL, resp.WebsiteId)
logger.SysLogf("Successfully generated and saved statistic script")
return resp, statisticScript, nil
}
}
return resp, "", nil
}
}
// checkWebsiteIdExists 检查 .env 文件中是否已有 WEBSITE_ID
func checkWebsiteIdExists() (string, bool, error) {
envMap, err := readEnvFile()
if err != nil {
return "", false, err
}
id, exists := envMap["WEBSITE_ID"]
return id, exists && id != "", nil
}
// addWebsiteIdToEnv 添加 WEBSITE_ID 到 .env 文件
func addWebsiteIdToEnv(websiteId string) error {
envMap, err := readEnvFile()
if err != nil {
return fmt.Errorf("读取 .env 文件失败: %v", err)
}
// 检查是否已存在
if existingID, exists := envMap["WEBSITE_ID"]; exists && existingID != "" {
logger.SysLogf("WEBSITE_ID 已存在: %s,跳过添加", existingID)
return nil
}
// 添加新的 WEBSITE_ID
envMap["WEBSITE_ID"] = websiteId
// 写回文件
if err := writeEnvFile(envMap); err != nil {
return fmt.Errorf("写入 .env 文件失败: %v", err)
}
logger.SysLogf("成功将 WEBSITE_ID=%s 添加到 %s", websiteId, EnvFilePath)
return nil
}
================================================
FILE: api/common/utils/wxbizjsonmsgcrypt/wxbizjsonmsgcrypt.go
================================================
package wxbizmsgcrypt
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"encoding/base64"
"encoding/binary"
"encoding/xml"
"fmt"
"math/rand"
"sort"
"strings"
)
const letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
ValidateSignatureError int = -40001
ParseXmlError int = -40002
ComputeSignatureError int = -40003
IllegalAesKey int = -40004
ValidateCorpidError int = -40005
EncryptAESError int = -40006
DecryptAESError int = -40007
IllegalBuffer int = -40008
EncodeBase64Error int = -40009
DecodeBase64Error int = -40010
GenXmlError int = -40010
ParseJsonError int = -40012
GenJsonError int = -40013
IllegalProtocolType int = -40014
)
type ProtocolType int
const (
XmlType ProtocolType = 1
)
type CryptError struct {
ErrCode int
ErrMsg string
}
func NewCryptError(err_code int, err_msg string) *CryptError {
return &CryptError{ErrCode: err_code, ErrMsg: err_msg}
}
type WXBizMsg4Recv struct {
Tousername string `xml:"ToUserName"`
Encrypt string `xml:"Encrypt"`
Agentid string `xml:"AgentID"`
}
type CDATA struct {
Value string `xml:",cdata"`
}
type WXBizMsg4Send struct {
XMLName xml.Name `xml:"xml"`
Encrypt CDATA `xml:"Encrypt"`
Signature CDATA `xml:"MsgSignature"`
Timestamp string `xml:"TimeStamp"`
Nonce CDATA `xml:"Nonce"`
}
func NewWXBizMsg4Send(encrypt, signature, timestamp, nonce string) *WXBizMsg4Send {
return &WXBizMsg4Send{Encrypt: CDATA{Value: encrypt}, Signature: CDATA{Value: signature}, Timestamp: timestamp, Nonce: CDATA{Value: nonce}}
}
type ProtocolProcessor interface {
parse(src_data []byte) (*WXBizMsg4Recv, *CryptError)
serialize(msg_send *WXBizMsg4Send) ([]byte, *CryptError)
}
type WXBizMsgCrypt struct {
token string
encoding_aeskey string
receiver_id string
protocol_processor ProtocolProcessor
}
type XmlProcessor struct {
}
func (self *XmlProcessor) parse(src_data []byte) (*WXBizMsg4Recv, *CryptError) {
var msg4_recv WXBizMsg4Recv
err := xml.Unmarshal(src_data, &msg4_recv)
if nil != err {
return nil, NewCryptError(ParseXmlError, "xml to msg fail")
}
return &msg4_recv, nil
}
func (self *XmlProcessor) serialize(msg4_send *WXBizMsg4Send) ([]byte, *CryptError) {
xml_msg, err := xml.Marshal(msg4_send)
if nil != err {
return nil, NewCryptError(GenXmlError, err.Error())
}
return xml_msg, nil
}
func NewWXBizMsgCrypt(token, encoding_aeskey, receiver_id string, protocol_type ProtocolType) *WXBizMsgCrypt {
var protocol_processor ProtocolProcessor
if protocol_type != XmlType {
panic("unsupport protocal")
} else {
protocol_processor = new(XmlProcessor)
}
return &WXBizMsgCrypt{token: token, encoding_aeskey: (encoding_aeskey + "="), receiver_id: receiver_id, protocol_processor: protocol_processor}
}
func (self *WXBizMsgCrypt) randString(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))]
}
return string(b)
}
func (self *WXBizMsgCrypt) pKCS7Padding(plaintext string, block_size int) []byte {
padding := block_size - (len(plaintext) % block_size)
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
var buffer bytes.Buffer
buffer.WriteString(plaintext)
buffer.Write(padtext)
return buffer.Bytes()
}
func (self *WXBizMsgCrypt) pKCS7Unpadding(plaintext []byte, block_size int) ([]byte, *CryptError) {
plaintext_len := len(plaintext)
if nil == plaintext || plaintext_len == 0 {
return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding error nil or zero")
}
if plaintext_len%block_size != 0 {
return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding text not a multiple of the block size")
}
padding_len := int(plaintext[plaintext_len-1])
return plaintext[:plaintext_len-padding_len], nil
}
func (self *WXBizMsgCrypt) cbcEncrypter(plaintext string) ([]byte, *CryptError) {
aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
const block_size = 32
pad_msg := self.pKCS7Padding(plaintext, block_size)
block, err := aes.NewCipher(aeskey)
if err != nil {
return nil, NewCryptError(EncryptAESError, err.Error())
}
ciphertext := make([]byte, len(pad_msg))
iv := aeskey[:aes.BlockSize]
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, pad_msg)
base64_msg := make([]byte, base64.StdEncoding.EncodedLen(len(ciphertext)))
base64.StdEncoding.Encode(base64_msg, ciphertext)
return base64_msg, nil
}
func (self *WXBizMsgCrypt) cbcDecrypter(base64_encrypt_msg string) ([]byte, *CryptError) {
aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
encrypt_msg, err := base64.StdEncoding.DecodeString(base64_encrypt_msg)
if nil != err {
return nil, NewCryptError(DecodeBase64Error, err.Error())
}
block, err := aes.NewCipher(aeskey)
if err != nil {
return nil, NewCryptError(DecryptAESError, err.Error())
}
if len(encrypt_msg) < aes.BlockSize {
return nil, NewCryptError(DecryptAESError, "encrypt_msg size is not valid")
}
iv := aeskey[:aes.BlockSize]
if len(encrypt_msg)%aes.BlockSize != 0 {
return nil, NewCryptError(DecryptAESError, "encrypt_msg not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypt_msg, encrypt_msg)
return encrypt_msg, nil
}
func (self *WXBizMsgCrypt) calSignature(timestamp, nonce, data string) string {
sort_arr := []string{self.token, timestamp, nonce, data}
sort.Strings(sort_arr)
var buffer bytes.Buffer
for _, value := range sort_arr {
buffer.WriteString(value)
}
sha := sha1.New()
sha.Write(buffer.Bytes())
signature := fmt.Sprintf("%x", sha.Sum(nil))
return string(signature)
}
func (self *WXBizMsgCrypt) ParsePlainText(plaintext []byte) ([]byte, uint32, []byte, []byte, *CryptError) {
const block_size = 32
plaintext, err := self.pKCS7Unpadding(plaintext, block_size)
if nil != err {
return nil, 0, nil, nil, err
}
text_len := uint32(len(plaintext))
if text_len < 20 {
return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 1")
}
random := plaintext[:16]
msg_len := binary.BigEndian.Uint32(plaintext[16:20])
if text_len < (20 + msg_len) {
return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 2")
}
msg := plaintext[20 : 20+msg_len]
receiver_id := plaintext[20+msg_len:]
return random, msg_len, msg, receiver_id, nil
}
func (self *WXBizMsgCrypt) VerifyURL(msg_signature, timestamp, nonce, echostr string) ([]byte, *CryptError) {
signature := self.calSignature(timestamp, nonce, echostr)
if strings.Compare(signature, msg_signature) != 0 {
return nil, NewCryptError(ValidateSignatureError, "signature not equal")
}
plaintext, err := self.cbcDecrypter(echostr)
if nil != err {
return nil, err
}
_, _, msg, receiver_id, err := self.ParsePlainText(plaintext)
if nil != err {
return nil, err
}
if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 {
fmt.Println(string(receiver_id), self.receiver_id, len(receiver_id), len(self.receiver_id))
return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil")
}
return msg, nil
}
func (self *WXBizMsgCrypt) EncryptMsg(reply_msg, timestamp, nonce string) ([]byte, *CryptError) {
rand_str := self.randString(16)
var buffer bytes.Buffer
buffer.WriteString(rand_str)
msg_len_buf := make([]byte, 4)
binary.BigEndian.PutUint32(msg_len_buf, uint32(len(reply_msg)))
buffer.Write(msg_len_buf)
buffer.WriteString(reply_msg)
buffer.WriteString(self.receiver_id)
tmp_ciphertext, err := self.cbcEncrypter(buffer.String())
if nil != err {
return nil, err
}
ciphertext := string(tmp_ciphertext)
signature := self.calSignature(timestamp, nonce, ciphertext)
msg4_send := NewWXBizMsg4Send(ciphertext, signature, timestamp, nonce)
return self.protocol_processor.serialize(msg4_send)
}
func (self *WXBizMsgCrypt) DecryptMsg(msg_signature, timestamp, nonce string, post_data []byte) ([]byte, *CryptError) {
msg4_recv, crypt_err := self.protocol_processor.parse(post_data)
if nil != crypt_err {
return nil, crypt_err
}
signature := self.calSignature(timestamp, nonce, msg4_recv.Encrypt)
if strings.Compare(signature, msg_signature) != 0 {
return nil, NewCryptError(ValidateSignatureError, "signature not equal")
}
plaintext, crypt_err := self.cbcDecrypter(msg4_recv.Encrypt)
if nil != crypt_err {
return nil, crypt_err
}
_, _, msg, receiver_id, crypt_err := self.ParsePlainText(plaintext)
if nil != crypt_err {
return nil, crypt_err
}
if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 {
return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil")
}
return msg, nil
}
================================================
FILE: api/common/validate.go
================================================
package common
import "github.com/go-playground/validator/v10"
var Validate *validator.Validate
func init() {
Validate = validator.New()
}
================================================
FILE: api/config/config.go
================================================
package config
import (
"os"
"path/filepath"
"strings"
"time"
"github.com/53AI/53AIHub/common/session"
"github.com/53AI/53AIHub/common/utils/env"
"github.com/53AI/53AIHub/common/utils/helper"
"github.com/gin-gonic/gin"
)
var Version = env.String("HUB_VERSION", "v0.1.0")
// build time make file
// go build -ldflags "-X 'config.VersionTime=$(date +%Y%m%d%H%M)'"
var VersionTime string
var Server = env.String("HUB_SERVER", "")
var LogDir = env.String("LOG_DIR", "")
var DebugEnabled = env.Bool("DEBUG", false)
var OnlyOneLogFile = env.Bool("ONLY_ONE_LOG_FILE", false)
var StartTime = time.Now().Format("2006-01-02 15:04:05")
var IS_SAAS = env.Bool("IS_SAAS", false)
var ApiHost = env.String("API_HOST", "")
var MigrateDBEnabled = env.Bool("MIGRATE_DB_ENABLED", true)
var REDIS_CONN = env.String("REDIS_CONN", "")
var MAX_UPLOAD_FILE_SIZE_STRING = env.String("MAX_UPLOAD_FILE_SIZE", "30MB")
var MAX_UPLOAD_FILE_SIZE, _ = helper.ParseSize(MAX_UPLOAD_FILE_SIZE_STRING)
var CHANNEL_RETRY_TIMES = env.Int64("CHANNEL_RETRY_TIMES", 3)
var EnforceIncludeUsage = env.Bool("ENFORCE_INCLUDE_USAGE", false)
var PreConsumedQuota int64 = 500
var WECOM_SUITE_ID = env.String("WECOM_SUITE_ID", "")
var IS_TEST_WECOM_SUITE = env.Bool("IS_TEST_WECOM_SUITE", false)
var HUAWEI_CLOUD_ACCESS_KEY = env.String("HUAWEI_CLOUD_ACCESS_KEY", "")
var DINGTALK_SUITE_ID = env.String("DINGTALK_SUITE_ID", "")
func GetApiHost() string {
if !strings.HasSuffix(ApiHost, "/") {
return ApiHost + "/"
}
return ApiHost
}
func GetEID(c *gin.Context) int64 {
eid, success := c.Get(session.ENV_EID)
if success && eid != nil {
return eid.(int64)
} else {
return env.Int64("EID", 1)
}
}
func GetUserId(c *gin.Context) int64 {
user_id, success := c.Get(session.SESSION_USER_ID)
if success && user_id != nil {
return user_id.(int64)
}
return 0
}
func GetUserNickname(c *gin.Context) string {
nickanme, success := c.Get(session.SESSION_USER_NICKNAME)
if success && nickanme != nil {
return nickanme.(string)
}
return ""
}
// GetUserGroup returns the group id of the user
func GetUserGroupID(c *gin.Context) int64 {
group_id, success := c.Get(session.SESSION_USER_GROUP_ID)
if success && group_id != nil {
return group_id.(int64)
}
return 0
}
// GetProtocol returns the request protocol from session
func GetProtocol(c *gin.Context) string {
protocol, success := c.Get(session.SESSION_REQUEST_PROTOCOL)
if success && protocol != nil {
return protocol.(string)
}
return "http"
}
// GetDomain returns the request domain from session
func GetDomain(c *gin.Context) string {
domain, success := c.Get(session.SESSION_REQUEST_DOMAIN)
if success && domain != nil {
return domain.(string)
}
return ""
}
func GetServer(c *gin.Context) string {
return Server
}
func Getwd() string {
workDir, err := os.Getwd()
if err != nil {
return ""
}
return workDir
}
func GetBinScriptPath(shName string) string {
workDir := Getwd()
base := filepath.Base(workDir)
if base == "bin" {
return filepath.Join(workDir, shName)
} else {
return filepath.Join(workDir, "bin", shName)
}
}
func GetWecomSuiteID() string {
return WECOM_SUITE_ID
}
func GetDingtalkSuiteID() string {
return DINGTALK_SUITE_ID
}
func GetUserRole(c *gin.Context) int64 {
role, success := c.Get(session.SESSION_USER_ROLE)
if success && role != nil {
return role.(int64)
}
return 0 // 默认返回 0,表示无权限或未登录
}
================================================
FILE: api/config/database.go
================================================
package config
import "github.com/53AI/53AIHub/common/utils/env"
var UsingSQLite = false
var UsingPostgreSQL = false
var UsingMySQL = false
var DebugSQLEnabled = env.Bool("DEBUG_SQL", false)
var SQLitePath = "53ai-hub.db"
var SQLiteBusyTimeout = env.Int("SQLITE_BUSY_TIMEOUT", 3000)
================================================
FILE: api/config/encryption.go
================================================
package config
import (
"os"
)
// GetEncryptionKey returns the encryption key for sensitive data
func GetEncryptionKey() string {
// In production, this should be a secure key stored in environment variables
// or a secure key management system
key := os.Getenv("53AIHub_ENCRYPTION_KEY")
if key == "" {
// Fallback to a default key (not recommended for production)
key = "default-encryption-key-32-bytes-long"
}
return key
}
================================================
FILE: api/config/storage.go
================================================
package config
import "github.com/53AI/53AIHub/common/utils/env"
var StorageType = env.String("STORAGE", "local")
var StorageBasePath = env.String("BASE_PATH", "static/uploads")
var AliyunOssAccessKeyID = env.String("ALIYUN_OSS_ACCESS_KEY_ID", "")
var AliyunOssAccessKeySecret = env.String("ALIYUN_OSS_ACCESS_KEY_SECRET", "")
var AliyunOssEndpoint = env.String("ALIYUN_OSS_ENDPOINT", "")
var AliyunOssBucketName = env.String("ALIYUN_OSS_BUCKET_NAME", "")
================================================
FILE: api/controller/agent.go
================================================
package controller
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/53AI/53AIHub/common"
"github.com/53AI/53AIHub/common/utils"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/53AI/53AIHub/service"
"github.com/gin-gonic/gin"
)
type AgentListRequest struct {
Keyword string `json:"keyword" form:"keyword" example:"Json"`
GroupId int64 `json:"group_id" form:"group_id" example:"0"`
Offset int `json:"offset" form:"offset" example:"0"`
Limit int `json:"limit" form:"limit" example:"10"`
ChannelTypes string `json:"channel_types" form:"channel_types" example:"0,1,2"`
AgentTypes string `json:"agent_types" form:"agent_types" example:"0,1,2"`
}
type AgentsResponse struct {
Count int64 `json:"count"`
Agents []*model.Agent `json:"agents"`
}
type AgentRequest struct {
Name string `json:"name" example:"OpenAI-ChatGPT"`
Logo string `json:"logo" example:"http://URL_ADDRESS.com/logo.png"`
Sort int `json:"sort" example:"0"`
Description string `json:"description" example:"A ChatGPT based agent for general conversation"`
Configs string `json:"configs" example:"{\"model\":\"gpt-3.5-turbo\",\"temperature\":0.7}"`
Prompt string `json:"prompt" example:"You are a helpful AI assistant"`
ChannelType int `json:"channel_type"`
Model string `json:"model" example:"gpt-3.5-turbo"`
GroupId int64 `json:"group_id" example:"0"`
UseCases string `json:"use_cases" example:"[]"`
Tools string `json:"tools" example:"[]"`
CustomConfig string `json:"custom_config" example:"{}"`
UserGroupIds []int64 `json:"user_group_ids"`
Enable bool `json:"enable" example:"true"`
SubscriptionGroupIds []int64 `json:"subscription_group_ids"` // 订阅分组IDs
Settings string `json:"settings" example:"{}"`
AgentType int `json:"agent_type" example:"0"` // Agent type (0=App, 1=Workflow), default is 0
}
type UpdateAgentEnableRequest struct {
Enable *bool `json:"enable" example:"true" binding:"required"` // Enable status (true=enabled, false=disabled)
}
// @Summary Create a new agent
// @Description Create agent with configurable parameters. agent_type: 0=App (default), 1=Workflow
// @Tags Agent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param Agent body AgentRequest true "Agent Data"
// @Success 200 {object} model.CommonResponse{data=model.Agent} "Success"
// @Router /api/agents [post]
func CreateAgent(c *gin.Context) {
var agentReq AgentRequest
if err := c.ShouldBindJSON(&agentReq); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
// Check if user is admin
if !common.IsAdmin(c) {
c.JSON(http.StatusForbidden, model.AuthFailed.ToResponse(nil))
return
}
agentReq.Model = model.ProcessModelNames(agentReq.Model, agentReq.ChannelType)
if agentReq.Model == "" {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(errors.New("model is required")))
return
}
params := map[string]interface{}{
"from": "agent",
}
_, err := service.IsFeatureAvailable(c, "agent", params)
if err != nil {
c.JSON(http.StatusForbidden, model.FeatureNotAvailableError.ToResponse(err))
return
}
// Start transaction
tx := model.DB.Begin()
if tx.Error != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
agent := model.Agent{
Eid: config.GetEID(c),
Name: agentReq.Name,
Logo: agentReq.Logo,
ChannelType: agentReq.ChannelType,
Sort: agentReq.Sort,
Description: agentReq.Description,
Model: agentReq.Model,
Prompt: agentReq.Prompt,
Configs: agentReq.Configs,
Tools: agentReq.Tools,
CustomConfig: agentReq.CustomConfig,
GroupID: agentReq.GroupId,
UseCases: agentReq.UseCases,
CreatedBy: config.GetUserId(c),
Enable: agentReq.Enable,
Settings: agentReq.Settings,
AgentType: agentReq.AgentType, // 添加 AgentType 字段,默认为 0
}
if err := tx.Create(&agent).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
allGroupIds := make([]int64, 0)
if len(agentReq.SubscriptionGroupIds) > 0 {
allGroupIds = append(allGroupIds, agentReq.SubscriptionGroupIds...)
}
if len(agentReq.UserGroupIds) > 0 {
allGroupIds = append(allGroupIds, agentReq.UserGroupIds...)
}
// Add permissions for user groups
if len(allGroupIds) > 0 {
for _, groupID := range allGroupIds {
permission := model.ResourcePermission{
GroupID: groupID,
ResourceID: agent.AgentID,
ResourceType: model.ResourceTypeAgent,
Permission: model.PermissionRead,
}
if err := tx.Create(&permission).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
}
}
// Commit transaction
if err := tx.Commit().Error; err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// Parse CustomConfig to get agent_type
var customConfig map[string]interface{}
if err := json.Unmarshal([]byte(agentReq.CustomConfig), &customConfig); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToErrorResponse(err))
return
}
agentType, ok := customConfig["agent_type"].(string)
if !ok {
agentType = "unknown"
}
log := model.SystemLog{
Eid: agent.Eid,
UserID: agent.CreatedBy,
Nickname: config.GetUserNickname(c),
Module: model.SystemLogModuleAgent,
Action: model.SystemLogActionCreate,
Content: fmt.Sprintf("新建智能体【】名称:【%s】;类型:%s", agent.Name, model.GetChannelDescription(agentType)),
IP: utils.GetClientIP(c),
}
model.CreateSystemLog(&log)
c.JSON(http.StatusOK, model.Success.ToResponse(agent))
}
// @Summary Get agent details
// @Description Get agent by AgentID
// @Tags Agent
// @Produce json
// @Security BearerAuth
// @Param agent_id path int true "Agent ID"
// @Success 200 {object} model.CommonResponse{data=model.Agent} "Success"
// @Router /api/agents/{agent_id} [get]
func GetAgent(c *gin.Context) {
agent_id, err := strconv.ParseInt(c.Param("agent_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
eid := config.GetEID(c)
agent, err := model.GetAgentByID(eid, agent_id)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
// Check if user is admin or has permission to access this agent
if !common.IsAdmin(c) {
hasPermission, err := model.CheckPermission(config.GetUserGroupID(c), agent_id, model.ResourceTypeAgent, model.PermissionRead)
if err != nil || !hasPermission {
c.JSON(http.StatusForbidden, model.AuthFailed.ToResponse(nil))
return
}
}
if err := agent.LoadUserGroupIds(); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(agent))
}
// @Summary Update agent
// @Description Update existing agent details. agent_type: 0=App (default), 1=Workflow
// @Tags Agent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param agent_id path int true "Agent ID"
// @Param agent body AgentRequest true "Agent data" example:{"name":"OpenAI-ChatGPT","description":"ChatGPT","configs":"{\"model\":\"gpt-3.5-turbo\",\"temperature\":0.7}","prompt":"你好","model":"gpt-3.5-turbo","group_id":0,"use_cases":"[]","tools":"[]","user_group_ids":[1,2,3],"agent_type":0}
// @Success 200 {object} model.CommonResponse{data=model.Agent} "Success"
// @Router /api/agents/{agent_id} [put]
func UpdateAgent(c *gin.Context) {
agent_id, err := strconv.ParseInt(c.Param("agent_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
eid := config.GetEID(c)
agent, err := model.GetAgentByID(eid, agent_id)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
// Check if user is admin
if !common.IsAdmin(c) {
c.JSON(http.StatusForbidden, model.AuthFailed.ToResponse(nil))
return
}
var agentReq AgentRequest
if err := c.ShouldBindJSON(&agentReq); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
agentReq.Model = model.ProcessModelNames(agentReq.Model, agentReq.ChannelType)
if agentReq.Model == "" {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(errors.New("model is required")))
return
}
// Start transaction
tx := model.DB.Begin()
if tx.Error != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
oldAgent := *agent
// Update agent fields
agent.Name = agentReq.Name
agent.Description = agentReq.Description
agent.Model = agentReq.Model
agent.Prompt = agentReq.Prompt
agent.Configs = agentReq.Configs
agent.Tools = agentReq.Tools
agent.GroupID = agentReq.GroupId
agent.UseCases = agentReq.UseCases
agent.ChannelType = agentReq.ChannelType
agent.Sort = agentReq.Sort
agent.Logo = agentReq.Logo
agent.CustomConfig = agentReq.CustomConfig
agent.Enable = agentReq.Enable
agent.Settings = agentReq.Settings
agent.AgentType = agentReq.AgentType // 添加 AgentType 字段更新
if err := tx.Save(agent).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// 获取企业信息
enterprise, err := model.GetEnterpriseByID(eid)
if err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
// 确定分组ID
var allGroupIds []int64
groupIDSet := make(map[int64]bool)
switch enterprise.Type {
case model.EnterpriseTypeIndustry:
// 取所有分组ID
if len(agentReq.SubscriptionGroupIds) > 0 {
for _, id := range agentReq.SubscriptionGroupIds {
groupIDSet[id] = true
}
}
if len(agentReq.UserGroupIds) > 0 {
for _, id := range agentReq.UserGroupIds {
groupIDSet[id] = true
}
}
case model.EnterpriseTypeIndependent:
// 只取订阅分组ID
if len(agentReq.SubscriptionGroupIds) > 0 {
for _, id := range agentReq.SubscriptionGroupIds {
groupIDSet[id] = true
}
}
case model.EnterpriseTypeEnterprise:
// 只取用户分组ID
if len(agentReq.UserGroupIds) > 0 {
for _, id := range agentReq.UserGroupIds {
groupIDSet[id] = true
}
}
}
// 转换为切片
allGroupIds = make([]int64, 0, len(groupIDSet))
for id := range groupIDSet {
allGroupIds = append(allGroupIds, id)
}
// 使用通用方法更新资源权限(带过滤)
if err := service.UpdateAgentResourcePermissions(c, tx, agent.AgentID, agentReq.SubscriptionGroupIds, agentReq.UserGroupIds, enterprise); err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// Commit transaction
if err := tx.Commit().Error; err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// Prepare for logging
fieldMap := map[string]string{
"Name": "名称",
"Description": "描述",
}
model.LogEntityChange(
fmt.Sprintf("智能体【%s】", oldAgent.Name),
model.SystemLogActionUpdate,
eid,
config.GetUserId(c),
config.GetUserNickname(c),
model.SystemLogModuleAgent,
oldAgent,
agent,
utils.GetClientIP(c),
fieldMap,
)
if err := agent.LoadUserGroupIds(); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(agent))
}
// @Summary Delete agent
// @Description Delete agent by ID
// @Tags Agent
// @Produce json
// @Security BearerAuth
// @Param agent_id path int true "Agent ID"
// @Success 200 {object} model.CommonResponse "Success"
// @Router /api/agents/{agent_id} [delete]
func DeleteAgent(c *gin.Context) {
agent_id, err := strconv.ParseInt(c.Param("agent_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
eid := config.GetEID(c)
agent, err := model.GetAgentByID(eid, agent_id)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
// Check if user is admin
if !common.IsAdmin(c) {
c.JSON(http.StatusForbidden, model.AuthFailed.ToResponse(nil))
return
}
// Start transaction
tx := model.DB.Begin()
if tx.Error != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// Delete agent
if err := tx.Delete(agent).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// Delete associated permissions
if err := tx.Where("resource_id = ? AND resource_type = ?", agent_id, model.ResourceTypeAgent).Delete(&model.ResourcePermission{}).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// Commit transaction
if err := tx.Commit().Error; err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
log := model.SystemLog{
Eid: agent.Eid,
UserID: agent.CreatedBy,
Nickname: config.GetUserNickname(c),
Module: model.SystemLogModuleAgent,
Action: model.SystemLogActionDelete,
Content: fmt.Sprintf("删除智能体【%s】", agent.Name),
IP: utils.GetClientIP(c),
}
model.CreateSystemLog(&log)
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
// @Summary Get agents list
// @Description Retrieve paginated list of agents
// @Tags Agent
// @Produce json
// @Security BearerAuth
// @Param keyword query string false "Keyword"
// @Param group_id query int false "Group ID"
// @Param offset query int false "Offset"
// @Param limit query int false "Limit" default(10)
// @Param channel_types query string false "Channel types , split by comma"
// @Param agent_types query string false "Agent types , split by comma"
// @Success 200 {object} model.CommonResponse{data=AgentsResponse} "Success"
// @Router /api/agents [get]
func GetAgents(c *gin.Context) {
var agentListRequest AgentListRequest
if err := c.ShouldBindQuery(&agentListRequest); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
// Set default limit to 10 if not specified
if agentListRequest.Limit == 0 {
agentListRequest.Limit = 10
}
// If user is not admin, get only agents they have permission to access
var total int64
var agents []*model.Agent
var err error
channelTypes := splitChannelTypesString(agentListRequest.ChannelTypes)
agentTypes := splitAgentTypesString(agentListRequest.AgentTypes)
if common.IsAdmin(c) {
total, agents, err = model.GetAgentListWithIDs(
config.GetEID(c), agentListRequest.Keyword, agentListRequest.GroupId,
nil, channelTypes, agentTypes, agentListRequest.Offset, agentListRequest.Limit)
} else {
// Get list of agent IDs the user has permission to access
permittedAgentIDs, getErr := model.GetResourcesByGroupAndType(config.GetUserGroupID(c), model.ResourceTypeAgent)
if getErr != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
total, agents, err = model.GetAgentListWithIDs(
config.GetEID(c), agentListRequest.Keyword, agentListRequest.GroupId,
permittedAgentIDs, channelTypes, agentTypes,
agentListRequest.Offset, agentListRequest.Limit)
}
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
for _, agent := range agents {
if err := agent.LoadUserGroupIds(); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
}
c.JSON(http.StatusOK, model.Success.ToResponse(AgentsResponse{
Count: total,
Agents: agents,
}))
}
// @Summary Get agents by group
// @Description Retrieve paginated list of agents by specified group
// @Tags Agent
// @Produce json
// @Security BearerAuth
// @Param keyword query string false "Search keyword"
// @Param group_id query int false "Target group ID"
// @Param offset query int false "Pagination offset" default(0)
// @Param limit query int false "Pagination limit" default(10)
// @Param channel_types query string false "Channel types , split by comma"
// @Param agent_types query string false "Agent types , split by comma"
// @Success 200 {object} model.CommonResponse{data=AgentsResponse} "Success response with agent list"
// @Router /api/agents/group [get]
func GetAgentsByGroup(c *gin.Context) {
var agentListRequest AgentListRequest
if err := c.ShouldBindQuery(&agentListRequest); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
// Set default limit to 10 if not specified
if agentListRequest.Limit == 0 {
agentListRequest.Limit = 10
}
channelTypes := splitChannelTypesString(agentListRequest.ChannelTypes)
agentTypes := splitAgentTypesString(agentListRequest.AgentTypes)
var total, agents, err = model.GetAgentListWithIDs(
config.GetEID(c), agentListRequest.Keyword, agentListRequest.GroupId,
nil, channelTypes, agentTypes, agentListRequest.Offset, agentListRequest.Limit)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
for _, agent := range agents {
if err := agent.LoadUserGroupIds(); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
}
c.JSON(http.StatusOK, model.Success.ToResponse(AgentsResponse{
Count: total,
Agents: agents,
}))
}
// @Summary Get available agents
// @Description Retrieve paginated list of available agents
// @Tags Agent
// @Produce json
// @Param offset query int false "Pagination offset" default(0)
// @Param limit query int false "Pagination limit" default(10)
// @Param agent_types query string false "Agent types , split by comma"
// @Success 200 {object} model.CommonResponse{data=AgentsResponse} "Success response with available agent list"
// @Router /api/agents/available [get]
func GetAvailableAgents(c *gin.Context) {
var agentListRequest AgentListRequest
if err := c.ShouldBindQuery(&agentListRequest); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
if agentListRequest.Limit == 0 {
agentListRequest.Limit = 10
}
agentTypes := splitAgentTypesString(agentListRequest.AgentTypes)
var total, agents, err = model.GetAvailableAgentList(
config.GetEID(c),
agentTypes,
agentListRequest.Offset,
agentListRequest.Limit,
)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
for _, agent := range agents {
if err = agent.LoadUserGroupIds(); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
if err = agent.LoadConversationCount(); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
}
c.JSON(http.StatusOK, model.Success.ToResponse(AgentsResponse{
Count: total,
Agents: agents,
}))
}
// Get Current Agents
// @Summary Get current agent list
// @Description Get agents list under the first agent-type group of current enterprise (no pagination required)
// @Tags Agent
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.CommonResponse{data=AgentsResponse} "Success response containing agent list"
// @Router /api/agents/current [get]
func GetCurrentAgents(c *gin.Context) {
eid := config.GetEID(c)
authHeader := c.GetHeader("Authorization")
authHeader = strings.Replace(authHeader, "Bearer ", "", 1)
var theGroup *model.Group
var err error
if authHeader == "" {
group, err := model.GetFirstGroupByEid(eid, model.USER_GROUP_TYPE)
if err != nil {
c.JSON(http.StatusNotFound, model.DBError.ToResponse(err))
return
}
theGroup = &group
} else {
user := model.ValidateAccessToken(authHeader)
if user == nil {
c.JSON(http.StatusUnauthorized, model.UnauthorizedError.ToResponse(nil))
return
}
if user.GroupId > 0 {
theGroup, err = model.GetGroupByID(user.GroupId)
if err != nil {
c.JSON(http.StatusNotFound, model.DBError.ToResponse(err))
return
}
}
}
group, err := model.GetGroupWithAgents(theGroup.GroupId, true)
if err != nil {
c.JSON(http.StatusNotFound, model.DBError.ToResponse(err))
return
}
for i := range group.Agents {
var count int64
model.DB.Model(&model.Conversation{}).
Where("eid = ? AND agent_id = ?", eid, group.Agents[i].AgentID).
Count(&count)
group.Agents[i].ConversationCount = count
}
c.JSON(http.StatusOK, model.Success.ToResponse(AgentsResponse{
Count: int64(len(group.Agents)),
Agents: group.Agents,
}))
}
// @Summary Update agent status
// @Description Update agent enable/disable status
// @Tags Agent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param agent_id path int true "Agent ID"
// @Param request body UpdateAgentEnableRequest true "Enable status"
// @Success 200 {object} model.CommonResponse "Success"
// @Router /api/agents/{agent_id}/status [patch]
func UpdateAgentStatus(c *gin.Context) {
agentID, err := strconv.ParseInt(c.Param("agent_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
var updateAgentEnableReq UpdateAgentEnableRequest
if err = c.ShouldBindJSON(&updateAgentEnableReq); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
eid := config.GetEID(c)
_, err = model.GetAgentByID(eid, agentID)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
err = model.UpdateAgentStatus(eid, agentID, updateAgentEnableReq.Enable)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
agent, err := model.GetAgentByID(eid, agentID)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
statusText := "启用"
if !agent.Enable {
statusText = "禁用"
}
log := model.SystemLog{
Eid: eid,
UserID: config.GetUserId(c),
Nickname: config.GetUserNickname(c),
Module: model.SystemLogModuleAgent,
Action: model.SystemLogActionToggle,
Content: fmt.Sprintf("%s智能体【%s】", statusText, agent.Name),
IP: utils.GetClientIP(c),
}
model.CreateSystemLog(&log)
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
func splitChannelTypesString(channelTypesStr string) []int {
var channelTypes []int
if channelTypesStr != "" {
strSlice := strings.Split(channelTypesStr, ",")
for _, s := range strSlice {
if i, err := strconv.Atoi(strings.TrimSpace(s)); err == nil {
channelTypes = append(channelTypes, i)
}
}
}
return channelTypes
}
func splitAgentTypesString(agentTypesStr string) []int {
var agentTypes []int
if agentTypesStr != "" {
strSlice := strings.Split(agentTypesStr, ",")
for _, s := range strSlice {
if i, err := strconv.Atoi(strings.TrimSpace(s)); err == nil {
agentTypes = append(agentTypes, i)
}
}
}
return agentTypes
}
// GetInternalUserAgents retrieves available agents for a specific internal user
// @Summary Get available agents for a specific internal user
// @Description Get all available agents for a specific internal user (including agents from user's groups and department groups, with duplicates removed)
// @Tags Agent
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.CommonResponse{data=AgentsResponse} "Success response containing agent list"
// @Router /api/agents/internal_users [get]
func GetInternalUserAgents(c *gin.Context) {
eid := config.GetEID(c)
userID := config.GetUserId(c)
user, err := model.GetUserByID(userID)
if err != nil {
c.JSON(http.StatusNotFound, model.DBError.ToResponse(err))
return
}
if user.Eid != eid || user.Type != model.UserTypeInternal {
c.JSON(http.StatusForbidden, model.AuthFailed.ToResponse("User is not an internal member of the current enterprise"))
return
}
var groupIDs []int64
groupIDs, err = model.GetGroupsByUserID(userID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
var dids []int64
dids, err = model.GetMemberDidsByBID(eid, userID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
var departmentGroupIDs []int64
if len(dids) == 0 {
dids = []int64{0}
}
for _, did := range dids {
deptGroupIDs, err := model.GetGroupsByDepartmentID(did)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
departmentGroupIDs = append(departmentGroupIDs, deptGroupIDs...)
}
if len(departmentGroupIDs) > 0 {
groupIDMap := make(map[int64]bool)
for _, id := range groupIDs {
groupIDMap[id] = true
}
for _, id := range departmentGroupIDs {
if !groupIDMap[id] {
groupIDs = append(groupIDs, id)
groupIDMap[id] = true
}
}
}
if len(groupIDs) == 0 {
c.JSON(http.StatusOK, model.Success.ToResponse(AgentsResponse{
Count: 0,
Agents: []*model.Agent{},
}))
return
}
var allAgents []*model.Agent
agentMap := make(map[int64]*model.Agent)
for _, groupID := range groupIDs {
group, err := model.GetGroupWithAgents(groupID, true)
if err != nil {
continue
}
for i := range group.Agents {
if group.Agents[i].Enable {
agentMap[group.Agents[i].AgentID] = group.Agents[i]
}
}
}
for _, agent := range agentMap {
var count int64
model.DB.Model(&model.Conversation{}).
Where("eid = ? AND agent_id = ?", eid, agent.AgentID).
Count(&count)
agent.ConversationCount = count
allAgents = append(allAgents, agent)
}
c.JSON(http.StatusOK, model.Success.ToResponse(AgentsResponse{
Count: int64(len(allAgents)),
Agents: allAgents,
}))
}
================================================
FILE: api/controller/ai53.go
================================================
package controller
import (
"net/http"
"strconv"
"strings"
"github.com/53AI/53AIHub/common/logger"
"github.com/53AI/53AIHub/common/utils/ai53"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/53AI/53AIHub/service"
"github.com/gin-gonic/gin"
)
// Get53AIAllBots Get all 53AI bots
// @Summary Get all 53AI bots list
// @Description Get all bots list from 53AI platform
// @Tags 53AI
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param provider_id query int false "Provider ID (optional, for backward compatibility)"
// @Success 200 {object} model.CommonResponse{data=[]ai53.AppResponse}
// @Router /api/53ai/bots [get]
func Get53AIAllBots(c *gin.Context) {
eid := config.GetEID(c)
providerID, _ := strconv.ParseInt(c.DefaultQuery("provider_id", "0"), 10, 64)
provider, err := model.GetProviderByEidAndProviderTypeWithOptionalID(eid, int64(model.ProviderType53AI), providerID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
ser := service.AI53Service{
Provider: &provider,
}
bots, err := ser.GetAllBots()
if err != nil {
logger.SysLogf("Get53AIAllBots: %s", err.Error())
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
Update53AIChannel(provider, bots)
c.JSON(http.StatusOK, model.Success.ToResponse(bots))
}
// Get53AIAllWorkflows Get all 53AI workflows
// @Summary Get all 53AI workflows list
// @Description Get all workflows list from 53AI platform
// @Tags 53AI
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param provider_id query int false "Provider ID (optional, for backward compatibility)"
// @Success 200 {object} model.CommonResponse{data=[]ai53.AppResponse}
// @Router /api/53ai/workflows [get]
func Get53AIAllWorkflows(c *gin.Context) {
eid := config.GetEID(c)
providerID, _ := strconv.ParseInt(c.DefaultQuery("provider_id", "0"), 10, 64)
provider, err := model.GetProviderByEidAndProviderTypeWithOptionalID(eid, int64(model.ProviderType53AI), providerID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
ser := service.AI53Service{
Provider: &provider,
}
workflows, err := ser.GetAllWorkflows()
if err != nil {
logger.SysLogf("Get53AIAllWorkflows: %s", err.Error())
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
Update53AIWorkflowChannel(provider, workflows)
c.JSON(http.StatusOK, model.Success.ToResponse(workflows))
}
func Update53AIChannel(provider model.Provider, apps []ai53.AppResponse) error {
var botIds []string
for _, bot := range apps {
botIds = append(botIds, "bot-"+bot.BotID)
}
// todo Call interface user ID all use the same
configStr := `{"region":"","sk":"","ak":"","user_id":"53AIHub","vertex_ai_project_id":"","vertex_ai_adc":""}`
// Create or update channel record
baseURL := provider.GetBaseURLByProviderType()
channel := &model.Channel{
Eid: provider.Eid,
Name: provider.Name,
Key: provider.AccessToken,
Type: model.ChannelApi53AI,
ProviderID: provider.ProviderID,
BaseURL: &baseURL,
Status: model.ChannelStatusEnabled,
Config: configStr,
}
existingChannel, err := model.GetFirstChannelByEidAndProviderId(channel.Eid, channel.ProviderID)
if err != nil {
// Create new record with initial botIds
channel.Models = strings.Join(botIds, ",")
return model.CreateChannel(channel)
} else {
// Update existing record with incremental botIds
channel.ChannelID = existingChannel.ChannelID
channel.CreatedTime = existingChannel.CreatedTime
// Get existing botIds
existingBotIds := strings.Split(existingChannel.Models, ",")
botIdMap := make(map[string]bool)
for _, id := range existingBotIds {
if id != "" {
botIdMap[id] = true
}
}
// Add new botIds
for _, id := range botIds {
botIdMap[id] = true
}
// Convert map back to slice
var updatedBotIds []string
for id := range botIdMap {
updatedBotIds = append(updatedBotIds, id)
}
channel.Models = strings.Join(updatedBotIds, ",")
return model.UpdateChannel(channel)
}
}
func Update53AIWorkflowChannel(provider model.Provider, apps []ai53.AppResponse) error {
var workflowIds []string
for _, workflow := range apps {
workflowIds = append(workflowIds, "workflow-"+workflow.BotID)
}
// todo Call interface user ID all use the same
configStr := `{"region":"","sk":"","ak":"","user_id":"53AIHub","vertex_ai_project_id":"","vertex_ai_adc":""}`
// Create or update channel record
baseURL := provider.GetBaseURLByProviderType()
channel := &model.Channel{
Eid: provider.Eid,
Name: provider.Name,
Key: provider.AccessToken,
Type: model.ChannelApi53AI,
ProviderID: provider.ProviderID,
BaseURL: &baseURL,
Status: model.ChannelStatusEnabled,
Config: configStr,
}
existingChannel, err := model.GetFirstChannelByEidAndProviderId(channel.Eid, channel.ProviderID)
if err != nil {
// Create new record with initial workflowIds
channel.Models = strings.Join(workflowIds, ",")
return model.CreateChannel(channel)
} else {
// Update existing record with incremental workflowIds
channel.ChannelID = existingChannel.ChannelID
channel.CreatedTime = existingChannel.CreatedTime
// Get existing workflowIds
existingWorkflowIds := strings.Split(existingChannel.Models, ",")
workflowIdMap := make(map[string]bool)
for _, id := range existingWorkflowIds {
if id != "" {
workflowIdMap[id] = true
}
}
// Add new workflowIds
for _, id := range workflowIds {
workflowIdMap[id] = true
}
// Convert map back to slice
var updatedWorkflowIds []string
for id := range workflowIdMap {
updatedWorkflowIds = append(updatedWorkflowIds, id)
}
channel.Models = strings.Join(updatedWorkflowIds, ",")
return model.UpdateChannel(channel)
}
}
// Get53AIAppParameters 获取 53AI 应用参数配置
// @Summary 获取 53AI 应用参数配置
// @Description 根据 botId 获取 53AI 应用的参数配置信息,支持带前缀或不带前缀的 botId
// @Tags 53AI
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param botId path string true "机器人ID (支持 bot-xxx, workflow-xxx 或直接 xxx 格式)"
// @Param provider_id query int false "Provider ID (optional, for backward compatibility)"
// @Success 200 {object} model.CommonResponse{data=interface{}}
// @Router /api/53ai/parameters/{botId} [get]
func Get53AIAppParameters(c *gin.Context) {
// 1. 获取并处理 botId 参数
botId := c.Param("botId")
if botId == "" {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse("botId 不能为空"))
return
}
logger.SysLogf("🔍 获取53AI应用参数 - Bot ID: %s", botId)
// 2. 获取 EID (遵循 53AI 渠道模式)
eid := config.GetEID(c)
// 3. 获取 53AI Provider (遵循 53AI 渠道模式)
providerID, _ := strconv.ParseInt(c.DefaultQuery("provider_id", "0"), 10, 64)
provider, err := model.GetProviderByEidAndProviderTypeWithOptionalID(eid, int64(model.ProviderType53AI), providerID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
// 4. 创建 AI53Service 实例 (遵循 53AI 渠道模式)
ser := service.AI53Service{
Provider: &provider,
}
// 5. 调用服务方法获取应用参数
appParams, err := ser.GetAppParameters(botId)
if err != nil {
logger.SysLogf("Get53AIAppParameters: %s", err.Error())
c.JSON(http.StatusInternalServerError, model.SystemError.ToResponse(err))
return
}
logger.SysLogf("✅ 53AI应用参数获取成功 - Bot ID: %s", botId)
// 6. 返回结果
c.JSON(http.StatusOK, model.Success.ToResponse(appParams))
}
================================================
FILE: api/controller/ai_link.go
================================================
package controller
import (
"net/http"
"strconv"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/53AI/53AIHub/service"
"github.com/gin-gonic/gin"
)
type AILinkRequest struct {
GroupID int64 `json:"group_id" example:"1"`
Name string `json:"name" example:"ai_link_name"`
Logo string `json:"logo" example:"logo_url"`
URL string `json:"url" example:"ai_link_url"`
Description string `json:"description" example:"ai_link_description"`
Sort int64 `json:"sort" example:"0"`
SharedAccount string `json:"shared_account" example:"[{'account':'admin', 'password':'<PASSWORD>', 'remark':''}]"`
// 使用范围
SubscriptionGroupIds []int64 `json:"subscription_group_ids"`
UserGroupIds []int64 `json:"user_group_ids"`
}
// @Summary Create AI Link
// @Description Create new AI link entry
// @Tags AI Link
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param link body AILinkRequest true "AI Link data"
// @Success 200 {object} model.CommonResponse
// @Router /api/ai_links [post]
func CreateAILink(c *gin.Context) {
var req AILinkRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
link := model.AILink{
Eid: config.GetEID(c),
GroupID: req.GroupID,
Name: req.Name,
Logo: req.Logo,
URL: req.URL,
Description: req.Description,
Sort: req.Sort,
CreatedBy: config.GetUserId(c),
SharedAccount: req.SharedAccount,
}
if err := model.CreateAILink(&link); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
// 添加分组关联
allGroupIds := make([]int64, 0)
// 添加订阅分组
if len(req.SubscriptionGroupIds) > 0 {
allGroupIds = append(allGroupIds, req.SubscriptionGroupIds...)
}
// 添加用户分组
if len(req.UserGroupIds) > 0 {
allGroupIds = append(allGroupIds, req.UserGroupIds...)
}
// 创建资源权限
if len(allGroupIds) > 0 {
tx := model.DB.Begin()
if tx.Error != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 使用通用方法更新资源权限
if err := service.UpdateResourcePermissions(c, tx, link.ID, model.ResourceTypeAILink, allGroupIds); err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// 提交事务
if err := tx.Commit().Error; err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
}
c.JSON(http.StatusOK, model.Success.ToResponse(link))
}
// @Summary Get AI Link
// @Description Get AI link by ID
// @Tags AI Link
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "Link ID"
// @Success 200 {object} model.CommonResponse{data=model.AILink}
// @Router /api/ai_links/{id} [get]
func GetAILink(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
link, err := model.GetAILinkByID(int64(id))
if err != nil || link.Eid != config.GetEID(c) {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
err = link.LoadUserGroupIds()
if err != nil {
link.UserGroupIds = []int64{}
}
link.LoadHasSharedAccount()
c.JSON(http.StatusOK, model.Success.ToResponse(link))
}
// @Summary Update AI Link
// @Description Update existing AI link
// @Tags AI Link
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "Link ID"
// @Param link body AILinkRequest true "Update data"
// @Success 200 {object} model.CommonResponse
// @Router /api/ai_links/{id} [put]
func UpdateAILink(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
link, err := model.GetAILinkByID(int64(id))
if err != nil || link.Eid != config.GetEID(c) {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
var req AILinkRequest
if c.ShouldBindJSON(&req) != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
link.GroupID = req.GroupID
link.Name = req.Name
link.Logo = req.Logo
link.URL = req.URL
link.Description = req.Description
link.Sort = req.Sort
link.SharedAccount = req.SharedAccount
if err := model.UpdateAILink(link); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
// 更新分组关联
allGroupIds := make([]int64, 0)
// 添加订阅分组
if len(req.SubscriptionGroupIds) > 0 {
allGroupIds = append(allGroupIds, req.SubscriptionGroupIds...)
}
// 添加用户分组
if len(req.UserGroupIds) > 0 {
allGroupIds = append(allGroupIds, req.UserGroupIds...)
}
tx := model.DB.Begin()
if tx.Error != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 使用通用方法更新资源权限
if err := service.UpdateResourcePermissions(c, tx, link.ID, model.ResourceTypeAILink, allGroupIds); err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// 提交事务
if err := tx.Commit().Error; err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
err = link.LoadUserGroupIds()
if err != nil {
link.UserGroupIds = []int64{}
}
c.JSON(http.StatusOK, model.Success.ToResponse(link))
}
// @Summary Delete AI Link
// @Description Delete AI link by ID
// @Tags AI Link
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "Link ID"
// @Success 200 {object} model.CommonResponse
// @Router /api/ai_links/{id} [delete]
func DeleteAILink(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
link, err := model.GetAILinkByID(int64(id))
if err != nil || link.Eid != config.GetEID(c) {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
// 开始事务
tx := model.DB.Begin()
if tx.Error != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(tx.Error))
return
}
// 删除AI链接
if err := tx.Delete(link).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// 使用通用方法删除资源权限
if err := service.UpdateResourcePermissions(c, tx, int64(id), model.ResourceTypeAILink, []int64{}); err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(nil))
return
}
// 提交事务
if err := tx.Commit().Error; err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
// @Summary Get AI Links
// @Description Get AI links by group ID
// @Tags AI Link
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param group_id query int false "Empty for all groups or group ID"
// @Param keyword query string false "Search by name"
// @Success 200 {object} model.CommonResponse{data=[]model.AILink}
// @Router /api/ai_links [get]
func GetAILinks(c *gin.Context) {
groupID, _ := strconv.ParseInt(c.Query("group_id"), 10, 64)
keyword := c.Query("keyword")
var links []model.AILink
var err error
if groupID != 0 {
if keyword != "" {
links, err = model.GetAILinksByEidAndGroupIdWithKeyword(config.GetEID(c), groupID, keyword)
} else {
links, err = model.GetAILinksByEidAndGroupId(config.GetEID(c), groupID)
}
} else {
if keyword != "" {
links, err = model.GetAILinksGroupedBySortWithKeyword(config.GetEID(c), keyword)
} else {
links, err = model.GetAILinksGroupedBySort(config.GetEID(c))
}
}
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(links))
}
// @Summary Get current site AI links
// @Description Get all AI links for current site
// @Tags AI Link
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.CommonResponse{data=[]model.AILink}
// @Router /api/ai_links/current [get]
func GetCurrentSiteAILinks(c *gin.Context) {
eid := config.GetEID(c)
links, err := model.GetAILinksGroupedBySort(eid)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(links))
}
// @Summary 获取默认AI链接数据
// @Description 获取预定义的AI工具分组及对应链接列表(如AI搜索、智能对话等分组)
// @Tags AI Link
// @Accept json
// @Produce json
// @Success 200 {object} model.CommonResponse{data=[]model.GroupInfo} "成功返回默认AI链接数据"
// @Router /api/ai_links/default [get]
func GetDefaultAILinks(c *gin.Context) {
links := model.GetDefaultGroupData()
c.JSON(http.StatusOK, model.Success.ToResponse(links))
}
type SortItem struct {
ID int64 `json:"id" example:"1"`
Sort int64 `json:"sort" example:"5"`
GroupID int64 `json:"group_id" example:"1"`
}
type BatchSortRequest struct {
Items []SortItem `json:"items"`
}
// @Summary Batch Sort AI Links
// @Description Batch update sort order of AI links
// @Tags AI Link
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param data body BatchSortRequest true "Batch sort data"
// @Success 200 {object} model.CommonResponse
// @Router /api/ai_links/batch/sort [post]
func BatchSortAILinks(c *gin.Context) {
var req BatchSortRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
eid := config.GetEID(c)
tx := model.DB.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
for _, item := range req.Items {
link, err := model.GetAILinkByID(item.ID)
if err != nil || link.Eid != eid {
tx.Rollback()
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
link.Sort = item.Sort
link.GroupID = item.GroupID
if err := tx.Model(&link).Updates(link).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
}
if err := tx.Commit().Error; err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
================================================
FILE: api/controller/appbuilder.go
================================================
package controller
import (
"net/http"
"strconv"
"strings"
"github.com/53AI/53AIHub/common/logger"
"github.com/53AI/53AIHub/common/utils/appbuilder"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/53AI/53AIHub/service"
"github.com/gin-gonic/gin"
)
// GetAppBuilderAllBots Get all AppBuilder bots
// @Summary Get all AppBuilder bots list
// @Description Get all bots list from AppBuilder
// @Tags AppBuilder
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param provider_id query int false "Provider ID (optional, for backward compatibility)"
// @Success 200 {object} model.CommonResponse{data=[]appbuilder.AppInfo}
// @Router /api/appbuilder/bots [get]
func GetAppBuilderAllBots(c *gin.Context) {
eid := config.GetEID(c)
providerID, _ := strconv.ParseInt(c.DefaultQuery("provider_id", "0"), 10, 64)
provider, err := model.GetProviderByEidAndProviderTypeWithOptionalID(eid, int64(model.ProviderTypeAppBuilder), providerID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
ser := service.AppBuilderService{
Provider: &provider,
}
apps, err := ser.GetAllDescribeApps()
if err != nil {
logger.SysLogf("GetAppBuilderAllBots: %s", err.Error())
if len(apps) == 0 {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
}
// update or channel
UpdateAppBuilderChannel(provider, apps)
c.JSON(http.StatusOK, model.Success.ToResponse(apps))
}
func UpdateAppBuilderChannel(provider model.Provider, apps []appbuilder.AppInfo) error {
var botIds []string
for _, bot := range apps {
if !bot.IsPublished {
continue
}
botIds = append(botIds, "bot-"+bot.ID)
}
// todo Call interface user ID all use the same
configStr := `{"region":"","sk":"","ak":"","user_id":"53AIHub","vertex_ai_project_id":"","vertex_ai_adc":""}`
// Create or update channel record
baseURL := provider.GetBaseURLByProviderType()
channel := &model.Channel{
Eid: provider.Eid,
Name: provider.Name,
Key: provider.AccessToken,
Type: model.ChannelApiAppBuilder,
ProviderID: provider.ProviderID,
BaseURL: &baseURL, // Fix: assign address of baseURL since Channel.BaseURL is *string
Models: strings.Join(botIds, ","),
Status: model.ChannelStatusEnabled,
Config: configStr,
}
existingChannel, err := model.GetFirstChannelByEidAndProviderId(channel.Eid, channel.ProviderID)
if err != nil {
// Create new record
return model.CreateChannel(channel) // Fix: return error instead of assigning i
} else {
// Update existing record
channel.ChannelID = existingChannel.ChannelID
channel.CreatedTime = existingChannel.CreatedTime
return model.UpdateChannel(channel)
}
}
================================================
FILE: api/controller/auth_sso.go
================================================
package controller
import (
"encoding/json"
"net/http"
"strconv"
"time"
"unicode"
"github.com/53AI/53AIHub/common/utils/helper"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/53AI/53AIHub/service"
"github.com/gin-gonic/gin"
)
// SSO 配置结构,存储于 enterprise-configs type="auth_sso" 的 JSON 内容
type SSOConfig struct {
Enable bool `json:"enable"`
EncryptEnabled bool `json:"encrypt_enabled"`
Secret string `json:"secret"`
}
// SSO 登录请求体
type SSOLoginRequest struct {
Username string `json:"username" binding:"required"`
Timestamp string `json:"timestamp"` // 10位秒
Sign string `json:"sign"` // 加密启用时必须传
}
// SaasLoginResponse 复用现有返回体格式
type SaasLoginResponse struct {
AccessToken string `json:"access_token"`
UserID int64 `json:"user_id"`
}
// @Summary API SSO Login
// @Description 站点API单点登录。时间戳为10位秒,窗口10分钟。eid无需传,使用站点环境。
// @Tags Auth
// @Accept json
// @Produce json
// @Param request body SSOLoginRequest true "SSO请求体"
// @Success 200 {object} model.CommonResponse{data=SaasLoginResponse} "成功,返回access_token与user_id"
// @Failure 401 {object} model.CommonResponse "未授权(超时或签名错误)"
// @Failure 403 {object} model.CommonResponse "拒绝(SSO关闭)"
// @Failure 404 {object} model.CommonResponse "用户不存在"
// @Router /api/auth/sso_login [post]
func ApiSSOSSOLogin(c *gin.Context) {
eid := config.GetEID(c)
// 加载 SSO 配置
cfg := loadSSOConfig(eid)
// 开关关闭:403
if !cfg.Enable {
c.JSON(http.StatusForbidden, model.ForbiddenError.ToNewErrorResponse("拒绝登录"))
return
}
// 绑定请求参数
var req SSOLoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusForbidden, model.ParamError.ToResponse(err))
return
}
// 签名校验(加密启用时)
if cfg.EncryptEnabled {
// 校验时间戳:必须10位数字
if !isValid10DigitTimestamp(req.Timestamp) {
c.JSON(http.StatusUnauthorized, model.UnauthorizedError.ToNewErrorResponse("sso timeout"))
return
}
ts, _ := strconv.ParseInt(req.Timestamp, 10, 64)
now := time.Now().Unix()
// 且600秒内有效
if now-ts > 600 {
c.JSON(http.StatusUnauthorized, model.UnauthorizedError.ToNewErrorResponse("sso timeout"))
return
}
if cfg.Secret == "" {
c.JSON(http.StatusUnauthorized, model.UnauthorizedError.ToNewErrorResponse("invalid sign"))
return
}
raw := helper.BuildSSORawString(req.Timestamp, req.Username, cfg.Secret)
expected := helper.CalcSSOSignLowerHex(raw)
if expected != req.Sign {
c.JSON(http.StatusUnauthorized, model.UnauthorizedError.ToNewErrorResponse("invalid sign"))
return
}
}
isEmail := helper.IsValidEmail(req.Username)
// 根据账号查找用户(邮箱或手机)
var user model.User
if isEmail {
u, err := model.GetUserByEmail(eid, req.Username)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToNewErrorResponse("user not found"))
return
}
user = u
} else {
u, err := model.GetUserByMobile(eid, req.Username)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToNewErrorResponse("user not found"))
return
}
user = u
}
// 刷新令牌并返回
if err := user.RefreshAccessToken(); err != nil {
c.JSON(http.StatusInternalServerError, model.SystemError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(SaasLoginResponse{
AccessToken: user.AccessToken,
UserID: user.UserID,
}))
}
func loadSSOConfig(eid int64) *SSOConfig {
// 从 enterprise-configs 读取 type="auth_sso"
conf, err := service.GetEnterpriseConfigByType(eid, model.EnterpriseConfigTypeSSO)
if err != nil || conf.Content == "" {
// 不存在则视为关闭
return &SSOConfig{Enable: false, EncryptEnabled: true, Secret: ""}
}
var cfg SSOConfig
_ = json.Unmarshal([]byte(conf.Content), &cfg)
cfg.Enable = conf.Enabled
return &cfg
}
func isValid10DigitTimestamp(ts string) bool {
if len(ts) != 10 {
return false
}
for _, r := range ts {
if !unicode.IsDigit(r) {
return false
}
}
return true
}
================================================
FILE: api/controller/channel-test.go
================================================
package controller
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"strings"
"time"
"github.com/53AI/53AIHub/common/ctxkey"
"github.com/53AI/53AIHub/common/logger"
"github.com/53AI/53AIHub/middleware"
"github.com/53AI/53AIHub/model"
"github.com/53AI/53AIHub/service"
"github.com/53AI/53AIHub/service/hub_adaptor/custom"
"github.com/gin-gonic/gin"
"github.com/songquanpeng/one-api/relay/adaptor/openai"
"github.com/songquanpeng/one-api/relay/meta"
relaymodel "github.com/songquanpeng/one-api/relay/model"
"github.com/songquanpeng/one-api/relay/relaymode"
)
type ChannelTestResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Time float64 `json:"time"`
}
// TestChannel Test channel availability
// @Summary Test channel connectivity
// @Description Verify channel configuration by invoking actual API endpoints
// @Tags Channel
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param channel_id path int true "Channel ID"
// @Param model query string false "Model name"
// @Success 200 {object} model.CommonResponse{data=ChannelTestResponse}
// @Router /api/channels/test/{channel_id} [get]
func TestChannel(c *gin.Context) {
ctx := c.Request.Context()
channel_id, err := strconv.Atoi(c.Param("channel_id"))
if err != nil {
c.JSON(http.StatusOK, model.ParamError.ToResponse(err))
return
}
channel, err := model.GetChannelByID(int64(channel_id))
if err != nil {
c.JSON(http.StatusOK, model.ParamError.ToResponse(err))
return
}
modelName := c.Query("model")
testRequest := buildTestRequest(modelName)
tik := time.Now()
responseMessage, err, _ := testChannel(ctx, channel, testRequest)
tok := time.Now()
milliseconds := tok.Sub(tik).Milliseconds()
if err != nil {
milliseconds = 0
}
go channel.UpdateResponseTime(milliseconds)
consumedTime := float64(milliseconds) / 1000.0
if err != nil {
c.JSON(http.StatusOK, model.ParamError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(ChannelTestResponse{
Success: true,
Message: responseMessage,
Time: consumedTime,
}))
}
func testChannel(ctx context.Context, channel *model.Channel, request *relaymodel.GeneralOpenAIRequest) (responseMessage string, err error, openaiErr *relaymodel.Error) {
//startTime := time.Now()
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = &http.Request{
Method: "POST",
URL: &url.URL{Path: "/v1/chat/completions"},
Body: nil,
Header: make(http.Header),
}
c.Request.Header.Set("Authorization", "Bearer "+channel.Key)
c.Request.Header.Set("Content-Type", "application/json")
c.Set(ctxkey.Channel, channel.Type)
c.Set(ctxkey.BaseURL, channel.GetBaseURL())
cfg, _ := channel.LoadConfig()
c.Set(ctxkey.Config, cfg)
middleware.SetupContextForSelectedChannel(c, channel, "")
meta := meta.GetByContext(c)
apiType := model.GetApiType(channel.Type)
meta.APIType = apiType
// apiType := channeltype.ToAPIType(channel.Type)
adaptor := service.GetAdaptor(meta.APIType)
err = service.SetCustomConfig(&adaptor, &custom.CustomConfig{
ConversationId: "",
UserId: "53AIHub",
})
if err != nil {
return "", err, nil
}
// adaptor := relay.GetAdaptor(apiType)
if adaptor == nil {
return "", fmt.Errorf("invalid api type: %d, adaptor is nil", apiType), nil
}
adaptor.Init(meta)
modelName := request.Model
modelMap := channel.GetModelMapping()
if modelName == "" || !strings.Contains(channel.Models, modelName) {
modelNames := strings.Split(channel.Models, ",")
if len(modelNames) > 0 {
modelName = modelNames[0]
}
}
if modelMap != nil && modelMap[modelName] != "" {
modelName = modelMap[modelName]
}
meta.OriginModelName, meta.ActualModelName = request.Model, modelName
request.Model = modelName
convertedRequest, err := adaptor.ConvertRequest(c, relaymode.ChatCompletions, request)
if err != nil {
return "", err, nil
}
jsonData, err := json.Marshal(convertedRequest)
if err != nil {
return "", err, nil
}
defer func() {
//logContent := fmt.Sprintf("渠道 %s 测试成功,响应:%s", channel.Name, responseMessage)
if err != nil || openaiErr != nil {
// errorMessage := ""
// if err != nil {
// errorMessage = err.Error()
// } else {
// errorMessage = openaiErr.Message
// }
//logContent = fmt.Sprintf("渠道 %s 测试失败,错误:%s", channel.Name, errorMessage)
}
// go model.RecordTestLog(ctx, &model.Log{
// ChannelId: channel.Id,
// ModelName: modelName,
// Content: logContent,
// ElapsedTime: helper.CalcElapsedTime(startTime),
// })
}()
logger.SysLog(string(jsonData))
requestBody := bytes.NewBuffer(jsonData)
c.Request.Body = io.NopCloser(requestBody)
resp, err := adaptor.DoRequest(c, meta, requestBody)
if err != nil {
return "", err, nil
}
if resp != nil && resp.StatusCode != http.StatusOK {
// err := controller.RelayErrorHandler(resp)
// err := errors.New("http status code: " + strconv.Itoa(resp.StatusCode))
// errorMessage := err.Error.Message
// if errorMessage != "" {
// errorMessage = ", error message: " + errorMessage
// }
return "", fmt.Errorf("http status code: %d%s", resp.StatusCode, ""), nil
}
usage, respErr := adaptor.DoResponse(c, resp, meta)
if respErr != nil {
return "", fmt.Errorf("%s", respErr.Error.Message), &respErr.Error
}
if usage == nil {
return "", errors.New("usage is nil"), nil
}
rawResponse := w.Body.String()
_, responseMessage, err = parseTestResponse(rawResponse)
if err != nil {
logger.SysError(fmt.Sprintf("failed to parse error: %s, \nresponse: %s", err.Error(), rawResponse))
return "", err, nil
}
result := w.Result()
// print result.Body
respBody, err := io.ReadAll(result.Body)
if err != nil {
return "", err, nil
}
logger.SysLog(fmt.Sprintf("testing channel #%d, response: \n%s", channel.ChannelID, string(respBody)))
return responseMessage, nil, nil
}
func parseTestResponse(resp string) (*openai.TextResponse, string, error) {
var response openai.TextResponse
err := json.Unmarshal([]byte(resp), &response)
if err != nil {
return nil, "", err
}
if len(response.Choices) == 0 {
return nil, "", errors.New("response has no choices")
}
stringContent, ok := response.Choices[0].Content.(string)
if !ok {
return nil, "", errors.New("response content is not string")
}
return &response, stringContent, nil
}
func buildTestRequest(model string) *relaymodel.GeneralOpenAIRequest {
if model == "" {
model = "gpt-3.5-turbo"
}
testRequest := &relaymodel.GeneralOpenAIRequest{
Model: model,
}
testMessage := relaymodel.Message{
Role: "user",
Content: "Output only your specific model name with no additional text.",
}
testRequest.Messages = append(testRequest.Messages, testMessage)
return testRequest
}
================================================
FILE: api/controller/channel.go
================================================
package controller
import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/gin-gonic/gin"
)
// autoAssignCozeStudioProvider automatically assigns a ProviderID for CozeStudio channels
// when ProviderID is 0 in the request
// In multi-provider environments, this should be explicitly specified by the client
func autoAssignCozeStudioProvider(channel *model.Channel) error {
// Check if this is a CozeStudio channel and ProviderID is 0
if channel.Type == model.ChannelApiTypeCozeStudio && channel.ProviderID == 0 {
// Get all CozeStudio providers for this enterprise
providers, err := model.GetProvidersByEidAndProviderType(channel.Eid, model.ProviderTypeCozeStudio)
if err != nil {
return err
}
if len(providers) == 0 {
return fmt.Errorf("no CozeStudio provider found for enterprise %d", channel.Eid)
}
// If there's only one provider, auto-assign it
if len(providers) == 1 {
channel.ProviderID = providers[0].ProviderID
} else {
// Multiple providers found - this is ambiguous in multi-provider environment
// Return error to force explicit provider selection
return fmt.Errorf("multiple CozeStudio providers found (%d), please specify provider_id explicitly", len(providers))
}
}
return nil
}
type ChannelRequest struct {
Type int `json:"type" example:"1"`
ModelType *int `json:"model_type" example:"1"`
Key string `json:"key" example:"channel_key"`
Name string `json:"name" example:"channel_name"`
Models string `json:"models" example:"gpt-3.5-turbo"`
Config string `json:"config" example:"{\"region\":\"us-east-1\"}"`
ModelMapping *string `json:"model_mapping"`
Weight *uint `json:"weight"`
Priority *int64 `json:"priority"`
BaseURL *string `json:"base_url"`
Other *string `json:"other"`
ProviderID *int64 `json:"provider_id" example:"181"`
}
// @Summary Create channel
// @Description Create new channel configuration
// @Tags Channel
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param channel body ChannelRequest true "Channel data"
// @Success 200 {object} model.CommonResponse
// @Router /api/channels [post]
func CreateChannel(c *gin.Context) {
var req ChannelRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
channel := model.Channel{
Eid: config.GetEID(c),
Type: req.Type,
ModelType: 1,
Key: req.Key,
Name: req.Name,
Models: req.Models,
Config: req.Config,
ModelMapping: req.ModelMapping,
Weight: req.Weight,
Priority: req.Priority,
BaseURL: req.BaseURL,
Other: req.Other,
ProviderID: 0, // Default to 0 if not provided
}
// Set ProviderID if provided in request
if req.ProviderID != nil {
channel.ProviderID = *req.ProviderID
}
// Set ModelType: default 1; if provided and valid (1,2,3), use it
if req.ModelType != nil {
if model.IsValidModelType(*req.ModelType) {
channel.ModelType = *req.ModelType
}
}
channel.Models = model.ProcessModelNames(req.Models, channel.Type)
if channel.Models == "" {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(strings.NewReader("models is required")))
return
}
// Auto assign ProviderID for CozeStudio channels if needed
if err := autoAssignCozeStudioProvider(&channel); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
if err := model.CreateChannel(&channel); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(channel))
}
// @Summary Get channel
// @Description Get channel configuration by ID
// @Tags Channel
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param channel_id path int true "Channel ID"
// @Success 200 {object} model.CommonResponse
// @Router /api/channels/{channel_id} [get]
func GetChannel(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("channel_id"), 10, 64)
channel, err := model.GetChannelByID(id)
if err != nil || channel.Eid != config.GetEID(c) {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(channel))
}
// @Summary Update channel
// @Description Update existing channel configuration
// @Tags Channel
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param channel_id path int true "Channel ID"
// @Param channel body ChannelRequest true "Update data"
// @Success 200 {object} model.CommonResponse
// @Router /api/channels/{channel_id} [put]
func UpdateChannel(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("channel_id"), 10, 64)
channel, err := model.GetChannelByID(id)
if err != nil || channel.Eid != config.GetEID(c) {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
var req ChannelRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
channel.Models = model.ProcessModelNames(req.Models, channel.Type)
if channel.Models == "" {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(strings.NewReader("models is required")))
return
}
channel.Type = req.Type
channel.Key = req.Key
channel.Name = req.Name
channel.Config = req.Config
channel.ModelMapping = req.ModelMapping
channel.Weight = req.Weight
channel.Priority = req.Priority
channel.BaseURL = req.BaseURL
channel.Other = req.Other
// Update ProviderID if provided in request
if req.ProviderID != nil {
channel.ProviderID = *req.ProviderID
}
// Update ModelType if provided and valid (1,2,3)
if req.ModelType != nil {
if model.IsValidModelType(*req.ModelType) {
channel.ModelType = *req.ModelType
}
}
// Auto assign ProviderID for CozeStudio channels if needed
if err := autoAssignCozeStudioProvider(channel); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
if err := model.UpdateChannel(channel); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(channel))
}
// @Summary Delete channel
// @Description Delete channel by ID
// @Tags Channel
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param channel_id path int true "Channel ID"
// @Success 200 {object} model.CommonResponse
// @Router /api/channels/{channel_id} [delete]
func DeleteChannel(c *gin.Context) {
id, _ := strconv.ParseInt(c.Param("channel_id"), 10, 64)
channel, err := model.GetChannelByID(id)
if err == nil && channel.Eid == config.GetEID(c) {
err = model.DeleteChannelByID(id)
}
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
// @Summary Get all channels
// @Description Get all channels for current enterprise
// @Tags Channel
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param provider_id query int false "Provider ID, 0 means platform-added keys, non-zero means get channels from other platforms" example:"0"
// @Param channel_types query string false "Channel type filters" example:"1,1001,1002"
// @Param model_type query string false "Model type filters: 1=LLM,2=Embedding,3=Rerank; comma-separated supported; 0 or empty means no filter" example:"1,3"
// @Success 200 {object} model.CommonResponse
// @Router /api/channels [get]
func GetChannels(c *gin.Context) {
providerId, _ := strconv.ParseInt(c.Query("provider_id"), 10, 64)
channelTypesStr := c.Query("channel_types")
var channelTypes []int
if channelTypesStr != "" {
for _, s := range strings.Split(channelTypesStr, ",") {
if t, err := strconv.Atoi(strings.TrimSpace(s)); err == nil {
channelTypes = append(channelTypes, t)
}
}
}
modelTypesStr := c.Query("model_type")
var modelTypes []int
if modelTypesStr != "" {
for _, s := range strings.Split(modelTypesStr, ",") {
if t, err := strconv.Atoi(strings.TrimSpace(s)); err == nil {
// Only accept defined model types; 0 or invalid values mean no filter
if model.IsValidModelType(t) {
modelTypes = append(modelTypes, t)
}
}
}
}
channels, err := model.GetChannelsByEidAndParams(config.GetEID(c), providerId, channelTypes, modelTypes)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(channels))
}
================================================
FILE: api/controller/conversation.go
================================================
package controller
import (
"net/http"
"strconv"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/gin-gonic/gin"
)
type ConversationRequest struct {
Title string `json:"title"`
AgentID int64 `json:"agent_id" binding:"required"`
}
type ConversationUpdateRequest struct {
Title string `json:"title"`
}
type ConversationResponse struct {
Count int64 `json:"count"`
Conversations []*model.Conversation `json:"conversations"`
}
type ConversationListRequest struct {
Keyword string `json:"keyword" form:"keyword"`
Offset int `json:"offset" form:"offset" example:"0"`
Limit int `json:"limit" form:"limit" example:"10"`
}
// @Summary Create conversation
// @Description Create a new conversation
// @Tags Conversation
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param conversation body ConversationRequest true "Conversation data"
// @Success 200 {object} model.CommonResponse{data=model.Conversation} "Success"
// @Router /api/conversations [post]
func CreateConversation(c *gin.Context) {
var req ConversationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
eid := config.GetEID(c)
agent, err := model.GetAgentByID(eid, req.AgentID)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
conversation := &model.Conversation{
Eid: eid,
UserID: config.GetUserId(c),
AgentID: req.AgentID,
Title: req.Title,
Status: model.ConversationStatusActive,
Model: agent.Model,
}
if err := model.CreateConversation(conversation); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
conversation.LoadAgent()
c.JSON(http.StatusOK, model.Success.ToResponse(conversation))
}
// @Summary Get conversation details
// @Description Get conversation details by ID
// @Tags Conversation
// @Produce json
// @Security BearerAuth
// @Param conversation_id path int true "Conversation ID"
// @Success 200 {object} model.CommonResponse{data=model.Conversation} "Success"
// @Router /api/conversations/{conversation_id} [get]
func GetConversation(c *gin.Context) {
conversationID, err := strconv.ParseInt(c.Param("conversation_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
conversation, err := model.GetConversationByID(config.GetEID(c), config.GetUserId(c), conversationID)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(conversation))
}
// @Summary Get user conversations
// @Description Get conversation list for current user
// @Tags Conversation
// @Produce json
// @Security BearerAuth
// @Param keyword query string false "Search keyword"
// @Param offset query int false "Offset" default(0)
// @Param limit query int false "Limit" default(10)
// @Success 200 {object} model.CommonResponse{data=ConversationResponse} "Success"
// @Router /api/conversations [get]
func GetConversations(c *gin.Context) {
var req ConversationListRequest
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
conversations, err := model.GetConversationsByUserID(config.GetEID(c), config.GetUserId(c))
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(&ConversationResponse{
Count: int64(len(conversations)),
Conversations: conversations,
}))
}
// @Summary Update conversation
// @Description Update conversation information
// @Tags Conversation
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param conversation_id path int true "Conversation ID"
// @Param conversation body ConversationUpdateRequest true "Conversation data"
// @Success 200 {object} model.CommonResponse{data=model.Conversation} "Success"
// @Router /api/conversations/{conversation_id} [put]
func UpdateConversation(c *gin.Context) {
conversationID, err := strconv.ParseInt(c.Param("conversation_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
var req ConversationUpdateRequest
if err = c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
conversation, err := model.GetConversationByID(config.GetEID(c), config.GetUserId(c), conversationID)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
conversation.Title = req.Title
if err := model.UpdateConversation(conversation); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(conversation))
}
type UserConversationListRequest struct {
ConversationListRequest
CreatedAtStart int64 `form:"created_at_start"`
CreatedAtEnd int64 `form:"created_at_end"`
AgentID int64 `form:"agent_id"`
}
// @Summary Get user conversations
// @Description Get paginated conversation list for specified user with time range filter
// @Tags Conversation
// @Produce json
// @Security BearerAuth
// @Param user_id path int true "Target user ID"
// @Param keyword query string false "Search keyword"
// @Param created_at_start query int64 false "Start time (millisecond timestamp)"
// @Param created_at_end query int64 false "End time (millisecond timestamp)"
// @Param offset query int false "Offset" default(0)
// @Param limit query int false "Limit" default(10)
// @Success 200 {object} model.CommonResponse{data=ConversationSummaryResponse} "Success"
// @Router /api/users/{user_id}/conversations [get]
func GetUserConversations(c *gin.Context) {
userID, err := strconv.ParseInt(c.Param("user_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
user, err := model.GetUserByID(userID)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(nil))
return
}
var req UserConversationListRequest
if err = c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
conversations, total, err := model.GetUserConversationsWithFilter(
config.GetEID(c),
userID,
req.Keyword,
req.CreatedAtStart,
req.CreatedAtEnd,
req.Offset,
req.Limit,
)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
var summaries []*ConversationSummary = make([]*ConversationSummary, 0)
for _, conv := range conversations {
messageCount, msgErr := model.GetMessageCountByConversationID(conv.ConversationID)
if msgErr != nil {
messageCount = 0
}
firstMessage, firstMsgErr := model.GetFirstMessageByConversationID(conv.ConversationID)
if firstMsgErr != nil {
firstMessage = ""
}
summaries = append(summaries, &ConversationSummary{
ID: conv.ConversationID,
Title: conv.Title,
CreatedAt: conv.CreatedTime,
Summary: firstMessage,
MessageCount: messageCount,
User: UserInfo{user.UserID, user.Username},
})
}
c.JSON(http.StatusOK, model.Success.ToResponse(&ConversationSummaryResponse{
Count: total,
Items: summaries,
}))
}
type UserInfo struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
}
// ConversationSummary 定义返回的会话摘要结构
type ConversationSummary struct {
ID int64 `json:"id"`
Title string `json:"title"`
CreatedAt int64 `json:"created_at"`
Summary string `json:"summary"`
MessageCount int `json:"message_count"`
User UserInfo `json:"user" omitempty:"true"`
}
// ConversationSummaryResponse 分页返回结构
type ConversationSummaryResponse struct {
Count int64 `json:"count"`
Items []*ConversationSummary `json:"items"`
}
// @Summary Get agent conversations
// @Description Get paginated conversation list for specified agent with time range filter
// @Tags Conversation
// @Produce json
// @Security BearerAuth
// @Param agent_id path int true "Target agent ID"
// @Param keyword query string false "Search keyword"
// @Param created_at_start query int64 false "Start time (millisecond timestamp)"
// @Param created_at_end query int64 false "End time (millisecond timestamp)"
// @Param offset query int false "Offset" default(0)
// @Param limit query int false "Limit" default(10)
// @Success 200 {object} model.CommonResponse{data=ConversationSummaryResponse} "Success"
// @Router /api/agents/{agent_id}/conversations [get]
func GetAgentConversations(c *gin.Context) {
agentID, err := strconv.ParseInt(c.Param("agent_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
var req UserConversationListRequest
if err = c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
conversations, total, err := model.GetAgentConversationsWithFilter(
config.GetEID(c),
agentID,
req.Keyword,
req.CreatedAtStart,
req.CreatedAtEnd,
req.Offset,
req.Limit,
)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
var summaries []*ConversationSummary = make([]*ConversationSummary, 0)
for _, conv := range conversations {
messageCount, msgErr := model.GetMessageCountByConversationID(conv.ConversationID)
if msgErr != nil {
messageCount = 0
}
firstMessage, firstMsgErr := model.GetFirstMessageByConversationID(conv.ConversationID)
if firstMsgErr != nil {
firstMessage = ""
}
conv.LoadUser()
summaries = append(summaries, &ConversationSummary{
ID: conv.ConversationID,
Title: conv.Title,
CreatedAt: conv.CreatedTime,
Summary: firstMessage,
MessageCount: messageCount,
User: UserInfo{conv.User.UserID, conv.User.Username},
})
}
c.JSON(http.StatusOK, model.Success.ToResponse(&ConversationSummaryResponse{
Count: total,
Items: summaries,
}))
}
// @Summary Delete conversation
// @Description Delete specified conversation
// @Tags Conversation
// @Produce json
// @Security BearerAuth
// @Param conversation_id path int true "Conversation ID"
// @Success 200 {object} model.CommonResponse "Success"
// @Router /api/conversations/{conversation_id} [delete]
func DeleteConversation(c *gin.Context) {
conversationID, err := strconv.ParseInt(c.Param("conversation_id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
if err := model.DeleteConversation(config.GetEID(c), conversationID); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
================================================
FILE: api/controller/coze.go
================================================
package controller
import (
"net/http"
"strconv"
"github.com/53AI/53AIHub/common/logger"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/53AI/53AIHub/service"
"github.com/gin-gonic/gin"
)
// GetCozeAllWorkspaces Get all Coze workspaces
// @Summary Get all Coze workspaces
// @Description Get all Coze workspaces list under current enterprise
// @Tags Coze
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param provider_id query int false "Provider ID (optional, for backward compatibility)"
// @Success 200 {object} model.CommonResponse{data=[]coze.Workspace}
// @Router /api/coze/workspaces [get]
func GetCozeAllWorkspaces(c *gin.Context) {
eid := config.GetEID(c)
providerID, _ := strconv.ParseInt(c.DefaultQuery("provider_id", "0"), 10, 64)
provider, err := model.GetProviderByEidAndProviderTypeWithOptionalID(eid, int64(model.ProviderTypeCozeCn), providerID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
ser := service.CozeService{
Provider: provider,
}
workspaces, err := ser.GetAllWorkspace()
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(workspaces))
}
// GetCozeAllBots Get all bots in specified workspace
// @Summary Get workspace bots list
// @Description Get all bots list under specified Coze workspace
// @Tags Coze
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param workspace_id path string true "Workspace ID"
// @Param provider_id query int false "Provider ID (optional, for backward compatibility)"
// @Success 200 {object} model.CommonResponse{data=[]coze.Bot}
// @Router /api/coze/workspaces/{workspace_id}/bots [get]
func GetCozeAllBots(c *gin.Context) {
workspaceID := c.Param("workspace_id")
if workspaceID == "" {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(nil))
return
}
eid := config.GetEID(c)
providerID, _ := strconv.ParseInt(c.DefaultQuery("provider_id", "0"), 10, 64)
provider, err := model.GetProviderByEidAndProviderTypeWithOptionalID(eid, int64(model.ProviderTypeCozeCn), providerID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
ser := service.CozeService{
Provider: provider,
}
bots, err := ser.GetAllBot(workspaceID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.ProviderNoFoundError.ToResponse(err))
return
}
// 缓存所有bot图标(使用新的基于UploadFile的方式)
logger.SysLogf("开始缓存 %d 个bot图标", len(bots))
for i := range bots {
if bots[i].IconURL != "" {
logger.SysLogf("开始缓存bot图标,bot_id: %s, icon_url: %s", bots[i].BotID, bots[i].IconURL)
cachedIconURL, err := ser.CacheBotIconWithUploadFile(bots[i].BotID, bots[i].IconURL, eid)
if err != nil {
// 如果缓存失败,记录日志但继续执行
logger.SysLogf("缓存bot图标失败,bot_id: %s, error: %v", bots[i].BotID, err)
// 不中断整个流程
continue
}
// 使用缓存的图标URL
logger.SysLogf("成功缓存bot图标,bot_id: %s, cached_url: %s", bots[i].BotID, cachedIconURL)
bots[i].IconURL = cachedIconURL
}
}
//重新合并请求
var botIds []string
for _, bot := range bots {
botIds = append(botIds, bot.BotID)
}
ser.UpdateCozeChannel(botIds, &provider)
c.JSON(http.StatusOK, model.Success.ToResponse(bots))
}
================================================
FILE: api/controller/department.go
================================================
package controller
import (
"net/http"
"strconv"
"github.com/53AI/53AIHub/config"
"github.com/53AI/53AIHub/model"
"github.com/gin-gonic/gin"
)
// DepartmentRequest represents the request body for department operations
type DepartmentRequest struct {
PDID int64 `json:"pdid"`
Name string `json:"name" binding:"required"`
Sort int `json:"sort"`
}
type UpdateDepartmentRequest struct {
Name string `json:"name" binding:"required"`
Sort int `json:"sort"`
}
// DepartmentResponse represents the response for department list
type DepartmentResponse struct {
Departments []*model.Department `json:"departments"`
Total int `json:"total"`
}
// DepartmentTreeResponse represents the response for department tree
type DepartmentTreeResponse struct {
Tree []*model.DepartmentNode `json:"tree"`
}
type BindRequest struct {
Bid int64 `json:"bid"`
From int `json:"from"`
UserID int64 `json:"user_id"`
}
type UnBindRequest struct {
From int `json:"from"`
UserID int64 `json:"user_id"`
}
// CreateDepartment creates a new department
// @Summary Create a new department
// @Description Create a new department in the organization
// @Tags Department
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body DepartmentRequest true "Department information"
// @Success 200 {object} model.CommonResponse{data=model.Department} "Success"
// @Failure 400 {object} model.CommonResponse "Bad request"
// @Failure 500 {object} model.CommonResponse "Internal server error"
// @Router /api/departments [post]
func CreateDepartment(c *gin.Context) {
var req DepartmentRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
// Create department object
dept := &model.Department{
PDID: req.PDID,
EID: config.GetEID(c),
Name: req.Name,
Sort: req.Sort,
From: model.DepartmentFromBackend,
}
// Create department in database
if err := model.CreateDepartment(dept); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(dept))
}
// GetDepartment retrieves a department by ID
// @Summary Get department by ID
// @Description Get department details by ID
// @Tags Department
// @Produce json
// @Security BearerAuth
// @Param did path int true "Department ID"
// @Success 200 {object} model.CommonResponse{data=model.Department} "Success"
// @Failure 404 {object} model.CommonResponse "Department not found"
// @Failure 500 {object} model.CommonResponse "Internal server error"
// @Router /api/departments/{did} [get]
func GetDepartment(c *gin.Context) {
didStr := c.Param("did")
did, err := strconv.ParseInt(didStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
dept, err := model.GetDepartmentByID(config.GetEID(c), did)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(dept))
}
// UpdateDepartment updates an existing department
// @Summary Update department
// @Description Update an existing department
// @Tags Department
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param did path int true "Department ID"
// @Param request body UpdateDepartmentRequest true "Department information"
// @Success 200 {object} model.CommonResponse{data=model.Department} "Success"
// @Failure 400 {object} model.CommonResponse "Bad request"
// @Failure 404 {object} model.CommonResponse "Department not found"
// @Failure 500 {object} model.CommonResponse "Internal server error"
// @Router /api/departments/{did} [put]
func UpdateDepartment(c *gin.Context) {
didStr := c.Param("did")
did, err := strconv.ParseInt(didStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
var req UpdateDepartmentRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
// Get existing department
dept, err := model.GetDepartmentByID(config.GetEID(c), did)
if err != nil {
c.JSON(http.StatusNotFound, model.NotFound.ToResponse(err))
return
}
// Update department fields
dept.Name = req.Name
dept.Sort = req.Sort
// Update department in database
if err := model.UpdateDepartment(dept); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(dept))
}
// DeleteDepartment deletes a department
// @Summary Delete department
// @Description Delete a department and optionally its children
// @Tags Department
// @Produce json
// @Security BearerAuth
// @Param did path int true "Department ID"
// @Param delete_children query bool false "Delete children" default(false)
// @Success 200 {object} model.CommonResponse "Success"
// @Failure 400 {object} model.CommonResponse "Bad request"
// @Failure 404 {object} model.CommonResponse "Department not found"
// @Failure 500 {object} model.CommonResponse "Internal server error"
// @Router /api/departments/{did} [delete]
func DeleteDepartment(c *gin.Context) {
didStr := c.Param("did")
did, err := strconv.ParseInt(didStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
deleteChildrenStr := c.DefaultQuery("delete_children", "false")
deleteChildren := deleteChildrenStr == "true"
if err := model.DeleteDepartment(config.GetEID(c), did, deleteChildren); err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
// GetDepartments retrieves all departments
// @Summary Get all departments
// @Description Get all departments for the current enterprise
// @Tags Department
// @Produce json
// @Security BearerAuth
// @Param keyword query string false "Search keyword"
// @Param limit query int false "Limit results" default(100)
// @Success 200 {object} model.CommonResponse{data=DepartmentResponse} "Success"
// @Failure 500 {object} model.CommonResponse "Internal server error"
// @Router /api/departments [get]
func GetDepartments(c *gin.Context) {
keyword := c.Query("keyword")
limitStr := c.DefaultQuery("limit", "100")
limit, _ := strconv.Atoi(limitStr)
departments, err := model.SearchDepartments(config.GetEID(c), keyword, limit)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(DepartmentResponse{
Departments: departments,
Total: len(departments),
}))
}
// GetChildDepartments retrieves child departments
// @Summary Get child departments
// @Description Get all child departments for a specific department
// @Tags Department
// @Produce json
// @Security BearerAuth
// @Param pdid path int true "Parent Department ID"
// @Success 200 {object} model.CommonResponse{data=DepartmentResponse} "Success"
// @Failure 400 {object} model.CommonResponse "Bad request"
// @Failure 500 {object} model.CommonResponse "Internal server error"
// @Router /api/departments/children/{pdid} [get]
func GetChildDepartments(c *gin.Context) {
pdidStr := c.Param("pdid")
pdid, err := strconv.ParseInt(pdidStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
departments, err := model.GetChildDepartments(config.GetEID(c), pdid)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(DepartmentResponse{
Departments: departments,
Total: len(departments),
}))
}
// GetDepartmentTree retrieves the department hierarchy
// @Summary Get department tree
// @Description Get hierarchical structure of departments
// @Tags Department
// @Produce json
// @Security BearerAuth
// @Param from query int false "Filter by source (0: backend [default], 1: wecom,2:dingtalk)" default(0)
// @Success 200 {object} model.CommonResponse{data=DepartmentTreeResponse} "Success"
// @Failure 500 {object} model.CommonResponse "Internal server error"
// @Router /api/departments/tree [get]
func GetDepartmentTree(c *gin.Context) {
fromStr := c.Query("from")
from, err := strconv.Atoi(fromStr)
if err != nil {
from = model.DepartmentFromBackend
}
tree, err := model.GetDepartmentTree(config.GetEID(c), from)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(DepartmentTreeResponse{
Tree: tree,
}))
}
// @Summary Bind member to department
// @Description Bind a member to specific department with given role
// @Tags Department
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body BindRequest true "Binding request parameters"
// @Success 200 {object} model.CommonResponse "Success"
// @Router /api/departments/bind-member [post]
func DepartmentBindMember(c *gin.Context) {
eid := config.GetEID(c)
// Replace query params with body params
var req BindRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
// Now use req.Bid, req.From, req.UserID instead of the query params
bid := req.Bid
from := req.From
userID := req.UserID
var user *model.User
err := model.DB.Where("eid = ? AND user_id = ?", eid, userID).First(&user).Error
if err != nil {
c.JSON(http.StatusBadRequest, model.NotFound.ToResponse(err))
return
}
var memberBinding *model.MemberBinding
memberBinding, _ = model.GetMemberBindingByMidAndFrom(user.UserID, from)
if memberBinding != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse("user already bound"))
return
}
err = model.DB.Where("eid =? AND id =? AND `from` =? AND mid = 0", eid, bid, from).First(&memberBinding).Error
if err != nil || memberBinding == nil {
c.JSON(http.StatusBadRequest, model.NotFound.ToResponse(err))
return
}
memberBinding.MID = user.UserID
memberBinding.Status = model.MemberBindingStatusActive
err = model.UpdateMemberBinding(memberBinding)
if err != nil {
c.JSON(http.StatusInternalServerError, model.DBError.ToResponse(err))
return
}
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
// @Summary Unbind member from department
// @Description Remove a member's binding from department
// @Tags Department
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body UnBindRequest true "Unbinding request parameters"
// @Success 200 {object} model.CommonResponse "Success"
// @Router /api/departments/bind-member [delete]
func DepartmentUnbindMember(c *gin.Context) {
eid := config.GetEID(c)
var req UnBindRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.ParamError.ToResponse(err))
return
}
var user *model.User
err := model.DB.Where("eid = ? AND user_id = ?", eid, req.UserID).First(&user).Error
if err != nil {
c.JSON(http.StatusBadRequest, model.NotFound.ToResponse(err))
return
}
memberBinding, err := model.GetMemberBindingByMidAndFrom(user.UserID, req.From)
if err != nil || memberBinding == nil {
c.JSON(http.StatusBadRequest, model.NotFound.ToResponse("user bind not bound"))
return
}
memberBinding.MID = 0
memberBinding.Status = model.MemberBindingStatusInactive
err = model.UpdateMemberBinding(memberBinding)
c.JSON(http.StatusOK, model.Success.ToResponse(nil))
}
================================================
FILE: api/controller/dify.go
================================================
package control
gitextract_88ren__n/
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── README_CN.md
├── README_JA.md
├── api/
│ ├── .gitattributes
│ ├── .gitignore
│ ├── Dockerfile
│ ├── Makefile
│ ├── README.md
│ ├── bin/
│ │ ├── restart.sh
│ │ └── version.txt
│ ├── build.sh
│ ├── common/
│ │ ├── cache.go
│ │ ├── ctxkey/
│ │ │ └── key.go
│ │ ├── email.go
│ │ ├── init.go
│ │ ├── lock.go
│ │ ├── logger/
│ │ │ └── logger.go
│ │ ├── permission.go
│ │ ├── redis.go
│ │ ├── session/
│ │ │ └── key.go
│ │ ├── storage/
│ │ │ ├── storage.go
│ │ │ └── storage_test.go
│ │ ├── utils/
│ │ │ ├── ai53/
│ │ │ │ └── api.go
│ │ │ ├── appbuilder/
│ │ │ │ └── api.go
│ │ │ ├── coze/
│ │ │ │ └── api.go
│ │ │ ├── env/
│ │ │ │ └── env.go
│ │ │ ├── helper/
│ │ │ │ ├── helper.go
│ │ │ │ ├── key.go
│ │ │ │ └── sso_sign.go
│ │ │ ├── huawei_cloud/
│ │ │ │ ├── model.go
│ │ │ │ └── signature.go
│ │ │ ├── ip.go
│ │ │ ├── jwt/
│ │ │ │ └── jwt.go
│ │ │ ├── random.go
│ │ │ ├── snowflake.go
│ │ │ ├── system/
│ │ │ │ ├── machine.go
│ │ │ │ └── version.go
│ │ │ └── wxbizjsonmsgcrypt/
│ │ │ └── wxbizjsonmsgcrypt.go
│ │ └── validate.go
│ ├── config/
│ │ ├── config.go
│ │ ├── database.go
│ │ ├── encryption.go
│ │ └── storage.go
│ ├── controller/
│ │ ├── agent.go
│ │ ├── ai53.go
│ │ ├── ai_link.go
│ │ ├── appbuilder.go
│ │ ├── auth_sso.go
│ │ ├── channel-test.go
│ │ ├── channel.go
│ │ ├── conversation.go
│ │ ├── coze.go
│ │ ├── department.go
│ │ ├── dify.go
│ │ ├── email.go
│ │ ├── enterprise.go
│ │ ├── enterprise_config.go
│ │ ├── group.go
│ │ ├── maxkb.go
│ │ ├── message.go
│ │ ├── model.go
│ │ ├── navigation.go
│ │ ├── navigation_icons.go
│ │ ├── order.go
│ │ ├── pay.go
│ │ ├── pay_setting.go
│ │ ├── prompt.go
│ │ ├── provider.go
│ │ ├── provider_callback.go
│ │ ├── relay.go
│ │ ├── rerank.go
│ │ ├── response_handler.go
│ │ ├── setting.go
│ │ ├── share.go
│ │ ├── status.go
│ │ ├── subscription.go
│ │ ├── sync_organization.go
│ │ ├── system_log.go
│ │ ├── tencent.go
│ │ ├── upload.go
│ │ └── user.go
│ ├── docker/
│ │ └── docker-compose.yml
│ ├── docs/
│ │ └── .gitignore
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ ├── middleware/
│ │ ├── auth.go
│ │ ├── cors.go
│ │ ├── distributor.go
│ │ ├── logger.go
│ │ └── relay_auth.go
│ ├── model/
│ │ ├── agent.go
│ │ ├── ai_link.go
│ │ ├── base.go
│ │ ├── cache.go
│ │ ├── channel.go
│ │ ├── channel_file_mapping.go
│ │ ├── conversation.go
│ │ ├── department.go
│ │ ├── dingtalk_corp.go
│ │ ├── dingtalk_suite.go
│ │ ├── enterprise.go
│ │ ├── enterprise_config.go
│ │ ├── enterprise_sync.go
│ │ ├── group.go
│ │ ├── like.go
│ │ ├── main.go
│ │ ├── member_binding.go
│ │ ├── member_department_relation.go
│ │ ├── message.go
│ │ ├── navigation.go
│ │ ├── navigation_content.go
│ │ ├── order.go
│ │ ├── pay_setting.go
│ │ ├── prompt.go
│ │ ├── provider.go
│ │ ├── resource_permission.go
│ │ ├── response.go
│ │ ├── setting.go
│ │ ├── share_record.go
│ │ ├── subscription.go
│ │ ├── system_log.go
│ │ ├── upload_file.go
│ │ ├── user.go
│ │ ├── verification_code.go
│ │ ├── wecom_corp.go
│ │ └── wecom_suite.go
│ ├── router/
│ │ ├── api.go
│ │ ├── main.go
│ │ ├── static.go
│ │ └── web.go
│ ├── service/
│ │ ├── adaptor.go
│ │ ├── ai53_provider.go
│ │ ├── appbuilder_provider.go
│ │ ├── channel_service.go
│ │ ├── coze_provider.go
│ │ ├── enterprise_config_service.go
│ │ ├── hub_adaptor/
│ │ │ ├── 53AI/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── appbuilder/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ └── model.go
│ │ │ ├── bailian/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ ├── rerank.go
│ │ │ │ └── rerank_model.go
│ │ │ ├── coze/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constant/
│ │ │ │ │ ├── contenttype/
│ │ │ │ │ │ └── define.go
│ │ │ │ │ ├── event/
│ │ │ │ │ │ └── define.go
│ │ │ │ │ └── messagetype/
│ │ │ │ │ └── define.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── helper.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── custom/
│ │ │ │ ├── common.go
│ │ │ │ ├── config.go
│ │ │ │ └── workflow.go
│ │ │ ├── dify/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── info.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── fastgpt/
│ │ │ │ └── workflow.go
│ │ │ ├── n8n/
│ │ │ │ ├── README.md
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── workflow.go
│ │ │ ├── openai/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── compatible.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── helper.go
│ │ │ │ ├── image.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ ├── token.go
│ │ │ │ └── util.go
│ │ │ ├── tencent/
│ │ │ │ ├── adaptor.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── helper.go
│ │ │ │ ├── main.go
│ │ │ │ ├── model.go
│ │ │ │ └── sdk/
│ │ │ │ ├── client.go
│ │ │ │ ├── errors.go
│ │ │ │ └── models.go
│ │ │ ├── volcengine/
│ │ │ │ └── main.go
│ │ │ └── yuanqi/
│ │ │ ├── adaptor.go
│ │ │ ├── constants.go
│ │ │ ├── main.go
│ │ │ └── model.go
│ │ ├── organizational_service.go
│ │ ├── payment/
│ │ │ ├── alipay.go
│ │ │ ├── manual.go
│ │ │ ├── payment.go
│ │ │ ├── paypal.go
│ │ │ └── wechatpay.go
│ │ ├── rerank_service.go
│ │ ├── resource_permission_service.go
│ │ ├── user_service.go
│ │ └── version_feature.go
│ ├── static/
│ │ └── libs/
│ │ └── js/
│ │ ├── UEditor/
│ │ │ ├── dialogs/
│ │ │ │ ├── anchor/
│ │ │ │ │ └── anchor.html
│ │ │ │ ├── attachment/
│ │ │ │ │ ├── attachment.css
│ │ │ │ │ ├── attachment.html
│ │ │ │ │ └── attachment.js
│ │ │ │ ├── background/
│ │ │ │ │ ├── background.css
│ │ │ │ │ ├── background.html
│ │ │ │ │ └── background.js
│ │ │ │ ├── charts/
│ │ │ │ │ ├── chart.config.js
│ │ │ │ │ ├── charts.css
│ │ │ │ │ ├── charts.html
│ │ │ │ │ └── charts.js
│ │ │ │ ├── emotion/
│ │ │ │ │ ├── emotion.css
│ │ │ │ │ ├── emotion.html
│ │ │ │ │ └── emotion.js
│ │ │ │ ├── gmap/
│ │ │ │ │ └── gmap.html
│ │ │ │ ├── help/
│ │ │ │ │ ├── help.css
│ │ │ │ │ ├── help.html
│ │ │ │ │ └── help.js
│ │ │ │ ├── image/
│ │ │ │ │ ├── image.css
│ │ │ │ │ ├── image.html
│ │ │ │ │ └── image.js
│ │ │ │ ├── insertframe/
│ │ │ │ │ └── insertframe.html
│ │ │ │ ├── internal.js
│ │ │ │ ├── link/
│ │ │ │ │ └── link.html
│ │ │ │ ├── map/
│ │ │ │ │ ├── map.html
│ │ │ │ │ └── show.html
│ │ │ │ ├── music/
│ │ │ │ │ ├── music.css
│ │ │ │ │ ├── music.html
│ │ │ │ │ └── music.js
│ │ │ │ ├── preview/
│ │ │ │ │ └── preview.html
│ │ │ │ ├── scrawl/
│ │ │ │ │ ├── scrawl.css
│ │ │ │ │ ├── scrawl.html
│ │ │ │ │ └── scrawl.js
│ │ │ │ ├── searchreplace/
│ │ │ │ │ ├── searchreplace.html
│ │ │ │ │ └── searchreplace.js
│ │ │ │ ├── snapscreen/
│ │ │ │ │ └── snapscreen.html
│ │ │ │ ├── spechars/
│ │ │ │ │ ├── spechars.html
│ │ │ │ │ └── spechars.js
│ │ │ │ ├── table/
│ │ │ │ │ ├── edittable.css
│ │ │ │ │ ├── edittable.html
│ │ │ │ │ ├── edittable.js
│ │ │ │ │ ├── edittd.html
│ │ │ │ │ └── edittip.html
│ │ │ │ ├── template/
│ │ │ │ │ ├── config.js
│ │ │ │ │ ├── template.css
│ │ │ │ │ ├── template.html
│ │ │ │ │ └── template.js
│ │ │ │ ├── video/
│ │ │ │ │ ├── video.css
│ │ │ │ │ ├── video.html
│ │ │ │ │ └── video.js
│ │ │ │ ├── webapp/
│ │ │ │ │ └── webapp.html
│ │ │ │ └── wordimage/
│ │ │ │ ├── fClipboard_ueditor.swf
│ │ │ │ ├── imageUploader.swf
│ │ │ │ ├── tangram.js
│ │ │ │ ├── wordimage.html
│ │ │ │ └── wordimage.js
│ │ │ ├── index.html
│ │ │ ├── lang/
│ │ │ │ ├── en/
│ │ │ │ │ └── en.js
│ │ │ │ └── zh-cn/
│ │ │ │ └── zh-cn.js
│ │ │ ├── themes/
│ │ │ │ ├── default/
│ │ │ │ │ ├── css/
│ │ │ │ │ │ └── ueditor.css
│ │ │ │ │ └── dialogbase.css
│ │ │ │ └── iframe.css
│ │ │ ├── third-party/
│ │ │ │ ├── SyntaxHighlighter/
│ │ │ │ │ ├── shCore.js
│ │ │ │ │ └── shCoreDefault.css
│ │ │ │ ├── codemirror/
│ │ │ │ │ ├── codemirror.css
│ │ │ │ │ └── codemirror.js
│ │ │ │ ├── highcharts/
│ │ │ │ │ ├── adapters/
│ │ │ │ │ │ ├── mootools-adapter.js
│ │ │ │ │ │ ├── mootools-adapter.src.js
│ │ │ │ │ │ ├── prototype-adapter.js
│ │ │ │ │ │ ├── prototype-adapter.src.js
│ │ │ │ │ │ ├── standalone-framework.js
│ │ │ │ │ │ └── standalone-framework.src.js
│ │ │ │ │ ├── highcharts-more.js
│ │ │ │ │ ├── highcharts-more.src.js
│ │ │ │ │ ├── highcharts.js
│ │ │ │ │ ├── highcharts.src.js
│ │ │ │ │ ├── modules/
│ │ │ │ │ │ ├── annotations.js
│ │ │ │ │ │ ├── annotations.src.js
│ │ │ │ │ │ ├── canvas-tools.js
│ │ │ │ │ │ ├── canvas-tools.src.js
│ │ │ │ │ │ ├── data.js
│ │ │ │ │ │ ├── data.src.js
│ │ │ │ │ │ ├── drilldown.js
│ │ │ │ │ │ ├── drilldown.src.js
│ │ │ │ │ │ ├── exporting.js
│ │ │ │ │ │ ├── exporting.src.js
│ │ │ │ │ │ ├── funnel.js
│ │ │ │ │ │ ├── funnel.src.js
│ │ │ │ │ │ ├── heatmap.js
│ │ │ │ │ │ ├── heatmap.src.js
│ │ │ │ │ │ ├── map.js
│ │ │ │ │ │ ├── map.src.js
│ │ │ │ │ │ ├── no-data-to-display.js
│ │ │ │ │ │ └── no-data-to-display.src.js
│ │ │ │ │ └── themes/
│ │ │ │ │ ├── dark-blue.js
│ │ │ │ │ ├── dark-green.js
│ │ │ │ │ ├── gray.js
│ │ │ │ │ ├── grid.js
│ │ │ │ │ └── skies.js
│ │ │ │ ├── jquery-1.10.2.js
│ │ │ │ ├── video-js/
│ │ │ │ │ ├── video-js.css
│ │ │ │ │ ├── video-js.swf
│ │ │ │ │ ├── video.dev.js
│ │ │ │ │ └── video.js
│ │ │ │ ├── webuploader/
│ │ │ │ │ ├── Uploader.swf
│ │ │ │ │ ├── webuploader.css
│ │ │ │ │ ├── webuploader.custom.js
│ │ │ │ │ ├── webuploader.flashonly.js
│ │ │ │ │ ├── webuploader.html5only.js
│ │ │ │ │ ├── webuploader.min.bak.js
│ │ │ │ │ └── webuploader.withoutimage.js
│ │ │ │ └── zeroclipboard/
│ │ │ │ ├── ZeroClipboard.js
│ │ │ │ └── ZeroClipboard.swf
│ │ │ ├── ueditor.all.min.bak.js
│ │ │ ├── ueditor.config.js
│ │ │ └── ueditor.parse.js
│ │ └── vditor/
│ │ └── dist/
│ │ ├── content-theme/
│ │ │ ├── ant-design.css
│ │ │ ├── dark.css
│ │ │ ├── light.css
│ │ │ └── wechat.css
│ │ ├── css/
│ │ │ └── content-theme/
│ │ │ ├── ant-design.css
│ │ │ ├── dark.css
│ │ │ ├── light.css
│ │ │ └── wechat.css
│ │ ├── index.css
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── js/
│ │ │ ├── graphviz/
│ │ │ │ ├── full.render.js
│ │ │ │ └── viz.js
│ │ │ ├── highlight.js/
│ │ │ │ ├── LICENSE
│ │ │ │ └── third-languages.js
│ │ │ ├── i18n/
│ │ │ │ ├── en_US.js
│ │ │ │ ├── fr_FR.js
│ │ │ │ ├── ja_JP.js
│ │ │ │ ├── ko_KR.js
│ │ │ │ ├── pt_BR.js
│ │ │ │ ├── ru_RU.js
│ │ │ │ ├── sv_SE.js
│ │ │ │ ├── zh_CN.js
│ │ │ │ └── zh_TW.js
│ │ │ ├── icons/
│ │ │ │ ├── ant.js
│ │ │ │ └── material.js
│ │ │ ├── markmap/
│ │ │ │ └── prism.css
│ │ │ └── mathjax/
│ │ │ ├── LICENSE
│ │ │ ├── a11y/
│ │ │ │ ├── assistive-mml.js
│ │ │ │ ├── complexity.js
│ │ │ │ ├── explorer.js
│ │ │ │ └── semantic-enrich.js
│ │ │ ├── input/
│ │ │ │ ├── asciimath.js
│ │ │ │ ├── mml/
│ │ │ │ │ └── entities.js
│ │ │ │ ├── mml.js
│ │ │ │ ├── tex/
│ │ │ │ │ └── extensions/
│ │ │ │ │ ├── action.js
│ │ │ │ │ ├── all-packages.js
│ │ │ │ │ ├── ams.js
│ │ │ │ │ ├── amscd.js
│ │ │ │ │ ├── autoload.js
│ │ │ │ │ ├── bbox.js
│ │ │ │ │ ├── boldsymbol.js
│ │ │ │ │ ├── braket.js
│ │ │ │ │ ├── bussproofs.js
│ │ │ │ │ ├── cancel.js
│ │ │ │ │ ├── color.js
│ │ │ │ │ ├── colorV2.js
│ │ │ │ │ ├── configMacros.js
│ │ │ │ │ ├── enclose.js
│ │ │ │ │ ├── extpfeil.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── mhchem.js
│ │ │ │ │ ├── newcommand.js
│ │ │ │ │ ├── noerrors.js
│ │ │ │ │ ├── noundefined.js
│ │ │ │ │ ├── physics.js
│ │ │ │ │ ├── require.js
│ │ │ │ │ ├── tagFormat.js
│ │ │ │ │ ├── textmacros.js
│ │ │ │ │ ├── unicode.js
│ │ │ │ │ └── verb.js
│ │ │ │ ├── tex-base.js
│ │ │ │ ├── tex-full.js
│ │ │ │ └── tex.js
│ │ │ ├── output/
│ │ │ │ ├── chtml/
│ │ │ │ │ └── fonts/
│ │ │ │ │ └── tex.js
│ │ │ │ ├── chtml.js
│ │ │ │ ├── svg/
│ │ │ │ │ └── fonts/
│ │ │ │ │ └── tex.js
│ │ │ │ └── svg.js
│ │ │ ├── sre/
│ │ │ │ ├── mathmaps/
│ │ │ │ │ ├── de.js
│ │ │ │ │ ├── en.js
│ │ │ │ │ ├── es.js
│ │ │ │ │ ├── fr.js
│ │ │ │ │ ├── mathmaps_ie.js
│ │ │ │ │ └── nemeth.js
│ │ │ │ ├── sre-node.js
│ │ │ │ └── sre_browser.js
│ │ │ ├── tex-mml-chtml.js
│ │ │ └── tex-svg-full.js
│ │ ├── method.d.ts
│ │ ├── method.js
│ │ ├── ts/
│ │ │ ├── constants.d.ts
│ │ │ ├── devtools/
│ │ │ │ └── index.d.ts
│ │ │ ├── export/
│ │ │ │ └── index.d.ts
│ │ │ ├── hint/
│ │ │ │ └── index.d.ts
│ │ │ ├── ir/
│ │ │ │ ├── expandMarker.d.ts
│ │ │ │ ├── highlightToolbarIR.d.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── input.d.ts
│ │ │ │ ├── process.d.ts
│ │ │ │ └── processKeydown.d.ts
│ │ │ ├── markdown/
│ │ │ │ ├── SMILESRender.d.ts
│ │ │ │ ├── abcRender.d.ts
│ │ │ │ ├── adapterRender.d.ts
│ │ │ │ ├── anchorRender.d.ts
│ │ │ │ ├── chartRender.d.ts
│ │ │ │ ├── codeRender.d.ts
│ │ │ │ ├── flowchartRender.d.ts
│ │ │ │ ├── getHTML.d.ts
│ │ │ │ ├── getMarkdown.d.ts
│ │ │ │ ├── graphvizRender.d.ts
│ │ │ │ ├── highlightRender.d.ts
│ │ │ │ ├── lazyLoadImageRender.d.ts
│ │ │ │ ├── markmapRender.d.ts
│ │ │ │ ├── mathRender.d.ts
│ │ │ │ ├── mediaRender.d.ts
│ │ │ │ ├── mermaidRender.d.ts
│ │ │ │ ├── mindmapRender.d.ts
│ │ │ │ ├── outlineRender.d.ts
│ │ │ │ ├── plantumlRender.d.ts
│ │ │ │ ├── previewRender.d.ts
│ │ │ │ ├── setLute.d.ts
│ │ │ │ └── speechRender.d.ts
│ │ │ ├── outline/
│ │ │ │ └── index.d.ts
│ │ │ ├── preview/
│ │ │ │ ├── image.d.ts
│ │ │ │ └── index.d.ts
│ │ │ ├── resize/
│ │ │ │ └── index.d.ts
│ │ │ ├── sv/
│ │ │ │ ├── combineFootnote.d.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── inputEvent.d.ts
│ │ │ │ ├── process.d.ts
│ │ │ │ └── processKeydown.d.ts
│ │ │ ├── tip/
│ │ │ │ └── index.d.ts
│ │ │ ├── toolbar/
│ │ │ │ ├── Both.d.ts
│ │ │ │ ├── Br.d.ts
│ │ │ │ ├── CodeTheme.d.ts
│ │ │ │ ├── ContentTheme.d.ts
│ │ │ │ ├── Copy.d.ts
│ │ │ │ ├── Counter.d.ts
│ │ │ │ ├── Custom.d.ts
│ │ │ │ ├── Devtools.d.ts
│ │ │ │ ├── Divider.d.ts
│ │ │ │ ├── EditMode.d.ts
│ │ │ │ ├── Emoji.d.ts
│ │ │ │ ├── Export.d.ts
│ │ │ │ ├── Fullscreen.d.ts
│ │ │ │ ├── Headings.d.ts
│ │ │ │ ├── Help.d.ts
│ │ │ │ ├── Indent.d.ts
│ │ │ │ ├── Info.d.ts
│ │ │ │ ├── InsertAfter.d.ts
│ │ │ │ ├── InsertBefore.d.ts
│ │ │ │ ├── InsertCode.d.ts
│ │ │ │ ├── MenuItem.d.ts
│ │ │ │ ├── Outdent.d.ts
│ │ │ │ ├── Outline.d.ts
│ │ │ │ ├── Preview.d.ts
│ │ │ │ ├── Record.d.ts
│ │ │ │ ├── Redo.d.ts
│ │ │ │ ├── Undo.d.ts
│ │ │ │ ├── Upload.d.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ └── setToolbar.d.ts
│ │ │ ├── ui/
│ │ │ │ ├── initUI.d.ts
│ │ │ │ ├── setCodeTheme.d.ts
│ │ │ │ ├── setContentTheme.d.ts
│ │ │ │ ├── setPreviewMode.d.ts
│ │ │ │ └── setTheme.d.ts
│ │ │ ├── undo/
│ │ │ │ └── index.d.ts
│ │ │ ├── util/
│ │ │ │ ├── Options.d.ts
│ │ │ │ ├── RecordMedia.d.ts
│ │ │ │ ├── addScript.d.ts
│ │ │ │ ├── addStyle.d.ts
│ │ │ │ ├── code160to32.d.ts
│ │ │ │ ├── compatibility.d.ts
│ │ │ │ ├── editorCommonEvent.d.ts
│ │ │ │ ├── fixBrowserBehavior.d.ts
│ │ │ │ ├── function.d.ts
│ │ │ │ ├── getSelectText.d.ts
│ │ │ │ ├── hasClosest.d.ts
│ │ │ │ ├── hasClosestByHeadings.d.ts
│ │ │ │ ├── highlightToolbar.d.ts
│ │ │ │ ├── hotKey.d.ts
│ │ │ │ ├── log.d.ts
│ │ │ │ ├── merge.d.ts
│ │ │ │ ├── processCode.d.ts
│ │ │ │ ├── selection.d.ts
│ │ │ │ └── toc.d.ts
│ │ │ └── wysiwyg/
│ │ │ ├── afterRenderEvent.d.ts
│ │ │ ├── highlightToolbarWYSIWYG.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── inlineTag.d.ts
│ │ │ ├── input.d.ts
│ │ │ ├── processKeydown.d.ts
│ │ │ ├── renderDomByMd.d.ts
│ │ │ ├── setHeading.d.ts
│ │ │ ├── showCode.d.ts
│ │ │ └── toolbarEvent.d.ts
│ │ └── types/
│ │ └── index.d.ts
│ └── tasks/
│ ├── channel_update_key.go
│ ├── main.go
│ └── order_tasks.go
├── docker/
│ └── docker-compose.yml
└── web/
├── README.md
├── console/
│ ├── .editorconfig
│ ├── .eslintignore
│ ├── .eslintrc.cjs
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .husky/
│ │ ├── commit-msg
│ │ └── pre-commit
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc.js
│ ├── LINT_SETUP.md
│ ├── README.md
│ ├── auto-imports.d.ts
│ ├── commitlint.config.js
│ ├── components.d.ts
│ ├── index.html
│ ├── lint-staged.config.js
│ ├── package.json
│ ├── postcss.config.js
│ ├── public/
│ │ ├── UEditor/
│ │ │ ├── dialogs/
│ │ │ │ ├── anchor/
│ │ │ │ │ └── anchor.html
│ │ │ │ ├── attachment/
│ │ │ │ │ ├── attachment.css
│ │ │ │ │ ├── attachment.html
│ │ │ │ │ └── attachment.js
│ │ │ │ ├── background/
│ │ │ │ │ ├── background.css
│ │ │ │ │ ├── background.html
│ │ │ │ │ └── background.js
│ │ │ │ ├── charts/
│ │ │ │ │ ├── chart.config.js
│ │ │ │ │ ├── charts.css
│ │ │ │ │ ├── charts.html
│ │ │ │ │ └── charts.js
│ │ │ │ ├── emotion/
│ │ │ │ │ ├── emotion.css
│ │ │ │ │ ├── emotion.html
│ │ │ │ │ └── emotion.js
│ │ │ │ ├── gmap/
│ │ │ │ │ └── gmap.html
│ │ │ │ ├── help/
│ │ │ │ │ ├── help.css
│ │ │ │ │ ├── help.html
│ │ │ │ │ └── help.js
│ │ │ │ ├── image/
│ │ │ │ │ ├── image.css
│ │ │ │ │ ├── image.html
│ │ │ │ │ └── image.js
│ │ │ │ ├── insertframe/
│ │ │ │ │ └── insertframe.html
│ │ │ │ ├── internal.js
│ │ │ │ ├── link/
│ │ │ │ │ └── link.html
│ │ │ │ ├── map/
│ │ │ │ │ ├── map.html
│ │ │ │ │ └── show.html
│ │ │ │ ├── music/
│ │ │ │ │ ├── music.css
│ │ │ │ │ ├── music.html
│ │ │ │ │ └── music.js
│ │ │ │ ├── preview/
│ │ │ │ │ └── preview.html
│ │ │ │ ├── scrawl/
│ │ │ │ │ ├── scrawl.css
│ │ │ │ │ ├── scrawl.html
│ │ │ │ │ └── scrawl.js
│ │ │ │ ├── searchreplace/
│ │ │ │ │ ├── searchreplace.html
│ │ │ │ │ └── searchreplace.js
│ │ │ │ ├── snapscreen/
│ │ │ │ │ └── snapscreen.html
│ │ │ │ ├── spechars/
│ │ │ │ │ ├── spechars.html
│ │ │ │ │ └── spechars.js
│ │ │ │ ├── table/
│ │ │ │ │ ├── edittable.css
│ │ │ │ │ ├── edittable.html
│ │ │ │ │ ├── edittable.js
│ │ │ │ │ ├── edittd.html
│ │ │ │ │ └── edittip.html
│ │ │ │ ├── template/
│ │ │ │ │ ├── config.js
│ │ │ │ │ ├── template.css
│ │ │ │ │ ├── template.html
│ │ │ │ │ └── template.js
│ │ │ │ ├── video/
│ │ │ │ │ ├── video.css
│ │ │ │ │ ├── video.html
│ │ │ │ │ └── video.js
│ │ │ │ ├── webapp/
│ │ │ │ │ └── webapp.html
│ │ │ │ └── wordimage/
│ │ │ │ ├── tangram.js
│ │ │ │ ├── wordimage.html
│ │ │ │ └── wordimage.js
│ │ │ ├── index.html
│ │ │ ├── lang/
│ │ │ │ ├── en/
│ │ │ │ │ └── en.js
│ │ │ │ └── zh-cn/
│ │ │ │ └── zh-cn.js
│ │ │ ├── themes/
│ │ │ │ ├── default/
│ │ │ │ │ ├── css/
│ │ │ │ │ │ └── ueditor.css
│ │ │ │ │ └── dialogbase.css
│ │ │ │ └── iframe.css
│ │ │ ├── third-party/
│ │ │ │ ├── SyntaxHighlighter/
│ │ │ │ │ ├── shCore.js
│ │ │ │ │ └── shCoreDefault.css
│ │ │ │ ├── codemirror/
│ │ │ │ │ ├── codemirror.css
│ │ │ │ │ └── codemirror.js
│ │ │ │ ├── highcharts/
│ │ │ │ │ ├── adapters/
│ │ │ │ │ │ ├── mootools-adapter.js
│ │ │ │ │ │ ├── mootools-adapter.src.js
│ │ │ │ │ │ ├── prototype-adapter.js
│ │ │ │ │ │ ├── prototype-adapter.src.js
│ │ │ │ │ │ ├── standalone-framework.js
│ │ │ │ │ │ └── standalone-framework.src.js
│ │ │ │ │ ├── highcharts-more.js
│ │ │ │ │ ├── highcharts-more.src.js
│ │ │ │ │ ├── highcharts.js
│ │ │ │ │ ├── highcharts.src.js
│ │ │ │ │ ├── modules/
│ │ │ │ │ │ ├── annotations.js
│ │ │ │ │ │ ├── annotations.src.js
│ │ │ │ │ │ ├── canvas-tools.js
│ │ │ │ │ │ ├── canvas-tools.src.js
│ │ │ │ │ │ ├── data.js
│ │ │ │ │ │ ├── data.src.js
│ │ │ │ │ │ ├── drilldown.js
│ │ │ │ │ │ ├── drilldown.src.js
│ │ │ │ │ │ ├── exporting.js
│ │ │ │ │ │ ├── exporting.src.js
│ │ │ │ │ │ ├── funnel.js
│ │ │ │ │ │ ├── funnel.src.js
│ │ │ │ │ │ ├── heatmap.js
│ │ │ │ │ │ ├── heatmap.src.js
│ │ │ │ │ │ ├── map.js
│ │ │ │ │ │ ├── map.src.js
│ │ │ │ │ │ ├── no-data-to-display.js
│ │ │ │ │ │ └── no-data-to-display.src.js
│ │ │ │ │ └── themes/
│ │ │ │ │ ├── dark-blue.js
│ │ │ │ │ ├── dark-green.js
│ │ │ │ │ ├── gray.js
│ │ │ │ │ ├── grid.js
│ │ │ │ │ └── skies.js
│ │ │ │ ├── jquery-1.10.2.js
│ │ │ │ ├── video-js/
│ │ │ │ │ ├── video-js.css
│ │ │ │ │ ├── video.dev.js
│ │ │ │ │ └── video.js
│ │ │ │ ├── webuploader/
│ │ │ │ │ ├── webuploader.css
│ │ │ │ │ ├── webuploader.custom.js
│ │ │ │ │ ├── webuploader.flashonly.js
│ │ │ │ │ ├── webuploader.html5only.js
│ │ │ │ │ ├── webuploader.min.bak.js
│ │ │ │ │ └── webuploader.withoutimage.js
│ │ │ │ └── zeroclipboard/
│ │ │ │ └── ZeroClipboard.js
│ │ │ ├── ueditor.all.min.bak.js
│ │ │ ├── ueditor.config.js
│ │ │ └── ueditor.parse.js
│ │ ├── km-login/
│ │ │ └── index.html
│ │ ├── manifest.json
│ │ ├── oauth_login.html
│ │ └── saas-login/
│ │ └── index.html
│ ├── src/
│ │ ├── App.vue
│ │ ├── api/
│ │ │ ├── code.ts
│ │ │ ├── config.ts
│ │ │ ├── errorHandler.ts
│ │ │ ├── index.ts
│ │ │ ├── modules/
│ │ │ │ ├── agent.ts
│ │ │ │ ├── agents/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── ai-link.ts
│ │ │ │ ├── auth.ts
│ │ │ │ ├── banner/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── channel/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── channel.ts
│ │ │ │ ├── chunk-setting.ts
│ │ │ │ ├── common.ts
│ │ │ │ ├── conversation.ts
│ │ │ │ ├── department.ts
│ │ │ │ ├── dingtalk.ts
│ │ │ │ ├── domain/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── enterprise.ts
│ │ │ │ ├── group.ts
│ │ │ │ ├── libraries/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── message.ts
│ │ │ │ ├── navigation/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── order.ts
│ │ │ │ ├── payment/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── permissions.ts
│ │ │ │ ├── platform-settings/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── prompt.ts
│ │ │ │ ├── provider.ts
│ │ │ │ ├── providers/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── saas.ts
│ │ │ │ ├── setting.ts
│ │ │ │ ├── spaces/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── subscription.ts
│ │ │ │ ├── system-log/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── template-style.ts
│ │ │ │ ├── upload.ts
│ │ │ │ ├── user.ts
│ │ │ │ └── wecom.ts
│ │ │ ├── readme.md
│ │ │ ├── signature.ts
│ │ │ └── types.ts
│ │ ├── apis/
│ │ │ ├── index.ts
│ │ │ ├── modules/
│ │ │ │ ├── conversation.ts
│ │ │ │ ├── enterprise.ts
│ │ │ │ ├── group.ts
│ │ │ │ ├── qyy.ts
│ │ │ │ ├── setting.ts
│ │ │ │ └── user.ts
│ │ │ └── readme.md
│ │ ├── components/
│ │ │ ├── AgentPicker/
│ │ │ │ └── index.vue
│ │ │ ├── CropperDialog/
│ │ │ │ └── index.vue
│ │ │ ├── DeptMemberPicker/
│ │ │ │ └── index.vue
│ │ │ ├── DialogueRecord/
│ │ │ │ ├── drawer.vue
│ │ │ │ └── index.vue
│ │ │ ├── EntityDisplay/
│ │ │ │ ├── README.md
│ │ │ │ ├── index.vue
│ │ │ │ └── types.ts
│ │ │ ├── Filter/
│ │ │ │ ├── date-range.vue
│ │ │ │ ├── select.vue
│ │ │ │ └── user.vue
│ │ │ ├── Fullscreen/
│ │ │ │ └── index.vue
│ │ │ ├── GroupDialog/
│ │ │ │ └── index.vue
│ │ │ ├── GroupSelect/
│ │ │ │ └── index.vue
│ │ │ ├── GroupTabs/
│ │ │ │ └── index.vue
│ │ │ ├── Header/
│ │ │ │ └── index.vue
│ │ │ ├── LanguageDropdown/
│ │ │ │ └── LanguageDropdown.vue
│ │ │ ├── Layout/
│ │ │ │ └── index.vue
│ │ │ ├── Markdown/
│ │ │ │ └── editor.vue
│ │ │ ├── Model/
│ │ │ │ ├── dialog.vue
│ │ │ │ ├── index.ts
│ │ │ │ ├── select.vue
│ │ │ │ └── view.vue
│ │ │ ├── OpenData/
│ │ │ │ └── index.vue
│ │ │ ├── Pagination/
│ │ │ │ ├── index.vue
│ │ │ │ └── simple.vue
│ │ │ ├── Permission/
│ │ │ │ ├── constant.ts
│ │ │ │ ├── data.ts
│ │ │ │ ├── member-selector.vue
│ │ │ │ └── selector.vue
│ │ │ ├── Prompt/
│ │ │ │ ├── README.md
│ │ │ │ ├── generate.vue
│ │ │ │ ├── input.vue
│ │ │ │ ├── optimize.vue
│ │ │ │ └── test/
│ │ │ │ ├── component.vue
│ │ │ │ └── index.ts
│ │ │ ├── ResourcePicker/
│ │ │ │ └── index.vue
│ │ │ ├── Scroller/
│ │ │ │ └── index.vue
│ │ │ ├── Search/
│ │ │ │ └── index.vue
│ │ │ ├── SelectPlus/
│ │ │ │ └── index.vue
│ │ │ ├── ServiceDialog/
│ │ │ │ └── index.vue
│ │ │ ├── Sortable/
│ │ │ │ └── index.vue
│ │ │ ├── SvgIcon/
│ │ │ │ └── index.vue
│ │ │ ├── TablePlus/
│ │ │ │ ├── create-slots.ts
│ │ │ │ └── index.vue
│ │ │ ├── TipConfirm/
│ │ │ │ ├── index.vue
│ │ │ │ └── setup.ts
│ │ │ ├── UEditor/
│ │ │ │ └── index.vue
│ │ │ ├── Upload/
│ │ │ │ ├── certificate.vue
│ │ │ │ ├── image.vue
│ │ │ │ └── index.vue
│ │ │ ├── UserLoginDialog/
│ │ │ │ ├── index.vue
│ │ │ │ └── setup.ts
│ │ │ └── VerificationCodeInput/
│ │ │ └── index.vue
│ │ ├── constants/
│ │ │ ├── .gitkeep
│ │ │ ├── agent.ts
│ │ │ ├── banner.ts
│ │ │ ├── chunk.ts
│ │ │ ├── domain.ts
│ │ │ ├── enterprise.ts
│ │ │ ├── group.ts
│ │ │ ├── navigation.ts
│ │ │ ├── order.ts
│ │ │ ├── payment.ts
│ │ │ ├── platform/
│ │ │ │ ├── agent.ts
│ │ │ │ ├── channel.ts
│ │ │ │ ├── config.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── model.ts
│ │ │ │ └── provider.ts
│ │ │ ├── sync.ts
│ │ │ ├── system-log.ts
│ │ │ └── user.ts
│ │ ├── directive/
│ │ │ ├── copy.ts
│ │ │ ├── debounce.ts
│ │ │ ├── index.ts
│ │ │ ├── overflow-tooltip.ts
│ │ │ ├── readme.md
│ │ │ ├── router.ts
│ │ │ ├── tooltip.ts
│ │ │ ├── truncate.ts
│ │ │ └── version.ts
│ │ ├── global/
│ │ │ ├── filters.ts
│ │ │ ├── index.ts
│ │ │ ├── methods.ts
│ │ │ └── readme.md
│ │ ├── hooks/
│ │ │ ├── useBasicLayout.ts
│ │ │ ├── useEntityInfo.ts
│ │ │ ├── useEnv.ts
│ │ │ ├── useMobile.ts
│ │ │ ├── useScroll.ts
│ │ │ ├── useSso.ts
│ │ │ ├── useTooltip.ts
│ │ │ └── useVmodel.ts
│ │ ├── icons/
│ │ │ ├── 403.vue
│ │ │ └── 500.vue
│ │ ├── layout/
│ │ │ ├── Child.vue
│ │ │ ├── Layout.vue
│ │ │ └── Sider.vue
│ │ ├── locales/
│ │ │ ├── en-v2.json
│ │ │ ├── en.json
│ │ │ ├── index.ts
│ │ │ ├── ja.json
│ │ │ ├── zh-cn.json
│ │ │ └── zh-tw.json
│ │ ├── main.ts
│ │ ├── plugins/
│ │ │ ├── assets.ts
│ │ │ └── index.ts
│ │ ├── router/
│ │ │ └── index.ts
│ │ ├── stores/
│ │ │ ├── index.ts
│ │ │ └── modules/
│ │ │ ├── channel.ts
│ │ │ ├── conversation.ts
│ │ │ ├── domain.ts
│ │ │ ├── enterprise.ts
│ │ │ ├── group.ts
│ │ │ ├── setting.ts
│ │ │ └── user.ts
│ │ ├── styles/
│ │ │ ├── element/
│ │ │ │ ├── _variables.scss
│ │ │ │ ├── override.scss
│ │ │ │ └── vars.scss
│ │ │ ├── global.scss
│ │ │ └── lib/
│ │ │ └── tailwind.css
│ │ ├── types/
│ │ │ ├── agent.d.ts
│ │ │ ├── ai-link.d.ts
│ │ │ ├── category.d.ts
│ │ │ ├── channel.d.ts
│ │ │ ├── domain.d.ts
│ │ │ ├── enterprise.d.ts
│ │ │ ├── entity.ts
│ │ │ ├── env.d.ts
│ │ │ ├── global.d.ts
│ │ │ ├── payment.d.ts
│ │ │ ├── platform.d.ts
│ │ │ ├── settings.d.ts
│ │ │ ├── subscription.d.ts
│ │ │ └── vue-template.d.ts
│ │ ├── utils/
│ │ │ ├── cache.ts
│ │ │ ├── config.ts
│ │ │ ├── copy.ts
│ │ │ ├── event-bus.ts
│ │ │ ├── filter.ts
│ │ │ ├── form-rule.ts
│ │ │ ├── form-rule.v2.ts
│ │ │ ├── form-validator.ts
│ │ │ ├── functions/
│ │ │ │ ├── debounce.ts
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── is/
│ │ │ │ └── index.ts
│ │ │ ├── loadLib.ts
│ │ │ ├── md5.ts
│ │ │ ├── moment.ts
│ │ │ ├── request/
│ │ │ │ ├── axios.ts
│ │ │ │ ├── blob.ts
│ │ │ │ ├── code.ts
│ │ │ │ ├── helper.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── signature.ts
│ │ │ ├── timer-manager.ts
│ │ │ ├── url.ts
│ │ │ ├── version.ts
│ │ │ └── wecom.ts
│ │ └── views/
│ │ ├── agent/
│ │ │ ├── create/
│ │ │ │ ├── components/
│ │ │ │ │ ├── agent-info.vue
│ │ │ │ │ ├── agent-type.vue
│ │ │ │ │ ├── base-config.vue
│ │ │ │ │ ├── expand-config.vue
│ │ │ │ │ ├── field-input-setting.vue
│ │ │ │ │ ├── field-input.vue
│ │ │ │ │ ├── limit-config.vue
│ │ │ │ │ ├── relate-agents-dialog.vue
│ │ │ │ │ ├── relate-agents-setting.vue
│ │ │ │ │ ├── relate-agents.vue
│ │ │ │ │ └── use-scope.vue
│ │ │ │ ├── drawer.vue
│ │ │ │ ├── guide.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── platform/
│ │ │ │ │ ├── 53ai-agent.vue
│ │ │ │ │ ├── app-builder-agent.vue
│ │ │ │ │ ├── bailian.vue
│ │ │ │ │ ├── coze-cn.vue
│ │ │ │ │ ├── coze-osv.vue
│ │ │ │ │ ├── dify-agent.vue
│ │ │ │ │ ├── fastgpt-agent.vue
│ │ │ │ │ ├── index.vue
│ │ │ │ │ ├── maxkb-agent.vue
│ │ │ │ │ ├── n8n.vue
│ │ │ │ │ ├── prompt.vue
│ │ │ │ │ ├── tencent.vue
│ │ │ │ │ ├── volcengine.vue
│ │ │ │ │ └── yuanqi.vue
│ │ │ │ ├── response/
│ │ │ │ │ ├── chat.vue
│ │ │ │ │ └── completion.vue
│ │ │ │ └── store.ts
│ │ │ └── index.vue
│ │ ├── banner/
│ │ │ └── index.vue
│ │ ├── chunk/
│ │ │ └── index.vue
│ │ ├── domain/
│ │ │ ├── components/
│ │ │ │ ├── exclusive-setting-dialog.vue
│ │ │ │ └── independent-setting-dialog.vue
│ │ │ └── index.vue
│ │ ├── exception/
│ │ │ ├── 404/
│ │ │ │ └── index.vue
│ │ │ ├── 500/
│ │ │ │ └── index.vue
│ │ │ └── mobile-tip/
│ │ │ └── index.vue
│ │ ├── index.vue
│ │ ├── info/
│ │ │ └── index.vue
│ │ ├── login/
│ │ │ ├── components/
│ │ │ │ ├── apply-form.vue
│ │ │ │ ├── create-enterprise-form.vue
│ │ │ │ ├── enterprise-list.vue
│ │ │ │ ├── forget-form.vue
│ │ │ │ ├── login-form.vue
│ │ │ │ ├── register-form.vue
│ │ │ │ └── wechat.vue
│ │ │ └── index.vue
│ │ ├── model/
│ │ │ └── index.vue
│ │ ├── navigation/
│ │ │ ├── components/
│ │ │ │ ├── nav-create-dialog.vue
│ │ │ │ ├── nav-create-drawer.vue
│ │ │ │ ├── pc-navigation-pane.vue
│ │ │ │ └── seo-setting-dialog.vue
│ │ │ ├── index.vue
│ │ │ └── web-setting.vue
│ │ ├── order/
│ │ │ ├── components/
│ │ │ │ └── order-add-dialog.vue
│ │ │ └── index.vue
│ │ ├── parse/
│ │ │ └── index.vue
│ │ ├── payment/
│ │ │ ├── components/
│ │ │ │ ├── alipay-setting-dialog.vue
│ │ │ │ ├── manual-setting-dialog.vue
│ │ │ │ ├── payment-card.vue
│ │ │ │ └── wechat-setting-dialog.vue
│ │ │ └── index.vue
│ │ ├── platform/
│ │ │ ├── components/
│ │ │ │ ├── agent-list-drawer.vue
│ │ │ │ ├── auth-list-drawer.vue
│ │ │ │ ├── model-group.vue
│ │ │ │ ├── model-save-dialog.vue
│ │ │ │ ├── model-select-dialog.vue
│ │ │ │ ├── model-setting-dialog.vue
│ │ │ │ ├── provider-authorize-dialog.vue
│ │ │ │ └── provider-card.vue
│ │ │ ├── componentsv2/
│ │ │ │ ├── model-group.vue
│ │ │ │ ├── model-save-dialog.vue
│ │ │ │ └── model-select-dialog.vue
│ │ │ ├── index.vue
│ │ │ ├── km.vue
│ │ │ └── view/
│ │ │ ├── file-editor.vue
│ │ │ ├── file-parser.vue
│ │ │ ├── model.vue
│ │ │ └── web-search.vue
│ │ ├── prompt/
│ │ │ ├── components/
│ │ │ │ ├── create-drawer.vue
│ │ │ │ ├── form.vue
│ │ │ │ └── links-dialog.vue
│ │ │ ├── create/
│ │ │ │ ├── guide.vue
│ │ │ │ ├── index.vue
│ │ │ │ └── store.ts
│ │ │ └── index.vue
│ │ ├── search/
│ │ │ └── index.vue
│ │ ├── smtp/
│ │ │ ├── components/
│ │ │ │ └── email-form.vue
│ │ │ └── index.vue
│ │ ├── space/
│ │ │ ├── components/
│ │ │ │ ├── info-save-dialog.vue
│ │ │ │ └── knowledge-list-drawer.vue
│ │ │ └── index.vue
│ │ ├── sso/
│ │ │ ├── components/
│ │ │ │ ├── access-dialog.vue
│ │ │ │ └── api-access-dialog.vue
│ │ │ └── index.vue
│ │ ├── statistics/
│ │ │ └── index.vue
│ │ ├── subscription/
│ │ │ ├── index.vue
│ │ │ └── utils.ts
│ │ ├── svg/
│ │ │ └── index.vue
│ │ ├── system-log/
│ │ │ └── index.vue
│ │ ├── template-style/
│ │ │ └── index.vue
│ │ ├── toolbox/
│ │ │ ├── components/
│ │ │ │ ├── add-account.vue
│ │ │ │ ├── create-dialog.vue
│ │ │ │ ├── create-drawer.vue
│ │ │ │ ├── store-dialog.vue
│ │ │ │ ├── store-view.vue
│ │ │ │ └── use-group.vue
│ │ │ └── index.vue
│ │ ├── user/
│ │ │ ├── admin/
│ │ │ │ └── index.vue
│ │ │ ├── components/
│ │ │ │ ├── department-add-dialog.vue
│ │ │ │ ├── department-tree-select.vue
│ │ │ │ ├── department-tree.vue
│ │ │ │ ├── group-add-dialog.vue
│ │ │ │ ├── user-add-dialog.vue
│ │ │ │ ├── user-internal-add-dialog.vue
│ │ │ │ ├── user-internal-edit-drawer.vue
│ │ │ │ ├── user-internal-status.vue
│ │ │ │ └── user-select-dialog.vue
│ │ │ ├── dialogue-record/
│ │ │ │ └── index.vue
│ │ │ ├── internal/
│ │ │ │ ├── account.vue
│ │ │ │ ├── group.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── member.vue
│ │ │ │ └── organization.vue
│ │ │ └── register/
│ │ │ └── index.vue
│ │ └── viewer/
│ │ └── index.vue
│ ├── stylelint.config.js
│ ├── tailwind.config.js
│ ├── tsconfig.json
│ ├── vite-plugins/
│ │ └── conditional-compilation.ts
│ └── vite.config.ts
└── front/
├── .editorconfig
├── .eslintignore
├── .eslintrc.cjs
├── .gitattributes
├── .gitignore
├── .husky/
│ ├── commit-msg
│ └── pre-commit
├── .npmrc
├── .prettierignore
├── .prettierrc.js
├── LINT_SETUP.md
├── README.md
├── build/
│ ├── entitlements.mac.plist
│ └── icon.icns
├── commitlint.config.js
├── dev-app-update.yml
├── electron-builder.yml
├── electron.vite.config.ts
├── lint-staged.config.js
├── native/
│ ├── binding.gyp
│ ├── mouse_select_status_mac.mm
│ └── mouse_select_status_win.cpp
├── package.json
├── postcss.config.js
├── src/
│ ├── main/
│ │ ├── enums/
│ │ │ └── SystemTypeEnum.ts
│ │ ├── helper/
│ │ │ └── web.ts
│ │ ├── host.ts
│ │ ├── index.ts
│ │ ├── service/
│ │ │ ├── AutoUpdater.ts
│ │ │ ├── Bookmarks.ts
│ │ │ ├── Container.ts
│ │ │ ├── FileSystem.ts
│ │ │ ├── GlobalShortcutEvent.ts
│ │ │ ├── Main.ts
│ │ │ ├── MouseEventsHandler.ts
│ │ │ └── Pages.ts
│ │ ├── utils/
│ │ │ ├── index.ts
│ │ │ └── validate.ts
│ │ └── window/
│ │ ├── FastChat.ts
│ │ ├── HoverMenu.ts
│ │ └── Main.ts
│ ├── preload/
│ │ ├── fastChat.ts
│ │ ├── hoverMenu.ts
│ │ └── index.ts
│ └── renderer/
│ ├── index.html
│ ├── main/
│ │ ├── App.vue
│ │ ├── api/
│ │ │ ├── code.ts
│ │ │ ├── config.ts
│ │ │ ├── errorHandler.ts
│ │ │ ├── host.ts
│ │ │ ├── index.ts
│ │ │ ├── modules/
│ │ │ │ ├── agent.ts
│ │ │ │ ├── chat.ts
│ │ │ │ ├── common.ts
│ │ │ │ ├── conversation.ts
│ │ │ │ ├── enterprise.ts
│ │ │ │ ├── group.ts
│ │ │ │ ├── links.ts
│ │ │ │ ├── navigation.ts
│ │ │ │ ├── order.ts
│ │ │ │ ├── payment.ts
│ │ │ │ ├── prompt.ts
│ │ │ │ ├── setting.ts
│ │ │ │ ├── share/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── transform.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── subscription.ts
│ │ │ │ ├── system.ts
│ │ │ │ ├── upload.ts
│ │ │ │ └── user.ts
│ │ │ ├── signature.ts
│ │ │ └── types.ts
│ │ ├── assets/
│ │ │ └── styles/
│ │ │ ├── animate.css
│ │ │ ├── custom.css
│ │ │ ├── element-plus.css
│ │ │ ├── global.css
│ │ │ └── tailwind.css
│ │ ├── components/
│ │ │ ├── AuthTagGroup/
│ │ │ │ └── index.vue
│ │ │ ├── CropperDialog/
│ │ │ │ └── index.vue
│ │ │ ├── ExpireModal/
│ │ │ │ └── index.vue
│ │ │ ├── FileUpload/
│ │ │ │ └── index.vue
│ │ │ ├── Filter/
│ │ │ │ └── date-range.vue
│ │ │ ├── Fullscreen/
│ │ │ │ └── index.vue
│ │ │ ├── LazyComponent/
│ │ │ │ └── index.vue
│ │ │ ├── Lead/
│ │ │ │ └── index.vue
│ │ │ ├── LoginModal/
│ │ │ │ ├── email.vue
│ │ │ │ ├── forgetPassword.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── register.vue
│ │ │ │ ├── resetPassword.vue
│ │ │ │ ├── wechat.vue
│ │ │ │ └── wecom.vue
│ │ │ ├── MarkMap/
│ │ │ │ ├── index.ts
│ │ │ │ ├── index.vue
│ │ │ │ └── vis.vue
│ │ │ ├── Markdown/
│ │ │ │ ├── editor.vue
│ │ │ │ ├── helper.ts
│ │ │ │ └── preview.vue
│ │ │ ├── Pagination/
│ │ │ │ └── index.vue
│ │ │ ├── Prompt/
│ │ │ │ └── input.vue
│ │ │ ├── RelatedScene/
│ │ │ │ └── index.vue
│ │ │ ├── Search/
│ │ │ │ └── index.vue
│ │ │ ├── Slider/
│ │ │ │ └── index.vue
│ │ │ ├── Sortable/
│ │ │ │ └── index.vue
│ │ │ ├── SvgIcon.vue
│ │ │ ├── TablePlus/
│ │ │ │ ├── create-slots.ts
│ │ │ │ └── index.vue
│ │ │ ├── Upgrade/
│ │ │ │ ├── index.vue
│ │ │ │ └── payment-qrcode.vue
│ │ │ ├── Upload/
│ │ │ │ ├── image.vue
│ │ │ │ └── index.vue
│ │ │ ├── VersionModal/
│ │ │ │ └── index.vue
│ │ │ └── modals/
│ │ │ └── .editorconfig
│ │ ├── constants/
│ │ │ ├── currency.ts
│ │ │ ├── events.ts
│ │ │ ├── navigation.ts
│ │ │ ├── payment.ts
│ │ │ ├── storage.ts
│ │ │ └── website.ts
│ │ ├── directive/
│ │ │ ├── README.md
│ │ │ ├── copy.ts
│ │ │ ├── debounce.ts
│ │ │ ├── index.ts
│ │ │ ├── permission.ts
│ │ │ ├── tooltip.ts
│ │ │ └── trim.ts
│ │ ├── global/
│ │ │ └── index.ts
│ │ ├── hooks/
│ │ │ ├── README.md
│ │ │ ├── useBasicLayout.ts
│ │ │ ├── useEmail.ts
│ │ │ ├── useEnv.ts
│ │ │ ├── useMobile.ts
│ │ │ ├── useScroll.ts
│ │ │ └── useVmodel.ts
│ │ ├── layout/
│ │ │ ├── header.vue
│ │ │ ├── index.vue
│ │ │ ├── m-footer.vue
│ │ │ └── sider.vue
│ │ ├── locales/
│ │ │ ├── en.ts
│ │ │ ├── index.ts
│ │ │ ├── jp.ts
│ │ │ ├── zh-cn.ts
│ │ │ └── zh-tw.ts
│ │ ├── main.ts
│ │ ├── plugins/
│ │ │ └── index.ts
│ │ ├── router/
│ │ │ └── index.ts
│ │ ├── stores/
│ │ │ ├── index.ts
│ │ │ └── modules/
│ │ │ ├── agent.ts
│ │ │ ├── browser-setting.ts
│ │ │ ├── conversation.ts
│ │ │ ├── enterprise.ts
│ │ │ ├── global.ts
│ │ │ ├── links.ts
│ │ │ ├── navigation.ts
│ │ │ ├── prompt.ts
│ │ │ └── user.ts
│ │ ├── typings/
│ │ │ ├── Browser.d.ts
│ │ │ ├── agent.d.ts
│ │ │ ├── category.d.ts
│ │ │ ├── conversation.d.ts
│ │ │ ├── enterprise.d.ts
│ │ │ ├── global.d.ts
│ │ │ ├── link.d.ts
│ │ │ ├── navigation.d.ts
│ │ │ ├── order.d.ts
│ │ │ ├── prompt.ts
│ │ │ ├── subscription.d.ts
│ │ │ └── user.d.ts
│ │ ├── utils/
│ │ │ ├── cache.ts
│ │ │ ├── copy.ts
│ │ │ ├── event-bus.ts
│ │ │ ├── file.ts
│ │ │ ├── filter.ts
│ │ │ ├── form-rules.ts
│ │ │ ├── functions/
│ │ │ │ ├── debounce.ts
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── loadLib.ts
│ │ │ ├── md5.ts
│ │ │ ├── moment.ts
│ │ │ ├── permission.ts
│ │ │ ├── router.ts
│ │ │ ├── scroll.ts
│ │ │ ├── storage.ts
│ │ │ └── url.ts
│ │ └── views/
│ │ ├── agent/
│ │ │ ├── components/
│ │ │ │ └── list.vue
│ │ │ └── index.vue
│ │ ├── chat/
│ │ │ ├── chat/
│ │ │ │ ├── components/
│ │ │ │ │ ├── agent-tooltip.vue
│ │ │ │ │ └── history.vue
│ │ │ │ └── index.vue
│ │ │ ├── completion/
│ │ │ │ └── index.vue
│ │ │ ├── helper.vue
│ │ │ ├── index.vue
│ │ │ └── store.ts
│ │ ├── custom/
│ │ │ └── index.vue
│ │ ├── desktop/
│ │ │ ├── components/
│ │ │ │ ├── BookMarks.vue
│ │ │ │ ├── Browser.vue
│ │ │ │ ├── Error.vue
│ │ │ │ ├── GNBTabs.vue
│ │ │ │ ├── MultiBrowser.vue
│ │ │ │ └── Reader/
│ │ │ │ ├── html.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── markdown.vue
│ │ │ │ └── summarize.vue
│ │ │ ├── index.vue
│ │ │ ├── stores/
│ │ │ │ ├── tabs.ts
│ │ │ │ └── user.ts
│ │ │ └── tools/
│ │ │ ├── index.vue
│ │ │ └── toolbox.vue
│ │ ├── discover/
│ │ │ └── index.vue
│ │ ├── index/
│ │ │ ├── agent/
│ │ │ │ ├── chat.vue
│ │ │ │ └── index.vue
│ │ │ ├── index.vue
│ │ │ ├── layout.vue
│ │ │ ├── prompt/
│ │ │ │ ├── detail.vue
│ │ │ │ └── index.vue
│ │ │ ├── redirect.vue
│ │ │ └── toolkit.vue
│ │ ├── order/
│ │ │ └── index.vue
│ │ ├── profile/
│ │ │ ├── about.vue
│ │ │ ├── changeMobile.vue
│ │ │ ├── common.vue
│ │ │ ├── glider.vue
│ │ │ ├── index.vue
│ │ │ ├── password.vue
│ │ │ ├── toolbar.vue
│ │ │ └── userinfo.vue
│ │ ├── prompt/
│ │ │ ├── detail/
│ │ │ │ └── index.vue
│ │ │ ├── index.vue
│ │ │ └── view.vue
│ │ ├── share/
│ │ │ └── chat.vue
│ │ ├── svglist/
│ │ │ └── index.vue
│ │ └── toolkit/
│ │ ├── components/
│ │ │ ├── account-dialog.vue
│ │ │ ├── group-list.vue
│ │ │ └── list.vue
│ │ └── index.vue
│ └── public/
│ └── oauth_login.html
├── stylelint.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.web.json
├── vite.common.ts
└── vite.config.ts
Showing preview only (2,128K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (12493 symbols across 590 files)
FILE: api/common/ctxkey/key.go
constant Config (line 4) | Config = "config"
constant Id (line 5) | Id = "id"
constant Username (line 6) | Username = "username"
constant Role (line 7) | Role = "role"
constant Status (line 8) | Status = "status"
constant Channel (line 9) | Channel = "channel"
constant ChannelId (line 10) | ChannelId = "channel_id"
constant SpecificChannelId (line 11) | SpecificChannelId = "specific_channel_id"
constant RequestModel (line 12) | RequestModel = "request_model"
constant ConvertedRequest (line 13) | ConvertedRequest = "converted_request"
constant OriginalModel (line 14) | OriginalModel = "original_model"
constant Group (line 15) | Group = "group"
constant ModelMapping (line 16) | ModelMapping = "model_mapping"
constant ChannelName (line 17) | ChannelName = "channel_name"
constant TokenId (line 18) | TokenId = "token_id"
constant TokenName (line 19) | TokenName = "token_name"
constant BaseURL (line 20) | BaseURL = "base_url"
constant AvailableModels (line 21) | AvailableModels = "available_models"
constant KeyRequestBody (line 22) | KeyRequestBody = "key_request_body"
constant SystemPrompt (line 23) | SystemPrompt = "system_prompt"
FILE: api/common/email.go
function ValidateEmailFormat (line 19) | func ValidateEmailFormat(email string) bool {
function sendQQMailWithTLS (line 25) | func sendQQMailWithTLS(e *email.Email, auth smtp.Auth, host string, port...
function SendEmail (line 106) | func SendEmail(e *email.Email, auth smtp.Auth, isSsl bool, host string, ...
function VerifyEmailCode (line 138) | func VerifyEmailCode(email, code string) (bool, error) {
function GenerateRandomCode (line 168) | func GenerateRandomCode(length int) (string, error) {
FILE: api/common/init.go
function printHelp (line 18) | func printHelp() {
function Init (line 26) | func Init() {
FILE: api/common/lock.go
function InitLocker (line 14) | func InitLocker() {
type Locker (line 22) | type Locker interface
function NewLocalLock (line 33) | func NewLocalLock() *LocalLock {
type LocalLock (line 37) | type LocalLock struct
method TryLock (line 49) | func (ll *LocalLock) TryLock(name string, ttl time.Duration) bool {
method Unlock (line 84) | func (ll *LocalLock) Unlock(name string) {
type lockEntry (line 41) | type lockEntry struct
type RedisLock (line 93) | type RedisLock struct
method TryLock (line 101) | func (rl *RedisLock) TryLock(name string, ttl time.Duration) bool {
method Unlock (line 108) | func (rl *RedisLock) Unlock(name string) {
function NewRedisLock (line 97) | func NewRedisLock(client redis.Cmdable) *RedisLock {
FILE: api/common/logger/logger.go
type loggerLevel (line 20) | type loggerLevel
constant loggerDEBUG (line 23) | loggerDEBUG loggerLevel = "DEBUG"
constant loggerINFO (line 24) | loggerINFO loggerLevel = "INFO"
constant loggerWARN (line 25) | loggerWARN loggerLevel = "WARN"
constant loggerERROR (line 26) | loggerERROR loggerLevel = "ERROR"
constant loggerFATAL (line 27) | loggerFATAL loggerLevel = "FATAL"
constant loggerNONE (line 28) | loggerNONE loggerLevel = "NONE"
function init (line 38) | func init() {
function SetLogLevel (line 63) | func SetLogLevel(level string) {
function GetLogLevel (line 84) | func GetLogLevel() string {
function shouldLog (line 89) | func shouldLog(level loggerLevel) bool {
function SetupLogger (line 110) | func SetupLogger() {
function SysLog (line 129) | func SysLog(s string) {
function SysLogf (line 133) | func SysLogf(format string, a ...any) {
function SysWarn (line 137) | func SysWarn(s string) {
function SysWarnf (line 141) | func SysWarnf(format string, a ...any) {
function SysError (line 145) | func SysError(s string) {
function SysErrorf (line 149) | func SysErrorf(format string, a ...any) {
function Debug (line 153) | func Debug(ctx context.Context, msg string) {
function Info (line 157) | func Info(ctx context.Context, msg string) {
function Warn (line 161) | func Warn(ctx context.Context, msg string) {
function Error (line 165) | func Error(ctx context.Context, msg string) {
function Debugf (line 169) | func Debugf(ctx context.Context, format string, a ...any) {
function Infof (line 173) | func Infof(ctx context.Context, format string, a ...any) {
function Warnf (line 177) | func Warnf(ctx context.Context, format string, a ...any) {
function Errorf (line 181) | func Errorf(ctx context.Context, format string, a ...any) {
function FatalLog (line 185) | func FatalLog(s string) {
function FatalLogf (line 189) | func FatalLogf(format string, a ...any) {
function logHelper (line 193) | func logHelper(ctx context.Context, level loggerLevel, msg string) {
function getLineInfo (line 219) | func getLineInfo() (string, string) {
FILE: api/common/permission.go
function IsAdmin (line 8) | func IsAdmin(c *gin.Context) bool {
FILE: api/common/redis.go
function InitRedisClient (line 19) | func InitRedisClient() error {
function checkRedisEnabled (line 45) | func checkRedisEnabled() bool {
function IsRedisEnabled (line 53) | func IsRedisEnabled() bool {
function RedisSet (line 57) | func RedisSet(key string, value string, expiration time.Duration) error {
function RedisGet (line 65) | func RedisGet(key string) (string, error) {
function RedisDel (line 73) | func RedisDel(key string) error {
function RedisDecrease (line 81) | func RedisDecrease(key string, value int64) error {
function RedisZAdd (line 94) | func RedisZAdd(key string, score int64, member string) (int64, error) {
function RedisZRangeByScore (line 111) | func RedisZRangeByScore(key string, min, max int64) ([]string, error) {
function RedisZRem (line 127) | func RedisZRem(key string, member string) (int64, error) {
function RedisZRemRangeByScore (line 140) | func RedisZRemRangeByScore(key string, min, max int64) (int64, error) {
function RedisZCount (line 153) | func RedisZCount(key string, min, max int64) (int64, error) {
function RedisExists (line 164) | func RedisExists(key string) (int64, error) {
function RedisExpire (line 176) | func RedisExpire(key string, expiration time.Duration) (bool, error) {
FILE: api/common/session/key.go
constant SESSION_USER_ID (line 4) | SESSION_USER_ID = "SESSION_USER_ID"
constant SESSION_USER_NICKNAME (line 5) | SESSION_USER_NICKNAME = "SESSION_USER_NICKNAME"
constant SESSION_USER_ROLE (line 6) | SESSION_USER_ROLE = "SESSION_USER_ROLE"
constant SESSION_USER_GROUP_ID (line 7) | SESSION_USER_GROUP_ID = "SESSION_USER_GROUP_ID"
constant ENV_EID (line 8) | ENV_EID = "ENV_EID"
constant SESSION_AGENT_MODEL (line 9) | SESSION_AGENT_MODEL = "SESSION_AGENT_MODEL"
constant SESSION_AGENT_ID (line 10) | SESSION_AGENT_ID = "SESSION_AGENT_ID"
constant SESSION_AGENT (line 11) | SESSION_AGENT = "SESSION_AGENT"
constant SESSION_CONVERSATION_ID (line 12) | SESSION_CONVERSATION_ID = "SESSION_CONVERSATION_ID"
constant SESSION_CONVERSATION (line 13) | SESSION_CONVERSATION = "SESSION_CONVERSATION"
constant SESSION_SAAS_USER (line 14) | SESSION_SAAS_USER = "SESSION_SAAS_USER"
constant SESSION_REQUEST_PROTOCOL (line 15) | SESSION_REQUEST_PROTOCOL = "SESSION_REQUEST_PROTOCOL"
constant SESSION_REQUEST_DOMAIN (line 16) | SESSION_REQUEST_DOMAIN = "SESSION_REQUEST_DOMAIN"
constant SESSION_ENV_VERSION (line 17) | SESSION_ENV_VERSION = "SESSION_ENV_VERSION"
FILE: api/common/storage/storage.go
type Storage (line 21) | type Storage interface
type LocalStorage (line 29) | type LocalStorage struct
method Save (line 69) | func (l *LocalStorage) Save(file []byte, fileName string) error {
method Exists (line 84) | func (l *LocalStorage) Exists(fileName string) bool {
method Delete (line 91) | func (l *LocalStorage) Delete(fileName string) error {
method Load (line 101) | func (l *LocalStorage) Load(fileName string) ([]byte, error) {
method GetBasePath (line 127) | func (l *LocalStorage) GetBasePath() string {
type AliyunOSSStorage (line 34) | type AliyunOSSStorage struct
method Save (line 131) | func (a *AliyunOSSStorage) Save(file []byte, fileName string) error {
method Load (line 142) | func (a *AliyunOSSStorage) Load(fileName string) ([]byte, error) {
method Exists (line 152) | func (a *AliyunOSSStorage) Exists(fileName string) bool {
method Delete (line 158) | func (a *AliyunOSSStorage) Delete(fileName string) error {
method GetBasePath (line 166) | func (a *AliyunOSSStorage) GetBasePath() string {
function NewStorage (line 44) | func NewStorage() Storage {
function GetFileHash (line 111) | func GetFileHash(file multipart.File) (string, error) {
FILE: api/common/storage/storage_test.go
function TestSaveFile (line 9) | func TestSaveFile(t *testing.T) {
FILE: api/common/utils/ai53/api.go
type AI53Api (line 12) | type AI53Api struct
method GetBaseURL (line 28) | func (a *AI53Api) GetBaseURL() string {
method GetApps (line 35) | func (a *AI53Api) GetApps(offset, limit int) ([]AppResponse, error) {
method GetWorkflows (line 72) | func (a *AI53Api) GetWorkflows(offset, limit int) ([]AppResponse, erro...
method cleanBotId (line 110) | func (a *AI53Api) cleanBotId(botId string) string {
method GetAppParameters (line 126) | func (a *AI53Api) GetAppParameters(botId string) (interface{}, error) {
type AppResponse (line 17) | type AppResponse struct
FILE: api/common/utils/appbuilder/api.go
type AppBuilderApi (line 14) | type AppBuilderApi struct
method DescribeApps (line 56) | func (a *AppBuilderApi) DescribeApps(marker string, maxKeys int) (*Des...
method CreateConversation (line 103) | func (a *AppBuilderApi) CreateConversation(appId string) (*Conversatio...
method doRequest (line 141) | func (a *AppBuilderApi) doRequest(method, url string, payload interfac...
type AppInfo (line 21) | type AppInfo struct
type DescribeAppsResponse (line 47) | type DescribeAppsResponse struct
type ConversationResponse (line 92) | type ConversationResponse struct
type ErrorResponse (line 97) | type ErrorResponse struct
FILE: api/common/utils/coze/api.go
type CozeApi (line 15) | type CozeApi struct
method doRequest (line 30) | func (c *CozeApi) doRequest(method, url string, payload interface{}, h...
method GetOAuthToken (line 64) | func (c *CozeApi) GetOAuthToken(clientID, clientSecret, code, redirect...
method RefreshOAuthToken (line 95) | func (c *CozeApi) RefreshOAuthToken(clientID, clientSecret, refreshTok...
method RefreshTokenIfNeeded (line 157) | func (c *CozeApi) RefreshTokenIfNeeded(provider *model.Provider) error {
method GetWorkspaces (line 189) | func (c *CozeApi) GetWorkspaces(provider *model.Provider, pageNum int,...
method GetPublishedBots (line 233) | func (c *CozeApi) GetPublishedBots(provider *model.Provider, spaceID s...
constant CozeCnUrl (line 20) | CozeCnUrl = "https://api.coze.cn"
constant CozeComUrl (line 21) | CozeComUrl = "https://api.coze.com"
type CozeApiTokenResponse (line 24) | type CozeApiTokenResponse struct
type Workspace (line 125) | type Workspace struct
type WorkspacesResponse (line 133) | type WorkspacesResponse struct
type Bot (line 138) | type Bot struct
type PublishedBotsResponse (line 146) | type PublishedBotsResponse struct
function IsTokenExpired (line 152) | func IsTokenExpired(provider *model.Provider) bool {
FILE: api/common/utils/env/env.go
function Int (line 10) | func Int(env string, defaultValue int) int {
function Int64 (line 21) | func Int64(env string, defaultValue int64) int64 {
function Float64 (line 32) | func Float64(env string, defaultValue float64) float64 {
function String (line 43) | func String(env string, defaultValue string) string {
function Bool (line 50) | func Bool(env string, defaultValue bool) bool {
FILE: api/common/utils/helper/helper.go
function GetRequestID (line 15) | func GetRequestID(ctx context.Context) string {
constant Chars (line 23) | Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
function RandomString (line 25) | func RandomString(n int) string {
function PasswordHash (line 34) | func PasswordHash(password string, salt string) (string, error) {
function Bytes2Size (line 45) | func Bytes2Size(num int64) string {
function ParseSize (line 63) | func ParseSize(sizeStr string) (int64, error) {
function CalcElapsedTime (line 89) | func CalcElapsedTime(start time.Time) int64 {
function IsValidPhone (line 95) | func IsValidPhone(phone string) bool {
function IsValidEmail (line 121) | func IsValidEmail(email string) bool {
function HasIntersection (line 127) | func HasIntersection(a, b []int64) bool {
function GetHost (line 143) | func GetHost(u string) (string, error) {
function StrInArray (line 153) | func StrInArray(str string, arr []string) bool {
FILE: api/common/utils/helper/key.go
constant RequestIdKey (line 4) | RequestIdKey = "X-Request-Id"
FILE: api/common/utils/helper/sso_sign.go
function BuildSSORawString (line 9) | func BuildSSORawString(timestamp string, normalizedUsername string, secr...
function CalcSSOSignLowerHex (line 14) | func CalcSSOSignLowerHex(raw string) string {
FILE: api/common/utils/huawei_cloud/model.go
type HuaweicloudBaseResponse (line 3) | type HuaweicloudBaseResponse struct
type HuaweicloudCallbackRequest (line 8) | type HuaweicloudCallbackRequest struct
type HuaweicloudCallbackQuery (line 13) | type HuaweicloudCallbackQuery struct
constant SUCCESS (line 20) | SUCCESS = "000000"
constant SUCCESS_MSG (line 24) | SUCCESS_MSG = "success"
type CreateInstanceResponse (line 27) | type CreateInstanceResponse struct
function GetSuccess (line 32) | func GetSuccess() HuaweicloudBaseResponse {
type HuaweiCloudBody (line 39) | type HuaweiCloudBody struct
type QueryInstanceResponse (line 60) | type QueryInstanceResponse struct
type InstanceInfo (line 65) | type InstanceInfo struct
type AppInfo (line 70) | type AppInfo struct
FILE: api/common/utils/huawei_cloud/signature.go
type IMessageResp (line 17) | type IMessageResp struct
constant TIMESTAMP (line 23) | TIMESTAMP = "timestamp"
constant NONCE (line 24) | NONCE = "nonce"
constant SIGNATURE (line 25) | SIGNATURE = "signature"
constant TIME_DIFF (line 26) | TIME_DIFF = 60 * time.Second
function VerifySignature (line 29) | func VerifySignature(c *gin.Context, accessKey string) error {
function generateSignature (line 68) | func generateSignature(accessKey string, body []byte, timestamp string, ...
function hmacSHA256 (line 82) | func hmacSHA256(data []byte, key string) []byte {
function validateReqTime (line 88) | func validateReqTime(timestamp string) bool {
FILE: api/common/utils/ip.go
function GetClientIP (line 11) | func GetClientIP(c *gin.Context) string {
FILE: api/common/utils/jwt/jwt.go
function UserGenerateJWT (line 12) | func UserGenerateJWT(userID int64, eid int64) (string, error) {
function UserParseJWT (line 23) | func UserParseJWT(tokenString string) (int64, int64, error) {
FILE: api/common/utils/random.go
function init (line 10) | func init() {
function GetRandomInt64 (line 15) | func GetRandomInt64(n int64) int64 {
FILE: api/common/utils/snowflake.go
type Snowflake (line 10) | type Snowflake struct
method NextId (line 31) | func (s *Snowflake) NextId() int64 {
method waitNextMillis (line 65) | func (s *Snowflake) waitNextMillis(lastTimestamp int64) int64 {
function NewSnowflake (line 19) | func NewSnowflake(workerId int64) *Snowflake {
function GenerateOrderId (line 78) | func GenerateOrderId() string {
FILE: api/common/utils/system/machine.go
constant EnvFilePath (line 16) | EnvFilePath = ".env"
type MachineInfo (line 20) | type MachineInfo struct
function GenerateMachineCode (line 29) | func GenerateMachineCode() (string, error) {
function GetMachineInfo (line 70) | func GetMachineInfo() (*MachineInfo, error) {
function GetOrGenerateMachineCode (line 90) | func GetOrGenerateMachineCode() (string, error) {
function GetVersion (line 125) | func GetVersion() string {
function readEnvFile (line 144) | func readEnvFile() (map[string]string, error) {
function writeEnvFile (line 174) | func writeEnvFile(envMap map[string]string) error {
function saveMachineCodeToEnv (line 195) | func saveMachineCodeToEnv(machineCode string) error {
function AppendToEnvFile (line 221) | func AppendToEnvFile(key, value string) error {
FILE: api/common/utils/system/version.go
constant VersionCheckURL (line 16) | VersionCheckURL = "https://update.53ai.net/checkversion/53aihub/"
type VersionCheckResponse (line 20) | type VersionCheckResponse struct
function CheckVersion (line 32) | func CheckVersion() (*VersionCheckResponse, error) {
function CheckVersionAndReturn (line 92) | func CheckVersionAndReturn() (*VersionCheckResponse, string, error) {
function checkWebsiteIdExists (line 128) | func checkWebsiteIdExists() (string, bool, error) {
function addWebsiteIdToEnv (line 138) | func addWebsiteIdToEnv(websiteId string) error {
FILE: api/common/utils/wxbizjsonmsgcrypt/wxbizjsonmsgcrypt.go
constant letterBytes (line 17) | letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU...
constant ValidateSignatureError (line 20) | ValidateSignatureError int = -40001
constant ParseXmlError (line 21) | ParseXmlError int = -40002
constant ComputeSignatureError (line 22) | ComputeSignatureError int = -40003
constant IllegalAesKey (line 23) | IllegalAesKey int = -40004
constant ValidateCorpidError (line 24) | ValidateCorpidError int = -40005
constant EncryptAESError (line 25) | EncryptAESError int = -40006
constant DecryptAESError (line 26) | DecryptAESError int = -40007
constant IllegalBuffer (line 27) | IllegalBuffer int = -40008
constant EncodeBase64Error (line 28) | EncodeBase64Error int = -40009
constant DecodeBase64Error (line 29) | DecodeBase64Error int = -40010
constant GenXmlError (line 30) | GenXmlError int = -40010
constant ParseJsonError (line 31) | ParseJsonError int = -40012
constant GenJsonError (line 32) | GenJsonError int = -40013
constant IllegalProtocolType (line 33) | IllegalProtocolType int = -40014
type ProtocolType (line 36) | type ProtocolType
constant XmlType (line 39) | XmlType ProtocolType = 1
type CryptError (line 42) | type CryptError struct
function NewCryptError (line 47) | func NewCryptError(err_code int, err_msg string) *CryptError {
type WXBizMsg4Recv (line 51) | type WXBizMsg4Recv struct
type CDATA (line 57) | type CDATA struct
type WXBizMsg4Send (line 61) | type WXBizMsg4Send struct
function NewWXBizMsg4Send (line 69) | func NewWXBizMsg4Send(encrypt, signature, timestamp, nonce string) *WXBi...
type ProtocolProcessor (line 73) | type ProtocolProcessor interface
type WXBizMsgCrypt (line 78) | type WXBizMsgCrypt struct
method randString (line 116) | func (self *WXBizMsgCrypt) randString(n int) string {
method pKCS7Padding (line 124) | func (self *WXBizMsgCrypt) pKCS7Padding(plaintext string, block_size i...
method pKCS7Unpadding (line 133) | func (self *WXBizMsgCrypt) pKCS7Unpadding(plaintext []byte, block_size...
method cbcEncrypter (line 145) | func (self *WXBizMsgCrypt) cbcEncrypter(plaintext string) ([]byte, *Cr...
method cbcDecrypter (line 170) | func (self *WXBizMsgCrypt) cbcDecrypter(base64_encrypt_msg string) ([]...
method calSignature (line 203) | func (self *WXBizMsgCrypt) calSignature(timestamp, nonce, data string)...
method ParsePlainText (line 217) | func (self *WXBizMsgCrypt) ParsePlainText(plaintext []byte) ([]byte, u...
method VerifyURL (line 240) | func (self *WXBizMsgCrypt) VerifyURL(msg_signature, timestamp, nonce, ...
method EncryptMsg (line 265) | func (self *WXBizMsgCrypt) EncryptMsg(reply_msg, timestamp, nonce stri...
method DecryptMsg (line 288) | func (self *WXBizMsgCrypt) DecryptMsg(msg_signature, timestamp, nonce ...
type XmlProcessor (line 85) | type XmlProcessor struct
method parse (line 88) | func (self *XmlProcessor) parse(src_data []byte) (*WXBizMsg4Recv, *Cry...
method serialize (line 97) | func (self *XmlProcessor) serialize(msg4_send *WXBizMsg4Send) ([]byte,...
function NewWXBizMsgCrypt (line 105) | func NewWXBizMsgCrypt(token, encoding_aeskey, receiver_id string, protoc...
FILE: api/common/validate.go
function init (line 7) | func init() {
FILE: api/config/config.go
function GetApiHost (line 42) | func GetApiHost() string {
function GetEID (line 49) | func GetEID(c *gin.Context) int64 {
function GetUserId (line 58) | func GetUserId(c *gin.Context) int64 {
function GetUserNickname (line 66) | func GetUserNickname(c *gin.Context) string {
function GetUserGroupID (line 75) | func GetUserGroupID(c *gin.Context) int64 {
function GetProtocol (line 84) | func GetProtocol(c *gin.Context) string {
function GetDomain (line 93) | func GetDomain(c *gin.Context) string {
function GetServer (line 101) | func GetServer(c *gin.Context) string {
function Getwd (line 105) | func Getwd() string {
function GetBinScriptPath (line 113) | func GetBinScriptPath(shName string) string {
function GetWecomSuiteID (line 123) | func GetWecomSuiteID() string {
function GetDingtalkSuiteID (line 127) | func GetDingtalkSuiteID() string {
function GetUserRole (line 131) | func GetUserRole(c *gin.Context) int64 {
FILE: api/config/encryption.go
function GetEncryptionKey (line 8) | func GetEncryptionKey() string {
FILE: api/controller/agent.go
type AgentListRequest (line 19) | type AgentListRequest struct
type AgentsResponse (line 28) | type AgentsResponse struct
type AgentRequest (line 33) | type AgentRequest struct
type UpdateAgentEnableRequest (line 53) | type UpdateAgentEnableRequest struct
function CreateAgent (line 66) | func CreateAgent(c *gin.Context) {
function GetAgent (line 193) | func GetAgent(c *gin.Context) {
function UpdateAgent (line 232) | func UpdateAgent(c *gin.Context) {
function DeleteAgent (line 388) | func DeleteAgent(c *gin.Context) {
function GetAgents (line 462) | func GetAgents(c *gin.Context) {
function GetAgentsByGroup (line 529) | func GetAgentsByGroup(c *gin.Context) {
function GetAvailableAgents (line 574) | func GetAvailableAgents(c *gin.Context) {
function GetCurrentAgents (line 623) | func GetCurrentAgents(c *gin.Context) {
function UpdateAgentStatus (line 686) | func UpdateAgentStatus(c *gin.Context) {
function splitChannelTypesString (line 736) | func splitChannelTypesString(channelTypesStr string) []int {
function splitAgentTypesString (line 749) | func splitAgentTypesString(agentTypesStr string) []int {
function GetInternalUserAgents (line 770) | func GetInternalUserAgents(c *gin.Context) {
FILE: api/controller/ai53.go
function Get53AIAllBots (line 26) | func Get53AIAllBots(c *gin.Context) {
function Get53AIAllWorkflows (line 60) | func Get53AIAllWorkflows(c *gin.Context) {
function Update53AIChannel (line 84) | func Update53AIChannel(provider model.Provider, apps []ai53.AppResponse)...
function Update53AIWorkflowChannel (line 139) | func Update53AIWorkflowChannel(provider model.Provider, apps []ai53.AppR...
function Get53AIAppParameters (line 205) | func Get53AIAppParameters(c *gin.Context) {
FILE: api/controller/ai_link.go
type AILinkRequest (line 13) | type AILinkRequest struct
function CreateAILink (line 35) | func CreateAILink(c *gin.Context) {
function GetAILink (line 112) | func GetAILink(c *gin.Context) {
function UpdateAILink (line 139) | func UpdateAILink(c *gin.Context) {
function DeleteAILink (line 221) | func DeleteAILink(c *gin.Context) {
function GetAILinks (line 270) | func GetAILinks(c *gin.Context) {
function GetCurrentSiteAILinks (line 306) | func GetCurrentSiteAILinks(c *gin.Context) {
function GetDefaultAILinks (line 325) | func GetDefaultAILinks(c *gin.Context) {
type SortItem (line 331) | type SortItem struct
type BatchSortRequest (line 337) | type BatchSortRequest struct
function BatchSortAILinks (line 350) | func BatchSortAILinks(c *gin.Context) {
FILE: api/controller/appbuilder.go
function GetAppBuilderAllBots (line 26) | func GetAppBuilderAllBots(c *gin.Context) {
function UpdateAppBuilderChannel (line 52) | func UpdateAppBuilderChannel(provider model.Provider, apps []appbuilder....
FILE: api/controller/auth_sso.go
type SSOConfig (line 18) | type SSOConfig struct
type SSOLoginRequest (line 25) | type SSOLoginRequest struct
type SaasLoginResponse (line 32) | type SaasLoginResponse struct
function ApiSSOSSOLogin (line 48) | func ApiSSOSSOLogin(c *gin.Context) {
function loadSSOConfig (line 125) | func loadSSOConfig(eid int64) *SSOConfig {
function isValid10DigitTimestamp (line 138) | func isValid10DigitTimestamp(ts string) bool {
FILE: api/controller/channel-test.go
type ChannelTestResponse (line 30) | type ChannelTestResponse struct
function TestChannel (line 47) | func TestChannel(c *gin.Context) {
function testChannel (line 81) | func testChannel(ctx context.Context, channel *model.Channel, request *r...
function parseTestResponse (line 193) | func parseTestResponse(resp string) (*openai.TextResponse, string, error) {
function buildTestRequest (line 209) | func buildTestRequest(model string) *relaymodel.GeneralOpenAIRequest {
FILE: api/controller/channel.go
function autoAssignCozeStudioProvider (line 17) | func autoAssignCozeStudioProvider(channel *model.Channel) error {
type ChannelRequest (line 41) | type ChannelRequest struct
function CreateChannel (line 65) | func CreateChannel(c *gin.Context) {
function GetChannel (line 128) | func GetChannel(c *gin.Context) {
function UpdateChannel (line 150) | func UpdateChannel(c *gin.Context) {
function DeleteChannel (line 217) | func DeleteChannel(c *gin.Context) {
function GetChannels (line 244) | func GetChannels(c *gin.Context) {
FILE: api/controller/conversation.go
type ConversationRequest (line 12) | type ConversationRequest struct
type ConversationUpdateRequest (line 17) | type ConversationUpdateRequest struct
type ConversationResponse (line 21) | type ConversationResponse struct
type ConversationListRequest (line 26) | type ConversationListRequest struct
function CreateConversation (line 41) | func CreateConversation(c *gin.Context) {
function GetConversation (line 81) | func GetConversation(c *gin.Context) {
function GetConversations (line 107) | func GetConversations(c *gin.Context) {
function UpdateConversation (line 136) | func UpdateConversation(c *gin.Context) {
type UserConversationListRequest (line 165) | type UserConversationListRequest struct
function GetUserConversations (line 185) | func GetUserConversations(c *gin.Context) {
type UserInfo (line 243) | type UserInfo struct
type ConversationSummary (line 249) | type ConversationSummary struct
type ConversationSummaryResponse (line 259) | type ConversationSummaryResponse struct
function GetAgentConversations (line 277) | func GetAgentConversations(c *gin.Context) {
function DeleteConversation (line 339) | func DeleteConversation(c *gin.Context) {
FILE: api/controller/coze.go
function GetCozeAllWorkspaces (line 24) | func GetCozeAllWorkspaces(c *gin.Context) {
function GetCozeAllBots (line 54) | func GetCozeAllBots(c *gin.Context) {
FILE: api/controller/department.go
type DepartmentRequest (line 13) | type DepartmentRequest struct
type UpdateDepartmentRequest (line 19) | type UpdateDepartmentRequest struct
type DepartmentResponse (line 25) | type DepartmentResponse struct
type DepartmentTreeResponse (line 31) | type DepartmentTreeResponse struct
type BindRequest (line 35) | type BindRequest struct
type UnBindRequest (line 40) | type UnBindRequest struct
function CreateDepartment (line 57) | func CreateDepartment(c *gin.Context) {
function GetDepartment (line 93) | func GetDepartment(c *gin.Context) {
function UpdateDepartment (line 124) | func UpdateDepartment(c *gin.Context) {
function DeleteDepartment (line 171) | func DeleteDepartment(c *gin.Context) {
function GetDepartments (line 201) | func GetDepartments(c *gin.Context) {
function GetChildDepartments (line 229) | func GetChildDepartments(c *gin.Context) {
function GetDepartmentTree (line 259) | func GetDepartmentTree(c *gin.Context) {
function DepartmentBindMember (line 285) | func DepartmentBindMember(c *gin.Context) {
function DepartmentUnbindMember (line 341) | func DepartmentUnbindMember(c *gin.Context) {
FILE: api/controller/dify.go
function GetDifyAppInfo (line 24) | func GetDifyAppInfo(c *gin.Context) {
function GetDifyAppParameters (line 82) | func GetDifyAppParameters(c *gin.Context) {
FILE: api/controller/email.go
constant verificationCodeLength (line 21) | verificationCodeLength = 6
constant duration (line 22) | duration = 15
constant codeExpiration (line 23) | codeExpiration = duration * time.Minute
type SendVerificationEmailRequest (line 26) | type SendVerificationEmailRequest struct
function SendVerificationEmail (line 40) | func SendVerificationEmail(c *gin.Context) {
type SendTestEmailRequest (line 107) | type SendTestEmailRequest struct
function SendTestEmail (line 128) | func SendTestEmail(c *gin.Context) {
type UpdateUserEmailRequest (line 163) | type UpdateUserEmailRequest struct
function UpdateUserEmail (line 182) | func UpdateUserEmail(c *gin.Context) {
FILE: api/controller/enterprise.go
type EnterpriseResponse (line 16) | type EnterpriseResponse struct
function GetEnterprise (line 32) | func GetEnterprise(c *gin.Context) {
function CreateEnterprise (line 58) | func CreateEnterprise(c *gin.Context) {
type UpdateEnterpriseRequest (line 76) | type UpdateEnterpriseRequest struct
function UpdateEnterprise (line 99) | func UpdateEnterprise(c *gin.Context) {
function DeleteEnterprise (line 228) | func DeleteEnterprise(c *gin.Context) {
function UpdateEnterpriseAttribute (line 259) | func UpdateEnterpriseAttribute(c *gin.Context) {
function GetCurrentEnterprise (line 295) | func GetCurrentEnterprise(c *gin.Context) {
type GetIsSaasResponse (line 321) | type GetIsSaasResponse struct
function GetIsSaas (line 334) | func GetIsSaas(c *gin.Context) {
type HomePageResponse (line 340) | type HomePageResponse struct
function GetHomePage (line 355) | func GetHomePage(c *gin.Context) {
function GetEnterpriseBanner (line 403) | func GetEnterpriseBanner(c *gin.Context) {
type UpdateEnterpriseBannerRequest (line 421) | type UpdateEnterpriseBannerRequest struct
function UpdateEnterpriseBanner (line 434) | func UpdateEnterpriseBanner(c *gin.Context) {
type UpdateEnterpriseTemplateTypeRequest (line 468) | type UpdateEnterpriseTemplateTypeRequest struct
function UpdateEnterpriseTemplateType (line 481) | func UpdateEnterpriseTemplateType(c *gin.Context) {
function GetEnterpriseTemplateType (line 534) | func GetEnterpriseTemplateType(c *gin.Context) {
FILE: api/controller/enterprise_config.go
type ConfigTypeStatus (line 15) | type ConfigTypeStatus struct
function GetEnterpriseConfigTypes (line 30) | func GetEnterpriseConfigTypes(c *gin.Context) {
function GetEnterpriseConfig (line 60) | func GetEnterpriseConfig(c *gin.Context) {
function IsEnterpriseConfigEnabled (line 94) | func IsEnterpriseConfigEnabled(c *gin.Context) {
type SaveEnterpriseConfigRequest (line 111) | type SaveEnterpriseConfigRequest struct
function SaveEnterpriseConfig (line 128) | func SaveEnterpriseConfig(c *gin.Context) {
function ToggleEnterpriseConfig (line 157) | func ToggleEnterpriseConfig(c *gin.Context) {
FILE: api/controller/group.go
type BaseGroupRequest (line 14) | type BaseGroupRequest struct
type GroupRequest (line 19) | type GroupRequest struct
type BatchSubmitGroupRequestItem (line 24) | type BatchSubmitGroupRequestItem struct
type BatchSubmitGroupsRequest (line 29) | type BatchSubmitGroupsRequest struct
function CreateGroup (line 43) | func CreateGroup(c *gin.Context) {
function GetGroup (line 79) | func GetGroup(c *gin.Context) {
function UpdateGroup (line 105) | func UpdateGroup(c *gin.Context) {
function DeleteGroup (line 150) | func DeleteGroup(c *gin.Context) {
function GetGroups (line 185) | func GetGroups(c *gin.Context) {
function GetCurrentGroups (line 209) | func GetCurrentGroups(c *gin.Context) {
function BatchSubmitGroups (line 239) | func BatchSubmitGroups(c *gin.Context) {
type AddAgentsToGroupRequest (line 283) | type AddAgentsToGroupRequest struct
type AddResourcesToGroupRequest (line 288) | type AddResourcesToGroupRequest struct
function AddAgentsToGroup (line 303) | func AddAgentsToGroup(c *gin.Context) {
function AddResourcesToGroup (line 387) | func AddResourcesToGroup(c *gin.Context) {
type RemoveAgentsFromGroupRequest (line 474) | type RemoveAgentsFromGroupRequest struct
type RemoveResourcesFromGroupRequest (line 479) | type RemoveResourcesFromGroupRequest struct
function RemoveAgentsFromGroup (line 494) | func RemoveAgentsFromGroup(c *gin.Context) {
function RemoveResourcesFromGroup (line 563) | func RemoveResourcesFromGroup(c *gin.Context) {
type GroupAgentListRequest (line 635) | type GroupAgentListRequest struct
type GroupAgentListResponse (line 642) | type GroupAgentListResponse struct
function GetGroupAgents (line 659) | func GetGroupAgents(c *gin.Context) {
function GetGroupResources (line 764) | func GetGroupResources(c *gin.Context) {
type GroupResourceListRequest (line 857) | type GroupResourceListRequest struct
type GroupResourceListResponse (line 865) | type GroupResourceListResponse struct
type BatchAddUsersToGroupRequest (line 871) | type BatchAddUsersToGroupRequest struct
function BatchAddUsersToGroup (line 886) | func BatchAddUsersToGroup(c *gin.Context) {
type GroupUsersRequest (line 1033) | type GroupUsersRequest struct
type GroupUsersResponse (line 1041) | type GroupUsersResponse struct
function GetGroupUsers (line 1060) | func GetGroupUsers(c *gin.Context) {
type RemoveUsersFromGroupRequest (line 1226) | type RemoveUsersFromGroupRequest struct
function RemoveUsersFromGroup (line 1240) | func RemoveUsersFromGroup(c *gin.Context) {
function handleAgentResources (line 1292) | func handleAgentResources(c *gin.Context, agentIDs []int64, keyword stri...
function handleAILinkResources (line 1323) | func handleAILinkResources(c *gin.Context, aiLinkIDs []int64, keyword st...
function handlePromptResources (line 1354) | func handlePromptResources(c *gin.Context, promptIDs []int64, keyword st...
FILE: api/controller/maxkb.go
type MaxKBProfileResponse (line 19) | type MaxKBProfileResponse struct
type MaxKBProfileData (line 25) | type MaxKBProfileData struct
function GetMaxKBApplicationProfile (line 57) | func GetMaxKBApplicationProfile(c *gin.Context) {
function extractBaseURL (line 130) | func extractBaseURL(fullURL string) (string, error) {
function makeMaxKBRequest (line 147) | func makeMaxKBRequest(url, applicationToken string) ([]byte, error) {
function findMaxKBChannelByBotID (line 188) | func findMaxKBChannelByBotID(eid int64, botID string) (*model.Channel, e...
function containsBotID (line 210) | func containsBotID(models, botID string) bool {
FILE: api/controller/message.go
type MessagesResponse (line 13) | type MessagesResponse struct
type EnhancedMessage (line 19) | type EnhancedMessage struct
type MessageListRequest (line 26) | type MessageListRequest struct
function convertToEnhancedMessages (line 34) | func convertToEnhancedMessages(messages []*model.Message) []*EnhancedMes...
function GetMessagesByUserAndAgent (line 87) | func GetMessagesByUserAndAgent(c *gin.Context) {
function GetUserMessages (line 129) | func GetUserMessages(c *gin.Context) {
function GetMessagesByConversation (line 186) | func GetMessagesByConversation(c *gin.Context) {
FILE: api/controller/model.go
type OpenAIModelPermission (line 14) | type OpenAIModelPermission struct
type OpenAIModels (line 29) | type OpenAIModels struct
type OpenAIModelsResponse (line 39) | type OpenAIModelsResponse struct
function init (line 47) | func init() {
function ListAllModels (line 158) | func ListAllModels(c *gin.Context) {
FILE: api/controller/navigation.go
function GetNavigations (line 22) | func GetNavigations(c *gin.Context) {
type NavigationRequest (line 48) | type NavigationRequest struct
function CreateNavigation (line 66) | func CreateNavigation(c *gin.Context) {
function GetNavigation (line 123) | func GetNavigation(c *gin.Context) {
function UpdateNavigation (line 153) | func UpdateNavigation(c *gin.Context) {
function DeleteNavigation (line 214) | func DeleteNavigation(c *gin.Context) {
type UpdateNavigationStatusRequest (line 266) | type UpdateNavigationStatusRequest struct
function UpdateNavigationStatus (line 280) | func UpdateNavigationStatus(c *gin.Context) {
type NavigationSortItem (line 319) | type NavigationSortItem struct
function SortNavigations (line 334) | func SortNavigations(c *gin.Context) {
function handleNotFound (line 358) | func handleNotFound(c *gin.Context, nav *model.Navigation, err error) bo...
function InitSystemNavigation (line 374) | func InitSystemNavigation(c *gin.Context) {
type CreateNavigationContentRequest (line 424) | type CreateNavigationContentRequest struct
function CreateNavigationContent (line 438) | func CreateNavigationContent(c *gin.Context) {
function GetNavigationContent (line 505) | func GetNavigationContent(c *gin.Context) {
FILE: api/controller/navigation_icons.go
type NavigationIcon (line 11) | type NavigationIcon struct
function GetNavigationIcons (line 24) | func GetNavigationIcons(c *gin.Context) {
FILE: api/controller/order.go
type Response (line 16) | type Response struct
type ErrorResponse (line 22) | type ErrorResponse struct
function CloseOrder (line 37) | func CloseOrder(c *gin.Context) {
type OrderListRequest (line 96) | type OrderListRequest struct
type OrderListResponse (line 109) | type OrderListResponse struct
function GetOrders (line 134) | func GetOrders(c *gin.Context) {
function GetOrder (line 211) | func GetOrder(c *gin.Context) {
function GetUserOrders (line 239) | func GetUserOrders(c *gin.Context) {
type UpdateOrderStatusRequest (line 254) | type UpdateOrderStatusRequest struct
function UpdateOrderStatus (line 269) | func UpdateOrderStatus(c *gin.Context) {
function DeleteOrder (line 334) | func DeleteOrder(c *gin.Context) {
function ConfirmManualPayment (line 375) | func ConfirmManualPayment(c *gin.Context) {
type UpdateManualTransferOrderRequest (line 455) | type UpdateManualTransferOrderRequest struct
function UpdateManualTransferOrder (line 477) | func UpdateManualTransferOrder(c *gin.Context) {
function QueryTradeOrder (line 521) | func QueryTradeOrder(c *gin.Context) {
function RefunTradeOrder (line 557) | func RefunTradeOrder(c *gin.Context) {
FILE: api/controller/pay.go
type WechatNotifyResponse (line 26) | type WechatNotifyResponse struct
type CreateOrderRequest (line 32) | type CreateOrderRequest struct
type OrderResponse (line 47) | type OrderResponse struct
type PayOrderRequest (line 53) | type PayOrderRequest struct
type PayOrderResponse (line 60) | type PayOrderResponse struct
function CreateOrder (line 77) | func CreateOrder(c *gin.Context) {
function getOrder (line 145) | func getOrder(c *gin.Context, eid int64, req CreateOrderRequest, paySett...
function getCachedOrder (line 197) | func getCachedOrder(orderId string) (*model.Order, bool) {
function removeCachedOrder (line 213) | func removeCachedOrder(orderId string) {
function createOrUpdateOrderFromCache (line 218) | func createOrUpdateOrderFromCache(eid int64, orderId string, status int,...
function createOrUpdateOrderFromCacheWithTime (line 278) | func createOrUpdateOrderFromCacheWithTime(eid int64, orderId string, sta...
function AlipayNotify (line 359) | func AlipayNotify(c *gin.Context) {
function WechatPayNotify (line 459) | func WechatPayNotify(c *gin.Context) {
function QueryOrderStatus (line 672) | func QueryOrderStatus(c *gin.Context) {
type OrderStatusResponse (line 808) | type OrderStatusResponse struct
function getTradeStateDesc (line 815) | func getTradeStateDesc(tradeState string) string {
function queryWechatOrderStatusWithOriginal (line 845) | func queryWechatOrderStatusWithOriginal(eid int64, orderId string) (int,...
function queryAlipayOrderStatusWithOriginal (line 901) | func queryAlipayOrderStatusWithOriginal(eid int64, order *model.Order) (...
type PayTypeStatus (line 955) | type PayTypeStatus struct
function GetAvailablePayTypes (line 969) | func GetAvailablePayTypes(c *gin.Context) {
FILE: api/controller/pay_setting.go
type PaySettingRequest (line 17) | type PaySettingRequest struct
type PaySettingsResponse (line 29) | type PaySettingsResponse struct
function CreatePaySetting (line 46) | func CreatePaySetting(c *gin.Context) {
function UpdatePaySetting (line 127) | func UpdatePaySetting(c *gin.Context) {
function DeletePaySetting (line 188) | func DeletePaySetting(c *gin.Context) {
function GetPaySetting (line 219) | func GetPaySetting(c *gin.Context) {
function GetPaySettings (line 244) | func GetPaySettings(c *gin.Context) {
function GetPaySettingByType (line 266) | func GetPaySettingByType(c *gin.Context) {
type PayConfigRequest (line 290) | type PayConfigRequest struct
type PayStatusRequest (line 296) | type PayStatusRequest struct
function UpdatePayConfig (line 311) | func UpdatePayConfig(c *gin.Context) {
function UpdatePayStatus (line 382) | func UpdatePayStatus(c *gin.Context) {
function isValidPayType (line 434) | func isValidPayType(payType int) bool {
function processWechatConfig (line 439) | func processWechatConfig(payConfig string) (string, error) {
FILE: api/controller/prompt.go
type PromptListRequest (line 19) | type PromptListRequest struct
type PromptsResponse (line 27) | type PromptsResponse struct
type PromptRequest (line 33) | type PromptRequest struct
function GetPrompts (line 58) | func GetPrompts(c *gin.Context) {
function CreatePrompt (line 143) | func CreatePrompt(c *gin.Context) {
function GetPrompt (line 262) | func GetPrompt(c *gin.Context) {
function UpdatePrompt (line 330) | func UpdatePrompt(c *gin.Context) {
function DeletePrompt (line 449) | func DeletePrompt(c *gin.Context) {
function UpdatePromptLike (line 514) | func UpdatePromptLike(c *gin.Context) {
type UpdatePromptStatusRequest (line 608) | type UpdatePromptStatusRequest struct
function UpdatePromptStatus (line 623) | func UpdatePromptStatus(c *gin.Context) {
function GetPromptGroups (line 669) | func GetPromptGroups(c *gin.Context) {
function getPromptListWithIDs (line 713) | func getPromptListWithIDs(eid int64, keyword string, groupIDStr string, ...
FILE: api/controller/provider.go
type ProviderRequest (line 15) | type ProviderRequest struct
function validateCozeConfig (line 23) | func validateCozeConfig(providerType int64, configStr string) error {
function checkSaveAccessToken (line 39) | func checkSaveAccessToken(ProviderType int64, req ProviderRequest) (bool...
function CreateProvider (line 64) | func CreateProvider(c *gin.Context) {
function DeleteProvider (line 111) | func DeleteProvider(c *gin.Context) {
function GetProviders (line 161) | func GetProviders(c *gin.Context) {
function UpdateProvider (line 184) | func UpdateProvider(c *gin.Context) {
FILE: api/controller/provider_callback.go
type CozeCallbackRequest (line 17) | type CozeCallbackRequest struct
function CozeCallBack (line 34) | func CozeCallBack(c *gin.Context) {
FILE: api/controller/relay.go
type Message (line 47) | type Message struct
type ChatRequest (line 52) | type ChatRequest struct
type WorkflowRunRequest (line 64) | type WorkflowRunRequest struct
function WorkflowRun (line 80) | func WorkflowRun(c *gin.Context) {
function GetSessionAgent (line 162) | func GetSessionAgent(c *gin.Context) (agent *model.Agent, err error) {
function extractWorkflowID (line 175) | func extractWorkflowID(modelName, customConfig string) string {
function GetSessionConversation (line 203) | func GetSessionConversation(c *gin.Context) (conversation *model.Convers...
function Relay (line 224) | func Relay(c *gin.Context) {
function handleChatRequest (line 254) | func handleChatRequest(c *gin.Context, body []byte, agent *model.Agent, ...
function processChatRequest (line 265) | func processChatRequest(c *gin.Context, chatRequest *ChatRequest, agent ...
function relayHelper (line 353) | func relayHelper(c *gin.Context, relayMode int) *relay_model.ErrorWithSt...
function processChannelRelayError (line 372) | func processChannelRelayError(ctx context.Context, userId int, channelId...
function getAndValidateTextRequest (line 381) | func getAndValidateTextRequest(c *gin.Context, relayMode int) (*relay_mo...
function getMappedModelName (line 400) | func getMappedModelName(modelName string, mapping map[string]string) (st...
function setSystemPrompt (line 411) | func setSystemPrompt(ctx context.Context, request *relay_model.GeneralOp...
function createInitialMessage (line 432) | func createInitialMessage(c *gin.Context, agent *model.Agent, user_id in...
function sendSaveMessageEvent (line 470) | func sendSaveMessageEvent(c *gin.Context, requestId, modelName string, m...
function getPromptTokens (line 503) | func getPromptTokens(textRequest *relay_model.GeneralOpenAIRequest, rela...
function getRequestBody (line 515) | func getRequestBody(c *gin.Context, meta *meta.Meta, textRequest *relay_...
function RelayTextHelper (line 563) | func RelayTextHelper(c *gin.Context) *relay_model.ErrorWithStatusCode {
function isErrorHappened (line 705) | func isErrorHappened(meta *meta.Meta, resp *http.Response) bool {
function addAgentPrompt (line 737) | func addAgentPrompt(ctx context.Context, textRequest *relay_model.Genera...
function postConsumeQuota (line 764) | func postConsumeQuota(c *gin.Context, agent *model.Agent, user_id int64,...
function preConsumeQuota (line 855) | func preConsumeQuota(ctx context.Context, textRequest *relay_model.Gener...
function getPreConsumedQuota (line 860) | func getPreConsumedQuota(textRequest *relay_model.GeneralOpenAIRequest, ...
function failUpdateMessage (line 869) | func failUpdateMessage(c *gin.Context, agent *model.Agent, messageID int...
function executeWorkflow (line 899) | func executeWorkflow(c *gin.Context, workflowRequest *WorkflowRunRequest...
function executeWorkflowDirect (line 952) | func executeWorkflowDirect(c *gin.Context, workflowRequest *WorkflowRunR...
function handleWorkflowError (line 979) | func handleWorkflowError(resp *http.Response, workflowType string) error {
function executeCozeWorkflow (line 1029) | func executeCozeWorkflow(c *gin.Context, workflowRequest *WorkflowRunReq...
function executeDifyWorkflow (line 1122) | func executeDifyWorkflow(c *gin.Context, workflowRequest *WorkflowRunReq...
function executeFastGPTWorkflow (line 1208) | func executeFastGPTWorkflow(c *gin.Context, workflowRequest *WorkflowRun...
function executeAI53Workflow (line 1293) | func executeAI53Workflow(c *gin.Context, workflowRequest *WorkflowRunReq...
function saveWorkflowMessage (line 1378) | func saveWorkflowMessage(c *gin.Context, workflowRequest *WorkflowRunReq...
function updateConversationLastMessage (line 1481) | func updateConversationLastMessage(eid, conversationId, userId int64, qu...
function calculateWorkflowTokens (line 1508) | func calculateWorkflowTokens(workflowRequest *WorkflowRunRequest, respon...
function executeN8nWorkflow (line 1548) | func executeN8nWorkflow(c *gin.Context, workflowRequest *WorkflowRunRequ...
function getWorkflowChannelType (line 1639) | func getWorkflowChannelType(response *custom.WorkflowResponseData) int {
function GetByContext (line 1651) | func GetByContext(c *gin.Context) *relay_meta.Meta {
FILE: api/controller/rerank.go
type RerankRequest (line 26) | type RerankRequest struct
type RerankResponse (line 35) | type RerankResponse struct
type RerankResult (line 43) | type RerankResult struct
type RerankDocument (line 51) | type RerankDocument struct
type RerankUsage (line 56) | type RerankUsage struct
function Rerank (line 72) | func Rerank(c *gin.Context) {
function validateRerankRequest (line 232) | func validateRerankRequest(req *RerankRequest) error {
function getChannelTypeByModel (line 255) | func getChannelTypeByModel(modelName string) int {
function executeRerankRequest (line 270) | func executeRerankRequest(c *gin.Context, req *RerankRequest, channel *m...
function executeAliRerankRequest (line 297) | func executeAliRerankRequest(c *gin.Context, req *RerankRequest, meta *m...
function convertBailianRerankResponse (line 347) | func convertBailianRerankResponse(bailianResp map[string]interface{}, re...
function calculateRerankUsage (line 406) | func calculateRerankUsage(req *RerankRequest, resultCount int) *relay_mo...
function recordRerankUsage (line 431) | func recordRerankUsage(ctx context.Context, userId, eid int64, req *Rera...
function maskAPIKey (line 492) | func maskAPIKey(apiKey string) string {
function truncateString (line 500) | func truncateString(s string, maxLen int) string {
FILE: api/controller/response_handler.go
function GetResponseContent (line 15) | func GetResponseContent(c *gin.Context, isStream bool, resp *http.Respon...
type StreamResponseCollector (line 80) | type StreamResponseCollector struct
method Collect (line 92) | func (c *StreamResponseCollector) Collect(chunk []byte) {
method GetContent (line 127) | func (c *StreamResponseCollector) GetContent() (string, string) {
function NewStreamResponseCollector (line 85) | func NewStreamResponseCollector() *StreamResponseCollector {
type StreamResponseInterceptor (line 132) | type StreamResponseInterceptor struct
method Write (line 138) | func (w *StreamResponseInterceptor) Write(b []byte) (int, error) {
method WriteHeader (line 146) | func (w *StreamResponseInterceptor) WriteHeader(statusCode int) {
method Flush (line 151) | func (w *StreamResponseInterceptor) Flush() {
function SetupStreamInterceptor (line 158) | func SetupStreamInterceptor(c *gin.Context) *StreamResponseCollector {
FILE: api/controller/setting.go
type SettingRequest (line 13) | type SettingRequest struct
type UpdateDefaultLinksRequest (line 18) | type UpdateDefaultLinksRequest struct
type LinkItem (line 22) | type LinkItem struct
function CreateSetting (line 36) | func CreateSetting(c *gin.Context) {
function GetSetting (line 65) | func GetSetting(c *gin.Context) {
function UpdateSetting (line 87) | func UpdateSetting(c *gin.Context) {
function DeleteSetting (line 122) | func DeleteSetting(c *gin.Context) {
function GetSettings (line 146) | func GetSettings(c *gin.Context) {
function GetSettingsByGroup (line 164) | func GetSettingsByGroup(c *gin.Context) {
function GetSettingByKey (line 183) | func GetSettingByKey(c *gin.Context) {
function BatchUpdateDefaultPromptLinks (line 212) | func BatchUpdateDefaultPromptLinks(c *gin.Context) {
function GetDefaultPromptLinks (line 284) | func GetDefaultPromptLinks(c *gin.Context) {
FILE: api/controller/share.go
type CreateShareRequest (line 12) | type CreateShareRequest struct
type CreateShareResponse (line 18) | type CreateShareResponse struct
function CreateShare (line 34) | func CreateShare(c *gin.Context) {
type GetShareResponse (line 90) | type GetShareResponse struct
function GetShare (line 120) | func GetShare(c *gin.Context) {
FILE: api/controller/status.go
type HealthData (line 11) | type HealthData struct
function HealthCheck (line 23) | func HealthCheck(c *gin.Context) {
type CodeInfo (line 30) | type CodeInfo struct
function GetAllResponseCodes (line 42) | func GetAllResponseCodes(c *gin.Context) {
FILE: api/controller/subscription.go
type BatchSubscriptionRelation (line 17) | type BatchSubscriptionRelation struct
type BatchSubscriptionItem (line 42) | type BatchSubscriptionItem struct
type BatchSubscriptionRequest (line 74) | type BatchSubscriptionRequest struct
type GetSubscriptionSettingsRequest (line 80) | type GetSubscriptionSettingsRequest struct
type SubscriptionSettingsResponse (line 86) | type SubscriptionSettingsResponse struct
function BatchSubscriptionOperation (line 100) | func BatchSubscriptionOperation(c *gin.Context) {
function GetSubscriptionList (line 346) | func GetSubscriptionList(c *gin.Context) {
FILE: api/controller/sync_organization.go
function SyncOrganization (line 23) | func SyncOrganization(c *gin.Context) {
function GetSyncProgress (line 40) | func GetSyncProgress(c *gin.Context) {
function GetAllSyncProgress (line 54) | func GetAllSyncProgress(c *gin.Context) {
function GetSyncProgressByFrom (line 70) | func GetSyncProgressByFrom(c *gin.Context) {
FILE: api/controller/system_log.go
function GetModules (line 20) | func GetModules(c *gin.Context) {
function GetActions (line 34) | func GetActions(c *gin.Context) {
type CreateLogRequest (line 40) | type CreateLogRequest struct
type GetSystemLogsRequest (line 46) | type GetSystemLogsRequest struct
type SystemLogsResponse (line 56) | type SystemLogsResponse struct
function GetSystemLogs (line 78) | func GetSystemLogs(c *gin.Context) {
function CreateSystemLogs (line 116) | func CreateSystemLogs(c *gin.Context) {
FILE: api/controller/tencent.go
function GetTencentAllApps (line 29) | func GetTencentAllApps(c *gin.Context) {
function GetTencentAppDetail (line 95) | func GetTencentAppDetail(c *gin.Context) {
function UpdateTencentChannel (line 141) | func UpdateTencentChannel(client *tencent_sdk.Client, provider model.Pro...
function parseTencentCredentials (line 193) | func parseTencentCredentials(configs string) (secretId, secretKey, regio...
function initTencentClient (line 228) | func initTencentClient(secretId, secretKey, region string) (*tencent_sdk...
FILE: api/controller/upload.go
function Upload (line 26) | func Upload(c *gin.Context) {
function PreviewFile (line 122) | func PreviewFile(c *gin.Context) {
FILE: api/controller/user.go
type LoginRequest (line 24) | type LoginRequest struct
type LoginResponse (line 29) | type LoginResponse struct
type PasswordRegisterUserRequest (line 34) | type PasswordRegisterUserRequest struct
type EnterpriseAddUserRequest (line 41) | type EnterpriseAddUserRequest struct
type EnterpriseUserGetRequest (line 52) | type EnterpriseUserGetRequest struct
type EnterpriseUsersResponse (line 63) | type EnterpriseUsersResponse struct
function Login (line 77) | func Login(c *gin.Context) {
type SmsLoginRequest (line 141) | type SmsLoginRequest struct
type SmsLoginResponse (line 146) | type SmsLoginResponse struct
function SmsLogin (line 160) | func SmsLogin(c *gin.Context) {
function PasswordRegister (line 215) | func PasswordRegister(c *gin.Context) {
function EnterpriseAddUser (line 322) | func EnterpriseAddUser(c *gin.Context) {
function EnterpriseUsers (line 374) | func EnterpriseUsers(c *gin.Context) {
function DeleteEnterpriseUser (line 463) | func DeleteEnterpriseUser(c *gin.Context) {
function UpdateEnterpriseUser (line 517) | func UpdateEnterpriseUser(c *gin.Context) {
type GetCurrentUserResponse (line 575) | type GetCurrentUserResponse struct
function GetCurrentUser (line 588) | func GetCurrentUser(c *gin.Context) {
type UpdatePasswordRequest (line 616) | type UpdatePasswordRequest struct
function UpdateUserPassword (line 630) | func UpdateUserPassword(c *gin.Context) {
type UpdateCurrentUserRequest (line 659) | type UpdateCurrentUserRequest struct
function UpdateCurrentUser (line 673) | func UpdateCurrentUser(c *gin.Context) {
type CheckAccountRequest (line 709) | type CheckAccountRequest struct
type CheckAccountResponse (line 714) | type CheckAccountResponse struct
function CheckAccountExists (line 729) | func CheckAccountExists(c *gin.Context) {
type BatchSetAdminRequest (line 756) | type BatchSetAdminRequest struct
type BatchSetAdminResponse (line 761) | type BatchSetAdminResponse struct
function SetUserAsAdmin (line 780) | func SetUserAsAdmin(c *gin.Context) {
function UnsetUserAsAdmin (line 874) | func UnsetUserAsAdmin(c *gin.Context) {
type BatchAddInternalUserRequest (line 963) | type BatchAddInternalUserRequest struct
type InternalUserInfo (line 968) | type InternalUserInfo struct
type BatchInternalUserInfo (line 977) | type BatchInternalUserInfo struct
type BatchAddInternalUserResponse (line 985) | type BatchAddInternalUserResponse struct
function BatchAddInternalUsers (line 1003) | func BatchAddInternalUsers(c *gin.Context) {
type RegisterUserToInternalRequest (line 1063) | type RegisterUserToInternalRequest struct
function RegisterUserToInternal (line 1080) | func RegisterUserToInternal(c *gin.Context) {
type InternalUserRequest (line 1121) | type InternalUserRequest struct
type InternalUserResponse (line 1132) | type InternalUserResponse struct
function GetInternalUsers (line 1156) | func GetInternalUsers(c *gin.Context) {
function UpdateUserStatus (line 1217) | func UpdateUserStatus(c *gin.Context) {
type UpdateUserStatusRequest (line 1278) | type UpdateUserStatusRequest struct
type UpdateInternalUserRequest (line 1283) | type UpdateInternalUserRequest struct
function UpdateInternalUser (line 1302) | func UpdateInternalUser(c *gin.Context) {
type ResetPasswordRequest (line 1492) | type ResetPasswordRequest struct
function Logout (line 1509) | func Logout(c *gin.Context) {
function ResetPassword (line 1570) | func ResetPassword(c *gin.Context) {
type UpdateUserMobileRequest (line 1668) | type UpdateUserMobileRequest struct
function UpdateUserMobile (line 1688) | func UpdateUserMobile(c *gin.Context) {
function GetOrganizationUserList (line 1768) | func GetOrganizationUserList(c *gin.Context) {
function SetUserToDefaultSubscription (line 1816) | func SetUserToDefaultSubscription(c *gin.Context) {
function IsInit (line 1902) | func IsInit(c *gin.Context) {
FILE: api/main.go
function main (line 21) | func main() {
FILE: api/middleware/auth.go
function UserTokenAuth (line 14) | func UserTokenAuth(role int64) func(c *gin.Context) {
function HandleTokenAuth (line 47) | func HandleTokenAuth(token string, role int64) (user *model.User, err er...
FILE: api/middleware/cors.go
function CORS (line 8) | func CORS() gin.HandlerFunc {
FILE: api/middleware/distributor.go
type ModelRequest (line 12) | type ModelRequest struct
function SetupContextForSelectedChannel (line 16) | func SetupContextForSelectedChannel(c *gin.Context, channel *model.Chann...
FILE: api/middleware/logger.go
function Logger (line 11) | func Logger() gin.HandlerFunc {
FILE: api/middleware/relay_auth.go
function RelayTokenAuth (line 21) | func RelayTokenAuth() func(c *gin.Context) {
FILE: api/model/agent.go
type Agent (line 9) | type Agent struct
method Create (line 38) | func (agent *Agent) Create() error {
method Update (line 57) | func (agent *Agent) Update() error {
method Delete (line 62) | func (agent *Agent) Delete() error {
method GetUserGroupIds (line 123) | func (a *Agent) GetUserGroupIds() ([]int64, error) {
method LoadUserGroupIds (line 144) | func (a *Agent) LoadUserGroupIds() error {
method LoadConversationCount (line 153) | func (a *Agent) LoadConversationCount() error {
method GetProviderID (line 175) | func (a *Agent) GetProviderID() int64 {
constant AgentTypeApp (line 34) | AgentTypeApp = 0
constant AgentTypeWorkflow (line 35) | AgentTypeWorkflow = 1
function GetAgentByID (line 67) | func GetAgentByID(eid int64, agentID int64) (*Agent, error) {
function GetAgentListWithIDs (line 76) | func GetAgentListWithIDs(eid int64, keyword string, group_id int64, perm...
function GetAvailableAgentList (line 108) | func GetAvailableAgentList(eid int64, agent_types []int, offset int, lim...
function UpdateAgentStatus (line 163) | func UpdateAgentStatus(eid, agentID int64, enable *bool) error {
function GetAgentCountByEID (line 169) | func GetAgentCountByEID(eid int64) (int64, error) {
FILE: api/model/ai_link.go
type AILink (line 8) | type AILink struct
method CheckGroup (line 25) | func (aiLink *AILink) CheckGroup() error {
method LoadUserGroupIds (line 67) | func (aiLink *AILink) LoadUserGroupIds() error {
method LoadHasSharedAccount (line 178) | func (aiLink *AILink) LoadHasSharedAccount() {
function CreateAILink (line 36) | func CreateAILink(aiLink *AILink) error {
function DeleteAILinkByID (line 44) | func DeleteAILinkByID(id int64) error {
function UpdateAILink (line 48) | func UpdateAILink(aiLink *AILink) error {
function GetAILinkByID (line 58) | func GetAILinkByID(id int64) (*AILink, error) {
function GetAILinksByEidAndGroupId (line 78) | func GetAILinksByEidAndGroupId(eid int64, groupID int64) ([]AILink, erro...
function GetAILinksGroupedBySort (line 96) | func GetAILinksGroupedBySort(eid int64) ([]AILink, error) {
function GetAILinksByEidAndGroupIdWithKeyword (line 128) | func GetAILinksByEidAndGroupIdWithKeyword(eid int64, groupID int64, keyw...
function GetAILinksGroupedBySortWithKeyword (line 146) | func GetAILinksGroupedBySortWithKeyword(eid int64, keyword string) ([]AI...
FILE: api/model/base.go
type BaseModel (line 9) | type BaseModel struct
method BeforeCreate (line 14) | func (m *BaseModel) BeforeCreate(tx *gorm.DB) (err error) {
method BeforeUpdate (line 23) | func (m *BaseModel) BeforeUpdate(tx *gorm.DB) (err error) {
FILE: api/model/cache.go
constant LockOrganizationKeyPre (line 4) | LockOrganizationKeyPre = "lock_enterprise_organization_sync"
FILE: api/model/channel.go
constant ChannelStatusUnknown (line 16) | ChannelStatusUnknown = 0
constant ChannelStatusEnabled (line 17) | ChannelStatusEnabled = 1
constant ChannelStatusManuallyDisabled (line 18) | ChannelStatusManuallyDisabled = 2
constant ChannelStatusAutoDisabled (line 19) | ChannelStatusAutoDisabled = 3
constant ChannelApiDify (line 23) | ChannelApiDify = 1001
constant ChannelApi53AI (line 24) | ChannelApi53AI = 1002
constant ChannelApiBailian (line 25) | ChannelApiBailian = 1003
constant ChannelApiVolcengine (line 26) | ChannelApiVolcengine = 1004
constant ChannelApiAppBuilder (line 27) | ChannelApiAppBuilder = 1005
constant ChannelApiYuanqi (line 28) | ChannelApiYuanqi = 1006
constant ChannelApiTypeFastGpt (line 30) | ChannelApiTypeFastGpt = 1007
constant ChannelApiTypeMaxKB (line 31) | ChannelApiTypeMaxKB = 1008
constant ChannelApiTypeN8n (line 32) | ChannelApiTypeN8n = 1009
constant ChannelApiTypeCozeStudio (line 33) | ChannelApiTypeCozeStudio = 1010
constant ChannelApiTypeTencent (line 35) | ChannelApiTypeTencent = 1011
constant ModelTypeLLM (line 40) | ModelTypeLLM = 1
constant ModelTypeEmbedding (line 41) | ModelTypeEmbedding = 2
constant ModelTypeRerank (line 42) | ModelTypeRerank = 3
function IsValidModelType (line 46) | func IsValidModelType(t int) bool {
type ChannelDescription (line 55) | type ChannelDescription struct
function GetChannelDescription (line 80) | func GetChannelDescription(key string) string {
function GetAllChannelDescriptions (line 88) | func GetAllChannelDescriptions() []ChannelDescription {
type Channel (line 96) | type Channel struct
method GetBaseURL (line 179) | func (channel *Channel) GetBaseURL() string {
method LoadConfig (line 186) | func (channel *Channel) LoadConfig() (oneapi_model.ChannelConfig, erro...
method GetModelMapping (line 198) | func (channel *Channel) GetModelMapping() map[string]string {
method UpdateResponseTime (line 211) | func (channel *Channel) UpdateResponseTime(responseTime int64) {
method GetAddModelString (line 332) | func (channel *Channel) GetAddModelString(model string) string {
function CreateChannel (line 120) | func CreateChannel(channel *Channel) error {
function GetChannelByID (line 124) | func GetChannelByID(id int64) (*Channel, error) {
function UpdateChannel (line 130) | func UpdateChannel(channel *Channel) error {
function DeleteChannelByID (line 134) | func DeleteChannelByID(id int64) error {
function GetChannelsByEid (line 138) | func GetChannelsByEid(eid int64) ([]Channel, error) {
function GetChannelsByEidAndParams (line 147) | func GetChannelsByEidAndParams(eid int64, providerId int64, channelTypes...
function GetFirstChannelByEidAndProviderId (line 173) | func GetFirstChannelByEidAndProviderId(eid int64, providerId int64) (*Ch...
function GetRandomChannel (line 221) | func GetRandomChannel(eid int64, channelType int, modelName string) (*Ch...
function GetApiType (line 260) | func GetApiType(channelType int) int {
function GetFirstChannelByEidAndProviderType (line 274) | func GetFirstChannelByEidAndProviderType(eid int64, providerType int64, ...
function GetFirstAvailableChannelByEidAndProviderType (line 286) | func GetFirstAvailableChannelByEidAndProviderType(eid int64, providerTyp...
function StandardizationBotId (line 303) | func StandardizationBotId(botId string) string {
function StandardizationBotIdByChannelType (line 310) | func StandardizationBotIdByChannelType(botId string, channelType int) st...
function ProcessModelNames (line 318) | func ProcessModelNames(models string, channelType int) string {
FILE: api/model/channel_file_mapping.go
type ChannelFileMapping (line 10) | type ChannelFileMapping struct
type ObjectStringContent (line 22) | type ObjectStringContent struct
method GetUploadFile (line 48) | func (obj *ObjectStringContent) GetUploadFile() *UploadFile {
type ContentPart (line 27) | type ContentPart struct
function GetChannelFileMapping (line 32) | func GetChannelFileMapping(eid int64, channelId int64, fileId int64) *Ch...
function CreateChannelFileMapping (line 40) | func CreateChannelFileMapping(channelFileMapping *ChannelFileMapping) er...
function UpdateChannelFileMapping (line 44) | func UpdateChannelFileMapping(channelFileMapping *ChannelFileMapping) er...
FILE: api/model/conversation.go
type Conversation (line 3) | type Conversation struct
method LoadAgent (line 112) | func (c *Conversation) LoadAgent() error {
method LoadUser (line 121) | func (c *Conversation) LoadUser() error {
constant ConversationStatusActive (line 23) | ConversationStatusActive = 1
constant ConversationStatusArchived (line 24) | ConversationStatusArchived = 2
constant ConversationStatusDeleted (line 25) | ConversationStatusDeleted = 0
function CreateConversation (line 29) | func CreateConversation(conversation *Conversation) error {
function GetConversationByID (line 34) | func GetConversationByID(eid int64, user_id int64, conversation_id int64...
function AdminGetConversationByID (line 44) | func AdminGetConversationByID(eid int64, conversation_id int64) (*Conver...
function GetConversationsByUserID (line 54) | func GetConversationsByUserID(eid int64, userID int64) ([]*Conversation,...
function GetUserConversationsWithFilter (line 67) | func GetUserConversationsWithFilter(eid, userID int64, keyword string, c...
function GetMessageCountByConversationID (line 95) | func GetMessageCountByConversationID(conversationID int64) (int, error) {
function GetFirstMessageByConversationID (line 104) | func GetFirstMessageByConversationID(conversationID int64) (string, erro...
function GetConversationsByAgentID (line 131) | func GetConversationsByAgentID(eid int64, agentID int64) ([]*Conversatio...
function GetAgentConversationsWithFilter (line 141) | func GetAgentConversationsWithFilter(eid, agentID int64, keyword string,...
function UpdateConversation (line 169) | func UpdateConversation(conversation *Conversation) error {
function DeleteConversation (line 174) | func DeleteConversation(eid int64, conversation_id int64) error {
function GetConversationByIdAndUserId (line 178) | func GetConversationByIdAndUserId(eid int64, conversation_id int64, user...
FILE: api/model/department.go
constant DepartmentFromBackend (line 13) | DepartmentFromBackend = 0
constant DepartmentFromWecom (line 14) | DepartmentFromWecom = 1
constant DepartmentFromDingtalk (line 15) | DepartmentFromDingtalk = 2
constant DepartmentStatusNormal (line 20) | DepartmentStatusNormal = 0
constant DepartmentStatusDisabled (line 21) | DepartmentStatusDisabled = 1
constant DepartmentStatusDeleted (line 22) | DepartmentStatusDeleted = 2
constant DepartmentSortDefault (line 27) | DepartmentSortDefault = 0
constant DepartmentSortTop (line 28) | DepartmentSortTop = -1
type Department (line 32) | type Department struct
method TableName (line 45) | func (Department) TableName() string {
function InitDepartmentTable (line 50) | func InitDepartmentTable() error {
function CreateDepartment (line 78) | func CreateDepartment(dept *Department) error {
function validateDepartment (line 123) | func validateDepartment(dept *Department) error {
function GetDepartmentByID (line 137) | func GetDepartmentByID(eid int64, did int64) (*Department, error) {
function GetDepartmentsByEID (line 150) | func GetDepartmentsByEID(eid int64, from int) ([]*Department, error) {
function GetChildDepartments (line 160) | func GetChildDepartments(eid int64, pdid int64) ([]*Department, error) {
function BatchGetDepartmentsByIDs (line 170) | func BatchGetDepartmentsByIDs(eid int64, dids []int64) ([]*Department, e...
function UpdateDepartment (line 184) | func UpdateDepartment(dept *Department) error {
function handleParentChange (line 218) | func handleParentChange(dept *Department, existingDept *Department) error {
function isChildDepartment (line 252) | func isChildDepartment(path string, did int64) bool {
function updateChildDepartmentPaths (line 261) | func updateChildDepartmentPaths(eid int64, did int64, oldPath string, ne...
function updateSingleChildPath (line 312) | func updateSingleChildPath(childPath, oldPath, newPath string, did int64...
function DeleteDepartment (line 331) | func DeleteDepartment(eid int64, did int64, deleteChildren bool) error {
function BatchDeleteDepartments (line 393) | func BatchDeleteDepartments(eid int64, dids []int64) error {
function SearchDepartments (line 418) | func SearchDepartments(eid int64, keyword string, limit int) ([]*Departm...
function GetDepartmentTree (line 440) | func GetDepartmentTree(eid int64, from int) ([]*DepartmentNode, error) {
type DepartmentNode (line 484) | type DepartmentNode struct
function buildDepartmentTree (line 490) | func buildDepartmentTree(node *DepartmentNode, allDepts []*Department, d...
function sortDepartmentNodes (line 507) | func sortDepartmentNodes(nodes []*DepartmentNode) {
FILE: api/model/dingtalk_corp.go
type DingtalkCorp (line 10) | type DingtalkCorp struct
method GetAuthUserInfo (line 86) | func (d *DingtalkCorp) GetAuthUserInfo() *DingtalkAuthUserInfo {
method Update (line 94) | func (d *DingtalkCorp) Update() error {
method Delete (line 98) | func (d *DingtalkCorp) Delete() error {
method GetAuthCorpInfo (line 102) | func (d *DingtalkCorp) GetAuthCorpInfo() *DingtalkAuthCorpInfo {
type DingtalkAuthCorpInfo (line 31) | type DingtalkAuthCorpInfo struct
type DingtalkAuthUserInfo (line 40) | type DingtalkAuthUserInfo struct
type AuthInfo (line 44) | type AuthInfo struct
function GetDingtalkCorp (line 55) | func GetDingtalkCorp(suiteId string, corpId string) (*DingtalkCorp, erro...
function CreateDingtalkCorp (line 70) | func CreateDingtalkCorp(corp *DingtalkCorp) error {
function UpdateDingtalkCorp (line 78) | func UpdateDingtalkCorp(corp *DingtalkCorp) error {
FILE: api/model/dingtalk_suite.go
type DingtalkSuite (line 7) | type DingtalkSuite struct
method Create (line 31) | func (suite *DingtalkSuite) Create() error {
method Update (line 45) | func (suite *DingtalkSuite) Update() error {
method Delete (line 53) | func (suite *DingtalkSuite) Delete() error {
function GetDingtalkSuite (line 22) | func GetDingtalkSuite(suiteID string) (*DingtalkSuite, error) {
function GetDingtalkSuitesByCorpID (line 61) | func GetDingtalkSuitesByCorpID(corpID string) ([]*DingtalkSuite, error) {
FILE: api/model/enterprise.go
type Enterprise (line 13) | type Enterprise struct
method Update (line 107) | func (enterprise *Enterprise) Update() error {
method Delete (line 115) | func (enterprise *Enterprise) Delete() error {
method PartialUpdateEnterprise (line 119) | func (enterprise *Enterprise) PartialUpdateEnterprise(updateData map[s...
method LoadWecomCorpInfo (line 518) | func (e *Enterprise) LoadWecomCorpInfo(suiteID string, loadType int) e...
method LoadDingtalkCorpInfo (line 539) | func (e *Enterprise) LoadDingtalkCorpInfo(suiteID string, loadType int...
type WecomInstallInfo (line 37) | type WecomInstallInfo struct
type DingtalkInstallInfo (line 42) | type DingtalkInstallInfo struct
constant EnterpriseStatusNormal (line 48) | EnterpriseStatusNormal = 1
constant EnterpriseStatusDisabled (line 49) | EnterpriseStatusDisabled = 2
constant EnterpriseStatusNotActivated (line 50) | EnterpriseStatusNotActivated = 0
constant EnterpriseTypeIndependent (line 52) | EnterpriseTypeIndependent = "independent"
constant EnterpriseTypeEnterprise (line 53) | EnterpriseTypeEnterprise = "enterprise"
constant EnterpriseTypeIndustry (line 54) | EnterpriseTypeIndustry = "industry"
type EnterpriseTypeDescription (line 57) | type EnterpriseTypeDescription struct
function GetEnterpriseTypeDescription (line 68) | func GetEnterpriseTypeDescription(key string) string {
function GetAllEnterpriseTypeDescriptions (line 75) | func GetAllEnterpriseTypeDescriptions() []EnterpriseTypeDescription {
function GetEnterpriseModel (line 83) | func GetEnterpriseModel(id int64) (*Enterprise, error) {
function GetEnterpriseByID (line 94) | func GetEnterpriseByID(eid int64) (*Enterprise, error) {
function CreateEnterpriseModel (line 103) | func CreateEnterpriseModel(enterprise *Enterprise) error {
function GetEnterpriseName (line 155) | func GetEnterpriseName(eid int64) (string, error) {
function InitializeSystem (line 172) | func InitializeSystem() error {
function initAILinkData (line 443) | func initAILinkData(tx *gorm.DB, eid int64) error {
function GetEnterpriseByWecomCorpID (line 506) | func GetEnterpriseByWecomCorpID(wecomCorpID string) (*Enterprise, error) {
function GetEnterpriseByDingtalkCorpID (line 561) | func GetEnterpriseByDingtalkCorpID(dingtalkCorpID string) (*Enterprise, ...
FILE: api/model/enterprise_config.go
type EnterpriseConfig (line 7) | type EnterpriseConfig struct
constant EnterpriseConfigTypeSMTP (line 19) | EnterpriseConfigTypeSMTP = "smtp"
constant EnterpriseConfigTypeMobile (line 20) | EnterpriseConfigTypeMobile = "mobile"
constant EnterpriseConfigTypeSSO (line 21) | EnterpriseConfigTypeSSO = "auth_sso"
function GetEnterpriseConfigDefaultContent (line 31) | func GetEnterpriseConfigDefaultContent(configType string) (string, error) {
FILE: api/model/enterprise_sync.go
function FindEnterpriseUserByAccount (line 11) | func FindEnterpriseUserByAccount(account string) (*User, error) {
function SetRelatedID (line 37) | func SetRelatedID(enterpriseUserID int64, platformUserID int64) error {
function SetRelatedIDByEidAccount (line 46) | func SetRelatedIDByEidAccount(eid int64, account string, platformUserID ...
FILE: api/model/group.go
type Group (line 4) | type Group struct
constant USER_FREE_GROUP_NAME (line 17) | USER_FREE_GROUP_NAME = "免费版"
function GetGroupWithAgents (line 21) | func GetGroupWithAgents(groupId int64, enable bool) (*Group, error) {
function GetGroupsWithAgents (line 49) | func GetGroupsWithAgents(eid int64, groupType int64, offset, limit int) ...
constant USER_GROUP_TYPE (line 95) | USER_GROUP_TYPE = 1
constant AI_LINKS_TYPE (line 96) | AI_LINKS_TYPE = 2
constant AGENT_TYPE (line 97) | AGENT_TYPE = 3
constant INTERNAL_USER_GROUP_TYPE (line 98) | INTERNAL_USER_GROUP_TYPE = 4
constant SYSTEM_PROMPT_TYPE (line 99) | SYSTEM_PROMPT_TYPE = 5
constant PERSONAL_PROMPT_TYPE (line 100) | PERSONAL_PROMPT_TYPE = 6
function CreateGroup (line 103) | func CreateGroup(group *Group) error {
function DeleteGroupByID (line 107) | func DeleteGroupByID(groupID int64) error {
function UpdateGroup (line 111) | func UpdateGroup(group *Group) error {
function GetGroupByID (line 117) | func GetGroupByID(groupID int64) (*Group, error) {
function BatchSubmitGroups (line 128) | func BatchSubmitGroups(groupType int64, eid int64, groups []Group) error {
function GetGroupsByEid (line 168) | func GetGroupsByEid(eid int64, groupType int64) ([]Group, error) {
function GetFirstGroupByEid (line 190) | func GetFirstGroupByEid(eid int64, groupType int64) (Group, error) {
function ExistsGroupByIDAndType (line 198) | func ExistsGroupByIDAndType(Eid int64, groupId int64, groupType int64) (...
type AILinkInfo (line 208) | type AILinkInfo struct
type GroupInfo (line 217) | type GroupInfo struct
function GetDefaultGroupData (line 225) | func GetDefaultGroupData() []GroupInfo {
function GetUserFreeGroup (line 282) | func GetUserFreeGroup(eid int64) (*Group, error) {
FILE: api/model/like.go
type Like (line 10) | type Like struct
method TableName (line 31) | func (Like) TableName() string {
method Validate (line 36) | func (l *Like) Validate() error {
method Create (line 50) | func (l *Like) Create() error {
method UpdateStatus (line 69) | func (l *Like) UpdateStatus(newStatus int) error {
method Delete (line 81) | func (l *Like) Delete() error {
method HardDelete (line 86) | func (l *Like) HardDelete() error {
method Exists (line 91) | func (l *Like) Exists() (bool, error) {
method ToggleLike (line 135) | func (l *Like) ToggleLike() error {
constant LikeStatusActive (line 21) | LikeStatusActive = 1
constant LikeStatusCancel (line 22) | LikeStatusCancel = 0
constant LikeTypePrompt (line 27) | LikeTypePrompt = "prompt"
function GetLikeByID (line 100) | func GetLikeByID(likeID int64) (*Like, error) {
function GetUserLikes (line 113) | func GetUserLikes(userID int64, likeType string) ([]Like, error) {
function CountLikesByObject (line 126) | func CountLikesByObject(objectType string, objectID int64) (int64, error) {
function GetLikeByUserObject (line 159) | func GetLikeByUserObject(userID int64, objectType string, objectID int64...
FILE: api/model/main.go
function InitDB (line 20) | func InitDB() {
function GetDbConn (line 44) | func GetDbConn() (*gorm.DB, error) {
function openSQLite (line 59) | func openSQLite() (*gorm.DB, error) {
function openMySQL (line 68) | func openMySQL(dsn string) (*gorm.DB, error) {
function setDBConns (line 76) | func setDBConns(db *gorm.DB) *sql.DB {
function migrateDB (line 93) | func migrateDB() error {
FILE: api/model/member_binding.go
constant MemberBindingSourceNone (line 13) | MemberBindingSourceNone = 0
constant MemberBindingSourceWeChat (line 14) | MemberBindingSourceWeChat = 1
constant MemberBindingStatusInactive (line 19) | MemberBindingStatusInactive = 0
constant MemberBindingStatusActive (line 20) | MemberBindingStatusActive = 1
constant MemberBindingStatusDisabled (line 21) | MemberBindingStatusDisabled = 2
constant MemberBindingStatusExpired (line 22) | MemberBindingStatusExpired = 3
type MemberBinding (line 26) | type MemberBinding struct
method TableName (line 38) | func (MemberBinding) TableName() string {
function InitMemberBindingTable (line 43) | func InitMemberBindingTable() error {
function CreateMemberBinding (line 59) | func CreateMemberBinding(binding *MemberBinding) error {
function validateMemberBinding (line 70) | func validateMemberBinding(binding *MemberBinding) error {
function GetMemberBindingByID (line 87) | func GetMemberBindingByID(id int64) (*MemberBinding, error) {
function GetMemberBindingByMID (line 100) | func GetMemberBindingByMID(mid int64) ([]*MemberBinding, error) {
function GetMemberBindingByMidAndFrom (line 109) | func GetMemberBindingByMidAndFrom(mid int64, from int) (*MemberBinding, ...
function GetMemberBindingByDepartmentFromBackend (line 121) | func GetMemberBindingByDepartmentFromBackend(mid int64, tx *gorm.DB) (*M...
function GetMemberBindingByBindValue (line 152) | func GetMemberBindingByBindValue(eid int64, bindValue string, from int) ...
function GetMemberBindings (line 165) | func GetMemberBindings(eid int64, from int, status int, offset, limit in...
function UpdateMemberBinding (line 198) | func UpdateMemberBinding(binding *MemberBinding) error {
function DeleteMemberBinding (line 222) | func DeleteMemberBinding(id int64) error {
function BatchDeleteMemberBindings (line 235) | func BatchDeleteMemberBindings(ids []int64) error {
function DeleteMemberBindingsByMID (line 245) | func DeleteMemberBindingsByMID(mid int64) error {
function ActivateMemberBinding (line 251) | func ActivateMemberBinding(id int64) error {
function DeactivateMemberBinding (line 260) | func DeactivateMemberBinding(id int64) error {
function CountMemberBindings (line 269) | func CountMemberBindings(eid int64, from int) (int64, error) {
function GetMemberBindingsBySource (line 282) | func GetMemberBindingsBySource(eid int64, from int) ([]*MemberBinding, e...
FILE: api/model/member_department_relation.go
constant MemberDepartmentRelationFromBackend (line 12) | MemberDepartmentRelationFromBackend = 0
constant MemberDepartmentRelationFromWeChat (line 13) | MemberDepartmentRelationFromWeChat = 1
type MemberDepartmentRelation (line 17) | type MemberDepartmentRelation struct
method TableName (line 27) | func (MemberDepartmentRelation) TableName() string {
function CreateMemberDepartmentRelation (line 32) | func CreateMemberDepartmentRelation(relation *MemberDepartmentRelation) ...
function validateMemberDepartmentRelation (line 42) | func validateMemberDepartmentRelation(relation *MemberDepartmentRelation...
function GetMemberDepartmentRelationByID (line 59) | func GetMemberDepartmentRelationByID(id int64) (*MemberDepartmentRelatio...
function GetMemberDepartmentRelationsByEID (line 72) | func GetMemberDepartmentRelationsByEID(eid int64) ([]*MemberDepartmentRe...
function GetMemberDepartmentRelationsByDID (line 82) | func GetMemberDepartmentRelationsByDID(eid int64, did int64) ([]*MemberD...
function GetMemberDepartmentRelationsByBID (line 92) | func GetMemberDepartmentRelationsByBID(eid int64, bid int64) ([]*MemberD...
function GetMemberDidsByBID (line 101) | func GetMemberDidsByBID(eid int64, bid int64) ([]int64, error) {
function UpdateMemberDepartmentRelation (line 117) | func UpdateMemberDepartmentRelation(relation *MemberDepartmentRelation) ...
function DeleteMemberDepartmentRelation (line 140) | func DeleteMemberDepartmentRelation(id int64) error {
function DeleteMemberDepartmentRelationsByDID (line 153) | func DeleteMemberDepartmentRelationsByDID(eid int64, did int64) error {
function DeleteMemberDepartmentRelationsByBID (line 159) | func DeleteMemberDepartmentRelationsByBID(eid int64, bid int64) error {
function BatchCreateMemberDepartmentRelations (line 165) | func BatchCreateMemberDepartmentRelations(relations []*MemberDepartmentR...
function GetUsersByDepartmentIDs (line 199) | func GetUsersByDepartmentIDs(eid int64, dids []int64) ([]int64, error) {
FILE: api/model/message.go
type Message (line 5) | type Message struct
method GetMessageType (line 37) | func (m *Message) GetMessageType() MessageType {
method ParseChatMessage (line 53) | func (m *Message) ParseChatMessage() ([]map[string]interface{}, error) {
method ParseWorkflowParameters (line 62) | func (m *Message) ParseWorkflowParameters() (map[string]interface{}, e...
method ParseWorkflowOutput (line 71) | func (m *Message) ParseWorkflowOutput() (map[string]interface{}, error) {
type MessageType (line 29) | type MessageType
constant MessageTypeChat (line 32) | MessageTypeChat MessageType = "chat"
constant MessageTypeWorkflow (line 33) | MessageTypeWorkflow MessageType = "workflow"
function CreateMessage (line 80) | func CreateMessage(message *Message) error {
function GetMessageByID (line 85) | func GetMessageByID(eid int64, id int64) (*Message, error) {
function GetMessagesByUserID (line 95) | func GetMessagesByUserID(eid int64, userID int64) ([]*Message, error) {
function GetMessagesByAgentID (line 105) | func GetMessagesByAgentID(eid int64, agentID int64) ([]*Message, error) {
function GetMessagesByUserAndAgent (line 115) | func GetMessagesByUserAndAgent(eid int64, userID int64, agentID int64, k...
function UpdateMessage (line 145) | func UpdateMessage(message *Message) error {
function DeleteMessage (line 150) | func DeleteMessage(eid int64, id int64) error {
function DeleteMessagesByUserID (line 155) | func DeleteMessagesByUserID(eid int64, userID int64) error {
function DeleteMessagesByAgentID (line 160) | func DeleteMessagesByAgentID(eid int64, agentID int64) error {
function GetMessagesByConversationID (line 165) | func GetMessagesByConversationID(eid int64, conversationID int64, keywor...
function GetMessagesByConversationIDWithDirection (line 192) | func GetMessagesByConversationIDWithDirection(eid int64, conversationID ...
FILE: api/model/navigation.go
type Navigation (line 5) | type Navigation struct
method Create (line 28) | func (nav *Navigation) Create() error {
method Update (line 49) | func (nav *Navigation) Update() error {
method Delete (line 53) | func (nav *Navigation) Delete() error {
method LoadContent (line 67) | func (nav *Navigation) LoadContent() error {
constant NavigationTypeSystemBuiltIn (line 20) | NavigationTypeSystemBuiltIn = 1
constant NavigationTypeExternalLink (line 21) | NavigationTypeExternalLink = 2
constant NavigationTypeCustomPage (line 22) | NavigationTypeCustomPage = 3
constant NavigationStatusEnabled (line 24) | NavigationStatusEnabled = 1
constant NavigationStatusDisabled (line 25) | NavigationStatusDisabled = 2
function GetNavigationByID (line 57) | func GetNavigationByID(eid int64, navigationID int64) (*Navigation, erro...
function UpdateNavigation (line 77) | func UpdateNavigation(id int, updates map[string]interface{}) error {
function DeleteNavigation (line 81) | func DeleteNavigation(id int) error {
function UpdateNavigationStatus (line 85) | func UpdateNavigationStatus(id int, status int) error {
function BatchUpdateNavigationSort (line 89) | func BatchUpdateNavigationSort(sortList []struct {
function GetNavigationsByEid (line 110) | func GetNavigationsByEid(eid int64) ([]*Navigation, error) {
FILE: api/model/navigation_content.go
type NavigationContent (line 8) | type NavigationContent struct
method TableName (line 15) | func (NavigationContent) TableName() string {
method Create (line 19) | func (nc *NavigationContent) Create() error {
method Update (line 34) | func (nc *NavigationContent) Update() error {
method Delete (line 41) | func (nc *NavigationContent) Delete() error {
function GetContentByID (line 45) | func GetContentByID(contentID int64, navigationID int64) (*NavigationCon...
function GetNavigationContentByID (line 54) | func GetNavigationContentByID(navID int64) (*NavigationContent, error) {
function DeleteNavigationContentByNavID (line 62) | func DeleteNavigationContentByNavID(navID int64) error {
FILE: api/model/order.go
constant OrderStatusConfirming (line 10) | OrderStatusConfirming = 1
constant OrderStatusPending (line 11) | OrderStatusPending = 2
constant OrderStatusPaid (line 12) | OrderStatusPaid = 3
constant OrderStatusExpired (line 13) | OrderStatusExpired = 4
constant OrderStatusClosed (line 14) | OrderStatusClosed = 5
constant ServiceTypeSubscription (line 19) | ServiceTypeSubscription = 1
constant TradeTypeJSAPI (line 24) | TradeTypeJSAPI = "JSAPI"
constant TradeTypeNative (line 25) | TradeTypeNative = "NATIVE"
constant TradeTypeApp (line 26) | TradeTypeApp = "APP"
constant TradeTypeMicroPay (line 27) | TradeTypeMicroPay = "MICROPAY"
constant TradeTypeMWeb (line 28) | TradeTypeMWeb = "MWEB"
constant TradeTypeFacePay (line 29) | TradeTypeFacePay = "FACEPAY"
constant TradeStateSuccess (line 34) | TradeStateSuccess = "SUCCESS"
constant TradeStateRefund (line 35) | TradeStateRefund = "REFUND"
constant TradeStateNotPay (line 36) | TradeStateNotPay = "NOTPAY"
constant TradeStateClosed (line 37) | TradeStateClosed = "CLOSED"
constant TradeStateRevoked (line 38) | TradeStateRevoked = "REVOKED"
constant TradeStateUserPaying (line 39) | TradeStateUserPaying = "USERPAYING"
constant TradeStatePayError (line 40) | TradeStatePayError = "PAYERROR"
constant TradeStateWaitBuyerPay (line 43) | TradeStateWaitBuyerPay = "WAIT_BUYER_PAY"
constant TradeStateTradeClosed (line 44) | TradeStateTradeClosed = "TRADE_CLOSED"
constant TradeStateTradeSuccess (line 45) | TradeStateTradeSuccess = "TRADE_SUCCESS"
constant TradeStateTradeFinish (line 46) | TradeStateTradeFinish = "TRADE_FINISHED"
type Order (line 50) | type Order struct
method CalculateNewExpiredTime (line 72) | func (o *Order) CalculateNewExpiredTime(user *User) (int64, error) {
method TableName (line 200) | func (o *Order) TableName() string {
method Create (line 205) | func (o *Order) Create() error {
method Update (line 210) | func (o *Order) Update() error {
method Delete (line 215) | func (o *Order) Delete() error {
function GetOrderByID (line 108) | func GetOrderByID(eid int64, id int64) (*Order, error) {
function GetOrderByOrderId (line 115) | func GetOrderByOrderId(eid int64, orderId string) (*Order, error) {
function UpdateOrderStatus (line 122) | func UpdateOrderStatus(eid int64, orderId string, status int) error {
function UpdateOrderPaid (line 130) | func UpdateOrderPaid(eid int64, orderId string, transactionId string) er...
function UpdateOrderPaidWithTime (line 135) | func UpdateOrderPaidWithTime(eid int64, orderId string, transactionId st...
function GetOrders (line 220) | func GetOrders(eid, userID int64, status, page, pageSize int) ([]*Order,...
function GetUserOrders (line 249) | func GetUserOrders(eid int64, userID int64) ([]*Order, error) {
function GetPendingOrders (line 256) | func GetPendingOrders() ([]*Order, error) {
function GetExpiredOrders (line 263) | func GetExpiredOrders() ([]*Order, error) {
function GetOrdersByStatus (line 270) | func GetOrdersByStatus(eid int64, status int) ([]*Order, error) {
function CountOrdersByStatus (line 277) | func CountOrdersByStatus(eid int64, status int) (int64, error) {
function GetOrderStatistics (line 284) | func GetOrderStatistics(eid int64) (map[string]interface{}, error) {
function GetRecentOrders (line 326) | func GetRecentOrders(eid int64, limit int) ([]*Order, error) {
function GetOrdersWithFilters (line 333) | func GetOrdersWithFilters(eid int64, userID int64, status, payType int, ...
function UpdateExpiredOrders (line 387) | func UpdateExpiredOrders() (int64, error) {
function GetExpiredPendingOrders (line 397) | func GetExpiredPendingOrders(expireTime time.Time) ([]Order, error) {
FILE: api/model/pay_setting.go
constant PayTypeWechat (line 7) | PayTypeWechat = 1
constant PayTypeManual (line 8) | PayTypeManual = 2
constant PayTypePaypal (line 9) | PayTypePaypal = 3
constant PayTypeAlipay (line 10) | PayTypeAlipay = 4
constant PayStatusDisabled (line 15) | PayStatusDisabled = false
constant PayStatusEnabled (line 16) | PayStatusEnabled = true
type PaySetting (line 20) | type PaySetting struct
method TableName (line 55) | func (PaySetting) TableName() string {
method Create (line 60) | func (ps *PaySetting) Create() error {
method Update (line 65) | func (ps *PaySetting) Update() error {
method Delete (line 70) | func (ps *PaySetting) Delete() error {
type WechatPayConfig (line 31) | type WechatPayConfig struct
type AlipayConfig (line 46) | type AlipayConfig struct
function GetPaySettingByID (line 75) | func GetPaySettingByID(eid int64, id int64) (*PaySetting, error) {
function GetPaySettingsByEid (line 85) | func GetPaySettingsByEid(eid int64) ([]*PaySetting, error) {
function GetPaySettingByType (line 95) | func GetPaySettingByType(eid int64, payType int) (*PaySetting, error) {
function GetPayTypeText (line 104) | func GetPayTypeText(payType int) (string, error) {
FILE: api/model/prompt.go
type Prompt (line 10) | type Prompt struct
method TableName (line 40) | func (Prompt) TableName() string {
method Create (line 45) | func (p *Prompt) Create() error {
method Update (line 66) | func (p *Prompt) Update() error {
method Delete (line 81) | func (p *Prompt) Delete() error {
method HardDelete (line 90) | func (p *Prompt) HardDelete() error {
method IncrementViews (line 169) | func (p *Prompt) IncrementViews() error {
method UpdateSort (line 178) | func (p *Prompt) UpdateSort(sort int) error {
method UpdateCustomConfig (line 187) | func (p *Prompt) UpdateCustomConfig(config string) error {
method LoadPromptGroups (line 195) | func (p *Prompt) LoadPromptGroups() error {
method LoadIsLiked (line 210) | func (p *Prompt) LoadIsLiked(UserId int64) error {
constant PromptTypeSystem (line 31) | PromptTypeSystem = 1
constant PromptTypePersonal (line 32) | PromptTypePersonal = 2
constant PromptStatusDisable (line 34) | PromptStatusDisable = 0
constant PromptStatusNormal (line 35) | PromptStatusNormal = 1
constant PromptStatusDelete (line 36) | PromptStatusDelete = 2
function GetPromptByID (line 96) | func GetPromptByID(promptID int) (*Prompt, error) {
function GetPromptsByEid (line 107) | func GetPromptsByEid(eid int) ([]*Prompt, error) {
function GetPromptList (line 117) | func GetPromptList(eid int64, keyword string, groupIDStr string, status,...
FILE: api/model/provider.go
type Provider (line 7) | type Provider struct
method GetBaseURLByProviderType (line 37) | func (provider *Provider) GetBaseURLByProviderType() string {
type CozeConfig (line 22) | type CozeConfig struct
constant ProviderTypeCozeCn (line 28) | ProviderTypeCozeCn = 1
constant ProviderTypeCozeCom (line 29) | ProviderTypeCozeCom = 2
constant ProviderTypeAppBuilder (line 30) | ProviderTypeAppBuilder = 3
constant ProviderType53AI (line 31) | ProviderType53AI = 4
constant ProviderTypeCozeStudio (line 32) | ProviderTypeCozeStudio = 5
constant ProviderTypeTencent (line 33) | ProviderTypeTencent = 6
function CreateProvider (line 59) | func CreateProvider(provider *Provider) error {
function DeleteProviderByID (line 63) | func DeleteProviderByID(id, eid int64) error {
function UpdateProvider (line 67) | func UpdateProvider(provider *Provider) error {
function GetProviderByID (line 72) | func GetProviderByID(id, eid int64) (*Provider, error) {
function GetProvidersByEidAndProviderType (line 78) | func GetProvidersByEidAndProviderType(eid int64, providerType int64) ([]...
function GetProvidersByEidWithFilters (line 89) | func GetProvidersByEidWithFilters(eid int64, providerType int64, name st...
function GetFirstProviderByEidAndProviderType (line 105) | func GetFirstProviderByEidAndProviderType(eid int64, providerType int64)...
function GetProvidersByTypeAndAuthStatus (line 110) | func GetProvidersByTypeAndAuthStatus(providerType int64, authStatus bool...
function GetProviderByEidAndProviderTypeWithOptionalID (line 119) | func GetProviderByEidAndProviderTypeWithOptionalID(eid int64, providerTy...
FILE: api/model/resource_permission.go
constant ResourceTypeAgent (line 5) | ResourceTypeAgent = "agent"
constant ResourceTypeUser (line 6) | ResourceTypeUser = "user"
constant ResourceTypeDepartment (line 7) | ResourceTypeDepartment = "department"
constant ResourceTypePrompt (line 8) | ResourceTypePrompt = "prompt"
constant ResourceTypeAILink (line 9) | ResourceTypeAILink = "ai_link"
constant PermissionRead (line 14) | PermissionRead = "read"
constant PermissionWrite (line 15) | PermissionWrite = "write"
type ResourcePermission (line 19) | type ResourcePermission struct
method TableName (line 31) | func (ResourcePermission) TableName() string {
method Create (line 36) | func (rule *ResourcePermission) Create() error {
method Update (line 41) | func (rule *ResourcePermission) Update() error {
method Delete (line 46) | func (rule *ResourcePermission) Delete() error {
function GetResourcePermissionByID (line 51) | func GetResourcePermissionByID(id int64) (*ResourcePermission, error) {
function GetResourcePermissionsByGroupID (line 61) | func GetResourcePermissionsByGroupID(groupID int64) ([]*ResourcePermissi...
function CheckPermission (line 71) | func CheckPermission(groupID int64, resourceID int64, resourceType strin...
function GetResourcesByGroupAndType (line 86) | func GetResourcesByGroupAndType(groupID int64, resourceType string) ([]i...
function DeleteResourcePermissionsByResource (line 100) | func DeleteResourcePermissionsByResource(resourceID int64, resourceType ...
function GetGroupsByUserID (line 104) | func GetGroupsByUserID(userID int64) ([]int64, error) {
function GetGroupsByUserIDAndType (line 117) | func GetGroupsByUserIDAndType(userID int64, groupType int64) ([]int64, e...
function GetGroupsByDepartmentID (line 133) | func GetGroupsByDepartmentID(departmentID int64) ([]int64, error) {
function GetGroupIDsByDepartmentIDs (line 146) | func GetGroupIDsByDepartmentIDs(dids []int64) ([]int64, error) {
FILE: api/model/response.go
type CommonResponse (line 10) | type CommonResponse struct
type OpenAIErrorResponse (line 31) | type OpenAIErrorResponse struct
type ResponseCode (line 40) | type ResponseCode
method Message (line 101) | func (c ResponseCode) Message() string {
method ToResponse (line 108) | func (c ResponseCode) ToResponse(data interface{}) CommonResponse {
method ToErrorResponse (line 119) | func (c ResponseCode) ToErrorResponse(err error) CommonResponse {
method ToNewErrorResponse (line 127) | func (c ResponseCode) ToNewErrorResponse(message string) CommonResponse {
method ToOpenAIErrorRespone (line 136) | func (c ResponseCode) ToOpenAIErrorRespone(data interface{}) OpenAIErr...
constant Success (line 45) | Success ResponseCode = iota
constant ParamError (line 46) | ParamError
constant DBError (line 47) | DBError
constant NetworkError (line 48) | NetworkError
constant SystemError (line 49) | SystemError
constant AuthFailed (line 50) | AuthFailed
constant NotFound (line 51) | NotFound
constant UnauthorizedError (line 52) | UnauthorizedError
constant FileError (line 53) | FileError
constant ForbiddenError (line 54) | ForbiddenError
constant AgentAuthError (line 55) | AgentAuthError
constant TokenExpiredError (line 56) | TokenExpiredError
constant ChatError (line 57) | ChatError
constant ProviderNoFoundError (line 58) | ProviderNoFoundError
constant OperateTooFast (line 59) | OperateTooFast
constant FeatureNotAvailableError (line 60) | FeatureNotAvailableError
constant RecordAlreadyExists (line 61) | RecordAlreadyExists
constant InvalidVerificationCodeError (line 62) | InvalidVerificationCodeError
constant InvalidEnterpriseID (line 91) | InvalidEnterpriseID = "invalid enterprise id"
constant InvalidVerificationCode (line 92) | InvalidVerificationCode = "invalid or expired verification code"
constant InvalidMobileOrEmail (line 93) | InvalidMobileOrEmail = "invalid mobile number or email format"
constant InvalidMobileFormat (line 94) | InvalidMobileFormat = "invalid mobile number format"
constant PasswordNotMatch (line 95) | PasswordNotMatch = "password not match"
constant OrderNotFound (line 96) | OrderNotFound = "order not found"
constant FeatureNotAvailable (line 97) | FeatureNotAvailable = "feature not available"
constant FeatureOverLimit (line 98) | FeatureOverLimit = "feature over limit"
FILE: api/model/setting.go
type Setting (line 10) | type Setting struct
type SettingKey (line 18) | type SettingKey
constant ThirdPartyStatisticHeader (line 21) | ThirdPartyStatisticHeader SettingKey = "third_party_statistic_header"
constant ThirdPartyStatisticCss (line 22) | ThirdPartyStatisticCss SettingKey = "third_party_statistic_css"
constant DefaultPromptLinks (line 26) | DefaultPromptLinks string = "default_prompt_links"
type SettingGroup (line 29) | type SettingGroup
function GetSettingGroupByName (line 40) | func GetSettingGroupByName(group_name string) (SettingGroup, bool) {
function CreateSetting (line 45) | func CreateSetting(setting *Setting) error {
function DeleteSettingByID (line 49) | func DeleteSettingByID(id int64) error {
function UpdateSetting (line 53) | func UpdateSetting(setting *Setting) error {
function GetSettingByID (line 59) | func GetSettingByID(id int64) (*Setting, error) {
function GetSettingsByEid (line 68) | func GetSettingsByEid(eid int64) ([]Setting, error) {
function GetSettingsBySettingsGroup (line 76) | func GetSettingsBySettingsGroup(eid int64, group_name string) ([]Setting...
function GetSettingByEidAndKey (line 92) | func GetSettingByEidAndKey(eid int64, key string) (*Setting, error) {
function GetDefaultPromptLinks (line 105) | func GetDefaultPromptLinks(eid int64) ([]AILinkInfo, error) {
FILE: api/model/share_record.go
type ShareRecord (line 15) | type ShareRecord struct
method TableName (line 30) | func (ShareRecord) TableName() string {
function NormalizeMessageIDs (line 35) | func NormalizeMessageIDs(ids []int64) (string, []int64) {
function HashNormalizedKey (line 57) | func HashNormalizedKey(key string) string {
function ParseMessageIDsToIDs (line 63) | func ParseMessageIDsToIDs(key string) ([]int64, error) {
function ValidateMessagesBelongToConversation (line 81) | func ValidateMessagesBelongToConversation(eid, conversationID int64, ids...
function CreateShareRecord (line 99) | func CreateShareRecord(eid, conversationID int64, messageIDsNormalized s...
function GetShareRecordByShareID (line 136) | func GetShareRecordByShareID(shareID string) (*ShareRecord, error) {
function ListMessageIDsByConversation (line 146) | func ListMessageIDsByConversation(eid, conversationID int64) ([]int64, e...
function GetMessagesByIDsOrderedAsc (line 166) | func GetMessagesByIDsOrderedAsc(eid int64, ids []int64) ([]*Message, err...
FILE: api/model/subscription.go
constant CurrencyCNY (line 4) | CurrencyCNY = "CNY"
constant CurrencyUSD (line 5) | CurrencyUSD = "USD"
constant TimeUnitYear (line 7) | TimeUnitYear = "year"
constant TimeUnitMonth (line 8) | TimeUnitMonth = "month"
constant TimeUnitWeek (line 9) | TimeUnitWeek = "week"
constant TimeUnitDay (line 10) | TimeUnitDay = "day"
constant TimeUnitQuarter (line 11) | TimeUnitQuarter = "quarter"
constant SubscriptionTypeFee (line 13) | SubscriptionTypeFee = 1
constant SubscriptionTypePoints (line 14) | SubscriptionTypePoints = 2
type SubscriptionSetting (line 20) | type SubscriptionSetting struct
method LoadRelations (line 44) | func (s *SubscriptionSetting) LoadRelations() error {
method TableName (line 78) | func (SubscriptionSetting) TableName() string {
type SubscriptionRelation (line 51) | type SubscriptionRelation struct
method TableName (line 82) | func (SubscriptionRelation) TableName() string {
function CreateSubscriptionSetting (line 87) | func CreateSubscriptionSetting(setting *SubscriptionSetting) error {
function UpdateSubscriptionSetting (line 92) | func UpdateSubscriptionSetting(setting *SubscriptionSetting) error {
function DeleteSubscriptionSetting (line 100) | func DeleteSubscriptionSetting(settingId int64) error {
function GetSubscriptionSettingById (line 106) | func GetSubscriptionSettingById(settingId int64) (*SubscriptionSetting, ...
function GetAllSubscriptionSettings (line 113) | func GetAllSubscriptionSettings(offset, limit int) ([]SubscriptionSettin...
function CreateSubscriptionRelation (line 133) | func CreateSubscriptionRelation(relation *SubscriptionRelation) error {
function UpdateSubscriptionRelation (line 138) | func UpdateSubscriptionRelation(relation *SubscriptionRelation) error {
function DeleteSubscriptionRelation (line 148) | func DeleteSubscriptionRelation(relationId int64) error {
function DeleteSubscriptionRelationsBySettingId (line 154) | func DeleteSubscriptionRelationsBySettingId(settingId int64) error {
function GetSubscriptionRelationsBySettingId (line 160) | func GetSubscriptionRelationsBySettingId(settingId int64) ([]Subscriptio...
type SubscriptionSettingWithAgents (line 167) | type SubscriptionSettingWithAgents struct
function GetSubscriptionSettingsWithAgents (line 173) | func GetSubscriptionSettingsWithAgents(eid int64, offset, limit int) ([]...
function GetDefaultSubscription (line 204) | func GetDefaultSubscription(eid int64) (*SubscriptionSetting, error) {
FILE: api/model/system_log.go
type SystemLog (line 12) | type SystemLog struct
method TableName (line 74) | func (SystemLog) TableName() string {
constant SystemLogModuleSystem (line 26) | SystemLogModuleSystem uint8 = 1
constant SystemLogModuleAgent (line 27) | SystemLogModuleAgent uint8 = 2
constant SystemLogModulePrompt (line 28) | SystemLogModulePrompt uint8 = 3
constant SystemLogModuleAITool (line 29) | SystemLogModuleAITool uint8 = 4
constant SystemLogModuleOrder (line 30) | SystemLogModuleOrder uint8 = 5
constant SystemLogModuleRegistered (line 31) | SystemLogModuleRegistered uint8 = 6
constant SystemLogModuleInternalUser (line 32) | SystemLogModuleInternalUser uint8 = 7
constant SystemLogModuleSubscription (line 33) | SystemLogModuleSubscription uint8 = 8
constant SystemLogModuleAdmin (line 34) | SystemLogModuleAdmin uint8 = 9
constant SystemLogModuleTemplate (line 35) | SystemLogModuleTemplate uint8 = 10
constant SystemLogModuleBanner (line 36) | SystemLogModuleBanner uint8 = 11
constant SystemLogModuleNavigation (line 37) | SystemLogModuleNavigation uint8 = 12
constant SystemLogModuleSiteInfo (line 38) | SystemLogModuleSiteInfo uint8 = 13
constant SystemLogModulePlatform (line 39) | SystemLogModulePlatform uint8 = 14
constant SystemLogModulePayment (line 40) | SystemLogModulePayment uint8 = 15
constant SystemLogModuleDomain (line 41) | SystemLogModuleDomain uint8 = 16
constant SystemLogModuleStatistics (line 42) | SystemLogModuleStatistics uint8 = 17
function GetModuleByGroupType (line 46) | func GetModuleByGroupType(groupType int64) uint8 {
constant SystemLogActionCreate (line 66) | SystemLogActionCreate uint8 = 1
constant SystemLogActionUpdate (line 67) | SystemLogActionUpdate uint8 = 2
constant SystemLogActionDelete (line 68) | SystemLogActionDelete uint8 = 3
constant SystemLogActionToggle (line 69) | SystemLogActionToggle uint8 = 4
constant SystemLogActionLoginOut (line 70) | SystemLogActionLoginOut uint8 = 5
function GetSystemLogsByConditions (line 79) | func GetSystemLogsByConditions(eid, module, action, userID, startTime, e...
function CreateSystemLog (line 112) | func CreateSystemLog(log *SystemLog) {
function LogEntityChange (line 125) | func LogEntityChange(entityType string, action uint8, eid, userId int64,...
function generateChangeContent (line 146) | func generateChangeContent(entityType string, action uint8, oldEntity, n...
function compareEntities (line 167) | func compareEntities(oldEntity, newEntity interface{}, fieldMap map[stri...
type ModuleItem (line 232) | type ModuleItem struct
function GetAllModules (line 259) | func GetAllModules() []ModuleItem {
function GetModuleText (line 268) | func GetModuleText(value uint8) string {
type ActionItem (line 273) | type ActionItem struct
function GetAllActions (line 289) | func GetAllActions() []ActionItem {
function GetActionText (line 298) | func GetActionText(value uint8) string {
FILE: api/model/upload_file.go
type UploadFile (line 13) | type UploadFile struct
method Save (line 34) | func (uploadFile *UploadFile) Save() error {
method GetChannelFileMapping (line 83) | func (uploadFile *UploadFile) GetChannelFileMapping(channelId int, mod...
method GetPreviewFullUrl (line 92) | func (uploadFile *UploadFile) GetPreviewFullUrl() string {
function GetFileKey (line 27) | func GetFileKey(fileName string, Eid int64, UserId int64) string {
function GetPreviewKey (line 55) | func GetPreviewKey(hashStr string, extension string) (string, error) {
function GetUploadFileByEidAndPreviewKey (line 62) | func GetUploadFileByEidAndPreviewKey(Eid int64, PreviewKey string) (uplo...
function GetNoAuthUploadFileByEidAndPreviewKey (line 70) | func GetNoAuthUploadFileByEidAndPreviewKey(PreviewKey string) (uploadFil...
function GetUploadFileByID (line 78) | func GetUploadFileByID(id int64) (uploadFile *UploadFile, err error) {
FILE: api/model/user.go
type User (line 15) | type User struct
method Create (line 57) | func (user *User) Create() error {
method Update (line 112) | func (user *User) Update(updatePassword bool) error {
method Delete (line 139) | func (user *User) Delete() error {
method LoginValidate (line 153) | func (user *User) LoginValidate(eid int64, username string, password s...
method RefreshAccessToken (line 184) | func (user *User) RefreshAccessToken() error {
method UpdateStatusToJoin (line 201) | func (user *User) UpdateStatusToJoin() error {
method VerifyPassword (line 325) | func (user *User) VerifyPassword(password string) error {
method LoadDepartments (line 442) | func (u *User) LoadDepartments(from int) error {
method LoadMemberBindings (line 456) | func (u *User) LoadMemberBindings(from int) error {
method LoadUserInfo (line 469) | func (u *User) LoadUserInfo(from int) {
method GetUserGroupIds (line 475) | func (u *User) GetUserGroupIds() ([]int64, error) {
method LoadGroupIds (line 503) | func (u *User) LoadGroupIds() error {
method InvalidateAccessToken (line 571) | func (user *User) InvalidateAccessToken() error {
constant RoleGuestUser (line 43) | RoleGuestUser = 0
constant RoleCommonUser (line 44) | RoleCommonUser = 1
constant RoleAdminUser (line 45) | RoleAdminUser = 10
constant RoleCreatorUser (line 46) | RoleCreatorUser = 10000
constant RoleRootUser (line 47) | RoleRootUser = 100000
constant UserStatusNotJoined (line 49) | UserStatusNotJoined = 0
constant UserStatusJoined (line 50) | UserStatusJoined = 1
constant UserStatusDisabled (line 51) | UserStatusDisabled = 2
constant UserTypeRegistered (line 53) | UserTypeRegistered = 1
constant UserTypeInternal (line 54) | UserTypeInternal = 2
function GetUserByID (line 144) | func GetUserByID(userID int64) (*User, error) {
function GetUserByUserName (line 175) | func GetUserByUserName(eid int64, username string) (*User, error) {
function ValidateAccessToken (line 210) | func ValidateAccessToken(token string) (user *User) {
function GetUserList (line 221) | func GetUserList(eid int64, keyword string, group_id int64, offset int, ...
function DeleteUser (line 239) | func DeleteUser(eid int64, user_id int64) error {
function UpdateUserPassword (line 285) | func UpdateUserPassword(eid int64, userID int64, newPassword string) err...
function UpdateAllUsersPasswordByRelatedID (line 300) | func UpdateAllUsersPasswordByRelatedID(relatedId int64, newSalt string, ...
function GetUserByEmail (line 313) | func GetUserByEmail(eid int64, email string) (User, error) {
function GetUserByMobile (line 319) | func GetUserByMobile(eid int64, mobile string) (User, error) {
function GetUserByRelatedId (line 337) | func GetUserByRelatedId(eid int64, relatedId int64) (*User, error) {
function GetFirstUserByRelatedId (line 346) | func GetFirstUserByRelatedId(relatedId int64) (*User, error) {
function GetUserListWithRoles (line 356) | func GetUserListWithRoles(eid int64, keyword string, groupId int64, role...
function IsUserExistsByAccount (line 413) | func IsUserExistsByAccount(eid int64, account string) (bool, error) {
function GetLoginUser (line 515) | func GetLoginUser(c *gin.Context) (*User, error) {
function GetUserByOpenId (line 529) | func GetUserByOpenId(openId string, eid int64) (*User, error) {
function GetUserByUnionId (line 537) | func GetUserByUnionId(unionId string, eid int64) (*User, error) {
function GetFirstUserByUnionId (line 545) | func GetFirstUserByUnionId(unionId string) (*User, error) {
function IsOpenIdExists (line 554) | func IsOpenIdExists(openId string) (bool, error) {
function GetUserCountByEIDAndType (line 562) | func GetUserCountByEIDAndType(eid int64, theType int) (int64, error) {
function IsAdmin (line 578) | func IsAdmin(role int64) bool {
FILE: api/model/verification_code.go
type VerificationCode (line 5) | type VerificationCode struct
method TableName (line 21) | func (VerificationCode) TableName() string {
constant VerificationCodeTypePhone (line 16) | VerificationCodeTypePhone = "phone"
constant VerificationCodeTypeEmail (line 17) | VerificationCodeTypeEmail = "email"
FILE: api/model/wecom_corp.go
type WecomCorp (line 10) | type WecomCorp struct
method GetWecomAuthUserInfo (line 106) | func (w *WecomCorp) GetWecomAuthUserInfo() *AuthUserInfo {
method Delete (line 114) | func (w *WecomCorp) Delete() error {
method GetAgents (line 118) | func (w *WecomCorp) GetAgents() []AgentItem {
method GetAgentID (line 126) | func (w *WecomCorp) GetAgentID() int {
method GetAuthCorpInfo (line 134) | func (w *WecomCorp) GetAuthCorpInfo() *AuthCorpInfo {
type AuthCorpInfo (line 41) | type AuthCorpInfo struct
type AuthUserInfo (line 49) | type AuthUserInfo struct
type AgentItem (line 56) | type AgentItem struct
type Privilege (line 65) | type Privilege struct
function GetWecomCorp (line 75) | func GetWecomCorp(suiteID string, corpID string) (*WecomCorp, error) {
function CreateWecomCorp (line 90) | func CreateWecomCorp(corp *WecomCorp) error {
function UpdateWecomCorp (line 98) | func UpdateWecomCorp(corp *WecomCorp) error {
FILE: api/model/wecom_suite.go
type WecomSuite (line 7) | type WecomSuite struct
method Create (line 39) | func (suite *WecomSuite) Create() error {
method Update (line 53) | func (suite *WecomSuite) Update() error {
method Delete (line 61) | func (suite *WecomSuite) Delete() error {
function GetWecomSuite (line 30) | func GetWecomSuite(suiteID string) (*WecomSuite, error) {
function GetWecomSuitesByCorpID (line 69) | func GetWecomSuitesByCorpID(corpID string) ([]*WecomSuite, error) {
FILE: api/router/api.go
function SetApiRouter (line 10) | func SetApiRouter(router *gin.Engine) {
FILE: api/router/main.go
function SetRouter (line 25) | func SetRouter(router *gin.Engine, buildFS embed.FS) {
function setStaticImagesRouter (line 38) | func setStaticImagesRouter(router *gin.Engine, buildFS embed.FS) {
function setStaticLibsRouter (line 43) | func setStaticLibsRouter(router *gin.Engine, buildFS embed.FS) {
FILE: api/router/static.go
constant pathAPI (line 14) | pathAPI = "/api/"
constant pathStatic (line 15) | pathStatic = "/static/"
constant pathConsole (line 16) | pathConsole = "/console"
constant pathAssets (line 17) | pathAssets = "/assets/"
constant pathImages (line 18) | pathImages = "/images/"
constant contentTypeHTML (line 21) | contentTypeHTML = "text/html; charset=utf-8"
function serveHTMLFile (line 24) | func serveHTMLFile(c *gin.Context, fsys fs.FS, filename string, logMsg s...
function serveStaticFile (line 40) | func serveStaticFile(c *gin.Context, fsys fs.FS, filepath string, logMsg...
function tryServeFile (line 70) | func tryServeFile(c *gin.Context, fsys fs.FS, filePath string, logMsg st...
function SetStaticRouter (line 88) | func SetStaticRouter(router *gin.Engine, buildFS embed.FS) error {
FILE: api/router/web.go
function SetWebRouter (line 12) | func SetWebRouter(router *gin.Engine, buildFS embed.FS) {
FILE: api/service/adaptor.go
function GetAdaptor (line 40) | func GetAdaptor(apiType int) adaptor.Adaptor {
function SetCustomConfig (line 107) | func SetCustomConfig(a *adaptor.Adaptor, customConfig *custom.CustomConf...
function GetCustomConfig (line 145) | func GetCustomConfig(a *adaptor.Adaptor) *custom.CustomConfig {
FILE: api/service/ai53_provider.go
type AI53Service (line 8) | type AI53Service struct
method GetApiSdk (line 12) | func (a *AI53Service) GetApiSdk() *ai53.AI53Api {
method GetAllBots (line 20) | func (a *AI53Service) GetAllBots() ([]ai53.AppResponse, error) {
method GetAllWorkflows (line 43) | func (a *AI53Service) GetAllWorkflows() ([]ai53.AppResponse, error) {
method GetAppParameters (line 66) | func (a *AI53Service) GetAppParameters(botId string) (interface{}, err...
FILE: api/service/appbuilder_provider.go
type AppBuilderService (line 10) | type AppBuilderService struct
method GetApiSdk (line 14) | func (a *AppBuilderService) GetApiSdk() *appbuilder.AppBuilderApi {
method GetAllDescribeApps (line 25) | func (a *AppBuilderService) GetAllDescribeApps() ([]appbuilder.AppInfo...
FILE: api/service/channel_service.go
function GetChannelWithTokenRefresh (line 14) | func GetChannelWithTokenRefresh(ctx context.Context, eid int64, channelT...
FILE: api/service/coze_provider.go
type CozeService (line 22) | type CozeService struct
method GetCozeApiSdk (line 26) | func (ser *CozeService) GetCozeApiSdk() (*coze.CozeApi, error) {
method HandlerAccessTokenByCode (line 48) | func (ser *CozeService) HandlerAccessTokenByCode(coze string, callback...
method HandlerAccessTokenByRefreshToken (line 85) | func (ser *CozeService) HandlerAccessTokenByRefreshToken() error {
method CheckAndRefreshToken (line 128) | func (ser *CozeService) CheckAndRefreshToken() (ok bool, err error) {
method GetAllWorkspace (line 145) | func (ser *CozeService) GetAllWorkspace() ([]*coze.Workspace, error) {
method GetAllBot (line 194) | func (ser *CozeService) GetAllBot(workspaceId string) ([]*coze.Bot, er...
method CacheBotIconWithUploadFile (line 260) | func (ser *CozeService) CacheBotIconWithUploadFile(botID string, iconU...
method findUploadFileByHash (line 335) | func (ser *CozeService) findUploadFileByHash(hash string) *db_model.Up...
method downloadIcon (line 348) | func (ser *CozeService) downloadIcon(iconURL string) ([]byte, error) {
method UpdateCozeChannel (line 401) | func (ser *CozeService) UpdateCozeChannel(botIds []string, provider *m...
FILE: api/service/enterprise_config_service.go
type ConfigContent (line 14) | type ConfigContent struct
type SmtpConfig (line 20) | type SmtpConfig struct
method UnmarshalJSON (line 30) | func (s *SmtpConfig) UnmarshalJSON(data []byte) error {
function getStringValue (line 82) | func getStringValue(value interface{}) string {
function getBoolValue (line 100) | func getBoolValue(value interface{}) bool {
function GetEnterpriseConfigs (line 119) | func GetEnterpriseConfigs(eid int64) ([]model.EnterpriseConfig, error) {
function GetEnterpriseConfigByType (line 142) | func GetEnterpriseConfigByType(eid int64, configType string) (*model.Ent...
function SaveEnterpriseConfig (line 163) | func SaveEnterpriseConfig(eid int64, configType string, content string, ...
function IsEnterpriseConfigEnabled (line 193) | func IsEnterpriseConfigEnabled(eid int64, configType string) (bool, erro...
function ToggleEnterpriseConfig (line 207) | func ToggleEnterpriseConfig(eid int64, configType string) (bool, error) {
function GetSmtpConfig (line 228) | func GetSmtpConfig(eid int64) (smtp.Auth, string, string, int, bool, err...
function GetSmtpConfigFromEnv (line 263) | func GetSmtpConfigFromEnv() (smtp.Auth, string, string, int, bool, error) {
FILE: api/service/hub_adaptor/53AI/adaptor.go
type Adaptor (line 25) | type Adaptor struct
method Init (line 30) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 40) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 45) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 53) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method DoRequest (line 147) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method ConvertImageRequest (line 151) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoResponse (line 158) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 232) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 236) | func (a *Adaptor) GetChannelName() string {
function GetBaseURL (line 34) | func GetBaseURL(baseUrl string) string {
function ConvertRequest (line 61) | func ConvertRequest(textRequest model.GeneralOpenAIRequest, meta *meta.M...
function Handler (line 177) | func Handler(c *gin.Context, resp *http.Response, promptTokens int, mode...
function ResponseAi53OpenAI (line 210) | func ResponseAi53OpenAI(ai53Response *BlockResponse) *openai.TextResponse {
function AI53UploadFile (line 240) | func AI53UploadFile(meta *meta.Meta, uploadFile *db_model.UploadFile, fi...
function Get53AIFileType (line 367) | func Get53AIFileType(mimeType string, extension string) string {
FILE: api/service/hub_adaptor/53AI/main.go
function StreamHandler (line 18) | func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWit...
function StreamResponseai53OpenAI (line 75) | func StreamResponseai53OpenAI(ai53Response *StreamResponse) (*openai.Cha...
function BlockingResponseai53OpenAI (line 115) | func BlockingResponseai53OpenAI(ai53Response *BlockResponse) (*openai.Ch...
function stopReasonAi53OpenAI (line 129) | func stopReasonAi53OpenAI(reason *string) string {
constant TransferMethodRemoteUrl (line 146) | TransferMethodRemoteUrl = "remote_url"
constant TransferMethodLocalFile (line 147) | TransferMethodLocalFile = "local_file"
type File (line 150) | type File struct
constant ResponseModeStream (line 158) | ResponseModeStream = "streaming"
constant ResponseModeBlock (line 159) | ResponseModeBlock = "blocking"
type Request (line 162) | type Request struct
FILE: api/service/hub_adaptor/53AI/model.go
type StreamResponse (line 3) | type StreamResponse struct
type Response (line 15) | type Response struct
type Message (line 23) | type Message struct
type BlockResponse (line 30) | type BlockResponse struct
type AppendContent (line 41) | type AppendContent struct
type Metadata (line 46) | type Metadata struct
type Usage (line 50) | type Usage struct
type UploadResponse (line 65) | type UploadResponse struct
FILE: api/service/hub_adaptor/53AI/workflow.go
type readCloser (line 23) | type readCloser struct
method Close (line 27) | func (rc *readCloser) Close() error {
type AI53WorkflowAdaptor (line 32) | type AI53WorkflowAdaptor struct
method Init (line 58) | func (a *AI53WorkflowAdaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 63) | func (a *AI53WorkflowAdaptor) GetRequestURL(meta *meta.Meta) (string, ...
method SetupRequestHeader (line 75) | func (a *AI53WorkflowAdaptor) SetupRequestHeader(c *gin.Context, req *...
method extractBotId (line 87) | func (a *AI53WorkflowAdaptor) extractBotId(modelName string) string {
method ConvertRequest (line 96) | func (a *AI53WorkflowAdaptor) ConvertRequest(c *gin.Context, relayMode...
method processFile (line 165) | func (a *AI53WorkflowAdaptor) processFile(uploadFile *db_model.UploadF...
method processWorkflowParameters (line 200) | func (a *AI53WorkflowAdaptor) processWorkflowParameters(parameters map...
method processParameterValue (line 222) | func (a *AI53WorkflowAdaptor) processParameterValue(value interface{})...
method processFileIDString (line 258) | func (a *AI53WorkflowAdaptor) processFileIDString(value string) (inter...
method getUserID (line 313) | func (a *AI53WorkflowAdaptor) getUserID(request *model.GeneralOpenAIRe...
method DoRequest (line 321) | func (a *AI53WorkflowAdaptor) DoRequest(c *gin.Context, meta *meta.Met...
method DoResponse (line 392) | func (a *AI53WorkflowAdaptor) DoResponse(c *gin.Context, resp *http.Re...
method ConvertWorkflowToAI53Request (line 477) | func (a *AI53WorkflowAdaptor) ConvertWorkflowToAI53Request(parameters ...
method ProcessAI53WorkflowResponse (line 522) | func (a *AI53WorkflowAdaptor) ProcessAI53WorkflowResponse(resp *http.R...
method maskAPIKey (line 650) | func (a *AI53WorkflowAdaptor) maskAPIKey(apiKey string) string {
type AI53WorkflowRequest (line 38) | type AI53WorkflowRequest struct
type AI53WorkflowEvent (line 45) | type AI53WorkflowEvent struct
type AI53WorkflowResponse (line 52) | type AI53WorkflowResponse struct
FILE: api/service/hub_adaptor/appbuilder/adaptor.go
type Adaptor (line 25) | type Adaptor struct
method Init (line 30) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 34) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 42) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 49) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method DoRequest (line 128) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method ConvertImageRequest (line 132) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoResponse (line 139) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 158) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 162) | func (a *Adaptor) GetChannelName() string {
method GetConversationId (line 166) | func (a *Adaptor) GetConversationId() (string, error) {
function ConvertRequest (line 58) | func ConvertRequest(botID string, meta *meta.Meta, textRequest model.Gen...
function AppBuilderUploadFile (line 180) | func AppBuilderUploadFile(meta *meta.Meta, uploadFile *db_model.UploadFi...
FILE: api/service/hub_adaptor/appbuilder/main.go
function StreamHandler (line 20) | func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWit...
function Handler (line 76) | func Handler(c *gin.Context, resp *http.Response, promptTokens int, mode...
function StreamResponseToOpenAI (line 109) | func StreamResponseToOpenAI(appBuilderResponse *Response) (*openai.ChatC...
function stopReasonAppBuilderOpenAI (line 129) | func stopReasonAppBuilderOpenAI(reason *string) string {
function ResponseToOpenAI (line 145) | func ResponseToOpenAI(response *Response) *openai.TextResponse {
FILE: api/service/hub_adaptor/appbuilder/model.go
type Request (line 3) | type Request struct
type ToolChoice (line 16) | type ToolChoice struct
type Function (line 21) | type Function struct
type Tool (line 26) | type Tool struct
type ToolOutput (line 31) | type ToolOutput struct
type Action (line 36) | type Action struct
type InterruptEvent (line 41) | type InterruptEvent struct
type Response (line 47) | type Response struct
type Content (line 58) | type Content struct
type ToolCall (line 72) | type ToolCall struct
type Usage (line 80) | type Usage struct
FILE: api/service/hub_adaptor/bailian/adaptor.go
type Adaptor (line 22) | type Adaptor struct
method Init (line 27) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 30) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 39) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 67) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method IsRerankRequest (line 100) | func (a *Adaptor) IsRerankRequest(c *gin.Context, request *model.Gener...
method DoRequest (line 172) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method ConvertImageRequest (line 176) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoResponse (line 183) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 202) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 206) | func (a *Adaptor) GetChannelName() string {
function ConvertRequest (line 114) | func ConvertRequest(textRequest model.GeneralOpenAIRequest, meta *meta.M...
FILE: api/service/hub_adaptor/bailian/main.go
function StreamHandler (line 20) | func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWit...
function Handler (line 99) | func Handler(c *gin.Context, resp *http.Response, promptTokens int, mode...
function StreamResponseToOpenAI (line 132) | func StreamResponseToOpenAI(bailianResponse *Response) (*openai.ChatComp...
function stopReasonAppBuilderOpenAI (line 152) | func stopReasonAppBuilderOpenAI(reason *string) string {
function ResponseToOpenAI (line 168) | func ResponseToOpenAI(response *Response) *openai.TextResponse {
FILE: api/service/hub_adaptor/bailian/model.go
type Request (line 3) | type Request struct
type Input (line 8) | type Input struct
type Parameters (line 15) | type Parameters struct
type Response (line 19) | type Response struct
type Output (line 25) | type Output struct
type Usage (line 31) | type Usage struct
type Models (line 35) | type Models
type ErrorResponse (line 41) | type ErrorResponse struct
FILE: api/service/hub_adaptor/bailian/rerank.go
type RerankRequest (line 16) | type RerankRequest struct
method ConvertToRerankRequest (line 25) | func (a *Adaptor) ConvertToRerankRequest(request *RerankRequest) (*Baili...
method GetRerankURL (line 54) | func (a *Adaptor) GetRerankURL() string {
method DoRerankRequest (line 63) | func (a *Adaptor) DoRerankRequest(c *gin.Context, request *BailianRerank...
method ProcessRerankResponse (line 90) | func (a *Adaptor) ProcessRerankResponse(resp *http.Response) (*OpenAIRer...
method HandleRerankRequest (line 137) | func (a *Adaptor) HandleRerankRequest(c *gin.Context, request *RerankReq...
function ParseRerankRequest (line 170) | func ParseRerankRequest(c *gin.Context) (*RerankRequest, error) {
method IsRerankModel (line 189) | func (a *Adaptor) IsRerankModel(modelName string) bool {
FILE: api/service/hub_adaptor/bailian/rerank_model.go
type BailianRerankRequest (line 4) | type BailianRerankRequest struct
type BailianRerankInput (line 10) | type BailianRerankInput struct
type BailianRerankParameters (line 15) | type BailianRerankParameters struct
type BailianRerankResponse (line 21) | type BailianRerankResponse struct
type BailianRerankOutput (line 27) | type BailianRerankOutput struct
type BailianRerankResult (line 31) | type BailianRerankResult struct
type BailianRerankDocument (line 37) | type BailianRerankDocument struct
type RerankUsage (line 41) | type RerankUsage struct
type OpenAIRerankResponse (line 46) | type OpenAIRerankResponse struct
type OpenAIRerankResult (line 53) | type OpenAIRerankResult struct
type OpenAIRerankDocument (line 60) | type OpenAIRerankDocument struct
type OpenAIRerankUsage (line 64) | type OpenAIRerankUsage struct
FILE: api/service/hub_adaptor/coze/adaptor.go
type Adaptor (line 17) | type Adaptor struct
method Init (line 22) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 26) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 50) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 56) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method ConvertImageRequest (line 76) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoRequest (line 83) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method DoResponse (line 87) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 107) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 111) | func (a *Adaptor) GetChannelName() string {
FILE: api/service/hub_adaptor/coze/constant/contenttype/define.go
constant Text (line 4) | Text = "text"
FILE: api/service/hub_adaptor/coze/constant/event/define.go
constant Message (line 4) | Message = "message"
constant Done (line 5) | Done = "done"
constant Error (line 6) | Error = "error"
FILE: api/service/hub_adaptor/coze/constant/messagetype/define.go
constant Answer (line 4) | Answer = "answer"
constant FollowUp (line 5) | FollowUp = "follow_up"
FILE: api/service/hub_adaptor/coze/helper.go
function event2StopReason (line 5) | func event2StopReason(e *string) string {
FILE: api/service/hub_adaptor/coze/main.go
function stopReasonCoze2OpenAI (line 30) | func stopReasonCoze2OpenAI(reason *string) string {
function ConvertRequest (line 46) | func ConvertRequest(textRequest model.GeneralOpenAIRequest, meta *meta.M...
function StreamResponseCoze2OpenAI (line 141) | func StreamResponseCoze2OpenAI(cozeResponse *StreamResponseV3) (*openai....
function ResponseCoze2OpenAI (line 159) | func ResponseCoze2OpenAI(cozeResponse *Response) (*openai.TextResponse, ...
function StreamHandler (line 186) | func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWit...
function Handler (line 267) | func Handler(c *gin.Context, resp *http.Response, promptTokens int, mode...
function CozeUploadFile (line 307) | func CozeUploadFile(meta *meta.Meta, uploadFile *db_model.UploadFile, fi...
FILE: api/service/hub_adaptor/coze/model.go
type Message (line 3) | type Message struct
constant TypeQuestion (line 11) | TypeQuestion = "question"
constant TypeAnswer (line 12) | TypeAnswer = "answer"
constant TypeFunctionCall (line 13) | TypeFunctionCall = "function_call"
constant TypeToolResponse (line 14) | TypeToolResponse = "tool_response"
constant ContentTypeText (line 18) | ContentTypeText = "text"
constant ContentTypeObjectString (line 19) | ContentTypeObjectString = "object_string"
type AdditionalMessage (line 22) | type AdditionalMessage struct
type ErrorInformation (line 29) | type ErrorInformation struct
type Request (line 34) | type Request struct
type Response (line 41) | type Response struct
type StreamResponse (line 48) | type StreamResponse struct
type StreamResponseV3 (line 57) | type StreamResponseV3 struct
type WorkflowRequest (line 70) | type WorkflowRequest struct
type WorkflowResponse (line 75) | type WorkflowResponse struct
type WorkflowExecutionData (line 84) | type WorkflowExecutionData struct
type WorkflowError (line 91) | type WorkflowError struct
constant WorkflowStatusSuccess (line 97) | WorkflowStatusSuccess = "success"
constant WorkflowStatusFailed (line 98) | WorkflowStatusFailed = "failed"
constant WorkflowStatusRunning (line 99) | WorkflowStatusRunning = "running"
FILE: api/service/hub_adaptor/coze/workflow.go
type WorkflowAdaptor (line 22) | type WorkflowAdaptor struct
method Init (line 27) | func (a *WorkflowAdaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 31) | func (a *WorkflowAdaptor) GetRequestURL(meta *meta.Meta) (string, erro...
method SetupRequestHeader (line 39) | func (a *WorkflowAdaptor) SetupRequestHeader(c *gin.Context, req *http...
method ConvertRequest (line 45) | func (a *WorkflowAdaptor) ConvertRequest(c *gin.Context, relayMode int...
method ConvertWorkflowRequest (line 101) | func (a *WorkflowAdaptor) ConvertWorkflowRequest(workflowID string, pa...
method processWorkflowParameters (line 119) | func (a *WorkflowAdaptor) processWorkflowParameters(parameters map[str...
method processParameterValue (line 142) | func (a *WorkflowAdaptor) processParameterValue(value interface{}) (in...
method processFileIDString (line 178) | func (a *WorkflowAdaptor) processFileIDString(value string) (interface...
method ConvertImageRequest (line 261) | func (a *WorkflowAdaptor) ConvertImageRequest(request *model.ImageRequ...
method DoRequest (line 265) | func (a *WorkflowAdaptor) DoRequest(c *gin.Context, meta *meta.Meta, r...
method DoResponse (line 269) | func (a *WorkflowAdaptor) DoResponse(c *gin.Context, resp *http.Respon...
method GetModelList (line 334) | func (a *WorkflowAdaptor) GetModelList() []string {
method GetChannelName (line 338) | func (a *WorkflowAdaptor) GetChannelName() string {
method convertToOpenAIResponse (line 355) | func (a *WorkflowAdaptor) convertToOpenAIResponse(workflowResp *Workfl...
method ConvertToWorkflowResponseData (line 440) | func (a *WorkflowAdaptor) ConvertToWorkflowResponseData(responseBody [...
method parseWorkflowOutputData (line 470) | func (a *WorkflowAdaptor) parseWorkflowOutputData(rawData interface{})...
function extractWorkflowIDFromModel (line 343) | func extractWorkflowIDFromModel(modelName string) string {
function extractUnifiedOutput (line 419) | func extractUnifiedOutput(outputData map[string]interface{}) string {
FILE: api/service/hub_adaptor/custom/common.go
function SetupCommonRequestHeader (line 21) | func SetupCommonRequestHeader(c *gin.Context, req *http.Request, meta *m...
function DoRequestHelper (line 29) | func DoRequestHelper(a adaptor.Adaptor, c *gin.Context, meta *meta.Meta,...
function DoRequest (line 89) | func DoRequest(c *gin.Context, req *http.Request) (*http.Response, error) {
function GetBaseURL (line 102) | func GetBaseURL(baseUrl string) (string, error) {
FILE: api/service/hub_adaptor/custom/config.go
type CustomConfig (line 3) | type CustomConfig struct
type WorkflowParam (line 12) | type WorkflowParam struct
FILE: api/service/hub_adaptor/custom/workflow.go
type WorkflowResponseData (line 4) | type WorkflowResponseData struct
type WorkflowAdaptorResponse (line 13) | type WorkflowAdaptorResponse interface
FILE: api/service/hub_adaptor/dify/adaptor.go
type Adaptor (line 25) | type Adaptor struct
method Init (line 30) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 34) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 42) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 48) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method DoRequest (line 142) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method ConvertImageRequest (line 146) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoResponse (line 153) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 227) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 231) | func (a *Adaptor) GetChannelName() string {
function ConvertRequest (line 56) | func ConvertRequest(textRequest model.GeneralOpenAIRequest, meta *meta.M...
function Handler (line 172) | func Handler(c *gin.Context, resp *http.Response, promptTokens int, mode...
function ResponseDify2OpenAI (line 205) | func ResponseDify2OpenAI(difyResponse *BlockResponse) *openai.TextRespon...
function DIFYUploadFile (line 235) | func DIFYUploadFile(meta *meta.Meta, uploadFile *db_model.UploadFile, fi...
FILE: api/service/hub_adaptor/dify/info.go
type DifyInfoAdaptor (line 15) | type DifyInfoAdaptor struct
method GetAppInfo (line 87) | func (a *DifyInfoAdaptor) GetAppInfo(meta *meta.Meta) (*AppInfoRespons...
method GetAppParameters (line 138) | func (a *DifyInfoAdaptor) GetAppParameters(meta *meta.Meta) (*AppParam...
method buildInfoURL (line 189) | func (a *DifyInfoAdaptor) buildInfoURL(baseURL string) (string, error) {
method buildParametersURL (line 199) | func (a *DifyInfoAdaptor) buildParametersURL(baseURL string) (string, ...
type AppInfoResponse (line 18) | type AppInfoResponse struct
type AppParametersResponse (line 27) | type AppParametersResponse struct
type UserInputFormItem (line 34) | type UserInputFormItem struct
type TextInputConfig (line 41) | type TextInputConfig struct
type ParagraphConfig (line 49) | type ParagraphConfig struct
type SelectConfig (line 57) | type SelectConfig struct
type FileUploadConfig (line 66) | type FileUploadConfig struct
type ImageUploadConfig (line 71) | type ImageUploadConfig struct
type SystemParametersConfig (line 79) | type SystemParametersConfig struct
function maskAPIKey (line 209) | func maskAPIKey(apiKey string) string {
FILE: api/service/hub_adaptor/dify/main.go
function StreamHandler (line 18) | func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWit...
function StreamResponseDifyOpenAI (line 75) | func StreamResponseDifyOpenAI(difyResponse *StreamResponse) (*openai.Cha...
function BlockingResponseDifyOpenAI (line 95) | func BlockingResponseDifyOpenAI(difyResponse *BlockResponse) (*openai.Ch...
function stopReasonDifyOpenAI (line 109) | func stopReasonDifyOpenAI(reason *string) string {
type File (line 125) | type File struct
constant ResponseModeStream (line 133) | ResponseModeStream = "streaming"
constant ResponseModeBlock (line 134) | ResponseModeBlock = "blocking"
type Request (line 137) | type Request struct
FILE: api/service/hub_adaptor/dify/model.go
type StreamResponse (line 3) | type StreamResponse struct
type Response (line 13) | type Response struct
type Message (line 21) | type Message struct
type BlockResponse (line 28) | type BlockResponse struct
type Metadata (line 39) | type Metadata struct
type Usage (line 43) | type Usage struct
type DIFYUploadResponse (line 58) | type DIFYUploadResponse struct
FILE: api/service/hub_adaptor/dify/workflow.go
type DifyWorkflowAdaptor (line 23) | type DifyWorkflowAdaptor struct
method Init (line 57) | func (a *DifyWorkflowAdaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 61) | func (a *DifyWorkflowAdaptor) GetRequestURL(meta *meta.Meta) (string, ...
method SetupRequestHeader (line 73) | func (a *DifyWorkflowAdaptor) SetupRequestHeader(c *gin.Context, req *...
method ConvertWorkflowRequest (line 80) | func (a *DifyWorkflowAdaptor) ConvertWorkflowRequest(workflowID string...
method processWorkflowParameters (line 102) | func (a *DifyWorkflowAdaptor) processWorkflowParameters(parameters map...
method processParameterValue (line 124) | func (a *DifyWorkflowAdaptor) processParameterValue(value interface{})...
method processFileIDString (line 160) | func (a *DifyWorkflowAdaptor) processFileIDString(value string) (inter...
method getDifyFileType (line 240) | func (a *DifyWorkflowAdaptor) getDifyFileType(mimeType, extension stri...
method getUserID (line 286) | func (a *DifyWorkflowAdaptor) getUserID() string {
method DoRequest (line 294) | func (a *DifyWorkflowAdaptor) DoRequest(c *gin.Context, meta *meta.Met...
method ProcessStreamingResponse (line 350) | func (a *DifyWorkflowAdaptor) ProcessStreamingResponse(resp *http.Resp...
method ConvertImageRequest (line 479) | func (a *DifyWorkflowAdaptor) ConvertImageRequest(request *model.Image...
type DifyWorkflowRequest (line 29) | type DifyWorkflowRequest struct
type DifyFileInput (line 36) | type DifyFileInput struct
type DifyWorkflowEvent (line 43) | type DifyWorkflowEvent struct
type DifyWorkflowResponse (line 51) | type DifyWorkflowResponse struct
function DifyUploadFile (line 474) | func DifyUploadFile(meta *meta.Meta, uploadFile *db_model.UploadFile, fi...
FILE: api/service/hub_adaptor/fastgpt/workflow.go
type FastGPTWorkflowAdaptor (line 21) | type FastGPTWorkflowAdaptor struct
method Init (line 50) | func (a *FastGPTWorkflowAdaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 56) | func (a *FastGPTWorkflowAdaptor) GetRequestURL(meta *meta.Meta) (strin...
method ConvertWorkflowToWorkflowRequest (line 87) | func (a *FastGPTWorkflowAdaptor) ConvertWorkflowToWorkflowRequest(para...
method processFileParameters (line 105) | func (a *FastGPTWorkflowAdaptor) processFileParameters(parameters map[...
method processFileParameter (line 130) | func (a *FastGPTWorkflowAdaptor) processFileParameter(fileParam string...
method DoRequest (line 196) | func (a *FastGPTWorkflowAdaptor) DoRequest(c *gin.Context, meta *meta....
method ProcessWorkflowResponse (line 251) | func (a *FastGPTWorkflowAdaptor) ProcessWorkflowResponse(resp *http.Re...
method extractWorkflowOutput (line 286) | func (a *FastGPTWorkflowAdaptor) extractWorkflowOutput(responseData []...
method ExtractWorkflowOutputForTest (line 314) | func (a *FastGPTWorkflowAdaptor) ExtractWorkflowOutputForTest(response...
type FastGPTWorkflowRequest (line 28) | type FastGPTWorkflowRequest struct
type FastGPTWorkflowResponse (line 35) | type FastGPTWorkflowResponse struct
type ModuleResponse (line 40) | type ModuleResponse struct
function standardizeBaseURL (line 62) | func standardizeBaseURL(baseURL string) string {
function isImageFile (line 185) | func isImageFile(extension string) bool {
function maskAPIKey (line 319) | func maskAPIKey(apiKey string) string {
FILE: api/service/hub_adaptor/n8n/adaptor.go
type Adaptor (line 14) | type Adaptor struct
method Init (line 19) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 23) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 32) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 41) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method ConvertImageRequest (line 46) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoRequest (line 50) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method DoResponse (line 54) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 65) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 69) | func (a *Adaptor) GetChannelName() string {
FILE: api/service/hub_adaptor/n8n/main.go
function ProcessN8nWorkflowResponse (line 21) | func ProcessN8nWorkflowResponse(c *gin.Context, resp *http.Response, met...
function StreamHandler (line 35) | func StreamHandler(c *gin.Context, resp *http.Response) (*model.ErrorWit...
function Handler (line 75) | func Handler(c *gin.Context, resp *http.Response, promptTokens int, mode...
function ResponseN8nToOpenAI (line 109) | func ResponseN8nToOpenAI(workflowResponse *custom.WorkflowResponseData, ...
function ValidateN8nWorkflowID (line 155) | func ValidateN8nWorkflowID(workflowID string) bool {
FILE: api/service/hub_adaptor/n8n/model.go
type N8nWorkflowRequest (line 4) | type N8nWorkflowRequest
type N8nWorkflowResponse (line 7) | type N8nWorkflowResponse
type N8nWorkflowItem (line 10) | type N8nWorkflowItem struct
type N8nErrorResponse (line 18) | type N8nErrorResponse struct
FILE: api/service/hub_adaptor/n8n/workflow.go
type N8nWorkflowAdaptor (line 21) | type N8nWorkflowAdaptor struct
method Init (line 26) | func (a *N8nWorkflowAdaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 30) | func (a *N8nWorkflowAdaptor) GetRequestURL(meta *meta.Meta) (string, e...
method SetupRequestHeader (line 69) | func (a *N8nWorkflowAdaptor) SetupRequestHeader(c *gin.Context, req *h...
method ConvertWorkflowRequest (line 81) | func (a *N8nWorkflowAdaptor) ConvertWorkflowRequest(workflowID string,...
method processWorkflowParameters (line 99) | func (a *N8nWorkflowAdaptor) processWorkflowParameters(parameters map[...
method processParameterValue (line 121) | func (a *N8nWorkflowAdaptor) processParameterValue(value interface{}) ...
method processFileIDString (line 157) | func (a *N8nWorkflowAdaptor) processFileIDString(value string) (interf...
method DoRequest (line 213) | func (a *N8nWorkflowAdaptor) DoRequest(c *gin.Context, meta *meta.Meta...
method ProcessResponse (line 272) | func (a *N8nWorkflowAdaptor) ProcessResponse(resp *http.Response) (*cu...
method convertN8nResponseToOutputData (line 311) | func (a *N8nWorkflowAdaptor) convertN8nResponseToOutputData(n8nRespons...
function extractWorkflowID (line 347) | func extractWorkflowID(modelName string) string {
function maskAPIKey (line 358) | func maskAPIKey(apiKey string) string {
FILE: api/service/hub_adaptor/openai/adaptor.go
type Adaptor (line 28) | type Adaptor struct
method Init (line 33) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 37) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 75) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 89) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method ConvertImageRequest (line 105) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoRequest (line 112) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method DoResponse (line 116) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 138) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 143) | func (a *Adaptor) GetChannelName() string {
method HandlerUploadFileMessages (line 148) | func (a *Adaptor) HandlerUploadFileMessages(request *model.GeneralOpen...
function GetFileFastGptTypeString (line 237) | func GetFileFastGptTypeString(extension string) string {
FILE: api/service/hub_adaptor/openai/compatible.go
function GetCompatibleChannelMeta (line 39) | func GetCompatibleChannelMeta(channelType int) (string, []string) {
FILE: api/service/hub_adaptor/openai/helper.go
function ResponseText2Usage (line 11) | func ResponseText2Usage(responseText string, modelName string, promptTok...
function GetFullRequestURL (line 19) | func GetFullRequestURL(baseURL string, requestURL string, channelType in...
FILE: api/service/hub_adaptor/openai/image.go
function ImageHandler (line 12) | func ImageHandler(c *gin.Context, resp *http.Response) (*model.ErrorWith...
FILE: api/service/hub_adaptor/openai/main.go
constant dataPrefix (line 22) | dataPrefix = "data: "
constant done (line 23) | done = "[DONE]"
constant dataPrefixLength (line 24) | dataPrefixLength = len(dataPrefix)
function StreamHandler (line 27) | func StreamHandler(c *gin.Context, resp *http.Response, relayMode int) (...
function Handler (line 109) | func Handler(c *gin.Context, resp *http.Response, promptTokens int, mode...
FILE: api/service/hub_adaptor/openai/model.go
type TextContent (line 5) | type TextContent struct
type ImageContent (line 10) | type ImageContent struct
type ChatRequest (line 15) | type ChatRequest struct
type TextRequest (line 21) | type TextRequest struct
type ImageRequest (line 30) | type ImageRequest struct
type WhisperJSONResponse (line 41) | type WhisperJSONResponse struct
type WhisperVerboseJSONResponse (line 45) | type WhisperVerboseJSONResponse struct
type Segment (line 53) | type Segment struct
type TextToSpeechRequest (line 66) | type TextToSpeechRequest struct
type UsageOrResponseText (line 74) | type UsageOrResponseText struct
type SlimTextResponse (line 79) | type SlimTextResponse struct
type TextResponseChoice (line 85) | type TextResponseChoice struct
type TextResponse (line 91) | type TextResponse struct
type EmbeddingResponseItem (line 100) | type EmbeddingResponseItem struct
type EmbeddingResponse (line 106) | type EmbeddingResponse struct
type ImageData (line 113) | type ImageData struct
type ImageResponse (line 119) | type ImageResponse struct
type ChatCompletionsStreamResponseChoice (line 125) | type ChatCompletionsStreamResponseChoice struct
type ChatCompletionsStreamResponse (line 131) | type ChatCompletionsStreamResponse struct
type CompletionsStreamResponse (line 140) | type CompletionsStreamResponse struct
type FastGptFileContent (line 147) | type FastGptFileContent struct
FILE: api/service/hub_adaptor/openai/token.go
function InitTokenEncoders (line 22) | func InitTokenEncoders() {
function getTokenEncoder (line 52) | func getTokenEncoder(model string) *tiktoken.Tiktoken {
function getTokenNum (line 69) | func getTokenNum(tokenEncoder *tiktoken.Tiktoken, text string) int {
function CountTokenMessages (line 76) | func CountTokenMessages(messages []model.Message, model string) int {
constant lowDetailCost (line 137) | lowDetailCost = 85
constant highDetailCostPerTile (line 138) | highDetailCostPerTile = 170
constant additionalCost (line 139) | additionalCost = 85
constant gpt4oMiniLowDetailCost (line 141) | gpt4oMiniLowDetailCost = 2833
constant gpt4oMiniHighDetailCost (line 142) | gpt4oMiniHighDetailCost = 5667
constant gpt4oMiniAdditionalCost (line 143) | gpt4oMiniAdditionalCost = 2833
function countImageTokens (line 148) | func countImageTokens(url string, detail string, model string) (_ int, e...
function CountTokenInput (line 214) | func CountTokenInput(input any, model string) int {
function CountTokenText (line 228) | func CountTokenText(text string, model string) int {
function CountToken (line 233) | func CountToken(text string) int {
FILE: api/service/hub_adaptor/openai/util.go
function ErrorWrapper (line 11) | func ErrorWrapper(err error, code string, statusCode int) *model.ErrorWi...
FILE: api/service/hub_adaptor/tencent/adaptor.go
type Adaptor (line 14) | type Adaptor struct
method Init (line 19) | func (a *Adaptor) Init(meta *meta.Meta) {
method GetRequestURL (line 23) | func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
method SetupRequestHeader (line 32) | func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request...
method ConvertRequest (line 39) | func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, reques...
method ConvertImageRequest (line 51) | func (a *Adaptor) ConvertImageRequest(request *model.ImageRequest) (an...
method DoRequest (line 56) | func (a *Adaptor) DoRequest(c *gin.Context, meta *meta.Meta, requestBo...
method DoResponse (line 60) | func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, meta...
method GetModelList (line 83) | func (a *Adaptor) GetModelList() []string {
method GetChannelName (line 87) | func (a *Adaptor) GetChannelName() string {
FILE: api/service/hub_adaptor/tencent/constants.go
constant TencentBaseURL (line 16) | TencentBaseURL = "https://wss.lke.cloud.tencent.com"
FILE: api/service/hub_adaptor/tencent/helper.go
function ConvertRequest (line 16) | func ConvertRequest(request model.GeneralOpenAIRequest, conversationID i...
function generateUUID (line 59) | func generateUUID() string {
function ConvertResponse (line 71) | func ConvertResponse(tencentResp *TencentResponse, modelName string) *op...
function ConvertStreamResponse (line 98) | func ConvertStreamResponse(data string, modelName string, previousConten...
function IsStreamEnd (line 199) | func IsStreamEnd(event string) bool {
FILE: api/service/hub_adaptor/tencent/main.go
function Handler (line 19) | func Handler(c *gin.Context, resp *http.Response) (*model.ErrorWithStatu...
function StreamHandler (line 40) | func StreamHandler(c *gin.Context, meta *meta.Meta, resp *http.Response)...
FILE: api/service/hub_adaptor/tencent/model.go
type TencentRequest (line 4) | type TencentRequest struct
type VisitorLabel (line 23) | type VisitorLabel struct
type FileInfo (line 28) | type FileInfo struct
type TencentResponse (line 37) | type TencentResponse struct
type TencentResponsePayload (line 43) | type TencentResponsePayload struct
type TencentKnowledge (line 65) | type TencentKnowledge struct
type TencentQuoteInfo (line 72) | type TencentQuoteInfo struct
type TencentStreamResponse (line 78) | type TencentStreamResponse struct
type TencentErrorResponse (line 84) | type TencentErrorResponse struct
type TencentErrorInfo (line 89) | type TencentErrorInfo struct
FILE: api/service/hub_adaptor/tencent/sdk/client.go
constant APIVersion (line 26) | APIVersion = "2023-11-30"
type Client (line 28) | type Client struct
method CheckAttributeLabelExist (line 68) | func (c *Client) CheckAttributeLabelExist(request *CheckAttributeLabel...
method CheckAttributeLabelExistWithContext (line 74) | func (c *Client) CheckAttributeLabelExistWithContext(ctx context.Conte...
method CheckAttributeLabelRefer (line 111) | func (c *Client) CheckAttributeLabelRefer(request *CheckAttributeLabel...
method CheckAttributeLabelReferWithContext (line 117) | func (c *Client) CheckAttributeLabelReferWithContext(ctx context.Conte...
method CreateApp (line 154) | func (c *Client) CreateApp(request *CreateAppRequest) (response *Creat...
method CreateAppWithContext (line 160) | func (c *Client) CreateAppWithContext(ctx context.Context, request *Cr...
method CreateAttributeLabel (line 201) | func (c *Client) CreateAttributeLabel(request *CreateAttributeLabelReq...
method CreateAttributeLabelWithContext (line 211) | func (c *Client) CreateAttributeLabelWithContext(ctx context.Context, ...
method CreateDocCate (line 252) | func (c *Client) CreateDocCate(request *CreateDocCateRequest) (respons...
method CreateDocCateWithContext (line 262) | func (c *Client) CreateDocCateWithContext(ctx context.Context, request...
method CreateQA (line 303) | func (c *Client) CreateQA(request *CreateQARequest) (response *CreateQ...
method CreateQAWithContext (line 313) | func (c *Client) CreateQAWithContext(ctx context.Context, request *Cre...
method CreateQACate (line 354) | func (c *Client) CreateQACate(request *CreateQACateRequest) (response ...
method CreateQACateWithContext (line 364) | func (c *Client) CreateQACateWithContext(ctx context.Context, request ...
method CreateRejectedQuestion (line 405) | func (c *Client) CreateRejectedQuestion(request *CreateRejectedQuestio...
method CreateRejectedQuestionWithContext (line 415) | func (c *Client) CreateRejectedQuestionWithContext(ctx context.Context...
method CreateRelease (line 456) | func (c *Client) CreateRelease(request *CreateReleaseRequest) (respons...
method CreateReleaseWithContext (line 466) | func (c *Client) CreateReleaseWithContext(ctx context.Context, request...
method CreateSharedKnowledge (line 507) | func (c *Client) CreateSharedKnowledge(request *CreateSharedKnowledgeR...
method CreateSharedKnowledgeWithContext (line 517) | func (c *Client) CreateSharedKnowledgeWithContext(ctx context.Context,...
method CreateVar (line 559) | func (c *Client) CreateVar(request *CreateVarRequest) (response *Creat...
method CreateVarWithContext (line 570) | func (c *Client) CreateVarWithContext(ctx context.Context, request *Cr...
method CreateWorkflowRun (line 614) | func (c *Client) CreateWorkflowRun(request *CreateWorkflowRunRequest) ...
method CreateWorkflowRunWithContext (line 627) | func (c *Client) CreateWorkflowRunWithContext(ctx context.Context, req...
method DeleteAgent (line 668) | func (c *Client) DeleteAgent(request *DeleteAgentRequest) (response *D...
method DeleteAgentWithContext (line 678) | func (c *Client) DeleteAgentWithContext(ctx context.Context, request *...
method DeleteApp (line 719) | func (c *Client) DeleteApp(request *DeleteAppRequest) (response *Delet...
method DeleteAppWithContext (line 729) | func (c *Client) DeleteAppWithContext(ctx context.Context, request *De...
method DeleteAttributeLabel (line 770) | func (c *Client) DeleteAttributeLabel(request *DeleteAttributeLabelReq...
method DeleteAttributeLabelWithContext (line 780) | func (c *Client) DeleteAttributeLabelWithContext(ctx context.Context, ...
method DeleteDoc (line 821) | func (c *Client) DeleteDoc(request *DeleteDocRequest) (response *Delet...
method DeleteDocWithContext (line 831) | func (c *Client) DeleteDocWithContext(ctx context.Context, request *De...
method DeleteDocCate (line 872) | func (c *Client) DeleteDocCate(request *DeleteDocCateRequest) (respons...
method DeleteDocCateWithContext (line 882) | func (c *Client) DeleteDocCateWithContext(ctx context.Context, request...
method DeleteQA (line 923) | func (c *Client) DeleteQA(request *DeleteQARequest) (response *DeleteQ...
method DeleteQAWithContext (line 933) | func (c *Client) DeleteQAWithContext(ctx context.Context, request *Del...
method DeleteQACate (line 974) | func (c *Client) DeleteQACate(request *DeleteQACateRequest) (response ...
method DeleteQACateWithContext (line 984) | func (c *Client) DeleteQACateWithContext(ctx context.Context, request ...
method DeleteRejectedQuestion (line 1025) | func (c *Client) DeleteRejectedQuestion(request *DeleteRejectedQuestio...
method DeleteRejectedQuestionWithContext (line 1035) | func (c *Client) DeleteRejectedQuestionWithContext(ctx context.Context...
method DeleteSharedKnowledge (line 1076) | func (c *Client) DeleteSharedKnowledge(request *DeleteSharedKnowledgeR...
method DeleteSharedKnowledgeWithContext (line 1086) | func (c *Client) DeleteSharedKnowledgeWithContext(ctx context.Context,...
method DeleteVar (line 1127) | func (c *Client) DeleteVar(request *DeleteVarRequest) (response *Delet...
method DeleteVarWithContext (line 1137) | func (c *Client) DeleteVarWithContext(ctx context.Context, request *De...
method DescribeApp (line 1178) | func (c *Client) DescribeApp(request *DescribeAppRequest) (response *D...
method DescribeAppWithContext (line 1188) | func (c *Client) DescribeAppWithContext(ctx context.Context, request *...
method DescribeAppAgentList (line 1229) | func (c *Client) DescribeAppAgentList(request *DescribeAppAgentListReq...
method DescribeAppAgentListWithContext (line 1239) | func (c *Client) DescribeAppAgentListWithContext(ctx context.Context, ...
method DescribeAttributeLabel (line 1280) | func (c *Client) DescribeAttributeLabel(request *DescribeAttributeLabe...
method DescribeAttributeLabelWithContext (line 1290) | func (c *Client) DescribeAttributeLabelWithContext(ctx context.Context...
method DescribeCallStatsGraph (line 1331) | func (c *Client) DescribeCallStatsGraph(request *DescribeCallStatsGrap...
method DescribeCallStatsGraphWithContext (line 1341) | func (c *Client) DescribeCallStatsGraphWithContext(ctx context.Context...
method DescribeConcurrencyUsage (line 1382) | func (c *Client) DescribeConcurrencyUsage(request *DescribeConcurrency...
method DescribeConcurrencyUsageWithContext (line 1392) | func (c *Client) DescribeConcurrencyUsageWithContext(ctx context.Conte...
method DescribeConcurrencyUsageGraph (line 1433) | func (c *Client) DescribeConcurrencyUsageGraph(request *DescribeConcur...
method DescribeConcurrencyUsageGraphWithContext (line 1443) | func (c *Client) DescribeConcurrencyUsageGraphWithContext(ctx context....
method DescribeDoc (line 1484) | func (c *Client) DescribeDoc(request *DescribeDocRequest) (response *D...
method DescribeDocWithContext (line 1494) | func (c *Client) DescribeDocWithContext(ctx context.Context, request *...
method DescribeKnowledgeUsage (line 1535) | func (c *Client) DescribeKnowledgeUsage(request *DescribeKnowledgeUsag...
method DescribeKnowledgeUsageWithContext (line 1545) | func (c *Client) DescribeKnowledgeUsageWithContext(ctx context.Context...
method DescribeKnowledgeUsagePieGraph (line 1586) | func (c *Client) DescribeKnowledgeUsagePieGraph(request *DescribeKnowl...
method DescribeKnowledgeUsagePieGraphWithContext (line 1596) | func (c *Client) DescribeKnowledgeUsagePieGraphWithContext(ctx context...
method DescribeNodeRun (line 1638) | func (c *Client) DescribeNodeRun(request *DescribeNodeRunRequest) (res...
method DescribeNodeRunWithContext (line 1649) | func (c *Client) DescribeNodeRunWithContext(ctx context.Context, reque...
method DescribeQA (line 1691) | func (c *Client) DescribeQA(request *DescribeQARequest) (response *Des...
method DescribeQAWithContext (line 1702) | func (c *Client) DescribeQAWithContext(ctx context.Context, request *D...
method DescribeRefer (line 1744) | func (c *Client) DescribeRefer(request *DescribeReferRequest) (respons...
method DescribeReferWithContext (line 1755) | func (c *Client) DescribeReferWithContext(ctx context.Context, request...
method DescribeRelease (line 1797) | func (c *Client) DescribeRelease(request *DescribeReleaseRequest) (res...
method DescribeReleaseWithContext (line 1808) | func (c *Client) DescribeReleaseWithContext(ctx context.Context, reque...
method DescribeReleaseInfo (line 1850) | func (c *Client) DescribeReleaseInfo(request *DescribeReleaseInfoReque...
method DescribeReleaseInfoWithContext (line 1861) | func (c *Client) DescribeReleaseInfoWithContext(ctx context.Context, r...
method DescribeRobotBizIDByAppKey (line 1902) | func (c *Client) DescribeRobotBizIDByAppKey(request *DescribeRobotBizI...
method DescribeRobotBizIDByAppKeyWithContext (line 1912) | func (c *Client) DescribeRobotBizIDByAppKeyWithContext(ctx context.Con...
method DescribeSearchStatsGraph (line 1953) | func (c *Client) DescribeSearchStatsGraph(request *DescribeSearchStats...
method DescribeSearchStatsGraphWithContext (line 1963) | func (c *Client) DescribeSearchStatsGraphWithContext(ctx context.Conte...
method DescribeSegments (line 2004) | func (c *Client) DescribeSegments(request *DescribeSegmentsRequest) (r...
method DescribeSegmentsWithContext (line 2014) | func (c *Client) DescribeSegmentsWithContext(ctx context.Context, requ...
method DescribeSharedKnowledge (line 2055) | func (c *Client) DescribeSharedKnowledge(request *DescribeSharedKnowle...
method DescribeSharedKnowledgeWithContext (line 2065) | func (c *Client) DescribeSharedKnowledgeWithContext(ctx context.Contex...
method DescribeStorageCredential (line 2106) | func (c *Client) DescribeStorageCredential(request *DescribeStorageCre...
method DescribeStorageCredentialWithContext (line 2116) | func (c *Client) DescribeStorageCredentialWithContext(ctx context.Cont...
method DescribeTokenUsage (line 2157) | func (c *Client) DescribeTokenUsage(request *DescribeTokenUsageRequest...
method DescribeTokenUsageWithContext (line 2167) | func (c *Client) DescribeTokenUsageWithContext(ctx context.Context, re...
method DescribeTokenUsageGraph (line 2208) | func (c *Client) DescribeTokenUsageGraph(request *DescribeTokenUsageGr...
method DescribeTokenUsageGraphWithContext (line 2218) | func (c *Client) DescribeTokenUsageGraphWithContext(ctx context.Contex...
method DescribeUnsatisfiedReplyContext (line 2260) | func (c *Client) DescribeUnsatisfiedReplyContext(request *DescribeUnsa...
method DescribeUnsatisfiedReplyContextWithContext (line 2271) | func (c *Client) DescribeUnsatisfiedReplyContextWithContext(ctx contex...
method DescribeWorkflowRun (line 2313) | func (c *Client) DescribeWorkflowRun(request *DescribeWorkflowRunReque...
method DescribeWorkflowRunWithContext (line 2324) | func (c *Client) DescribeWorkflowRunWithContext(ctx context.Context, r...
method ExportAttributeLabel (line 2366) | func (c *Client) ExportAttributeLabel(request *ExportAttributeLabelReq...
method ExportAttributeLabelWithContext (line 2377) | func (c *Client) ExportAttributeLabelWithContext(ctx context.Context, ...
method ExportQAList (line 2419) | func (c *Client) ExportQAList(request *ExportQAListRequest) (response ...
method ExportQAListWithContext (line 2430) | func (c *Client) ExportQAListWithContext(ctx context.Context, request ...
method ExportUnsatisfiedReply (line 2472) | func (c *Client) ExportUnsatisfiedReply(request *ExportUnsatisfiedRepl...
method ExportUnsatisfiedReplyWithContext (line 2483) | func (c *Client) ExportUnsatisfiedReplyWithContext(ctx context.Context...
method GenerateQA (line 2524) | func (c *Client) GenerateQA(request *GenerateQARequest) (response *Gen...
method GenerateQAWithContext (line 2534) | func (c *Client) GenerateQAWithContext(ctx context.Context, request *G...
method GetAnswerTypeDataCount (line 2576) | func (c *Client) GetAnswerTypeDataCount(request *GetAnswerTypeDataCoun...
method GetAnswerTypeDataCountWithContext (line 2587) | func (c *Client) GetAnswerTypeDataCountWithContext(ctx context.Context...
method GetAppKnowledgeCount (line 2628) | func (c *Client) GetAppKnowledgeCount(request *GetAppKnowledgeCountReq...
method GetAppKnowledgeCountWithContext (line 2638) | func (c *Client) GetAppKnowledgeCountWithContext(ctx context.Context, ...
method GetAppSecret (line 2679) | func (c *Client) GetAppSecret(request *GetAppSecretRequest) (response ...
method GetAppSecretWithContext (line 2689) | func (c *Client) GetAppSecretWithContext(ctx context.Context, request ...
method GetDocPreview (line 2730) | func (c *Client) GetDocPreview(request *GetDocPreviewRequest) (respons...
method GetDocPreviewWithContext (line 2740) | func (c *Client) GetDocPreviewWithContext(ctx context.Context, request...
method GetLikeDataCount (line 2782) | func (c *Client) GetLikeDataCount(request *GetLikeDataCountRequest) (r...
method GetLikeDataCountWithContext (line 2793) | func (c *Client) GetLikeDataCountWithContext(ctx context.Context, requ...
method GetMsgRecord (line 2837) | func (c *Client) GetMsgRecord(request *GetMsgRecordRequest) (response ...
method GetMsgRecordWithContext (line 2850) | func (c *Client) GetMsgRecordWithContext(ctx context.Context, request ...
method GetTaskStatus (line 2892) | func (c *Client) GetTaskStatus(request *GetTaskStatusRequest) (respons...
method GetTaskStatusWithContext (line 2903) | func (c *Client) GetTaskStatusWithContext(ctx context.Context, request...
method GetVarList (line 2945) | func (c *Client) GetVarList(request *GetVarListRequest) (response *Get...
method GetVarListWithContext (line 2956) | func (c *Client) GetVarListWithContext(ctx context.Context, request *G...
method GetWsToken (line 2997) | func (c *Client) GetWsToken(request *GetWsTokenRequest) (response *Get...
method GetWsTokenWithContext (line 3007) | func (c *Client) GetWsTokenWithContext(ctx context.Context, request *G...
method GroupDoc (line 3048) | func (c *Client) GroupDoc(request *GroupDocRequest) (response *GroupDo...
method GroupDocWithContext (line 3058) | func (c *Client) GroupDocWithContext(ctx context.Context, request *Gro...
method GroupQA (line 3099) | func (c *Client) GroupQA(request *GroupQARequest) (response *GroupQARe...
method GroupQAWithContext (line 3109) | func (c *Client) GroupQAWithContext(ctx context.Context, request *Grou...
method IgnoreUnsatisfiedReply (line 3150) | func (c *Client) IgnoreUnsatisfiedReply(request *IgnoreUnsatisfiedRepl...
method IgnoreUnsatisfiedReplyWithContext (line 3160) | func (c *Client) IgnoreUnsatisfiedReplyWithContext(ctx context.Context...
method IsTransferIntent (line 3201) | func (c *Client) IsTransferIntent(request *IsTransferIntentRequest) (r...
method IsTransferIntentWithContext (line 3211) | func (c *Client) IsTransferIntentWithContext(ctx context.Context, requ...
method ListApp (line 3252) | func (c *Client) ListApp(request *ListAppRequest) (response *ListAppRe...
method ListAppWithContext (line 3262) | func (c *Client) ListAppWithContext(ctx context.Context, request *List...
method ListAppKnowledgeDetail (line 3303) | func (c *Client) ListAppKnowledgeDetail(request *ListAppKnowledgeDetai...
method ListAppKnowledgeDetailWithContext (line 3313) | func (c *Client) ListAppKnowledgeDetailWithContext(ctx context.Context...
method ListAttributeLabel (line 3354) | func (c *Client) ListAttributeLabel(request *ListAttributeLabelRequest...
method ListAttributeLabelWithContext (line 3364) | func (c *Client) ListAttributeLabelWithContext(ctx context.Context, re...
method ListChannel (line 3405) | func (c *Client) ListChannel(request *ListChannelRequest) (response *L...
method ListChannelWithContext (line 3415) | func (c *Client) ListChannelWithContext(ctx context.Context, request *...
method ListDoc (line 3456) | func (c *Client) ListDoc(request *ListDocRequest) (response *ListDocRe...
method ListDocWithContext (line 3466) | func (c *Client) ListDocWithContext(ctx context.Context, request *List...
method ListDocCate (line 3507) | func (c *Client) ListDocCate(request *ListDocCateRequest) (response *L...
method ListDocCateWithContext (line 3517) | func (c *Client) ListDocCateWithContext(ctx context.Context, request *...
method ListModel (line 3558) | func (c *Client) ListModel(request *ListModelRequest) (response *ListM...
method ListModelWithContext (line 3568) | func (c *Client) ListModelWithContext(ctx context.Context, request *Li...
method ListQA (line 3609) | func (c *Client) ListQA(request *ListQARequest) (response *ListQARespo...
method ListQAWithContext (line 3619) | func (c *Client) ListQAWithContext(ctx context.Context, request *ListQ...
method ListQACate (line 3660) | func (c *Client) ListQACate(request *ListQACateRequest) (response *Lis...
method ListQACateWithContext (line 3670) | func (c *Client) ListQACateWithContext(ctx context.Context, request *L...
method ListReferShareKnowledge (line 3711) | func (c *Client) ListReferShareKnowledge(request *ListReferShareKnowle...
method ListReferShareKnowledgeWithContext (line 3721) | func (c *Client) ListReferShareKnowledgeWithContext(ctx context.Contex...
method ListRejectedQuestion (line 3762) | func (c *Client) ListRejectedQuestion(request *ListRejectedQuestionReq...
method ListRejectedQuestionWithContext (line 3772) | func (c *Client) ListRejectedQuestionWithContext(ctx context.Context, ...
method ListRejectedQuestionPreview (line 3813) | func (c *Client) ListRejectedQuestionPreview(request *ListRejectedQues...
method ListRejectedQuestionPreviewWithContext (line 3823) | func (c *Client) ListRejectedQuestionPreviewWithContext(ctx context.Co...
method ListRelease (line 3864) | func (c *Client) ListRelease(request *ListReleaseRequest) (response *L...
method ListReleaseWithContext (line 3874) | func (c *Client) ListReleaseWithContext(ctx context.Context, request *...
method ListReleaseConfigPreview (line 3915) | func (c *Client) ListReleaseConfigPreview(request *ListReleaseConfigPr...
method ListReleaseConfigPreviewWithContext (line 3925) | func (c *Client) ListReleaseConfigPreviewWithContext(ctx context.Conte...
method ListReleaseDocPreview (line 3966) | func (c *Client) ListReleaseDocPreview(request *ListReleaseDocPreviewR...
method ListReleaseDocPreviewWithContext (line 3976) | func (c *Client) ListReleaseDocPreviewWithContext(ctx context.Context,...
method ListReleaseQAPreview (line 4017) | func (c *Client) ListReleaseQAPreview(request *ListReleaseQAPreviewReq...
method ListReleaseQAPreviewWithContext (line 4027) | func (c *Client) ListReleaseQAPreviewWithContext(ctx context.Context, ...
method ListSelectDoc (line 4068) | func (c *Client) ListSelectDoc(request *ListSelectDocRequest) (respons...
method ListSelectDocWithContext (line 4078) | func (c *Client) ListSelectDocWithContext(ctx context.Context, request...
method ListSharedKnowledge (line 4119) | func (c *Client) ListSharedKnowledge(request *ListSharedKnowledgeReque...
method ListSharedKnowledgeWithContext (line 4129) | func (c *Client) ListSharedKnowledgeWithContext(ctx context.Context, r...
method ListUnsatisfiedReply (line 4171) | func (c *Client) ListUnsatisfiedReply(request *ListUnsatisfiedReplyReq...
method ListUnsatisfiedReplyWithContext (line 4182) | func (c *Client) ListUnsatisfiedReplyWithContext(ctx context.Context, ...
method ListUsageCallDetail (line 4224) | func (c *Client) ListUsageCallDetail(request *ListUsageCallDetailReque...
method ListUsageCallDetailWithContext (line 4235) | func (c *Client) ListUsageCallDetailWithContext(ctx context.Context, r...
method ListWorkflowRuns (line 4277) | func (c *Client) ListWorkflowRuns(request *ListWorkflowRunsRequest) (r...
method ListWorkflowRunsWithContext (line 4288) | func (c *Client) ListWorkflowRunsWithContext(ctx context.Context, requ...
method ModifyApp (line 4330) | func (c *Client) ModifyApp(request *ModifyAppRequest) (response *Modif...
method ModifyAppWithContext (line 4341) | func (c *Client) ModifyAppWithContext(ctx context.Context, request *Mo...
method ModifyAttributeLabel (line 4383) | func (c *Client) ModifyAttributeLabel(request *ModifyAttributeLabelReq...
method ModifyAttributeLabelWithContext (line 4394) | func (c *Client) ModifyAttributeLabelWithContext(ctx context.Context, ...
method ModifyDoc (line 4436) | func (c *Client) ModifyDoc(request *ModifyDocRequest) (response *Modif...
method ModifyDocWithContext (line 4447) | func (c *Client) ModifyDocWithContext(ctx context.Context, request *Mo...
method ModifyDocAttrRange (line 4488) | func (c *Client) ModifyDocAttrRange(request *ModifyDocAttrRangeRequest...
method ModifyDocAttrRangeWithContext (line 4498) | func (c *Client) ModifyDocAttrRangeWithContext(ctx context.Context, re...
method ModifyDocCate (line 4539) | func (c *Client) ModifyDocCate(request *ModifyDocCateRequest) (respons...
method ModifyDocCateWithContext (line 4549) | func (c *Client) ModifyDocCateWithContext(ctx context.Context, request...
method ModifyQA (line 4590) | func (c *Client) ModifyQA(request *ModifyQARequest) (response *ModifyQ...
method ModifyQAWithContext (line 4600) | func (c *Client) ModifyQAWithContext(ctx context.Context, request *Mod...
method ModifyQAAttrRange (line 4641) | func (c *Client) ModifyQAAttrRange(request *ModifyQAAttrRangeRequest) ...
method ModifyQAAttrRangeWithContext (line 4651) | func (c *Client) ModifyQAAttrRangeWithContext(ctx context.Context, req...
method ModifyQACate (line 4692) | func (c *Client) ModifyQACate(request *ModifyQACateRequest) (response ...
method ModifyQACateWithContext (line 4702) | func (c *Client) ModifyQACateWithContext(ctx context.Context, request ...
method ModifyRejectedQuestion (line 4743) | func (c *Client) ModifyRejectedQuestion(request *ModifyRejectedQuestio...
method ModifyRejectedQuestionWithContext (line 4753) | func (c *Client) ModifyRejectedQuestionWithContext(ctx context.Context...
method RateMsgRecord (line 4794) | func (c *Client) RateMsgRecord(request *RateMsgRecordRequest) (respons...
method RateMsgRecordWithContext (line 4804) | func (c *Client) RateMsgRecordWithContext(ctx context.Context, request...
method ReferShareKnowledge (line 4845) | func (c *Client) ReferShareKnowledge(request *ReferShareKnowledgeReque...
method ReferShareKnowledgeWithContext (line 4855) | func (c *Client) ReferShareKnowledgeWithContext(ctx context.Context, r...
method RenameDoc (line 4896) | func (c *Client) RenameDoc(request *RenameDocRequest) (response *Renam...
method RenameDocWithContext (line 4906) | func (c *Client) RenameDocWithContext(ctx context.Context, request *Re...
method RetryDocAudit (line 4947) | func (c *Client) RetryDocAudit(request *RetryDocAuditRequest) (respons...
method RetryDocAuditWithContext (line 4957) | func (c *Client) RetryDocAuditWithContext(ctx context.Context, request...
method RetryDocParse (line 4998) | func (c *Client) RetryDocParse(request *RetryDocParseRequest) (respons...
method RetryDocParseWithContext (line 5008) | func (c *Client) RetryDocParseWithContext(ctx context.Context, request...
method RetryRelease (line 5049) | func (c *Client) RetryRelease(request *RetryReleaseRequest) (response ...
method RetryReleaseWithContext (line 5059) | func (c *Client) RetryReleaseWithContext(ctx context.Context, request ...
method SaveDoc (line 5110) | func (c *Client) SaveDoc(request *SaveDocRequest) (response *SaveDocRe...
method SaveDocWithContext (line 5130) | func (c *Client) SaveDocWithContext(ctx context.Context, request *Save...
method StopDocParse (line 5171) | func (c *Client) StopDocParse(request *StopDocParseRequest) (response ...
method StopDocParseWithContext (line 5181) | func (c *Client) StopDocParseWithContext(ctx context.Context, request ...
method StopWorkflowRun (line 5223) | func (c *Client) StopWorkflowRun(request *StopWorkflowRunRequest) (res...
method StopWorkflowRunWithContext (line 5234) | func (c *Client) StopWorkflowRunWithContext(ctx context.Context, reque...
method UpdateSharedKnowledge (line 5276) | func (c *Client) UpdateSharedKnowledge(request *UpdateSharedKnowledgeR...
method UpdateSharedKnowledgeWithContext (line 5287) | func (c *Client) UpdateSharedKnowledgeWithContext(ctx context.Context,...
method UpdateVar (line 5329) | func (c *Client) UpdateVar(request *UpdateVarRequest) (response *Updat...
method UpdateVarWithContext (line 5340) | func (c *Client) UpdateVarWithContext(ctx context.Context, request *Up...
method UploadAttributeLabel (line 5382) | func (c *Client) UploadAttributeLabel(request *UploadAttributeLabelReq...
method UploadAttributeLabelWithContext (line 5393) | func (c *Client) UploadAttributeLabelWithContext(ctx context.Context, ...
method VerifyQA (line 5435) | func (c *Client) VerifyQA(request *VerifyQARequest) (response *VerifyQ...
method VerifyQAWithContext (line 5446) | func (c *Client) VerifyQAWithContext(ctx context.Context, request *Ver...
function NewClientWithSecretId (line 33) | func NewClientWithSecretId(secretId, secretKey, region string) (client *...
function NewClient (line 40) | func NewClient(credential common.CredentialIface, region string, clientP...
function NewCheckAttributeLabelExistRequest (line 48) | func NewCheckAttributeLabelExistRequest() (request *CheckAttributeLabelE...
function NewCheckAttributeLabelExistResponse (line 58) | func NewCheckAttributeLabelExistResponse() (response *CheckAttributeLabe...
function NewCheckAttributeLabelReferRequest (line 91) | func NewCheckAttributeLabelReferRequest() (request *CheckAttributeLabelR...
function NewCheckAttributeLabelReferResponse (line 101) | func NewCheckAttributeLabelReferResponse() (response *CheckAttributeLabe...
function NewCreateAppRequest (line 134) | func NewCreateAppRequest() (request *CreateAppRequest) {
function NewCreateAppResponse (line 144) | func NewCreateAppResponse() (response *CreateAppResponse) {
function NewCreateAttributeLabelRequest (line 177) | func NewCreateAttributeLabelRequest() (request *CreateAttributeLabelRequ...
function NewCreateAttributeLabelResponse (line 187) | func NewCreateAttributeLabelResponse() (response *CreateAttributeLabelRe...
function NewCreateDocCateRequest (line 228) | func NewCreateDocCateRequest() (request *CreateDocCateRequest) {
function NewCreateDocCateResponse (line 238) | func NewCreateDocCateResponse() (response *CreateDocCateResponse) {
function NewCreateQARequest (line 279) | func NewCreateQARequest() (request *CreateQARequest) {
function NewCreateQAResponse (line 289) | func NewCreateQAResponse() (response *CreateQAResponse) {
function NewCreateQACateRequest (line 330) | func NewCreateQACateRequest() (request *CreateQACateRequest) {
function NewCreateQACateResponse (line 340) | func NewCreateQACateResponse() (response *CreateQACateResponse) {
function NewCreateRejectedQuestionRequest (line 381) | func NewCreateRejectedQuestionRequest() (request *CreateRejectedQuestion...
function NewCreateRejectedQuestionResponse (line 391) | func NewCreateRejectedQuestionResponse() (response *CreateRejectedQuesti...
function NewCreateReleaseRequest (line 432) | func NewCreateReleaseRequest() (request *CreateReleaseRequest) {
function NewCreateReleaseResponse (line 442) | func NewCreateReleaseResponse() (response *CreateReleaseResponse) {
function NewCreateSharedKnowledgeRequest (line 483) | func NewCreateSharedKnowledgeRequest() (request *CreateSharedKnowledgeRe...
function NewCreateSharedKnowledgeResponse (line 493) | func NewCreateSharedKnowledgeResponse() (response *CreateSharedKnowledge...
function NewCreateVarRequest (line 534) | func NewCreateVarRequest() (request *CreateVarRequest) {
function NewCreateVarResponse (line 544) | func NewCreateVarResponse() (response *CreateVarResponse) {
function NewCreateWorkflowRunRequest (line 587) | func NewCreateWorkflowRunRequest() (request *CreateWorkflowRunRequest) {
function NewCreateWorkflowRunResponse (line 597) | func NewCreateWorkflowRunResponse() (response *CreateWorkflowRunResponse) {
function NewDeleteAgentRequest (line 644) | func NewDeleteAgentRequest() (request *DeleteAgentRequest) {
function NewDeleteAgentResponse (line 654) | func NewDeleteAgentResponse() (response *DeleteAgentResponse) {
function NewDeleteAppRequest (line 695) | func NewDeleteAppRequest() (request *DeleteAppRequest) {
function NewDeleteAppResponse (line 705) | func NewDeleteAppResponse() (response *DeleteAppResponse) {
function NewDeleteAttributeLabelRequest (line 746) | func NewDeleteAttributeLabelRequest() (request *DeleteAttributeLabelRequ...
function NewDeleteAttributeLabelResponse (line 756) | func NewDeleteAttributeLabelResponse() (response *DeleteAttributeLabelRe...
function NewDeleteDocRequest (line 797) | func NewDeleteDocRequest() (request *DeleteDocRequest) {
function NewDeleteDocResponse (line 807) | func NewDeleteDocResponse() (response *DeleteDocResponse) {
function NewDeleteDocCateRequest (line 848) | func NewDeleteDocCateRequest() (request *DeleteDocCateRequest) {
function NewDeleteDocCateResponse (line 858) | func NewDeleteDocCateResponse() (response *DeleteDocCateResponse) {
function NewDeleteQARequest (line 899) | func NewDeleteQARequest() (request *DeleteQARequest) {
function NewDeleteQAResponse (line 909) | func NewDeleteQAResponse() (response *DeleteQAResponse) {
function NewDeleteQACateRequest (line 950) | func NewDeleteQACateRequest() (request *DeleteQACateRequest) {
function NewDeleteQACateResponse (line 960) | func NewDeleteQACateResponse() (response *DeleteQACateResponse) {
function NewDeleteRejectedQuestionRequest (line 1001) | func NewDeleteRejectedQuestionRequest() (request *DeleteRejectedQuestion...
function NewDeleteRejectedQuestionResponse (line 1011) | func NewDeleteRejectedQuestionResponse() (response *DeleteRejectedQuesti...
function NewDeleteSharedKnowledgeRequest (line 1052) | func NewDeleteSharedKnowledgeRequest() (request *DeleteSharedKnowledgeRe...
function NewDeleteSharedKnowledgeResponse (line 1062) | func NewDeleteSharedKnowledgeResponse() (response *DeleteSharedKnowledge...
function NewDeleteVarRequest (line 1103) | func NewDeleteVarRequest() (request *DeleteVarRequest) {
function NewDeleteVarResponse (line 1113) | func NewDeleteVarResponse() (response *DeleteVarResponse) {
function NewDescribeAppRequest (line 1154) | func NewDescribeAppRequest() (request *DescribeAppRequest) {
function NewDescribeAppResponse (line 1164) | func NewDescribeAppResponse() (response *DescribeAppResponse) {
function NewDescribeAppAgentListRequest (line 1205) | func NewDescribeAppAgentListRequest() (request *DescribeAppAgentListRequ...
function NewDescribeAppAgentListResponse (line 1215) | func NewDescribeAppAgentListResponse() (response *DescribeAppAgentListRe...
function NewDescribeAttributeLabelRequest (line 1256) | func NewDescribeAttributeLabelRequest() (request *DescribeAttributeLabel...
function NewDescribeAttributeLabelResponse (line 1266) | func NewDescribeAttributeLabelResponse() (response *DescribeAttributeLab...
function NewDescribeCallStatsGraphRequest (line 1307) | func NewDescribeCallStatsGraphRequest() (request *DescribeCallStatsGraph...
function NewDescribeCallStatsGraphResponse (line 1317) | func NewDescribeCallStatsGraphResponse() (response *DescribeCallStatsGra...
function NewDescribeConcurrencyUsageRequest (line 1358) | func NewDescribeConcurrencyUsageRequest() (request *DescribeConcurrencyU...
function NewDescribeConcurrencyUsageResponse (line 1368) | func NewDescribeConcurrencyUsageResponse() (response *DescribeConcurrenc...
function NewDescribeConcurrencyUsageGraphRequest (line 1409) | func NewDescribeConcurrencyUsageGraphRequest() (request *DescribeConcurr...
function NewDescribeConcurrencyUsageGraphResponse (line 1419) | func NewDescribeConcurrencyUsageGraphResponse() (response *DescribeConcu...
function NewDescribeDocRequest (line 1460) | func NewDescribeDocRequest() (request *DescribeDocRequest) {
function NewDescribeDocResponse (line 1470) | func NewDescribeDocResponse() (response *DescribeDocResponse) {
function NewDescribeKnowledgeUsageRequest (line 1511) | func NewDescribeKnowledgeUsageRequest() (request *DescribeKnowledgeUsage...
function NewDescribeKnowledgeUsageResponse (line 1521) | func NewDescribeKnowledgeUsageResponse() (response *DescribeKnowledgeUsa...
function NewDescribeKnowledgeUsagePieGraphRequest (line 1562) | func NewDescribeKnowledgeUsagePieGraphRequest() (request *DescribeKnowle...
function NewDescribeKnowledgeUsagePieGraphResponse (line 1572) | func NewDescribeKnowledgeUsagePieGraphResponse() (response *DescribeKnow...
function NewDescribeNodeRunRequest (line 1613) | func NewDescribeNodeRunRequest() (request *DescribeNodeRunRequest) {
function NewDescribeNodeRunResponse (line 1623) | func NewDescribeNodeRunResponse() (response *DescribeNodeRunResponse) {
function NewDescribeQARequest (line 1666) | func NewDescribeQARequest() (request *DescribeQARequest) {
function NewDescribeQAResponse (line 1676) | func NewDescribeQAResponse() (response *DescribeQAResponse) {
function NewDescribeReferRequest (line 1719) | func NewDescribeReferRequest() (request *DescribeReferRequest) {
function NewDescribeReferResponse (line 1729) | func NewDescribeReferResponse() (response *DescribeReferResponse) {
function NewDescribeReleaseRequest (line 1772) | func NewDescribeReleaseRequest() (request *DescribeReleaseRequest) {
function NewDescribeReleaseResponse (line 1782) | func NewDescribeReleaseResponse() (response *DescribeReleaseResponse) {
function NewDescribeReleaseInfoRequest (line 1825) | func NewDescribeReleaseInfoRequest() (request *DescribeReleaseInfoReques...
function NewDescribeReleaseInfoResponse (line 1835) | func NewDescribeReleaseInfoResponse() (response *DescribeReleaseInfoResp...
function NewDescribeRobotBizIDByAppKeyRequest (line 1878) | func NewDescribeRobotBizIDByAppKeyRequest() (request *DescribeRobotBizID...
function NewDescribeRobotBizIDByAppKeyResponse (line 1888) | func NewDescribeRobotBizIDByAppKeyResponse() (response *DescribeRobotBiz...
function NewDescribeSearchStatsGraphRequest (line 1929) | func NewDescribeSearchStatsGraphRequest() (request *DescribeSearchStatsG...
function NewDescribeSearchStatsGraphResponse (line 1939) | func NewDescribeSearchStatsGraphResponse() (response *DescribeSearchStat...
function NewDescribeSegmentsRequest (line 1980) | func NewDescribeSegmentsRequest() (request *DescribeSegmentsRequest) {
function NewDescribeSegmentsResponse (line 1990) | func NewDescribeSegmentsResponse() (response *DescribeSegmentsResponse) {
function NewDescribeSharedKnowledgeRequest (line 2031) | func NewDescribeSharedKnowledgeRequest() (request *DescribeSharedKnowled...
function NewDescribeSharedKnowledgeResponse (line 2041) | func NewDescribeSharedKnowledgeResponse() (response *DescribeSharedKnowl...
function NewDescribeStorageCredentialRequest (line 2082) | func NewDescribeStorageCredentialRequest() (request *DescribeStorageCred...
function NewDescribeStorageCredentialResponse (line 2092) | func NewDescribeStorageCredentialResponse() (response *DescribeStorageCr...
function NewDescribeTokenUsageRequest (line 2133) | func NewDescribeTokenUsageRequest() (request *DescribeTokenUsageRequest) {
function NewDescribeTokenUsageResponse (line 2143) | func NewDescribeTokenUsageResponse() (response *DescribeTokenUsageRespon...
function NewDescribeTokenUsageGraphRequest (line 2184) | func NewDescribeTokenUsageGraphRequest() (request *DescribeTokenUsageGra...
function NewDescribeTokenUsageGraphResponse (line 2194) | func NewDescribeTokenUsageGraphResponse() (response *DescribeTokenUsageG...
function NewDescribeUnsatisfiedReplyContextRequest (line 2235) | func NewDescribeUnsatisfiedReplyContextRequest() (request *DescribeUnsat...
function NewDescribeUnsatisfiedReplyContextResponse (line 2245) | func NewDescribeUnsatisfiedReplyContextResponse() (response *DescribeUns...
function NewDescribeWorkflowRunRequest (line 2288) | func NewDescribeWorkflowRunRequest() (request *DescribeWorkflowRunReques...
function NewDescribeWorkflowRunResponse (line 2298) | func NewDescribeWorkflowRunResponse() (response *DescribeWorkflowRunResp...
function NewExportAttributeLabelRequest (line 2341) | func NewExportAttributeLabelRequest() (request *ExportAttributeLabelRequ...
function NewExportAttributeLabelResponse (line 2351) | func NewExportAttributeLabelResponse() (response *ExportAttributeLabelRe...
function NewExportQAListRequest (line 2394) | func NewExportQAListRequest() (request *ExportQAListRequest) {
function NewExportQAListResponse (line 2404) | func NewExportQAListResponse() (response *ExportQAListResponse) {
function NewExportUnsatisfiedReplyRequest (line 2447) | func NewExportUnsatisfiedReplyRequest() (request *ExportUnsatisfiedReply...
function NewExportUnsatisfiedReplyResponse (line 2457) | func NewExportUnsatisfiedReplyResponse() (response *ExportUnsatisfiedRep...
function NewGenerateQARequest (line 2500) | func NewGenerateQARequest() (request *GenerateQARequest) {
function NewGenerateQAResponse (line 2510) | func NewGenerateQAResponse() (response *GenerateQAResponse) {
function NewGetAnswerTypeDataCountRequest (line 2551) | func NewGetAnswerTypeDataCountRequest() (request *GetAnswerTypeDataCount...
function NewGetAnswerTypeDataCountResponse (line 2561) | func NewGetAnswerTypeDataCountResponse() (response *GetAnswerTypeDataCou...
function NewGetAppKnowledgeCountRequest (line 2604) | func NewGetAppKnowledgeCountRequest() (request *GetAppKnowledgeCountRequ...
function NewGetAppKnowledgeCountResponse (line 2614) | func NewGetAppKnowledgeCountResponse() (response *GetAppKnowledgeCountRe...
function NewGetAppSecretRequest (line 2655) | func NewGetAppSecretRequest() (request *GetAppSecretRequest) {
function NewGetAppSecretResponse (line 2665) | func NewGetAppSecretResponse() (response *GetAppSecretResponse) {
function NewGetDocPreviewRequest (line 2706) | func NewGetDocPreviewRequest() (request *GetDocPreviewRequest) {
function NewGetDocPreviewResponse (line 2716) | func NewGetDocPreviewResponse() (response *GetDocPreviewResponse) {
function NewGetLikeDataCountRequest (line 2757) | func NewGetLikeDataCountRequest() (request *GetLikeDataCountRequest) {
function NewGetLikeDataCountResponse (line 2767) | func NewGetLikeDataCountResponse() (response *GetLikeDataCountResponse) {
function NewGetMsgRecordRequest (line 2810) | func NewGetMsgRecordRequest() (request *GetMsgRecordRequest) {
function NewGetMsgRecordResponse (line 2820) | func NewGetMsgRecordResponse() (response *GetMsgRecordResponse) {
function NewGetTaskStatusRequest (line 2867) | func NewGetTaskStatusRequest() (request *GetTaskStatusRequest) {
function NewGetTaskStatusResponse (line 2877) | func NewGetTaskStatusResponse() (response *GetTaskStatusResponse) {
function NewGetVarListRequest (line 2920) | func NewGetVarListRequest() (request *GetVarListRequest) {
function NewGetVarListResponse (line 2930) | func NewGetVarListResponse() (response *GetVarListResponse) {
function NewGetWsTokenRequest (line 2973) | func NewGetWsTokenRequest() (request *GetWsTokenRequest) {
function NewGetWsTokenResponse (line 2983) | func NewGetWsTokenResponse() (response *GetWsTokenResponse) {
function NewGroupDocRequest (line 3024) | func NewGroupDocRequest() (request *GroupDocRequest) {
function NewGroupDocResponse (line 3034) | func NewGroupDocResponse() (response *GroupDocResponse) {
function NewGroupQARequest (line 3075) | func NewGroupQARequest() (request *GroupQARequest) {
function NewGroupQAResponse (line 3085) | func NewGroupQAResponse() (response *GroupQAResponse) {
function NewIgnoreUnsatisfiedReplyRequest (line 3126) | func NewIgnoreUnsatisfiedReplyRequest() (request *IgnoreUnsatisfiedReply...
function NewIgnoreUnsatisfiedReplyResponse (line 3136) | func NewIgnoreUnsatisfiedReplyResponse() (response *IgnoreUnsatisfiedRep...
function NewIsTransferIntentRequest (line 3177) | func NewIsTransferIntentRequest() (request *IsTransferIntentRequest) {
function NewIsTransferIntentResponse (line 3187) | func NewIsTransferIntentResponse() (response *IsTransferIntentResponse) {
function NewListAppRequest (line 3228) | func NewListAppRequest() (request *ListAppRequest) {
function NewListAppResponse (line 3238) | func NewListAppResponse() (response *ListAppResponse) {
function NewListAppKnowledgeDetailRequest (line 3279) | func NewListAppKnowledgeDetailRequest() (request *ListAppKnowledgeDetail...
function NewListAppKnowledgeDetailResponse (line 3289) | func NewListAppKnowledgeDetailResponse() (response *ListAppKnowledgeDeta...
function NewListAttributeLabelRequest (line 3330) | func NewListAttributeLabelRequest() (request *ListAttributeLabelRequest) {
function NewListAttributeLabelResponse (line 3340) | func NewListAttributeLabelResponse() (response *ListAttributeLabelRespon...
function NewListChannelRequest (line 3381) | func NewListChannelRequest() (request *ListChannelRequest) {
function NewListChannelResponse (line 3391) | func NewListChannel
Copy disabled (too large)
Download .json
Condensed preview — 1265 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (28,015K chars).
[
{
"path": "CONTRIBUTING.md",
"chars": 661,
"preview": "# 贡献指南\n\n感谢您考虑为53AI Hub项目做出贡献!以下是一些指导方针,帮助您参与到项目中来。\n\n## 行为准则\n\n请尊重所有项目参与者,保持专业和友好的交流环境。\n\n## 如何贡献\n\n### 报告问题\n\n如果您发现了bug或有新功能"
},
{
"path": "LICENSE",
"chars": 1846,
"preview": "## 53AI 开源许可证 \n**53AI Open Source License** \n\n53AI Hub 基于 Apache License 2.0 的开源协议,并附加以下条件: \n53AI Hub is licensed und"
},
{
"path": "README.md",
"chars": 5997,
"preview": "<div align=\"center\">\n <a href=\"https://www.53ai.com/products/53AIHub\"><img alt=\"Product Introduction Page\" src=\"https:/"
},
{
"path": "README_CN.md",
"chars": 5086,
"preview": "<div align=\"center\">\n <a href=\"https://www.53ai.com/products/53AIHub\"><img alt=\"产品介绍页\" src=\"https://oss.ibos.cn/53ai/co"
},
{
"path": "README_JA.md",
"chars": 3912,
"preview": "<div align=\"center\">\n <a href=\"https://www.53ai.com/products/53AIHub\"><img alt=\"製品紹介ページ\" src=\"https://oss.ibos.cn/53ai/"
},
{
"path": "api/.gitattributes",
"chars": 18,
"preview": "saas/** merge=ours"
},
{
"path": "api/.gitignore",
"chars": 291,
"preview": ".idea\n.vscode\nupload\n*.exe\n*.db\nbuild\n*.db-journal\nlogs\ndata\n/web/node_modules\ncmd.md\n.env\ntemp\n.DS_Store\n__debug_bin*\ns"
},
{
"path": "api/Dockerfile",
"chars": 1086,
"preview": "FROM golang:1.24.1 as builder\n\n# 设置工作目录\nWORKDIR /app\n\n# 设置GOPROXY为中国大陆代理\nENV GOPROXY=https://goproxy.cn,direct\n\n# 安装构建依赖"
},
{
"path": "api/Makefile",
"chars": 2824,
"preview": "# Go parameters\nGOBIN = go\nGOFMT = gofmt\nGOLINT = golangci-lint\nGOTEST = go test\nGOBUILD = go build\nGOCLEAN = go clean\n\n"
},
{
"path": "api/README.md",
"chars": 2934,
"preview": "# 53AIHub 后端接口\n\n53AIHub 是一个强大的 AI 代理管理平台,支持多种 AI 模型的接入和管理。本指南将帮助您快速上手并开始使用 53AIHub。\n\n## 目录\n\n- [53AIHub 后端接口](#53aihub-后端"
},
{
"path": "api/bin/restart.sh",
"chars": 383,
"preview": "#!/bin/bash\n\n# 1. 找到 53aihub 运行的 pid \nPID=$(ps aux | grep '[5]3aihub' | awk '{print $2}')\n\n# 2. 优雅 kill 掉\nif [ -n \"$PID\""
},
{
"path": "api/bin/version.txt",
"chars": 6,
"preview": "v0.1.0"
},
{
"path": "api/build.sh",
"chars": 29,
"preview": "#!/bin/bash\nmake static-build"
},
{
"path": "api/common/cache.go",
"chars": 15,
"preview": "package common\n"
},
{
"path": "api/common/ctxkey/key.go",
"chars": 713,
"preview": "package ctxkey\n\nconst (\n\tConfig = \"config\"\n\tId = \"id\"\n\tUsername = \"username\"\n\tRole "
},
{
"path": "api/common/email.go",
"chars": 4304,
"preview": "package common\n\nimport (\n\t\"crypto/rand\"\n\t\"crypto/tls\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/smtp\"\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n\n\t\"githu"
},
{
"path": "api/common/init.go",
"chars": 945,
"preview": "package common\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/53AI/53AIHub/config\"\n)\n\nvar (\n\tPort = flag.Int(\"1por"
},
{
"path": "api/common/lock.go",
"chars": 1974,
"preview": "package common\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/go-redis/redi"
},
{
"path": "api/common/logger/logger.go",
"chars": 5607,
"preview": "package logger\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\""
},
{
"path": "api/common/permission.go",
"chars": 263,
"preview": "package common\n\nimport (\n\t\"github.com/53AI/53AIHub/model\"\n\t\"github.com/gin-gonic/gin\"\n)\n\nfunc IsAdmin(c *gin.Context) bo"
},
{
"path": "api/common/redis.go",
"chars": 5070,
"preview": "package common\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/"
},
{
"path": "api/common/session/key.go",
"chars": 715,
"preview": "package session\n\nconst (\n\tSESSION_USER_ID = \"SESSION_USER_ID\"\n\tSESSION_USER_NICKNAME = \"SESSION_USER_NICKNAM"
},
{
"path": "api/common/storage/storage.go",
"chars": 3979,
"preview": "package storage\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"os\"\n\t\"path\"\n\t\"path/"
},
{
"path": "api/common/storage/storage_test.go",
"chars": 646,
"preview": "package storage\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc TestSaveFile(t *testing.T) {\n\t// 创建 LocalStorage 实例\n"
},
{
"path": "api/common/utils/ai53/api.go",
"chars": 3698,
"preview": "package ai53\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype AI53Api struct {\n\tBaseUrl"
},
{
"path": "api/common/utils/appbuilder/api.go",
"chars": 4256,
"preview": "package appbuilder\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/co"
},
{
"path": "api/common/utils/coze/api.go",
"chars": 7341,
"preview": "package coze\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/"
},
{
"path": "api/common/utils/env/env.go",
"chars": 1042,
"preview": "package env\n\nimport (\n\t\"os\"\n\t\"strconv\"\n\n\t_ \"github.com/joho/godotenv/autoload\"\n)\n\nfunc Int(env string, defaultValue int)"
},
{
"path": "api/common/utils/helper/helper.go",
"chars": 3331,
"preview": "package helper\n\nimport (\n\t\"context\"\n\t\"crypto/md5\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\""
},
{
"path": "api/common/utils/helper/key.go",
"chars": 57,
"preview": "package helper\n\nconst (\n\tRequestIdKey = \"X-Request-Id\"\n)\n"
},
{
"path": "api/common/utils/helper/sso_sign.go",
"chars": 462,
"preview": "package helper\n\nimport (\n\t\"crypto/md5\"\n\t\"fmt\"\n)\n\n// BuildSSORawString 构造原始签名串:timestamp={10位}&username={规范化用户名}{secret}\n"
},
{
"path": "api/common/utils/huawei_cloud/model.go",
"chars": 1833,
"preview": "package huawei_cloud\n\ntype HuaweicloudBaseResponse struct {\n\tResultCode string `json:\"resultCode\"`\n\tResultMsg string `j"
},
{
"path": "api/common/utils/huawei_cloud/signature.go",
"chars": 1914,
"preview": "package huawei_cloud\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"strconv\"\n\t\"str"
},
{
"path": "api/common/utils/ip.go",
"chars": 783,
"preview": "package utils\n\nimport (\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// GetClientIP 获取请求客户端真实IP\n// 优先级:X-Real-Ip > X-Forwa"
},
{
"path": "api/common/utils/jwt/jwt.go",
"chars": 953,
"preview": "package jwt\n\nimport (\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/utils/env\"\n\t\"github.com/golang-jwt/jwt/v5\"\n)\n\nvar secret"
},
{
"path": "api/common/utils/random.go",
"chars": 282,
"preview": "package utils\n\nimport (\n\t\"math/rand\"\n\t\"time\"\n)\n\nvar randomGenerator *rand.Rand\n\nfunc init() {\n\tsource := rand.NewSource("
},
{
"path": "api/common/utils/snowflake.go",
"chars": 2703,
"preview": "package utils\n\nimport (\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n)\n\n// Snowflake ID generator\ntype Snowflake struct {\n\tmutex sync"
},
{
"path": "api/common/utils/system/machine.go",
"chars": 5227,
"preview": "package system\n\nimport (\n\t\"bufio\"\n\t\"crypto/md5\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/com"
},
{
"path": "api/common/utils/system/version.go",
"chars": 4405,
"preview": "package system\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/lo"
},
{
"path": "api/common/utils/wxbizjsonmsgcrypt/wxbizjsonmsgcrypt.go",
"chars": 8972,
"preview": "package wxbizmsgcrypt\n\nimport (\n\t\"bytes\"\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/sha1\"\n\t\"encoding/base64\"\n\t\"encoding/bin"
},
{
"path": "api/common/validate.go",
"chars": 143,
"preview": "package common\n\nimport \"github.com/go-playground/validator/v10\"\n\nvar Validate *validator.Validate\n\nfunc init() {\n\tValida"
},
{
"path": "api/config/config.go",
"chars": 3395,
"preview": "package config\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/session\"\n\t\"github.c"
},
{
"path": "api/config/database.go",
"chars": 286,
"preview": "package config\n\nimport \"github.com/53AI/53AIHub/common/utils/env\"\n\nvar UsingSQLite = false\nvar UsingPostgreSQL = false\nv"
},
{
"path": "api/config/encryption.go",
"chars": 438,
"preview": "package config\n\nimport (\n\t\"os\"\n)\n\n// GetEncryptionKey returns the encryption key for sensitive data\nfunc GetEncryptionKe"
},
{
"path": "api/config/storage.go",
"chars": 457,
"preview": "package config\n\nimport \"github.com/53AI/53AIHub/common/utils/env\"\n\nvar StorageType = env.String(\"STORAGE\", \"local\")\nvar "
},
{
"path": "api/controller/agent.go",
"chars": 25775,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AI"
},
{
"path": "api/controller/ai53.go",
"chars": 7569,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/53"
},
{
"path": "api/controller/ai_link.go",
"chars": 10101,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53AI/53AIHub/model\"\n"
},
{
"path": "api/controller/appbuilder.go",
"chars": 2784,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/53"
},
{
"path": "api/controller/auth_sso.go",
"chars": 3880,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"time\"\n\t\"unicode\"\n\n\t\"github.com/53AI/53AIHub/commo"
},
{
"path": "api/controller/channel-test.go",
"chars": 6832,
"preview": "package controller\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest"
},
{
"path": "api/controller/channel.go",
"chars": 8630,
"preview": "package controller\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53"
},
{
"path": "api/controller/conversation.go",
"chars": 10890,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53AI/53AIHub/model\"\n"
},
{
"path": "api/controller/coze.go",
"chars": 3341,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/53AI/53AIHub/"
},
{
"path": "api/controller/department.go",
"chars": 11568,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53AI/53AIHub/model\"\n"
},
{
"path": "api/controller/dify.go",
"chars": 3511,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/model\"\n\t\"github.com/53AI/53AIHub/service/"
},
{
"path": "api/controller/email.go",
"chars": 6874,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/smtp\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/comm"
},
{
"path": "api/controller/enterprise.go",
"chars": 16511,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/common/utils\"\n\t\"github.com/53AI/53AIHub/c"
},
{
"path": "api/controller/enterprise_config.go",
"chars": 5039,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53AI/53AIHub/model\"\n\t"
},
{
"path": "api/controller/group.go",
"chars": 41760,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\t\"errors\"\n\n\t\"github.com/53AI/53AIHub/common/utils\"\n\t\"github.com/53AI"
},
{
"path": "api/controller/maxkb.go",
"chars": 7042,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/"
},
{
"path": "api/controller/message.go",
"chars": 7727,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/common\"\n\t\"github.com/53AI/53AIHub/config\""
},
{
"path": "api/controller/model.go",
"chars": 4750,
"preview": "package controller\n\nimport (\n\t\"github.com/53AI/53AIHub/model\"\n\t\"github.com/53AI/53AIHub/service\"\n\t\"github.com/gin-gonic/"
},
{
"path": "api/controller/navigation.go",
"chars": 13377,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/utils\"\n\t\""
},
{
"path": "api/controller/navigation_icons.go",
"chars": 2123,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/53AI/53AIHub/model\"\n\t\"github.com/gin-gonic/gin\"\n)\n\n// NavigationI"
},
{
"path": "api/controller/order.go",
"chars": 17685,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53AI/53AIHub"
},
{
"path": "api/controller/pay.go",
"chars": 33793,
"preview": "package controller\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "api/controller/pay_setting.go",
"chars": 14639,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/common/utils\"\n\t\"g"
},
{
"path": "api/controller/prompt.go",
"chars": 23772,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/com"
},
{
"path": "api/controller/provider.go",
"chars": 7262,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/config\""
},
{
"path": "api/controller/provider_callback.go",
"chars": 5395,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger"
},
{
"path": "api/controller/relay.go",
"chars": 53752,
"preview": "package controller\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"net/http\"\n\t\"strings\"\n"
},
{
"path": "api/controller/rerank.go",
"chars": 15953,
"preview": "package controller\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/53A"
},
{
"path": "api/controller/response_handler.go",
"chars": 4398,
"preview": "package controller\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/lo"
},
{
"path": "api/controller/setting.go",
"chars": 7881,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53A"
},
{
"path": "api/controller/share.go",
"chars": 5592,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53AI/53AIHub/model\"\n"
},
{
"path": "api/controller/status.go",
"chars": 1370,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/53AI/53AIHub/config\"\n\t\"github.com/53AI/53AIHub/model\"\n\t\"github.co"
},
{
"path": "api/controller/subscription.go",
"chars": 12873,
"preview": "package controller\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/utils\"\n\t\"github.com/53AI/53"
},
{
"path": "api/controller/sync_organization.go",
"chars": 2776,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/53AI/53AIHub/model\"\n\t\"github.com/gin-gonic/gin\"\n)\n\n// SyncOrganiz"
},
{
"path": "api/controller/system_log.go",
"chars": 4020,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/53AI/53AIHub/common/utils\"\n\t\"github.com/53AI/53AIHub/config\"\n\t\"gi"
},
{
"path": "api/controller/tencent.go",
"chars": 7412,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common"
},
{
"path": "api/controller/upload.go",
"chars": 4050,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\n\t\"github.com/53AI/53AIHub/common/sto"
},
{
"path": "api/controller/user.go",
"chars": 56806,
"preview": "package controller\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/5"
},
{
"path": "api/docker/docker-compose.yml",
"chars": 814,
"preview": "version: '3.8'\n\nservices:\n 53aihub:\n build:\n context: ..\n dockerfile: Dockerfile\n env_file: .env\n po"
},
{
"path": "api/docs/.gitignore",
"chars": 49,
"preview": "# 忽略文件夹内所有文件\n*\n# 但不忽略 .gitignore 文件本身\n!.gitignore"
},
{
"path": "api/go.mod",
"chars": 6208,
"preview": "module github.com/53AI/53AIHub\n\ngo 1.24.1\n\nrequire (\n\tgithub.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13\n\tgithub.co"
},
{
"path": "api/go.sum",
"chars": 49349,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go/auth v0.6.1 h1:T0"
},
{
"path": "api/main.go",
"chars": 1854,
"preview": "package main\n\nimport (\n\t\"embed\"\n\t\"os\"\n\n\t\"github.com/53AI/53AIHub/common\"\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"gith"
},
{
"path": "api/middleware/auth.go",
"chars": 2009,
"preview": "package middleware\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/session\"\n\t\"github.com/53"
},
{
"path": "api/middleware/cors.go",
"chars": 364,
"preview": "package middleware\n\nimport (\n\t\"github.com/gin-contrib/cors\"\n\t\"github.com/gin-gonic/gin\"\n)\n\nfunc CORS() gin.HandlerFunc {"
},
{
"path": "api/middleware/distributor.go",
"chars": 1998,
"preview": "package middleware\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/53AI/53AIHub/common/ctxkey\"\n\t\"github.com/53AI/53AIHub/model\"\n\t\"github."
},
{
"path": "api/middleware/logger.go",
"chars": 688,
"preview": "package middleware\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/session\"\n\t\"github.com/gin-gonic/gin\"\n)\n\nfu"
},
{
"path": "api/middleware/relay_auth.go",
"chars": 4060,
"preview": "package middleware\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/5"
},
{
"path": "api/model/agent.go",
"chars": 5290,
"preview": "package model\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"strconv\"\n)\n\ntype Agent struct {\n\tAgentID int64 `json:\"a"
},
{
"path": "api/model/ai_link.go",
"chars": 5964,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"log\"\n)\n\ntype AILink struct {\n\tID int64 `json:\"id\" gorm:\"primaryKey;autoInc"
},
{
"path": "api/model/base.go",
"chars": 488,
"preview": "package model\n\nimport (\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype BaseModel struct {\n\tCreatedTime int64 `json:\"created_time\" gorm"
},
{
"path": "api/model/cache.go",
"chars": 87,
"preview": "package model\n\nconst (\n\tLockOrganizationKeyPre = \"lock_enterprise_organization_sync\"\n)\n"
},
{
"path": "api/model/channel.go",
"chars": 10081,
"preview": "package model\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/53AI/5"
},
{
"path": "api/model/channel_file_mapping.go",
"chars": 1807,
"preview": "package model\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n)\n\ntype ChannelFileMapping struc"
},
{
"path": "api/model/conversation.go",
"chars": 6716,
"preview": "package model\n\ntype Conversation struct {\n\tConversationID int64 `json:\"conversation_id\" gorm:\"column"
},
{
"path": "api/model/department.go",
"chars": 13675,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"gorm.io/gorm\"\n)\n\n// Department source constants\nconst (\n\tDepartme"
},
{
"path": "api/model/dingtalk_corp.go",
"chars": 3486,
"preview": "package model\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype DingtalkCorp struct {\n\tCorpId strin"
},
{
"path": "api/model/dingtalk_suite.go",
"chars": 2043,
"preview": "package model\n\nimport (\n\t\"errors\"\n)\n\ntype DingtalkSuite struct {\n\tSuiteID string `json:\"suite_id\" gorm:\""
},
{
"path": "api/model/enterprise.go",
"chars": 20617,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/53AI/53AIHub/common/uti"
},
{
"path": "api/model/enterprise_config.go",
"chars": 1452,
"preview": "package model\n\nimport (\n\t\"fmt\"\n)\n\ntype EnterpriseConfig struct {\n\tID int64 `gorm:\"primaryKey;autoIncrement\" json:\""
},
{
"path": "api/model/enterprise_sync.go",
"chars": 1775,
"preview": "package model\n\nimport (\n\t\"errors\"\n\n\t\"github.com/53AI/53AIHub/common/utils/helper\"\n)\n\n// FindEnterpriseUserByAccount 在所有企"
},
{
"path": "api/model/group.go",
"chars": 14073,
"preview": "package model\n\n// Group represents a group entity with optional agent associations\ntype Group struct {\n\tGroupId int64 "
},
{
"path": "api/model/like.go",
"chars": 3662,
"preview": "package model\n\nimport (\n\t\"errors\"\n\n\t\"gorm.io/gorm\"\n)\n\n// Like 点赞记录表\ntype Like struct {\n\tLikeID int64 `json:\"like_id\" "
},
{
"path": "api/model/main.go",
"chars": 3721,
"preview": "package model\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/53AI"
},
{
"path": "api/model/member_binding.go",
"chars": 8150,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n)\n\n// Member binding source constants\nconst (\n\tMemberB"
},
{
"path": "api/model/member_department_relation.go",
"chars": 6688,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"gorm.io/gorm\"\n)\n\n// MemberDepartmentRelation source constants\nconst (\n\tMembe"
},
{
"path": "api/model/message.go",
"chars": 7052,
"preview": "package model\n\nimport \"encoding/json\"\n\ntype Message struct {\n\tID int64 `json:\"id\" gorm:\"column:id;primar"
},
{
"path": "api/model/navigation.go",
"chars": 3206,
"preview": "package model\n\nimport \"errors\"\n\ntype Navigation struct {\n\tNavigationID int64 `json:\"navigation_id\" gorm:\"pr"
},
{
"path": "api/model/navigation_content.go",
"chars": 1663,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"time\"\n)\n\ntype NavigationContent struct {\n\tContentID int64 `json:\"content_id\" gor"
},
{
"path": "api/model/order.go",
"chars": 13509,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"time\"\n)\n\n// Order status constants\nconst (\n\tOrderStatusConfirming = 1 // Manual paym"
},
{
"path": "api/model/pay_setting.go",
"chars": 4157,
"preview": "package model\n\nimport \"errors\"\n\n// Payment type constants\nconst (\n\tPayTypeWechat = 1 // WeChat Pay\n\tPayTypeManual = 2 //"
},
{
"path": "api/model/prompt.go",
"chars": 5681,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Prompt 提示词表\ntype Prompt struct {\n\tPromptID int64 "
},
{
"path": "api/model/provider.go",
"chars": 5013,
"preview": "package model\n\nimport (\n\t\"github.com/53AI/53AIHub/common/logger\"\n)\n\ntype Provider struct {\n\tProviderID int64 `json:\""
},
{
"path": "api/model/resource_permission.go",
"chars": 4980,
"preview": "package model\n\n// ResourceType defines constants for resource types\nconst (\n\tResourceTypeAgent = \"agent\" // Ag"
},
{
"path": "api/model/response.go",
"chars": 5917,
"preview": "package model\n\nimport \"errors\"\n\n// CommonResponse represents the standard API response format\n// @Description Standard A"
},
{
"path": "api/model/setting.go",
"chars": 3914,
"preview": "package model\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype Setting struct {\n\tSettingID int64 `json:\"se"
},
{
"path": "api/model/share_record.go",
"chars": 5374,
"preview": "package model\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/google/uuid\"\n"
},
{
"path": "api/model/subscription.go",
"chars": 7652,
"preview": "package model\n\nconst (\n\tCurrencyCNY = \"CNY\"\n\tCurrencyUSD = \"USD\"\n\n\tTimeUnitYear = \"year\"\n\tTimeUnitMonth = \"month\"\n\t"
},
{
"path": "api/model/system_log.go",
"chars": 8777,
"preview": "package model\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\t\"time\"\n)\n\n// SystemLog 系统日志模型\n// @Description 对应数据库system_logs表,记录"
},
{
"path": "api/model/upload_file.go",
"chars": 3325,
"preview": "package model\n\nimport (\n\t\"crypto/md5\"\n\t\"fmt\"\n\t\"path\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/common/storage\"\n\t\"github.com/"
},
{
"path": "api/model/user.go",
"chars": 16342,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/utils/helper\"\n\t"
},
{
"path": "api/model/verification_code.go",
"chars": 911,
"preview": "package model\n\n// VerificationCode 验证码数据表\n// @Description 存储手机号/邮箱验证码及发送次数等信息\ntype VerificationCode struct {\n\tID "
},
{
"path": "api/model/wecom_corp.go",
"chars": 4586,
"preview": "package model\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype WecomCorp struct {\n\tCorpID st"
},
{
"path": "api/model/wecom_suite.go",
"chars": 2625,
"preview": "package model\n\nimport (\n\t\"errors\"\n)\n\ntype WecomSuite struct {\n\tSuiteID string `json:\"suite_id\" gorm:\"pri"
},
{
"path": "api/router/api.go",
"chars": 18547,
"preview": "package router\n\nimport (\n\t\"github.com/53AI/53AIHub/controller\"\n\t\"github.com/53AI/53AIHub/middleware\"\n\t\"github.com/53AI/5"
},
{
"path": "api/router/main.go",
"chars": 1329,
"preview": "package router\n\nimport (\n\t\"embed\"\n\t\"io/fs\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/53AI/53AIHub/controller\"\n\t_ \"github.com/53AI/"
},
{
"path": "api/router/static.go",
"chars": 5571,
"preview": "package router\n\nimport (\n\t\"embed\"\n\t\"io/fs\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com"
},
{
"path": "api/router/web.go",
"chars": 790,
"preview": "package router\n\nimport (\n\t\"embed\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nfunc SetWebRouter(router *gin"
},
{
"path": "api/service/adaptor.go",
"chars": 5270,
"preview": "package service\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/model\"\n\tadaptor53AI \"github.com/53AI/53AIH"
},
{
"path": "api/service/ai53_provider.go",
"chars": 1286,
"preview": "package service\n\nimport (\n\t\"github.com/53AI/53AIHub/common/utils/ai53\"\n\t\"github.com/53AI/53AIHub/model\"\n)\n\ntype AI53Serv"
},
{
"path": "api/service/appbuilder_provider.go",
"chars": 1239,
"preview": "package service\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/53AI/53AIHub/common/utils/appbuilder\"\n\t\"github.com/53AI/53AIHub/model\"\n)\n"
},
{
"path": "api/service/channel_service.go",
"chars": 2030,
"preview": "package service\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"github.com/53AI/53AIHub/config\"\n"
},
{
"path": "api/service/coze_provider.go",
"chars": 13661,
"preview": "package service\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"path\"\n\t\"strings\"\n\t\"time\"\n\n"
},
{
"path": "api/service/enterprise_config_service.go",
"chars": 6436,
"preview": "package service\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"net/smtp\"\n\t\"strconv\"\n\n\t\"github.com/53AI/53AIHub/common/utils/env\""
},
{
"path": "api/service/hub_adaptor/53AI/adaptor.go",
"chars": 12447,
"preview": "package adaptor53AI\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"net/textp"
},
{
"path": "api/service/hub_adaptor/53AI/constants.go",
"chars": 48,
"preview": "package adaptor53AI\n\nvar ModelList = []string{}\n"
},
{
"path": "api/service/hub_adaptor/53AI/main.go",
"chars": 4816,
"preview": "package adaptor53AI\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\""
},
{
"path": "api/service/hub_adaptor/53AI/model.go",
"chars": 2483,
"preview": "package adaptor53AI\n\ntype StreamResponse struct {\n\tEvent string `json:\"event\"`\n\tConversationID string "
},
{
"path": "api/service/hub_adaptor/53AI/workflow.go",
"chars": 17633,
"preview": "package adaptor53AI\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings"
},
{
"path": "api/service/hub_adaptor/appbuilder/adaptor.go",
"chars": 7254,
"preview": "package appbuilder\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"strings\"\n\n"
},
{
"path": "api/service/hub_adaptor/appbuilder/constants.go",
"chars": 47,
"preview": "package appbuilder\n\nvar ModelList = []string{}\n"
},
{
"path": "api/service/hub_adaptor/appbuilder/main.go",
"chars": 4861,
"preview": "package appbuilder\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/co"
},
{
"path": "api/service/hub_adaptor/appbuilder/model.go",
"chars": 2630,
"preview": "package appbuilder\n\ntype Request struct {\n\tAppID string `json:\"app_id\"`\n\tEndUserID string `jso"
},
{
"path": "api/service/hub_adaptor/bailian/adaptor.go",
"chars": 5466,
"preview": "package bailian\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.c"
},
{
"path": "api/service/hub_adaptor/bailian/constants.go",
"chars": 63,
"preview": "package bailian\n\nvar ModelList = []string{\n\t\"gte-rerank-v2\",\n}\n"
},
{
"path": "api/service/hub_adaptor/bailian/main.go",
"chars": 5192,
"preview": "package bailian\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/co"
},
{
"path": "api/service/hub_adaptor/bailian/model.go",
"chars": 1022,
"preview": "package bailian\n\ntype Request struct {\n\tInput Input `json:\"input\"`\n\tParameters Parameters `json:\"parameters\"`\n"
},
{
"path": "api/service/hub_adaptor/bailian/rerank.go",
"chars": 5173,
"preview": "package bailian\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/commo"
},
{
"path": "api/service/hub_adaptor/bailian/rerank_model.go",
"chars": 1813,
"preview": "package bailian\n\n// Rerank 请求结构 - 百炼格式\ntype BailianRerankRequest struct {\n\tModel string `json:\"mod"
},
{
"path": "api/service/hub_adaptor/coze/adaptor.go",
"chars": 2997,
"preview": "package coze\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/service/hub_adaptor/cust"
},
{
"path": "api/service/hub_adaptor/coze/constant/contenttype/define.go",
"chars": 46,
"preview": "package contenttype\n\nconst (\n\tText = \"text\"\n)\n"
},
{
"path": "api/service/hub_adaptor/coze/constant/event/define.go",
"chars": 83,
"preview": "package event\n\nconst (\n\tMessage = \"message\"\n\tDone = \"done\"\n\tError = \"error\"\n)\n"
},
{
"path": "api/service/hub_adaptor/coze/constant/messagetype/define.go",
"chars": 76,
"preview": "package messagetype\n\nconst (\n\tAnswer = \"answer\"\n\tFollowUp = \"follow_up\"\n)\n"
},
{
"path": "api/service/hub_adaptor/coze/constants.go",
"chars": 41,
"preview": "package coze\n\nvar ModelList = []string{}\n"
},
{
"path": "api/service/hub_adaptor/coze/helper.go",
"chars": 202,
"preview": "package coze\n\nimport \"github.com/songquanpeng/one-api/relay/adaptor/coze/constant/event\"\n\nfunc event2StopReason(e *strin"
},
{
"path": "api/service/hub_adaptor/coze/main.go",
"chars": 10617,
"preview": "package coze\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"githu"
},
{
"path": "api/service/hub_adaptor/coze/model.go",
"chars": 2983,
"preview": "package coze\n\ntype Message struct {\n\tRole string `json:\"role\"`\n\tType string `json:\"type\"`\n\tContent str"
},
{
"path": "api/service/hub_adaptor/coze/workflow.go",
"chars": 14653,
"preview": "package coze\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\tdb_model \"github.com/"
},
{
"path": "api/service/hub_adaptor/custom/common.go",
"chars": 2773,
"preview": "package custom\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AI"
},
{
"path": "api/service/hub_adaptor/custom/config.go",
"chars": 695,
"preview": "package custom\n\ntype CustomConfig struct {\n\tUserId string `json:\"user_id,omitempty"
},
{
"path": "api/service/hub_adaptor/custom/workflow.go",
"chars": 597,
"preview": "package custom\n\n// WorkflowResponseData 工作流标准响应数据结构\ntype WorkflowResponseData struct {\n\tWorkflowOutputData map[string]in"
},
{
"path": "api/service/hub_adaptor/dify/adaptor.go",
"chars": 9164,
"preview": "package dify\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"net/textproto\"\n\t"
},
{
"path": "api/service/hub_adaptor/dify/constants.go",
"chars": 41,
"preview": "package dify\n\nvar ModelList = []string{}\n"
},
{
"path": "api/service/hub_adaptor/dify/info.go",
"chars": 5965,
"preview": "package dify\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/songquanpeng/one-api/common/lo"
},
{
"path": "api/service/hub_adaptor/dify/main.go",
"chars": 3988,
"preview": "package dify\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n\t\"gith"
},
{
"path": "api/service/hub_adaptor/dify/model.go",
"chars": 2177,
"preview": "package dify\n\ntype StreamResponse struct {\n\tEvent string `json:\"event\"`\n\tConversationID string `json:\"conversat"
},
{
"path": "api/service/hub_adaptor/dify/workflow.go",
"chars": 12975,
"preview": "package dify\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\tdb_"
},
{
"path": "api/service/hub_adaptor/fastgpt/workflow.go",
"chars": 9403,
"preview": "package fastgpt\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/53AI/53"
},
{
"path": "api/service/hub_adaptor/n8n/README.md",
"chars": 4044,
"preview": "# n8n 工作流适配器\n\nn8n 是一个强大的工作流自动化平台,本适配器实现了与 n8n webhook 的完整集成,支持文件上传和复杂参数传递。\n\n## 功能特性\n\n### ✅ 核心功能\n- **渠道类型**: ChannelApiTy"
},
{
"path": "api/service/hub_adaptor/n8n/adaptor.go",
"chars": 1891,
"preview": "package n8n\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\n\t\"github.com/53AI/53AIHub/service/hub_adaptor/custom\"\n\t\"github.com/gi"
},
{
"path": "api/service/hub_adaptor/n8n/constants.go",
"chars": 40,
"preview": "package n8n\n\nvar ModelList = []string{}\n"
},
{
"path": "api/service/hub_adaptor/n8n/main.go",
"chars": 4518,
"preview": "package n8n\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger\"\n"
},
{
"path": "api/service/hub_adaptor/n8n/model.go",
"chars": 582,
"preview": "package n8n\n\n// N8nWorkflowRequest n8n 工作流请求结构\ntype N8nWorkflowRequest map[string]interface{}\n\n// N8nWorkflowResponse n8"
},
{
"path": "api/service/hub_adaptor/n8n/workflow.go",
"chars": 10102,
"preview": "package n8n\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"git"
},
{
"path": "api/service/hub_adaptor/openai/adaptor.go",
"chars": 8237,
"preview": "package openai\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com"
},
{
"path": "api/service/hub_adaptor/openai/compatible.go",
"chars": 2355,
"preview": "package openai\n\nimport (\n\t\"github.com/songquanpeng/one-api/relay/adaptor/ai360\"\n\t\"github.com/songquanpeng/one-api/relay/"
},
{
"path": "api/service/hub_adaptor/openai/constants.go",
"chars": 1061,
"preview": "package openai\n\nvar ModelList = []string{\n\t\"gpt-3.5-turbo\", \"gpt-3.5-turbo-0301\", \"gpt-3.5-turbo-0613\", \"gpt-3.5-turbo-1"
},
{
"path": "api/service/hub_adaptor/openai/helper.go",
"chars": 966,
"preview": "package openai\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/songquanpeng/one-api/relay/channeltype\"\n\t\"github.com/songquanpe"
},
{
"path": "api/service/hub_adaptor/openai/image.go",
"chars": 1225,
"preview": "package openai\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/songquanpeng/one-api/relay/m"
},
{
"path": "api/service/hub_adaptor/openai/main.go",
"chars": 5226,
"preview": "package openai\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/songquanpeng/one-"
},
{
"path": "api/service/hub_adaptor/openai/model.go",
"chars": 4609,
"preview": "package openai\n\nimport \"github.com/songquanpeng/one-api/relay/model\"\n\ntype TextContent struct {\n\tType string `json:\"type"
},
{
"path": "api/service/hub_adaptor/openai/token.go",
"chars": 7755,
"preview": "package openai\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"strings\"\n\n\t\"github.com/pkoukk/tiktoken-go\"\n\n\t\"github.com/songquanpen"
},
{
"path": "api/service/hub_adaptor/openai/util.go",
"chars": 475,
"preview": "package openai\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/songquanpeng/one-api/common/logger\"\n\t\"github.com/songquanpeng/o"
},
{
"path": "api/service/hub_adaptor/tencent/adaptor.go",
"chars": 2411,
"preview": "package tencent\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\n\t\"github.com/53AI/53AIHub/service/hub_adaptor/custom\"\n\t\"github.com/g"
},
{
"path": "api/service/hub_adaptor/tencent/constants.go",
"chars": 300,
"preview": "package tencent\n\nvar ModelList = []string{\n\t\"tencent-bot\",\n\t\"hunyuan\",\n\t\"hunyuan-13B\",\n\t\"hunyuan-turbo\",\n\t\"hunyuan-stand"
},
{
"path": "api/service/hub_adaptor/tencent/helper.go",
"chars": 4972,
"preview": "package tencent\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/53AI/53AIHub/common/logg"
},
{
"path": "api/service/hub_adaptor/tencent/main.go",
"chars": 3308,
"preview": "package tencent\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logg"
},
{
"path": "api/service/hub_adaptor/tencent/model.go",
"chars": 3334,
"preview": "package tencent\n\n// TencentRequest 腾讯云请求结构体\ntype TencentRequest struct {\n\tRequestID string `json:\"req"
},
{
"path": "api/service/hub_adaptor/tencent/sdk/client.go",
"chars": 138808,
"preview": "// Copyright (c) 2017-2025 Tencent. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "api/service/hub_adaptor/tencent/sdk/errors.go",
"chars": 810,
"preview": "// Copyright (c) 2017-2025 Tencent. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "api/service/hub_adaptor/tencent/sdk/models.go",
"chars": 389479,
"preview": "// Copyright (c) 2017-2025 Tencent. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "api/service/hub_adaptor/volcengine/main.go",
"chars": 391,
"preview": "package volcengine\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/songquanpeng/one-api/relay/meta\"\n\t\"github.com/songquanpeng/one-api/rel"
},
{
"path": "api/service/hub_adaptor/yuanqi/adaptor.go",
"chars": 5233,
"preview": "package yuanqi\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/commo"
},
{
"path": "api/service/hub_adaptor/yuanqi/constants.go",
"chars": 43,
"preview": "package yuanqi\n\nvar ModelList = []string{}\n"
},
{
"path": "api/service/hub_adaptor/yuanqi/main.go",
"chars": 4491,
"preview": "package yuanqi\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/53AI/53AIHub/common/logger"
}
]
// ... and 1065 more files (download for full content)
About this extraction
This page contains the full source code of the 53AI/53AIHub GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1265 files (25.2 MB), approximately 6.7M tokens, and a symbol index with 12493 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.